From c4689ff1d06792b56a004a3b3fcb056813294ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis-Francis=20Ratt=C3=A9-Boulianne?= Date: Tue, 28 Nov 2017 20:42:47 -0500 Subject: [PATCH] input: introduce touch event mode for calibrator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition to the normal touch event processing mode, introduce a new mode for calibrating a touchscreen input device. In the calibration mode, normal touch event processing is skipped, and the raw events are forwarded to the calibrator instead. The calibrator is not yet implemented, so the calls will be added in a following patch. To switch between modes, two functions are added, one for entering each mode. The mode switch happens only when no touches are down on any touch device, to avoid confusing touch grabs and clients. To realise this, the state machine has four states: prepare and actual state for both normal and calibrator modes. At this point nothing will attempt to change the touch event mode. The new calibrator mode is necessary, because when calibrating a touchscreen, the touch events must be routed to the calibration client directly. The touch coordinates are expected to be wrong, so they cannot go through the normal focus surface picking. The calibrator code also cannot use the normal touch grab interface, because it needs to be able to distinguish between different physical touch input devices, even if they are part of the same weston_seat. This requirement makes calibration special enough to warrant the new mode, a sort of "super grab". Co-developed by Louis-Francis and Pekka. Signed-off-by: Louis-Francis Ratté-Boulianne Signed-off-by: Pekka Paalanen v1 Tested-by: Matt Hoosier Reviewed-by: Peter Hutterer --- libweston/compositor.c | 2 + libweston/compositor.h | 39 +++++++++++ libweston/input.c | 146 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 182 insertions(+), 5 deletions(-) diff --git a/libweston/compositor.c b/libweston/compositor.c index 619e88b3..101096cd 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -6334,6 +6334,8 @@ weston_compositor_create(struct wl_display *display, void *user_data) ec->activate_serial = 1; + ec->touch_mode = WESTON_TOUCH_MODE_NORMAL; + if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4, ec, compositor_bind)) goto fail; diff --git a/libweston/compositor.h b/libweston/compositor.h index 083c154d..67d4db7c 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -489,6 +489,34 @@ struct weston_touch_device_ops { const struct weston_touch_device_matrix *cal); }; +enum weston_touch_mode { + /** Normal touch event handling */ + WESTON_TOUCH_MODE_NORMAL, + + /** Prepare moving to WESTON_TOUCH_MODE_CALIB. + * + * Move to WESTON_TOUCH_MODE_CALIB as soon as no touches are down on + * any seat. Until then, all touch events are routed normally. + */ + WESTON_TOUCH_MODE_PREP_CALIB, + + /** Calibration mode + * + * Only a single weston_touch_device forwards events to the calibrator + * all other touch device cause a calibrator "wrong device" event to + * be sent. + */ + WESTON_TOUCH_MODE_CALIB, + + /** Prepare moving to WESTON_TOUCH_MODE_NORMAL. + * + * Move to WESTON_TOUCH_MODE_NORMAL as soon as no touches are down on + * any seat. Until then, touch events are routed as in + * WESTON_TOUCH_MODE_CALIB except "wrong device" events are not sent. + */ + WESTON_TOUCH_MODE_PREP_NORMAL +}; + /** Represents a physical touchscreen input device */ struct weston_touch_device { char *syspath; /**< unique name */ @@ -1092,6 +1120,8 @@ struct weston_compositor { */ struct wl_signal heads_changed_signal; struct wl_event_source *heads_changed_source; + + enum weston_touch_mode touch_mode; }; struct weston_buffer { @@ -1573,6 +1603,15 @@ notify_touch_frame(struct weston_touch_device *device); void notify_touch_cancel(struct weston_touch_device *device); +void +weston_compositor_set_touch_mode_normal(struct weston_compositor *compositor); + +void +weston_compositor_set_touch_mode_calib(struct weston_compositor *compositor); + +static inline void +touch_calibrator_mode_changed(struct weston_compositor *compositor) { /* stub */ } + void weston_layer_entry_insert(struct weston_layer_entry *list, struct weston_layer_entry *entry); diff --git a/libweston/input.c b/libweston/input.c index 5bea691a..ba211f38 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -187,6 +187,12 @@ weston_touch_device_can_calibrate(struct weston_touch_device *device) return !!device->ops; } +static enum weston_touch_mode +weston_touch_device_get_mode(struct weston_touch_device *device) +{ + return device->aggregate->seat->compositor->touch_mode; +} + static struct weston_pointer_client * weston_pointer_client_create(struct wl_client *client) { @@ -2403,6 +2409,105 @@ process_touch_normal(struct weston_touch_device *device, } } +static enum weston_touch_mode +get_next_touch_mode(enum weston_touch_mode from) +{ + switch (from) { + case WESTON_TOUCH_MODE_PREP_NORMAL: + return WESTON_TOUCH_MODE_NORMAL; + + case WESTON_TOUCH_MODE_PREP_CALIB: + return WESTON_TOUCH_MODE_CALIB; + + case WESTON_TOUCH_MODE_NORMAL: + case WESTON_TOUCH_MODE_CALIB: + return from; + } + + return WESTON_TOUCH_MODE_NORMAL; +} + +/** Global touch mode update + * + * If no seat has a touch down and the compositor is in a PREP touch mode, + * set the compositor to the goal touch mode. + * + * Calls calibrator if touch mode changed. + */ +static void +weston_compositor_update_touch_mode(struct weston_compositor *compositor) +{ + struct weston_seat *seat; + struct weston_touch *touch; + enum weston_touch_mode goal; + + wl_list_for_each(seat, &compositor->seat_list, link) { + touch = weston_seat_get_touch(seat); + if (!touch) + continue; + + if (touch->num_tp > 0) + return; + } + + goal = get_next_touch_mode(compositor->touch_mode); + if (compositor->touch_mode != goal) { + compositor->touch_mode = goal; + touch_calibrator_mode_changed(compositor); + } +} + +/** Start transition to normal touch event handling + * + * The touch event mode changes when all touches on all touch devices have + * been lifted. If no touches are currently down, the transition is immediate. + * + * \sa weston_touch_mode + */ +void +weston_compositor_set_touch_mode_normal(struct weston_compositor *compositor) +{ + switch (compositor->touch_mode) { + case WESTON_TOUCH_MODE_PREP_NORMAL: + case WESTON_TOUCH_MODE_NORMAL: + return; + case WESTON_TOUCH_MODE_PREP_CALIB: + compositor->touch_mode = WESTON_TOUCH_MODE_NORMAL; + touch_calibrator_mode_changed(compositor); + return; + case WESTON_TOUCH_MODE_CALIB: + compositor->touch_mode = WESTON_TOUCH_MODE_PREP_NORMAL; + } + + weston_compositor_update_touch_mode(compositor); +} + +/** Start transition to calibrator touch event handling + * + * The touch event mode changes when all touches on all touch devices have + * been lifted. If no touches are currently down, the transition is immediate. + * + * \sa weston_touch_mode + */ +void +weston_compositor_set_touch_mode_calib(struct weston_compositor *compositor) +{ + switch (compositor->touch_mode) { + case WESTON_TOUCH_MODE_PREP_CALIB: + case WESTON_TOUCH_MODE_CALIB: + assert(0); + return; + case WESTON_TOUCH_MODE_PREP_NORMAL: + compositor->touch_mode = WESTON_TOUCH_MODE_CALIB; + touch_calibrator_mode_changed(compositor); + return; + case WESTON_TOUCH_MODE_NORMAL: + compositor->touch_mode = WESTON_TOUCH_MODE_PREP_CALIB; + } + + weston_compositor_update_touch_mode(compositor); +} + /** Feed in touch down, motion, and up events, calibratable device. * * It assumes always the correct cycle sequence until it gets here: touch_down @@ -2470,23 +2575,54 @@ notify_touch_normalized(struct weston_touch_device *device, break; } - process_touch_normal(device, time, touch_id, x, y, touch_type); + /* Properly forward the touch event */ + switch (weston_touch_device_get_mode(device)) { + case WESTON_TOUCH_MODE_NORMAL: + case WESTON_TOUCH_MODE_PREP_CALIB: + process_touch_normal(device, time, touch_id, x, y, touch_type); + break; + case WESTON_TOUCH_MODE_CALIB: + case WESTON_TOUCH_MODE_PREP_NORMAL: + break; + } } WL_EXPORT void notify_touch_frame(struct weston_touch_device *device) { - struct weston_touch_grab *grab = device->aggregate->grab; + struct weston_touch_grab *grab; - grab->interface->frame(grab); + switch (weston_touch_device_get_mode(device)) { + case WESTON_TOUCH_MODE_NORMAL: + case WESTON_TOUCH_MODE_PREP_CALIB: + grab = device->aggregate->grab; + grab->interface->frame(grab); + break; + case WESTON_TOUCH_MODE_CALIB: + case WESTON_TOUCH_MODE_PREP_NORMAL: + break; + } + + weston_compositor_update_touch_mode(device->aggregate->seat->compositor); } WL_EXPORT void notify_touch_cancel(struct weston_touch_device *device) { - struct weston_touch_grab *grab = device->aggregate->grab; + struct weston_touch_grab *grab; + + switch (weston_touch_device_get_mode(device)) { + case WESTON_TOUCH_MODE_NORMAL: + case WESTON_TOUCH_MODE_PREP_CALIB: + grab = device->aggregate->grab; + grab->interface->cancel(grab); + break; + case WESTON_TOUCH_MODE_CALIB: + case WESTON_TOUCH_MODE_PREP_NORMAL: + break; + } - grab->interface->cancel(grab); + weston_compositor_update_touch_mode(device->aggregate->seat->compositor); } static int