From 8dc6db8c76ac3065d1c37b5a7fb375651f6dab49 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Tue, 20 Mar 2018 13:29:40 +0200 Subject: [PATCH] libweston: require connected heads for input devices The use case driving this change is a clone mode setup, where the user is hotplugging or unplugging a cloned touchscreen. Even if the output and head are force-enabled, the touch device should still follow the connector connection status. If there is no video signal for the touchscreen (disconnected connector), then the touch input should be ignored as well. When the output is force-enabled, we need to trigger output_heads_changed from connector status changes. If the head or output are not force-enabled, the compositor will likely attach and detach the head as appropriate. In clone mode, the attach or detach needs to trigger output_heads_changed directly. In other cases, it may be handled through the output getting enabled or disabled which are different signals. Signed-off-by: Pekka Paalanen Reviewed-by: Peter Hutterer --- libweston/compositor.c | 30 ++++++++++++++++++++++++++++++ libweston/compositor.h | 8 ++++++++ libweston/libinput-seat.c | 39 ++++++++++++++++++++++++++++++++++----- libweston/libinput-seat.h | 1 + 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/libweston/compositor.c b/libweston/compositor.c index a9de4ac..dbf61ef 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -4463,15 +4463,40 @@ weston_head_init(struct weston_head *head, const char *name) head->name = strdup(name); } +/** Send output heads changed signal + * + * \param output The output that changed. + * + * Notify that the enabled output gained and/or lost heads, or that the + * associated heads may have changed their connection status. This does not + * include cases where the output becomes enabled or disabled. The registered + * callbacks are called after the change has successfully happened. + * + * If connection status change causes the compositor to attach or detach a head + * to an enabled output, the registered callbacks may be called multiple times. + */ +static void +weston_output_emit_heads_changed(struct weston_output *output) +{ + wl_signal_emit(&output->compositor->output_heads_changed_signal, + output); +} + /** Idle task for emitting heads_changed_signal */ static void weston_compositor_call_heads_changed(void *data) { struct weston_compositor *compositor = data; + struct weston_head *head; compositor->heads_changed_source = NULL; wl_signal_emit(&compositor->heads_changed_signal, compositor); + + wl_list_for_each(head, &compositor->head_list, compositor_link) { + if (head->output && head->output->enabled) + weston_output_emit_heads_changed(head->output); + } } /** Schedule a call on idle to heads_changed callback @@ -4678,6 +4703,8 @@ weston_output_attach_head(struct weston_output *output, weston_log("Output '%s' updated to have head(s) %s\n", output->name, head_names); free(head_names); + + weston_output_emit_heads_changed(output); } return 0; @@ -4723,6 +4750,8 @@ weston_head_detach(struct weston_head *head) weston_log("Output '%s' updated to have head(s) %s\n", output->name, head_names); free(head_names); + + weston_output_emit_heads_changed(output); } } } @@ -6255,6 +6284,7 @@ weston_compositor_create(struct wl_display *display, void *user_data) wl_signal_init(&ec->output_moved_signal); wl_signal_init(&ec->output_resized_signal); wl_signal_init(&ec->heads_changed_signal); + wl_signal_init(&ec->output_heads_changed_signal); wl_signal_init(&ec->session_signal); ec->session_active = 1; diff --git a/libweston/compositor.h b/libweston/compositor.h index f3137de..ca23407 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -963,6 +963,11 @@ struct weston_compositor { struct wl_signal output_moved_signal; struct wl_signal output_resized_signal; /* callback argument: resized output */ + /* Signal for output changes triggered by configuration from frontend + * or head state changes from backend. + */ + struct wl_signal output_heads_changed_signal; /* arg: weston_output */ + struct wl_signal session_signal; int session_active; @@ -1031,6 +1036,9 @@ struct weston_compositor { /* Whether to let the compositor run without any input device. */ bool require_input; + /* Signal for a backend to inform a frontend about possible changes + * in head status. + */ struct wl_signal heads_changed_signal; struct wl_event_source *heads_changed_source; }; diff --git a/libweston/libinput-seat.c b/libweston/libinput-seat.c index 3cece3a..ac1e8e9 100644 --- a/libweston/libinput-seat.c +++ b/libweston/libinput-seat.c @@ -68,9 +68,16 @@ output_find_by_head_name(struct weston_compositor *compositor, if (!head_name) return NULL; - /* only enabled outputs */ + /* Only enabled outputs with connected heads. + * This means force-enabled outputs but with disconnected heads + * will be ignored; if the touchscreen doesn't have a video signal, + * touching it is meaningless. + */ wl_list_for_each(output, &compositor->output_list, link) { wl_list_for_each(head, &output->head_list, output_link) { + if (!weston_head_is_connected(head)) + continue; + if (strcmp(head_name, head->name) == 0) return output; } @@ -377,12 +384,9 @@ udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds) } static void -notify_output_create(struct wl_listener *listener, void *data) +udev_seat_output_changed(struct udev_seat *seat, struct weston_output *output) { - struct udev_seat *seat = container_of(listener, struct udev_seat, - output_create_listener); struct evdev_device *device; - struct weston_output *output = data; struct weston_output *found; wl_list_for_each(device, &seat->devices_list, link) { @@ -406,6 +410,26 @@ notify_output_create(struct wl_listener *listener, void *data) } } +static void +notify_output_create(struct wl_listener *listener, void *data) +{ + struct udev_seat *seat = container_of(listener, struct udev_seat, + output_create_listener); + struct weston_output *output = data; + + udev_seat_output_changed(seat, output); +} + +static void +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); +} + static struct udev_seat * udev_seat_create(struct udev_input *input, const char *seat_name) { @@ -423,6 +447,10 @@ udev_seat_create(struct udev_input *input, const char *seat_name) wl_signal_add(&c->output_created_signal, &seat->output_create_listener); + seat->output_heads_listener.notify = notify_output_heads_changed; + wl_signal_add(&c->output_heads_changed_signal, + &seat->output_heads_listener); + wl_list_init(&seat->devices_list); return seat; @@ -440,6 +468,7 @@ 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_heads_listener.link); free(seat); } diff --git a/libweston/libinput-seat.h b/libweston/libinput-seat.h index 65c9b64..8c6a5bf 100644 --- a/libweston/libinput-seat.h +++ b/libweston/libinput-seat.h @@ -39,6 +39,7 @@ struct udev_seat { struct weston_seat base; struct wl_list devices_list; struct wl_listener output_create_listener; + struct wl_listener output_heads_listener; }; typedef void (*udev_configure_device_t)(struct weston_compositor *compositor, -- 2.7.4