input: introduce touch event mode for calibrator

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@collabora.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
v1 Tested-by: Matt Hoosier <matt.hoosier@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
dev
Louis-Francis Ratté-Boulianne 7 years ago committed by Pekka Paalanen
parent 332a45e096
commit c4689ff1d0
  1. 2
      libweston/compositor.c
  2. 39
      libweston/compositor.h
  3. 140
      libweston/input.c

@ -6334,6 +6334,8 @@ weston_compositor_create(struct wl_display *display, void *user_data)
ec->activate_serial = 1; ec->activate_serial = 1;
ec->touch_mode = WESTON_TOUCH_MODE_NORMAL;
if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4, if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
ec, compositor_bind)) ec, compositor_bind))
goto fail; goto fail;

@ -489,6 +489,34 @@ struct weston_touch_device_ops {
const struct weston_touch_device_matrix *cal); 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 */ /** Represents a physical touchscreen input device */
struct weston_touch_device { struct weston_touch_device {
char *syspath; /**< unique name */ char *syspath; /**< unique name */
@ -1092,6 +1120,8 @@ struct weston_compositor {
*/ */
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;
enum weston_touch_mode touch_mode;
}; };
struct weston_buffer { struct weston_buffer {
@ -1573,6 +1603,15 @@ notify_touch_frame(struct weston_touch_device *device);
void void
notify_touch_cancel(struct weston_touch_device *device); 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 void
weston_layer_entry_insert(struct weston_layer_entry *list, weston_layer_entry_insert(struct weston_layer_entry *list,
struct weston_layer_entry *entry); struct weston_layer_entry *entry);

@ -187,6 +187,12 @@ weston_touch_device_can_calibrate(struct weston_touch_device *device)
return !!device->ops; 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 * static struct weston_pointer_client *
weston_pointer_client_create(struct wl_client *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. /** Feed in touch down, motion, and up events, calibratable device.
* *
* It assumes always the correct cycle sequence until it gets here: touch_down * 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; break;
} }
/* 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); 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 WL_EXPORT void
notify_touch_frame(struct weston_touch_device *device) notify_touch_frame(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->frame(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 WL_EXPORT void
notify_touch_cancel(struct weston_touch_device *device) 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); grab->interface->cancel(grab);
break;
case WESTON_TOUCH_MODE_CALIB:
case WESTON_TOUCH_MODE_PREP_NORMAL:
break;
}
weston_compositor_update_touch_mode(device->aggregate->seat->compositor);
} }
static int static int

Loading…
Cancel
Save