Hey Carlos, ----- Original Message ----- > 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. We work our way to the > device's lastSlave here so as not to break assumption #1 above. > > Also, simplify the actual nested call to XYToWindow, the method pointer > in ScreenPtr was reinstaurated before calling, and moved back to > xwl_screen domain afterwards. This seems kind of pointless, as we have > the function pointer anyway. > > Signed-off-by: Carlos Garnacho <carl...@gnome.org> > --- > hw/xwayland/xwayland-input.c | 64 > ++++++++++++++++++++++++++------------------ > 1 file changed, 38 insertions(+), 26 deletions(-) > > diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c > index 32cfb35..9b385dc 100644 > --- a/hw/xwayland/xwayland-input.c > +++ b/hw/xwayland/xwayland-input.c > @@ -945,43 +945,55 @@ DDXRingBell(int volume, int pitch, int duration) > { > } > > -static WindowPtr > -xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) > +static DeviceIntPtr > +sprite_get_last_active_device(SpritePtr sprite, struct xwl_seat **xwl_seat) > { > - struct xwl_seat *xwl_seat = NULL; > DeviceIntPtr device; > - WindowPtr ret; > > for (device = inputInfo.devices; device; device = device->next) { > - if (device->deviceProc == xwl_pointer_proc && > - device->spriteInfo->sprite == sprite) { > - xwl_seat = device->public.devicePrivate; > + /* Ignore non-wayland devices */ > + if (device->deviceProc != xwl_pointer_proc && > + device->deviceProc != xwl_touch_proc && > + device->deviceProc != xwl_keyboard_proc) > + continue; > + > + if (device->spriteInfo->sprite == sprite) > break; > - } > } > > - if (xwl_seat == NULL) { > - sprite->spriteTraceGood = 1; > - return sprite->spriteTrace[0]; > - } > + if (!device || IsFloating(device)) > + return NULL; > > - screen->XYToWindow = xwl_seat->xwl_screen->XYToWindow; > - ret = screen->XYToWindow(screen, sprite, x, y); > - xwl_seat->xwl_screen->XYToWindow = screen->XYToWindow; > - screen->XYToWindow = xwl_xy_to_window;
That wrapping is on purpose, see Daniel's review on my initial patch here: https://lists.x.org/archives/xorg-devel/2016-June/050238.html > + *xwl_seat = device->public.devicePrivate; > > - /* If the pointer has left the Wayland surface but the DIX still > - * finds the pointer within the previous 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. > + /* 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 (xwl_seat->focus_window == NULL && xwl_seat->last_xwindow == ret) { > - sprite->spriteTraceGood = 1; > - return sprite->spriteTrace[0]; > - } > + return device->master->lastSlave; I wonder, would it make sense to use the GetMaster() API here or else check if master is actually non-null? (note, I tried to detach the xwayland-pointer (with xinput float) from its master, it doesn't crash because we actually get no more events from Xwayland for this device after that) > +} > > - xwl_seat->last_xwindow = ret; > +static WindowPtr > +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; > + > + xwl_screen = xwl_screen_get(screen); > + ret = xwl_screen->XYToWindow(screen, sprite, x, y); > + > + device = sprite_get_last_active_device(sprite, &xwl_seat); Do you plan to reuse that sprite_get_last_active_device() elsewhere? If not, the whole logic below (device && xwl_seat && xwl_seat->pointer == device) could be moved to the function that would return either the right xwl_seat or NULL, as we don't actually use the value of device here, apart from this test. > + if (device && xwl_seat && xwl_seat->pointer == device) { > + if (xwl_seat->focus_window == NULL && xwl_seat->last_xwindow == ret) > { > + sprite->spriteTraceGood = 1; > + return sprite->spriteTrace[0]; > + } > + > + xwl_seat->last_xwindow = ret; > + } > > return ret; > } > -- > 2.10.0 Cheers, Olivier _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel