From 17bccaed428ac1f6ec9f8e667175ad81e90508ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 16 Jan 2014 16:46:28 -0800 Subject: [PATCH] input: Handle unplugging the output for a touchscreen device A paired touch screen will stop sending events if its corresponding output is unplugged. An unpaired touchscreen will pick the new primary output. https://bugs.freedesktop.org/show_bug.cgi?id=73637 --- desktop-shell/shell.c | 4 ++- src/evdev.c | 57 +++++++++++++++++++++++++++++++++++++------ src/evdev.h | 4 +++ src/udev-seat.c | 12 ++++++--- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 3ef6424c..79e65187 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1795,7 +1795,7 @@ ping_timeout_handler(void *data) shsurf->unresponsive = 1; wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link) - if (seat->pointer && seat->pointer->focus && + if (seat->pointer->focus && seat->pointer->focus->surface == shsurf->surface) set_busy_cursor(shsurf, seat->pointer); @@ -5432,6 +5432,8 @@ shell_destroy(struct wl_listener *listener, void *data) struct workspace **ws; struct shell_output *shell_output, *tmp; + /* Force state to unlocked so we don't try to fade */ + shell->locked = false; if (shell->child.client) wl_client_destroy(shell->child.client); diff --git a/src/evdev.c b/src/evdev.c index d38f63bd..352cb411 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -102,6 +102,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) device->rel.dy = 0; goto handled; case EVDEV_ABSOLUTE_MT_DOWN: + if (device->output == NULL) + break; weston_output_transform_coordinate(device->output, wl_fixed_from_int(device->mt.slots[slot].x), wl_fixed_from_int(device->mt.slots[slot].y), @@ -113,6 +115,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) notify_touch(master, time, seat_slot, x, y, WL_TOUCH_DOWN); goto handled; case EVDEV_ABSOLUTE_MT_MOTION: + if (device->output == NULL) + break; weston_output_transform_coordinate(device->output, wl_fixed_from_int(device->mt.slots[slot].x), wl_fixed_from_int(device->mt.slots[slot].y), @@ -126,6 +130,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) notify_touch(master, time, seat_slot, 0, 0, WL_TOUCH_UP); goto handled; case EVDEV_ABSOLUTE_TOUCH_DOWN: + if (device->output == NULL) + break; transform_absolute(device, &cx, &cy); weston_output_transform_coordinate(device->output, wl_fixed_from_int(cx), @@ -137,6 +143,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) notify_touch(master, time, seat_slot, x, y, WL_TOUCH_DOWN); goto handled; case EVDEV_ABSOLUTE_MOTION: + if (device->output == NULL) + break; transform_absolute(device, &cx, &cy); weston_output_transform_coordinate(device->output, wl_fixed_from_int(cx), @@ -219,8 +227,13 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e, uint32_t time) { - const int screen_width = device->output->current_mode->width; - const int screen_height = device->output->current_mode->height; + int screen_width, screen_height; + + if (device->output == NULL) + return; + + screen_width = device->output->current_mode->width; + screen_height = device->output->current_mode->height; switch (e->code) { case ABS_MT_SLOT: @@ -257,8 +270,13 @@ static inline void evdev_process_absolute_motion(struct evdev_device *device, struct input_event *e) { - const int screen_width = device->output->current_mode->width; - const int screen_height = device->output->current_mode->height; + int screen_width, screen_height; + + if (device->output == NULL) + return; + + screen_width = device->output->current_mode->width; + screen_height = device->output->current_mode->height; switch (e->code) { case ABS_X: @@ -575,6 +593,34 @@ evdev_configure_device(struct evdev_device *device) return 0; } +static void +notify_output_destroy(struct wl_listener *listener, void *data) +{ + struct evdev_device *device = + container_of(listener, + struct evdev_device, output_destroy_listener); + struct weston_compositor *c = device->seat->compositor; + struct weston_output *output; + + if (device->output_name) { + output = container_of(c->output_list.next, + struct weston_output, link); + evdev_device_set_output(device, output); + } else { + device->output = NULL; + } +} + +void +evdev_device_set_output(struct evdev_device *device, + struct weston_output *output) +{ + device->output = output; + device->output_destroy_listener.notify = notify_output_destroy; + wl_signal_add(&output->destroy_signal, + &device->output_destroy_listener); +} + struct evdev_device * evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) { @@ -587,9 +633,6 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) return NULL; ec = seat->compositor; - device->output = - container_of(ec->output_list.next, struct weston_output, link); - device->seat = seat; device->seat_caps = 0; device->is_mt = 0; diff --git a/src/evdev.h b/src/evdev.h index 36a52e34..10f9724e 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -53,6 +53,7 @@ struct evdev_device { struct wl_event_source *source; struct weston_output *output; struct evdev_dispatch *dispatch; + struct wl_listener output_destroy_listener; char *devnode; char *devname; char *output_name; @@ -123,6 +124,9 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds); struct evdev_device * evdev_device_create(struct weston_seat *seat, const char *path, int device_fd); +void +evdev_device_set_output(struct evdev_device *device, + struct weston_output *output); void evdev_device_destroy(struct evdev_device *device); diff --git a/src/udev-seat.c b/src/udev-seat.c index f9723f2f..f5c2fa88 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -126,7 +126,11 @@ device_added(struct udev_device *udev_device, struct udev_input *input) device->output_name = strdup(output_name); wl_list_for_each(output, &c->output_list, link) if (strcmp(output->name, device->output_name) == 0) - device->output = output; + evdev_device_set_output(device, output); + } else if (device->output == NULL) { + output = container_of(c->output_list.next, + struct weston_output, link); + evdev_device_set_output(device, output); } if (input->enabled == 1) @@ -354,8 +358,10 @@ notify_output_create(struct wl_listener *listener, void *data) wl_list_for_each(device, &seat->devices_list, link) if (device->output_name && - strcmp(output->name, device->output_name) == 0) - device->output = output; + strcmp(output->name, device->output_name) == 0) { + evdev_device_set_output(device, output); + break; + } } static struct udev_seat *