summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2016-09-28 12:35:36 +0200
committerAdam Jackson <ajax@redhat.com>2016-10-05 13:27:12 -0400
commitee526285882995289846648f3122c4295e3e8284 (patch)
tree265fc9e8fd4e98f268106a7a070a1ea6c20745ed
parent2b6a068d21997ca812e665ed058e72eb4626c129 (diff)
xwayland: Apply "last pointer window" check only to the pointer device
The checks in xwayland's XYToWindow handler pretty much assumes that the sprite is managed by the wl_pointer, which is not entirely right, given 1) The Virtual Core Pointer may be controlled from other interfaces, and 2) there may be other SpriteRecs than the VCP's. This makes XYToWindow calls return a sprite trace with just the root window if any of those two assumptions are broken, eg. on touch events. So turn the check upside down, first assume that the default XYToWindow proc behavior is right, and later cut down the spriteTrace if the current device happens to be the pointer and is out of focus. We work our way to the device's lastSlave here so as not to break assumption #1 above. Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Carlos Garnacho <carlosg@gnome.org> Acked-by: Olivier Fourdan <ofourdan@redhat.com>
-rw-r--r--hw/xwayland/xwayland-input.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 32cfb35fa..1872bdcc6 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -945,44 +945,65 @@ DDXRingBell(int volume, int pitch, int duration)
{
}
-static WindowPtr
-xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
+static Bool
+sprite_check_lost_focus(SpritePtr sprite, WindowPtr window)
{
- struct xwl_seat *xwl_seat = NULL;
- DeviceIntPtr device;
- WindowPtr ret;
+ DeviceIntPtr device, master;
+ struct xwl_seat *xwl_seat;
for (device = inputInfo.devices; device; device = device->next) {
+ /* Ignore non-wayland devices */
if (device->deviceProc == xwl_pointer_proc &&
- device->spriteInfo->sprite == sprite) {
- xwl_seat = device->public.devicePrivate;
+ device->spriteInfo->sprite == sprite)
break;
- }
}
- if (xwl_seat == NULL) {
- sprite->spriteTraceGood = 1;
- return sprite->spriteTrace[0];
- }
+ if (!device)
+ return FALSE;
+
+ xwl_seat = device->public.devicePrivate;
+
+ master = GetMaster(device, POINTER_OR_FLOAT);
+ if (!master || !master->lastSlave)
+ return FALSE;
- screen->XYToWindow = xwl_seat->xwl_screen->XYToWindow;
+ /* We do want the last active slave, we only check on slave xwayland
+ * devices so we can find out the xwl_seat, but those don't actually own
+ * their sprite, so the match doesn't mean a lot.
+ */
+ if (master->lastSlave == xwl_seat->pointer &&
+ xwl_seat->focus_window == NULL &&
+ xwl_seat->last_xwindow == window)
+ return TRUE;
+
+ xwl_seat->last_xwindow = window;
+ return FALSE;
+}
+
+static WindowPtr
+xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
+{
+ struct xwl_screen *xwl_screen;
+ WindowPtr ret;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->XYToWindow = xwl_screen->XYToWindow;
ret = screen->XYToWindow(screen, sprite, x, y);
- xwl_seat->xwl_screen->XYToWindow = screen->XYToWindow;
+ xwl_screen->XYToWindow = screen->XYToWindow;
screen->XYToWindow = xwl_xy_to_window;
- /* If the pointer has left the Wayland surface but the DIX still
- * finds the pointer within the previous X11 window, it means that
+ /* If the device controlling the sprite has left the Wayland surface but
+ * the DIX still finds the pointer within the X11 window, it means that
* the pointer has crossed to another native Wayland window, in this
* case, pretend we entered the root window so that a LeaveNotify
* event is emitted.
*/
- if (xwl_seat->focus_window == NULL && xwl_seat->last_xwindow == ret) {
+ if (sprite_check_lost_focus(sprite, ret)) {
sprite->spriteTraceGood = 1;
return sprite->spriteTrace[0];
}
- xwl_seat->last_xwindow = ret;
-
return ret;
}