From ef1deb5c9e572341d7fd8c948bbbaa02d393048a Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 2 Apr 2021 09:49:09 +0800 Subject: [PATCH 44/74] libinput-seat: Improve input device and output associating An input device can associate with an output using udev rules's WL_OUTPUT property, for example: ATTRS{idVendor}=="0eef", ATTRS{idProduct}=="0001", ENV{WL_OUTPUT}="HDMI-A-1" An input device can be added into a wl_seat using udev rules's WL_SEAT property, for example: ATTRS{idVendor}=="0eef", ATTRS{idProduct}=="0001", ENV{WL_SEAT}="seat1" An output can associate with a wl_seat using seat entry in weston.ini's output section, for example: [output] name=HDMI-A-1 seat=seat1 Signed-off-by: Jeffy Chen --- libweston/backend-drm/drm.c | 1 + libweston/libinput-seat.c | 117 +++++++++++++++++++++++------------- libweston/libinput-seat.h | 5 +- 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 149ac01..884dcba 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -1700,6 +1700,7 @@ setup_output_seat_constraint(struct drm_backend *b, return; seat->base.output = output; + seat->has_output = true; pointer = weston_seat_get_pointer(&seat->base); if (pointer) diff --git a/libweston/libinput-seat.c b/libweston/libinput-seat.c index a9c7d6f..57ff181 100644 --- a/libweston/libinput-seat.c +++ b/libweston/libinput-seat.c @@ -89,12 +89,54 @@ output_find_by_head_name(struct weston_compositor *compositor, return NULL; } +static void +udev_seat_update_output(struct udev_seat *seat) +{ + struct weston_compositor *c = seat->base.compositor; + struct weston_output *found, *prefered = NULL; + struct evdev_device *device; + + if (seat->has_output) { + if (weston_output_valid(seat->base.output)) + prefered = seat->base.output; + else + /* The seat's output been removed */ + seat->base.output = NULL; + } else { + struct weston_output *output; + + /* default assignment to an arbitrary output */ + wl_list_for_each(output, &c->output_list, link) { + if (weston_output_valid(output)) { + prefered = output; + break; + } + } + } + + wl_list_for_each(device, &seat->devices_list, link) { + /* If we find any input device without an associated output + * or an output name to associate with, just tie it with the + * output we got here - the default assignment. + */ + if (!device->output_name) { + evdev_device_set_output(device, prefered); + continue; + } + + /* Update all devices' output associations, may they gain or + * lose it. + */ + found = output_find_by_head_name(c, device->output_name); + evdev_device_set_output(device, found); + } +} + static int device_added(struct udev_input *input, struct libinput_device *libinput_device) { struct weston_compositor *c; struct evdev_device *device; - struct weston_output *output; const char *output_name; struct weston_seat *seat; struct udev_seat *udev_seat; @@ -128,16 +170,10 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) &pointer->y); output_name = libinput_device_get_output_name(libinput_device); - if (output_name) { + if (output_name) device->output_name = strdup(output_name); - output = output_find_by_head_name(c, output_name); - evdev_device_set_output(device, output); - } else if (!wl_list_empty(&c->output_list)) { - /* default assignment to an arbitrary output */ - output = container_of(c->output_list.next, - struct weston_output, link); - evdev_device_set_output(device, output); - } + + udev_seat_update_output(udev_seat); if (!input->suspended) { weston_seat_repick(seat); @@ -403,40 +439,27 @@ udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds) } static void -udev_seat_output_changed(struct udev_seat *seat, struct weston_output *output) +notify_output_created(struct wl_listener *listener, void *data) { - struct evdev_device *device; - struct weston_output *found; - - wl_list_for_each(device, &seat->devices_list, link) { - /* If we find any input device without an associated output - * or an output name to associate with, just tie it with the - * output we got here - the default assignment. - */ - if (!device->output_name) { - if (!device->output) - evdev_device_set_output(device, output); - - continue; - } - - /* Update all devices' output associations, may they gain or - * lose it. - */ - found = output_find_by_head_name(output->compositor, - device->output_name); - evdev_device_set_output(device, found); - } + struct udev_seat *seat = container_of(listener, struct udev_seat, + output_created_listener); + udev_seat_update_output(seat); } static void -notify_output_create(struct wl_listener *listener, void *data) +notify_output_moved(struct wl_listener *listener, void *data) { struct udev_seat *seat = container_of(listener, struct udev_seat, - output_create_listener); - struct weston_output *output = data; + output_moved_listener); + udev_seat_update_output(seat); +} - udev_seat_output_changed(seat, output); +static void +notify_output_destroyed(struct wl_listener *listener, void *data) +{ + struct udev_seat *seat = container_of(listener, struct udev_seat, + output_destroyed_listener); + udev_seat_update_output(seat); } static void @@ -444,9 +467,7 @@ notify_output_heads_changed(struct wl_listener *listener, void *data) { struct udev_seat *seat = container_of(listener, struct udev_seat, output_heads_listener); - struct weston_output *output = data; - - udev_seat_output_changed(seat, output); + udev_seat_update_output(seat); } static struct udev_seat * @@ -462,9 +483,17 @@ udev_seat_create(struct udev_input *input, const char *seat_name) weston_seat_init(&seat->base, c, seat_name); seat->base.led_update = udev_seat_led_update; - seat->output_create_listener.notify = notify_output_create; + seat->output_created_listener.notify = notify_output_created; wl_signal_add(&c->output_created_signal, - &seat->output_create_listener); + &seat->output_created_listener); + + seat->output_destroyed_listener.notify = notify_output_destroyed; + wl_signal_add(&c->output_destroyed_signal, + &seat->output_destroyed_listener); + + seat->output_moved_listener.notify = notify_output_moved; + wl_signal_add(&c->output_moved_signal, + &seat->output_moved_listener); seat->output_heads_listener.notify = notify_output_heads_changed; wl_signal_add(&c->output_heads_changed_signal, @@ -486,7 +515,9 @@ udev_seat_destroy(struct udev_seat *seat) udev_seat_remove_devices(seat); weston_seat_release(&seat->base); - wl_list_remove(&seat->output_create_listener.link); + wl_list_remove(&seat->output_created_listener.link); + wl_list_remove(&seat->output_destroyed_listener.link); + wl_list_remove(&seat->output_moved_listener.link); wl_list_remove(&seat->output_heads_listener.link); free(seat); } diff --git a/libweston/libinput-seat.h b/libweston/libinput-seat.h index 315980d..636636f 100644 --- a/libweston/libinput-seat.h +++ b/libweston/libinput-seat.h @@ -37,8 +37,11 @@ struct libinput_device; struct udev_seat { struct weston_seat base; + bool has_output; struct wl_list devices_list; - struct wl_listener output_create_listener; + struct wl_listener output_created_listener; + struct wl_listener output_destroyed_listener; + struct wl_listener output_moved_listener; struct wl_listener output_heads_listener; }; -- 2.20.1