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>
This commit is contained in:
Carlos Garnacho 2016-09-28 12:35:36 +02:00 committed by Adam Jackson
parent 2b6a068d21
commit ee52628588

View File

@ -945,44 +945,65 @@ DDXRingBell(int volume, int pitch, int duration)
{ {
} }
static Bool
sprite_check_lost_focus(SpritePtr sprite, WindowPtr window)
{
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)
break;
}
if (!device)
return FALSE;
xwl_seat = device->public.devicePrivate;
master = GetMaster(device, POINTER_OR_FLOAT);
if (!master || !master->lastSlave)
return FALSE;
/* 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 static WindowPtr
xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
{ {
struct xwl_seat *xwl_seat = NULL; struct xwl_screen *xwl_screen;
DeviceIntPtr device;
WindowPtr ret; WindowPtr ret;
for (device = inputInfo.devices; device; device = device->next) { xwl_screen = xwl_screen_get(screen);
if (device->deviceProc == xwl_pointer_proc &&
device->spriteInfo->sprite == sprite) {
xwl_seat = device->public.devicePrivate;
break;
}
}
if (xwl_seat == NULL) { screen->XYToWindow = xwl_screen->XYToWindow;
sprite->spriteTraceGood = 1;
return sprite->spriteTrace[0];
}
screen->XYToWindow = xwl_seat->xwl_screen->XYToWindow;
ret = screen->XYToWindow(screen, sprite, x, y); 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; screen->XYToWindow = xwl_xy_to_window;
/* If the pointer has left the Wayland surface but the DIX still /* If the device controlling the sprite has left the Wayland surface but
* finds the pointer within the previous X11 window, it means that * the DIX still finds the pointer within the X11 window, it means that
* the pointer has crossed to another native Wayland window, in this * the pointer has crossed to another native Wayland window, in this
* case, pretend we entered the root window so that a LeaveNotify * case, pretend we entered the root window so that a LeaveNotify
* event is emitted. * event is emitted.
*/ */
if (xwl_seat->focus_window == NULL && xwl_seat->last_xwindow == ret) { if (sprite_check_lost_focus(sprite, ret)) {
sprite->spriteTraceGood = 1; sprite->spriteTraceGood = 1;
return sprite->spriteTrace[0]; return sprite->spriteTrace[0];
} }
xwl_seat->last_xwindow = ret;
return ret; return ret;
} }