[PATCH weston 20/25] input: introduce touch event mode for calibrator

Pekka Paalanen ppaalanen at gmail.com
Fri Mar 23 12:01:00 UTC 2018


From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>

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 <lfrb at collabora.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 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 8452c5d2..d7922799 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -6289,6 +6289,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 129e15b8..48a9af55 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -482,6 +482,34 @@ struct weston_touch_device_ops {
 				const struct weston_touch_device_matrix *matrix);
 };
 
+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 *devpath;			/**< unique name */
@@ -1080,6 +1108,8 @@ struct weston_compositor {
 
 	weston_heads_changed_func_t heads_changed;
 	struct wl_event_source *heads_changed_source;
+
+	enum weston_touch_mode touch_mode;
 };
 
 struct weston_buffer {
@@ -1560,6 +1590,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 7e4677e6..4a82203c 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -185,6 +185,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)
 {
@@ -2401,6 +2407,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
@@ -2471,23 +2576,54 @@ notify_touch_cal(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
-- 
2.16.1



More information about the wayland-devel mailing list