[PATCH 1/3] Factor evdev and TTY out of the DRM backend.
Yuval Fledel
yuvalfl at gmail.com
Mon Nov 29 11:35:46 PST 2010
evdev and TTY handling are not specific for DRM, and could be
useful for Linux framebuffer too.
This patch will move them to evdev.c
---
compositor/Makefile.am | 1 +
compositor/compositor-drm.c | 296 +---------------------------------
compositor/compositor.h | 15 ++
compositor/evdev.c | 377 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 398 insertions(+), 291 deletions(-)
create mode 100644 compositor/evdev.c
diff --git a/compositor/Makefile.am b/compositor/Makefile.am
index f8f2307..bcb6cf3 100644
--- a/compositor/Makefile.am
+++ b/compositor/Makefile.am
@@ -20,6 +20,7 @@ compositor_SOURCES = \
screenshooter-protocol.c \
screenshooter-server-protocol.h \
drm.c \
+ evdev.c \
shm.c
udevrulesddir = $(sysconfdir)/udev/rules.d
diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c
index e3e9b6f..db5f1e4 100644
--- a/compositor/compositor-drm.c
+++ b/compositor/compositor-drm.c
@@ -42,16 +42,8 @@ struct drm_compositor {
struct udev *udev;
struct wl_event_source *drm_source;
- struct wl_event_source *term_signal_source;
-
/* tty handling state */
- int tty_fd;
- uint32_t vt_active : 1;
-
- struct termios terminal_attributes;
- struct wl_event_source *tty_input_source;
- struct wl_event_source *enter_vt_source;
- struct wl_event_source *leave_vt_source;
+ struct tty_evdev *ttyevdev;
};
struct drm_output {
@@ -66,197 +58,6 @@ struct drm_output {
uint32_t current;
};
-struct drm_input {
- struct wlsc_input_device base;
-};
-
-struct evdev_input_device {
- struct drm_input *master;
- struct wl_event_source *source;
- int tool, new_x, new_y;
- int base_x, base_y;
- int fd;
-};
-
-static void evdev_input_device_data(int fd, uint32_t mask, void *data)
-{
- struct drm_compositor *c;
- struct evdev_input_device *device = data;
- struct input_event ev[8], *e, *end;
- int len, value, dx, dy, absolute_event;
- int x, y;
- uint32_t time;
-
- c = (struct drm_compositor *) device->master->base.ec;
- if (!c->vt_active)
- return;
-
- dx = 0;
- dy = 0;
- absolute_event = 0;
- x = device->master->base.x;
- y = device->master->base.y;
-
- len = read(fd, &ev, sizeof ev);
- if (len < 0 || len % sizeof e[0] != 0) {
- /* FIXME: handle error... reopen device? */;
- return;
- }
-
- e = ev;
- end = (void *) ev + len;
- for (e = ev; e < end; e++) {
- /* Get the signed value, earlier kernels had this as unsigned */
- value = e->value;
- time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
-
- switch (e->type) {
- case EV_REL:
- switch (e->code) {
- case REL_X:
- dx += value;
- break;
-
- case REL_Y:
- dy += value;
- break;
- }
- break;
-
- case EV_ABS:
- absolute_event = 1;
- switch (e->code) {
- case ABS_X:
- if (device->new_x) {
- device->base_x = x - value;
- device->new_x = 0;
- }
- x = device->base_x + value;
- break;
- case ABS_Y:
- if (device->new_y) {
- device->base_y = y - value;
- device->new_y = 0;
- }
- y = device->base_y + value;
- break;
- }
- break;
-
- case EV_KEY:
- if (value == 2)
- break;
-
- switch (e->code) {
- case BTN_TOUCH:
- case BTN_TOOL_PEN:
- case BTN_TOOL_RUBBER:
- case BTN_TOOL_BRUSH:
- case BTN_TOOL_PENCIL:
- case BTN_TOOL_AIRBRUSH:
- case BTN_TOOL_FINGER:
- case BTN_TOOL_MOUSE:
- case BTN_TOOL_LENS:
- if (device->tool == 0 && value) {
- device->new_x = 1;
- device->new_y = 1;
- }
- device->tool = value ? e->code : 0;
- break;
-
- case BTN_LEFT:
- case BTN_RIGHT:
- case BTN_MIDDLE:
- case BTN_SIDE:
- case BTN_EXTRA:
- case BTN_FORWARD:
- case BTN_BACK:
- case BTN_TASK:
- notify_button(&device->master->base,
- time, e->code, value);
- break;
-
- default:
- notify_key(&device->master->base,
- time, e->code, value);
- break;
- }
- }
- }
-
- if (dx != 0 || dy != 0)
- notify_motion(&device->master->base, time, x + dx, y + dy);
- if (absolute_event && device->tool)
- notify_motion(&device->master->base, time, x, y);
-}
-
-static struct evdev_input_device *
-evdev_input_device_create(struct drm_input *master,
- struct wl_display *display, const char *path)
-{
- struct evdev_input_device *device;
- struct wl_event_loop *loop;
-
- device = malloc(sizeof *device);
- if (device == NULL)
- return NULL;
-
- device->tool = 1;
- device->new_x = 1;
- device->new_y = 1;
- device->master = master;
-
- device->fd = open(path, O_RDONLY);
- if (device->fd < 0) {
- free(device);
- fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
- return NULL;
- }
-
- loop = wl_display_get_event_loop(display);
- device->source = wl_event_loop_add_fd(loop, device->fd,
- WL_EVENT_READABLE,
- evdev_input_device_data, device);
- if (device->source == NULL) {
- close(device->fd);
- free(device);
- return NULL;
- }
-
- return device;
-}
-
-static void
-drm_input_create(struct drm_compositor *c)
-{
- struct drm_input *input;
- struct udev_enumerate *e;
- struct udev_list_entry *entry;
- struct udev_device *device;
- const char *path;
-
- input = malloc(sizeof *input);
- if (input == NULL)
- return;
-
- memset(input, 0, sizeof *input);
- wlsc_input_device_init(&input->base, &c->base);
-
- e = udev_enumerate_new(c->udev);
- udev_enumerate_add_match_subsystem(e, "input");
- udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
- udev_enumerate_scan_devices(e);
- udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
- path = udev_list_entry_get_name(entry);
- device = udev_device_new_from_syspath(c->udev, path);
- evdev_input_device_create(input, c->base.wl_display,
- udev_device_get_devnode(device));
- }
- udev_enumerate_unref(e);
-
- c->base.input_device = &input->base;
-}
-
static void
drm_compositor_present(struct wlsc_compositor *ec)
{
@@ -498,7 +299,7 @@ create_outputs(struct drm_compositor *ec, int
option_connector)
return 0;
}
-static void on_enter_vt(int signal_number, void *data)
+static void on_enter_vt(void *data)
{
struct drm_compositor *ec = data;
struct drm_output *output;
@@ -513,12 +314,6 @@ static void on_enter_vt(int signal_number, void *data)
fprintf(stderr, "enter vt\n");
- ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
- ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
- if (ret)
- fprintf(stderr, "failed to set KD_GRAPHICS mode on console: %m\n");
- ec->vt_active = 1;
-
wl_list_for_each(output, &ec->base.output_list, base.link) {
ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id,
output->fb_id[output->current ^ 1], 0, 0,
@@ -530,7 +325,7 @@ static void on_enter_vt(int signal_number, void *data)
}
}
-static void on_leave_vt(int signal_number, void *data)
+static void on_leave_vt(void *data)
{
struct drm_compositor *ec = data;
int ret;
@@ -541,86 +336,6 @@ static void on_leave_vt(int signal_number, void *data)
kill(0, SIGTERM);
return;
}
-
- ioctl (ec->tty_fd, VT_RELDISP, 1);
- ret = ioctl(ec->tty_fd, KDSETMODE, KD_TEXT);
- if (ret)
- fprintf(stderr, "failed to set KD_TEXT mode on console: %m\n");
- ec->vt_active = 0;
-}
-
-static void
-on_tty_input(int fd, uint32_t mask, void *data)
-{
- struct drm_compositor *ec = data;
-
- /* Ignore input to tty. We get keyboard events from evdev
- */
- tcflush(ec->tty_fd, TCIFLUSH);
-}
-
-static void on_term_signal(int signal_number, void *data)
-{
- struct drm_compositor *ec = data;
-
- if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
- fprintf(stderr, "could not restore terminal to canonical mode\n");
-
- exit(0);
-}
-
-static int setup_tty(struct drm_compositor *ec, struct wl_event_loop *loop)
-{
- struct termios raw_attributes;
- struct vt_mode mode = { 0 };
- int ret;
-
- ec->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
- if (ec->tty_fd <= 0) {
- fprintf(stderr, "failed to open active tty: %m\n");
- return -1;
- }
-
- if (tcgetattr(ec->tty_fd, &ec->terminal_attributes) < 0) {
- fprintf(stderr, "could not get terminal attributes: %m\n");
- return -1;
- }
-
- /* Ignore control characters and disable echo */
- raw_attributes = ec->terminal_attributes;
- cfmakeraw(&raw_attributes);
-
- /* Fix up line endings to be normal (cfmakeraw hoses them) */
- raw_attributes.c_oflag |= OPOST | OCRNL;
-
- if (tcsetattr(ec->tty_fd, TCSANOW, &raw_attributes) < 0)
- fprintf(stderr, "could not put terminal into raw mode: %m\n");
-
- ec->term_signal_source =
- wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec);
-
- ec->tty_input_source =
- wl_event_loop_add_fd(loop, ec->tty_fd,
- WL_EVENT_READABLE, on_tty_input, ec);
-
- ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
- if (ret)
- fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
-
- ec->vt_active = 1;
- mode.mode = VT_PROCESS;
- mode.relsig = SIGUSR1;
- mode.acqsig = SIGUSR2;
- if (!ioctl(ec->tty_fd, VT_SETMODE, &mode) < 0) {
- fprintf(stderr, "failed to take control of vt handling\n");
- }
-
- ec->leave_vt_source =
- wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, ec);
- ec->enter_vt_source =
- wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, ec);
-
- return 0;
}
static int
@@ -684,13 +399,12 @@ drm_compositor_create(struct wl_display
*display, int connector)
return NULL;
}
- drm_input_create(ec);
-
loop = wl_display_get_event_loop(ec->base.wl_display);
ec->drm_source =
wl_event_loop_add_fd(loop, ec->base.drm.fd,
WL_EVENT_READABLE, on_drm_input, ec);
- setup_tty(ec, loop);
+ ec->ttyevdev = evdev_tty_setup(&ec->base, loop, ec->udev,
on_enter_vt, on_leave_vt, ec);
+
ec->base.authenticate = drm_authenticate;
ec->base.present = drm_compositor_present;
ec->base.focus = 1;
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 85535f3..4280a33 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -40,6 +40,7 @@ struct wlsc_matrix {
};
struct wlsc_surface;
+struct tty_evdev;
struct wlsc_listener {
struct wl_list link;
@@ -228,12 +229,26 @@ struct wl_buffer *
wl_buffer_create_drm(struct wlsc_compositor *compositor,
struct wl_visual *visual);
+/* Backends */
+
struct wlsc_compositor *
x11_compositor_create(struct wl_display *display, int width, int height);
struct wlsc_compositor *
drm_compositor_create(struct wl_display *display, int connector);
+/* TTY and evdev */
+
+typedef void (* on_enter_vt_t)(void *data);
+typedef void (* on_leave_vt_t)(void *data);
+
+struct tty_evdev *evdev_tty_setup(struct wlsc_compositor *ec,
+ struct wl_event_loop *loop, struct udev *udev,
+ on_enter_vt_t on_enter, on_leave_vt_t on_leave,
+ void *callback_data);
+
+/* Extensions */
+
void
screenshooter_create(struct wlsc_compositor *ec);
diff --git a/compositor/evdev.c b/compositor/evdev.c
new file mode 100644
index 0000000..8ff23ce
--- /dev/null
+++ b/compositor/evdev.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright ֲ© 2008-2010 Kristian Hֳ¸gsberg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <signal.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <linux/input.h>
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "compositor.h"
+
+struct tty_evdev {
+ struct wlsc_compositor *ec;
+ struct wl_list input_devices;
+
+ /* tty handling state */
+ int tty_fd;
+ uint32_t vt_active : 1;
+ struct termios terminal_attributes;
+ struct wl_event_source *term_signal_source;
+ struct wl_event_source *tty_input_source;
+ struct wl_event_source *enter_vt_source;
+ struct wl_event_source *leave_vt_source;
+
+ on_enter_vt_t on_enter;
+ on_leave_vt_t on_leave;
+ void *callback_data;
+};
+
+struct evdev_input_device {
+ struct wlsc_input_device *master;
+ struct tty_evdev *tty_evdev;
+ struct wl_event_source *source;
+ int tool, new_x, new_y;
+ int base_x, base_y;
+ int fd;
+};
+
+static void evdev_input_device_data(int fd, uint32_t mask, void *data)
+{
+ struct evdev_input_device *device = data;
+ struct input_event ev[8], *e, *end;
+ int len, value, dx, dy, absolute_event;
+ int x, y;
+ uint32_t time;
+
+ dx = 0;
+ dy = 0;
+ absolute_event = 0;
+ x = device->master->x;
+ y = device->master->y;
+
+ len = read(fd, &ev, sizeof ev);
+ if (len < 0 || len % sizeof e[0] != 0) {
+ /* FIXME: handle error... reopen device? */;
+ return;
+ }
+
+ /* evdev events aren't targeted only to the current VT */
+ if (!device->tty_evdev->vt_active)
+ return;
+
+ e = ev;
+ end = (void *) ev + len;
+ for (e = ev; e < end; e++) {
+ /* Get the signed value, earlier kernels had this as unsigned */
+ value = e->value;
+ time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
+
+ switch (e->type) {
+ case EV_REL:
+ switch (e->code) {
+ case REL_X:
+ dx += value;
+ break;
+
+ case REL_Y:
+ dy += value;
+ break;
+ }
+ break;
+
+ case EV_ABS:
+ absolute_event = 1;
+ switch (e->code) {
+ case ABS_X:
+ if (device->new_x) {
+ device->base_x = x - value;
+ device->new_x = 0;
+ }
+ x = device->base_x + value;
+ break;
+ case ABS_Y:
+ if (device->new_y) {
+ device->base_y = y - value;
+ device->new_y = 0;
+ }
+ y = device->base_y + value;
+ break;
+ }
+ break;
+
+ case EV_KEY:
+ if (value == 2)
+ break;
+
+ switch (e->code) {
+ case BTN_TOUCH:
+ case BTN_TOOL_PEN:
+ case BTN_TOOL_RUBBER:
+ case BTN_TOOL_BRUSH:
+ case BTN_TOOL_PENCIL:
+ case BTN_TOOL_AIRBRUSH:
+ case BTN_TOOL_FINGER:
+ case BTN_TOOL_MOUSE:
+ case BTN_TOOL_LENS:
+ if (device->tool == 0 && value) {
+ device->new_x = 1;
+ device->new_y = 1;
+ }
+ device->tool = value ? e->code : 0;
+ break;
+
+ case BTN_LEFT:
+ case BTN_RIGHT:
+ case BTN_MIDDLE:
+ case BTN_SIDE:
+ case BTN_EXTRA:
+ case BTN_FORWARD:
+ case BTN_BACK:
+ case BTN_TASK:
+ notify_button(device->master,
+ time, e->code, value);
+ break;
+
+ default:
+ notify_key(device->master,
+ time, e->code, value);
+ break;
+ }
+ }
+ }
+
+ if (dx != 0 || dy != 0)
+ notify_motion(device->master, time, x + dx, y + dy);
+ if (absolute_event && device->tool)
+ notify_motion(device->master, time, x, y);
+}
+
+static struct evdev_input_device *
+evdev_input_device_create(struct tty_evdev *te,
+ struct wlsc_input_device *master,
+ struct wl_display *display, const char *path)
+{
+ struct evdev_input_device *device;
+ struct wl_event_loop *loop;
+
+ if (path == NULL)
+ return NULL;
+
+ device = malloc(sizeof *device);
+ if (device == NULL)
+ return NULL;
+
+ device->tool = 1;
+ device->new_x = 1;
+ device->new_y = 1;
+ device->master = master;
+ device->tty_evdev = te;
+
+ device->fd = open(path, O_RDONLY);
+ if (device->fd < 0) {
+ free(device);
+ fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
+ return NULL;
+ }
+
+ loop = wl_display_get_event_loop(display);
+ device->source = wl_event_loop_add_fd(loop, device->fd,
+ WL_EVENT_READABLE,
+ evdev_input_device_data, device);
+ if (device->source == NULL) {
+ close(device->fd);
+ free(device);
+ return NULL;
+ }
+
+ return device;
+}
+
+static void
+evdev_input_init(struct tty_evdev *te, struct udev *udev)
+{
+ struct wlsc_compositor *c = te->ec;
+ struct wlsc_input_device *input;
+ struct udev_enumerate *e;
+ struct udev_list_entry *entry;
+ struct udev_device *device;
+ const char *path;
+
+ input = malloc(sizeof *input);
+ if (input == NULL)
+ return;
+
+ memset(input, 0, sizeof *input);
+ wlsc_input_device_init(input, c);
+
+ e = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(e, "input");
+// udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
+ udev_enumerate_scan_devices(e);
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+ path = udev_list_entry_get_name(entry);
+ device = udev_device_new_from_syspath(udev, path);
+ evdev_input_device_create(te, input, c->wl_display,
+ udev_device_get_devnode(device));
+ }
+ udev_enumerate_unref(e);
+
+ c->input_device = input;
+}
+
+static void on_enter_vt(int signal_number, void *data)
+{
+ struct tty_evdev *te = data;
+ int ret;
+
+ ioctl(te->tty_fd, VT_RELDISP, VT_ACKACQ);
+ ret = ioctl(te->tty_fd, KDSETMODE, KD_GRAPHICS);
+ if (ret)
+ fprintf(stderr,
+ "failed to set KD_GRAPHICS mode on console: %m\n");
+ te->vt_active = 1;
+
+ if (te->on_enter != NULL)
+ (*te->on_enter)(te->callback_data);
+}
+
+static void on_leave_vt(int signal_number, void *data)
+{
+ struct tty_evdev *te = data;
+ int ret;
+
+ if (te->on_leave != NULL)
+ (*te->on_leave)(te->callback_data);
+
+ ioctl (te->tty_fd, VT_RELDISP, 1);
+ ret = ioctl(te->tty_fd, KDSETMODE, KD_TEXT);
+ if (ret)
+ fprintf(stderr,
+ "failed to set KD_TEXT mode on console: %m\n");
+ te->vt_active = 0;
+}
+
+static void
+on_tty_input(int fd, uint32_t mask, void *data)
+{
+ struct tty_evdev *te = data;
+
+ /* Ignore input to tty. We get keyboard events from evdev. */
+ tcflush(te->tty_fd, TCIFLUSH);
+}
+
+static void on_term_signal(int signal_number, void *data)
+{
+ struct tty_evdev *te = data;
+
+ if (tcsetattr(te->tty_fd, TCSANOW, &te->terminal_attributes) < 0)
+ fprintf(stderr,
+ "Could not restore terminal to canonical mode\n");
+
+ exit(0);
+}
+
+static int setup_tty(struct tty_evdev *te, struct wl_event_loop *loop)
+{
+ struct termios raw_attributes;
+ struct vt_mode mode = { 0 };
+ int ret;
+
+ te->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
+ if (te->tty_fd <= 0) {
+ fprintf(stderr, "failed to open active tty: %m\n");
+ return -1;
+ }
+
+ if (tcgetattr(te->tty_fd, &te->terminal_attributes) < 0) {
+ fprintf(stderr, "could not get terminal attributes: %m\n");
+ return -1;
+ }
+
+ /* Ignore control characters and disable echo */
+ raw_attributes = te->terminal_attributes;
+ cfmakeraw(&raw_attributes);
+
+ /* Fix up line endings to be normal (cfmakeraw hoses them) */
+ raw_attributes.c_oflag |= OPOST | OCRNL;
+
+ if (tcsetattr(te->tty_fd, TCSANOW, &raw_attributes) < 0)
+ fprintf(stderr, "could not put terminal into raw mode: %m\n");
+
+ te->term_signal_source =
+ wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, te);
+
+ te->tty_input_source =
+ wl_event_loop_add_fd(loop, te->tty_fd,
+ WL_EVENT_READABLE, on_tty_input, te);
+
+ ret = ioctl(te->tty_fd, KDSETMODE, KD_GRAPHICS);
+ if (ret)
+ fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
+
+ te->vt_active = 1;
+ mode.mode = VT_PROCESS;
+ mode.relsig = SIGUSR1;
+ mode.acqsig = SIGUSR2;
+ if (!ioctl(te->tty_fd, VT_SETMODE, &mode) < 0) {
+ fprintf(stderr, "failed to take control of vt handling\n");
+ }
+
+ te->leave_vt_source =
+ wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, te);
+ te->enter_vt_source =
+ wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, te);
+
+ return 0;
+}
+
+struct tty_evdev *evdev_tty_setup(struct wlsc_compositor *ec,
+ struct wl_event_loop *loop, struct udev *udev,
+ on_enter_vt_t on_enter, on_leave_vt_t on_leave,
+ void *callback_data)
+{
+ struct tty_evdev *te;
+
+ te = calloc(1, sizeof(*te));
+ if (te == NULL)
+ return NULL;
+
+ te->ec = ec;
+ te->on_enter = on_enter;
+ te->on_leave = on_leave;
+ te->callback_data = callback_data;
+ wl_list_init(&te->input_devices);
+
+ evdev_input_init(te, udev);
+ setup_tty(te, loop);
+
+ return te;
+}
--
1.7.1
More information about the wayland-devel
mailing list