summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2020-12-29 11:30:22 +0100
committerMarge Bot <marge-bot@gnome.org>2021-02-14 13:23:29 +0000
commita5db9ee2d78ba746a3bc4bcfd11f7ebcd94fc5f5 (patch)
treed4d0f8268ad191186475bdd955b71581c4517cc9
parent437f5d1c663e5d5467ad57d287181a7a7dbc978c (diff)
downloadmutter-wip/carlosg/sync-pointer-in-mutter.tar.gz
backends/x11: Emulate pointer motion while the pointer is off stagewip/carlosg/sync-pointer-in-mutter
Given X11 nature, the pointer "leaves" the stage anytime it wanders into a client window, or any other areas that are not deemed part of the stage input region. Yet we want to stay correct in those situations, e.g. have the clutter side reasonably in sync, picking and highlighting to work properly, etc. In order to achieve that, emulate motion events on XI_RawMotion. These are as much throttled as our pointer tracking for a11y, in order to avoid too many XIQueryPointer sync calls. This emulation only kicks in anytime that X11 notifies us that we are not "on" the stage. This replaces some sync_pointer() calls in GNOME Shell code that are there just to compensate for this trait of X11, e.g. in the message tray code. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1659>
-rw-r--r--src/backends/x11/meta-seat-x11.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
index 009d596fe..1e0d19120 100644
--- a/src/backends/x11/meta-seat-x11.c
+++ b/src/backends/x11/meta-seat-x11.c
@@ -73,6 +73,7 @@ struct _MetaSeatX11
int opcode;
guint has_touchscreens : 1;
guint touch_mode : 1;
+ guint has_pointer_focus : 1;
};
static GParamSpec *props[N_PROPS] = { 0 };
@@ -872,6 +873,29 @@ translate_property_event (MetaSeatX11 *seat_x11,
}
static void
+emulate_motion (MetaSeatX11 *seat_x11,
+ double x,
+ double y)
+{
+ ClutterInputDevice *pointer;
+ ClutterEvent *event;
+ ClutterStage *stage;
+
+ pointer = clutter_seat_get_pointer (CLUTTER_SEAT (seat_x11));
+ stage = CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
+
+ event = clutter_event_new (CLUTTER_MOTION);
+ clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
+ clutter_event_set_coords (event, x, y);
+ clutter_event_set_device (event, pointer);
+ clutter_event_set_source_device (event, NULL);
+ clutter_event_set_stage (event, stage);
+
+ clutter_event_put (event);
+ clutter_event_free (event);
+}
+
+static void
translate_raw_event (MetaSeatX11 *seat_x11,
XEvent *xevent)
{
@@ -890,9 +914,6 @@ translate_raw_event (MetaSeatX11 *seat_x11,
if (device == NULL)
return;
- if (!_clutter_is_input_pointer_a11y_enabled (device))
- return;
-
switch (cookie->evtype)
{
case XI_RawMotion:
@@ -906,7 +927,12 @@ translate_raw_event (MetaSeatX11 *seat_x11,
* so we need to explicitly query the pointer here...
*/
if (meta_input_device_x11_get_pointer_location (device, &x, &y))
- _clutter_input_pointer_a11y_on_motion_event (device, x, y);
+ {
+ if (_clutter_is_input_pointer_a11y_enabled (device))
+ _clutter_input_pointer_a11y_on_motion_event (device, x, y);
+ if (!seat_x11->has_pointer_focus)
+ emulate_motion (seat_x11, x, y);
+ }
break;
case XI_RawButtonPress:
case XI_RawButtonRelease:
@@ -917,9 +943,12 @@ translate_raw_event (MetaSeatX11 *seat_x11,
meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (device),
xev->detail);
- _clutter_input_pointer_a11y_on_button_event (device,
- xev->detail,
- (cookie->evtype == XI_RawButtonPress));
+ if (_clutter_is_input_pointer_a11y_enabled (device))
+ {
+ _clutter_input_pointer_a11y_on_button_event (device,
+ xev->detail,
+ (cookie->evtype == XI_RawButtonPress));
+ }
break;
}
}
@@ -2291,6 +2320,9 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
event->crossing.time = xev->time;
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y);
+
+ if (xev->deviceid == seat->pointer_id)
+ seat->has_pointer_focus = TRUE;
}
else
{
@@ -2302,6 +2334,9 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
event->crossing.time = xev->time;
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y);
+
+ if (xev->deviceid == seat->pointer_id)
+ seat->has_pointer_focus = FALSE;
}
meta_input_device_x11_reset_scroll_info (source_device);