diff --git a/configure.ac b/configure.ac index 5a08af5f..fdf03148 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(LIBDRM, [libdrm]) -PKG_CHECK_MODULES(EGL_COMPOSITOR, [eagle libpng cairo gdk-pixbuf-2.0]) +PKG_CHECK_MODULES(EGL_COMPOSITOR, [eagle libpng cairo gdk-pixbuf-2.0 libudev]) PKG_CHECK_MODULES(GL_COMPOSITOR, [gl x11]) PKG_CHECK_MODULES(CLIENT, [eagle cairo glib-2.0]) diff --git a/wayland-system-compositor.c b/wayland-system-compositor.c index a2f534b8..0cc3e46c 100644 --- a/wayland-system-compositor.c +++ b/wayland-system-compositor.c @@ -42,6 +42,9 @@ #include #include +#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE +#include + #include #include @@ -105,6 +108,8 @@ struct egl_compositor { uint32_t crtc_id; uint32_t connector_id; + struct udev *udev; + /* Repaint state. */ struct wl_event_source *timer_source; int repaint_needed; @@ -687,18 +692,14 @@ struct evdev_input_device * evdev_input_device_create(struct wlsc_input_device *device, struct wl_display *display, const char *path); -static void -create_input_device(struct egl_compositor *ec, const char *glob) +static struct wlsc_input_device * +create_input_device(struct egl_compositor *ec) { struct wlsc_input_device *device; - struct dirent *de; - char path[PATH_MAX]; - const char *by_path_dir = "/dev/input/by-path"; - DIR *dir; device = malloc(sizeof *device); if (device == NULL) - return; + return NULL; memset(device, 0, sizeof *device); device->base.interface = &wl_input_device_interface; @@ -711,22 +712,9 @@ create_input_device(struct egl_compositor *ec, const char *glob) pointer_create(ec, device->x, device->y, 64, 64); device->ec = ec; - dir = opendir(by_path_dir); - if (dir == NULL) { - fprintf(stderr, "couldn't read dir %s\n", by_path_dir); - return; - } - - while (de = readdir(dir), de != NULL) { - if (fnmatch(glob, de->d_name, 0)) - continue; - - snprintf(path, sizeof path, "%s/%s", by_path_dir, de->d_name); - evdev_input_device_create(device, ec->wl_display, path); - } - closedir(dir); - wl_list_insert(ec->input_device_list.prev, &device->link); + + return device; } void @@ -859,19 +847,11 @@ post_output_geometry(struct wl_client *client, struct wl_object *global) static const char gem_device[] = "/dev/dri/card0"; -static const char *default_input_device[] = { - "*event*", - NULL -}; - static const char *option_background = "background.jpg"; -static const char **option_input_devices = default_input_device; static const GOptionEntry option_entries[] = { { "background", 'b', 0, G_OPTION_ARG_STRING, &option_background, "Background image" }, - { "input-device", 'i', 0, G_OPTION_ARG_STRING_ARRAY, - &option_input_devices, "Input device glob" }, { NULL } }; @@ -969,6 +949,64 @@ static int setup_tty(struct egl_compositor *ec, struct wl_event_loop *loop) return 0; } +static const char * +get_udev_property(struct udev_device *device, const char *name) +{ + struct udev_list_entry *entry; + + udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(device)) + if (strcmp(udev_list_entry_get_name(entry), name) == 0) + return udev_list_entry_get_value(entry); + + return NULL; +} + +static void +init_libudev(struct egl_compositor *ec) +{ + struct udev_enumerate *e; + struct udev_list_entry *entry; + struct udev_device *device; + const char *path, *seat; + struct wlsc_input_device *input_device; + + /* FIXME: Newer (version 135+) udev has two new features that + * make all this much easier: 1) we can enumerate by a + * specific property. This lets us directly iterate through + * the devices we care about. 2) We can attach properties to + * sysfs nodes without a device file, which lets us configure + * which connectors belong to a seat instead of tagging the + * overall drm node. I don't want to update my system udev, + * so I'm going to stick with this until the new version is in + * rawhide. */ + + ec->udev = udev_new(); + if (ec->udev == NULL) { + fprintf(stderr, "failed to initialize udev context\n"); + return; + } + + input_device = create_input_device(ec); + + e = udev_enumerate_new(ec->udev); + 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(ec->udev, path); + + /* FIXME: Should the property namespace be CK for console kit? */ + seat = get_udev_property(device, "WAYLAND_SEAT"); + if (!seat || strcmp(seat, "1") != 0) + continue; + if (strcmp(udev_device_get_subsystem(device), "input") == 0) { + evdev_input_device_create(input_device, ec->wl_display, + udev_device_get_devnode(device)); + continue; + } + } + udev_enumerate_unref(e); +} + static struct egl_compositor * egl_compositor_create(struct wl_display *display) { @@ -988,7 +1026,6 @@ egl_compositor_create(struct wl_display *display) struct egl_compositor *ec; struct screenshooter *shooter; uint32_t fb_name; - int i; struct wl_event_loop *loop; ec = malloc(sizeof *ec); @@ -1047,8 +1084,7 @@ egl_compositor_create(struct wl_display *display) add_visuals(ec); wl_list_init(&ec->input_device_list); - for (i = 0; option_input_devices[i]; i++) - create_input_device(ec, option_input_devices[i]); + init_libudev(ec); wl_list_init(&ec->surface_list); ec->background = background_create(ec, option_background,