[PATCH xserver v2] xwayland: Apply "last pointer window" check only to the pointer device

Olivier Fourdan ofourdan at redhat.com
Thu Sep 29 13:37:27 UTC 2016


Hi Carlos,

> 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.
> 
> Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
> ---
>  hw/xwayland/xwayland-input.c | 59
>  ++++++++++++++++++++++++++++++--------------
>  1 file changed, 40 insertions(+), 19 deletions(-)
> 
> diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
> index 32cfb35..029ae04 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;
>  }

It just feels odd that the function is called sprite_check_lost_focus() and updates the xwl_seat's last_xwindow value.

I am no input expert so maybe you'll want to wait for someone else's better review, but as far as I can see it looks good to me, so:

Acked-by: Olivier Fourdan <ofourdan at redhat.com>

Cheers,
Olivier


More information about the xorg-devel mailing list