diff --git a/src/core/display-private.h b/src/core/display-private.h index aed9e48f1..44d0878cf 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -253,6 +253,7 @@ struct _MetaDisplay MetaCompositor *compositor; MetaGestureTracker *gesture_tracker; + ClutterEventSequence *pointer_emulating_sequence; int composite_event_base; int composite_error_base; diff --git a/src/core/display.c b/src/core/display.c index d9550ade0..901221057 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -3239,3 +3239,23 @@ meta_display_request_restart (MetaDisplay *display) return result; } + +/** + * meta_display_is_pointer_emulating_sequence: + * @display: the display + * @sequence: (nullable): a #ClutterEventSequence + * + * Tells whether the event sequence is the used for pointer emulation + * and single-touch interaction. + * + * Returns: #TRUE if the sequence emulates pointer behavior + **/ +gboolean +meta_display_is_pointer_emulating_sequence (MetaDisplay *display, + ClutterEventSequence *sequence) +{ + if (!sequence) + return FALSE; + + return display->pointer_emulating_sequence == sequence; +} diff --git a/src/core/events.c b/src/core/events.c index df5dc4481..f15e39d53 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -99,6 +99,62 @@ handle_idletime_for_event (const ClutterEvent *event) #endif /* HAVE_NATIVE_BACKEND */ } +static gboolean +sequence_is_pointer_emulated (MetaDisplay *display, + const ClutterEvent *event) +{ + ClutterEventSequence *sequence; + MetaBackend *backend; + + sequence = clutter_event_get_event_sequence (event); + + if (!sequence) + return FALSE; + + if (clutter_event_is_pointer_emulated (event)) + return TRUE; + + backend = meta_get_backend (); + + /* When using Clutter's native input backend there is no concept of + * pointer emulating sequence, we still must make up our own to be + * able to implement single-touch (hence pointer alike) behavior. + * + * This is implemented similarly to X11, where only the first touch + * on screen gets the "pointer emulated" flag, and it won't get assigned + * to another sequence until the next first touch on an idle touchscreen. + */ + if (META_IS_BACKEND_NATIVE (backend)) + { + MetaGestureTracker *tracker; + + tracker = meta_display_get_gesture_tracker (display); + + if (event->type == CLUTTER_TOUCH_BEGIN && + meta_gesture_tracker_get_n_current_touches (tracker) == 0) + return TRUE; + } + + return FALSE; +} + +static void +meta_display_update_pointer_emulating_sequence (MetaDisplay *display, + const ClutterEvent *event) +{ + ClutterEventSequence *sequence; + + sequence = clutter_event_get_event_sequence (event); + + if (event->type == CLUTTER_TOUCH_BEGIN && + !display->pointer_emulating_sequence && + sequence_is_pointer_emulated (display, event)) + display->pointer_emulating_sequence = sequence; + else if (event->type == CLUTTER_TOUCH_END && + display->pointer_emulating_sequence == sequence) + display->pointer_emulating_sequence = NULL; +} + static gboolean meta_display_handle_event (MetaDisplay *display, const ClutterEvent *event) @@ -108,6 +164,8 @@ meta_display_handle_event (MetaDisplay *display, MetaWaylandCompositor *compositor = NULL; MetaGestureTracker *tracker; + meta_display_update_pointer_emulating_sequence (display, event); + if (meta_is_wayland_compositor ()) { compositor = meta_wayland_compositor_get_default (); diff --git a/src/meta/display.h b/src/meta/display.h index 0c420fde3..8b1289989 100644 --- a/src/meta/display.h +++ b/src/meta/display.h @@ -182,4 +182,7 @@ void meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp); void meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp); +gboolean meta_display_is_pointer_emulating_sequence (MetaDisplay *display, + ClutterEventSequence *sequence); + #endif