backends/x11: Emulate pointer motion while the pointer is off stage
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>
This commit is contained in:
parent
437f5d1c66
commit
a5db9ee2d7
@ -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 };
|
||||
@ -871,6 +872,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);
|
||||
|
Loading…
Reference in New Issue
Block a user