Commit 8dc6db8c authored by Pekka Paalanen's avatar Pekka Paalanen

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's avatarPekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent fd02efbc
...@@ -4463,15 +4463,40 @@ weston_head_init(struct weston_head *head, const char *name) ...@@ -4463,15 +4463,40 @@ weston_head_init(struct weston_head *head, const char *name)
head->name = strdup(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 */ /** Idle task for emitting heads_changed_signal */
static void static void
weston_compositor_call_heads_changed(void *data) weston_compositor_call_heads_changed(void *data)
{ {
struct weston_compositor *compositor = data; struct weston_compositor *compositor = data;
struct weston_head *head;
compositor->heads_changed_source = NULL; compositor->heads_changed_source = NULL;
wl_signal_emit(&compositor->heads_changed_signal, compositor); 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 /** Schedule a call on idle to heads_changed callback
...@@ -4678,6 +4703,8 @@ weston_output_attach_head(struct weston_output *output, ...@@ -4678,6 +4703,8 @@ weston_output_attach_head(struct weston_output *output,
weston_log("Output '%s' updated to have head(s) %s\n", weston_log("Output '%s' updated to have head(s) %s\n",
output->name, head_names); output->name, head_names);
free(head_names); free(head_names);
weston_output_emit_heads_changed(output);
} }
return 0; return 0;
...@@ -4723,6 +4750,8 @@ weston_head_detach(struct weston_head *head) ...@@ -4723,6 +4750,8 @@ weston_head_detach(struct weston_head *head)
weston_log("Output '%s' updated to have head(s) %s\n", weston_log("Output '%s' updated to have head(s) %s\n",
output->name, head_names); output->name, head_names);
free(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) ...@@ -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_moved_signal);
wl_signal_init(&ec->output_resized_signal); wl_signal_init(&ec->output_resized_signal);
wl_signal_init(&ec->heads_changed_signal); wl_signal_init(&ec->heads_changed_signal);
wl_signal_init(&ec->output_heads_changed_signal);
wl_signal_init(&ec->session_signal); wl_signal_init(&ec->session_signal);
ec->session_active = 1; ec->session_active = 1;
......
...@@ -963,6 +963,11 @@ struct weston_compositor { ...@@ -963,6 +963,11 @@ struct weston_compositor {
struct wl_signal output_moved_signal; struct wl_signal output_moved_signal;
struct wl_signal output_resized_signal; /* callback argument: resized output */ 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; struct wl_signal session_signal;
int session_active; int session_active;
...@@ -1031,6 +1036,9 @@ struct weston_compositor { ...@@ -1031,6 +1036,9 @@ struct weston_compositor {
/* Whether to let the compositor run without any input device. */ /* Whether to let the compositor run without any input device. */
bool require_input; 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_signal heads_changed_signal;
struct wl_event_source *heads_changed_source; struct wl_event_source *heads_changed_source;
}; };
......
...@@ -68,9 +68,16 @@ output_find_by_head_name(struct weston_compositor *compositor, ...@@ -68,9 +68,16 @@ output_find_by_head_name(struct weston_compositor *compositor,
if (!head_name) if (!head_name)
return NULL; 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(output, &compositor->output_list, link) {
wl_list_for_each(head, &output->head_list, output_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) if (strcmp(head_name, head->name) == 0)
return output; return output;
} }
...@@ -377,12 +384,9 @@ udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds) ...@@ -377,12 +384,9 @@ udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds)
} }
static void 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 evdev_device *device;
struct weston_output *output = data;
struct weston_output *found; struct weston_output *found;
wl_list_for_each(device, &seat->devices_list, link) { wl_list_for_each(device, &seat->devices_list, link) {
...@@ -406,6 +410,26 @@ notify_output_create(struct wl_listener *listener, void *data) ...@@ -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 * static struct udev_seat *
udev_seat_create(struct udev_input *input, const char *seat_name) 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) ...@@ -423,6 +447,10 @@ udev_seat_create(struct udev_input *input, const char *seat_name)
wl_signal_add(&c->output_created_signal, wl_signal_add(&c->output_created_signal,
&seat->output_create_listener); &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); wl_list_init(&seat->devices_list);
return seat; return seat;
...@@ -440,6 +468,7 @@ udev_seat_destroy(struct udev_seat *seat) ...@@ -440,6 +468,7 @@ udev_seat_destroy(struct udev_seat *seat)
udev_seat_remove_devices(seat); udev_seat_remove_devices(seat);
weston_seat_release(&seat->base); weston_seat_release(&seat->base);
wl_list_remove(&seat->output_create_listener.link); wl_list_remove(&seat->output_create_listener.link);
wl_list_remove(&seat->output_heads_listener.link);
free(seat); free(seat);
} }
......
...@@ -39,6 +39,7 @@ struct udev_seat { ...@@ -39,6 +39,7 @@ struct udev_seat {
struct weston_seat base; struct weston_seat base;
struct wl_list devices_list; struct wl_list devices_list;
struct wl_listener output_create_listener; struct wl_listener output_create_listener;
struct wl_listener output_heads_listener;
}; };
typedef void (*udev_configure_device_t)(struct weston_compositor *compositor, typedef void (*udev_configure_device_t)(struct weston_compositor *compositor,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment