[PATCH xserver 2/4 v5] xwayland: add a server sync before repeating keys

Peter Hutterer peter.hutterer at who-t.net
Fri Jun 3 04:21:55 UTC 2016


On Tue, May 24, 2016 at 09:51:42AM +0200, Olivier Fourdan wrote:
> Key repeat is handled by the X server, but input events need to be
> processed and forwarded by the Wayland compositor first.
> 
> Make sure the Wayland compositor is actually processing events, to
> avoid repeating keys in Xwayland while the Wayland compositor cannot
> deal with input events for whatever reason, thus not dispatching key
> release events, leading to repeated keys while the user has already
> released the key.
> 
> Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=762618
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
> ---
>  v2: A slightly less hack-y-ish version of the patch
>      Use xwl_seat to store the pending sync, set up callback fpr keyboard
>      in seat_handle_capabilities() and add a call to _dispatch_pending()
>      in the callback function to make sure we didn't miss a reply
>  v3: Small clean-up,
>      Remove the call to wl_display_dispatch_pending() that we added
>      in v2 as we shall do it in two other separate patches to follow.
>  v4: Use a list to store the devices pending a compositor sync per
>      xwl_seat, add the check repeat handler to xwl_seat->keyboard as
>      well, as per Daniel's last review.
>  v5: Remove device from pending sync on keyboard removal as well, to be
>      on the safe side.
> 
>  hw/xwayland/xwayland-input.c | 74 +++++++++++++++++++++++++++++++++++++++++++-
>  hw/xwayland/xwayland.h       |  2 ++
>  2 files changed, 75 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
> index cbc1bf2..5c979f5 100644
> --- a/hw/xwayland/xwayland-input.c
> +++ b/hw/xwayland/xwayland-input.c
> @@ -41,6 +41,11 @@
>          (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
>          (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
>  
> +struct sync_pending {
> +    struct xorg_list l;
> +    DeviceIntPtr pending_dev;
> +};
> +
>  static void
>  xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl)
>  {
> @@ -527,6 +532,59 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
>  }
>  
>  static void
> +remove_sync_pending(DeviceIntPtr dev)
> +{
> +    struct xwl_seat *xwl_seat = dev->public.devicePrivate;
> +    struct sync_pending *p, *npd;
> +
> +    xorg_list_for_each_entry_safe(p, npd, &xwl_seat->sync_pending, l)
> +        if (p->pending_dev == dev) {
> +            xorg_list_del(&xwl_seat->sync_pending);
> +            free (p);
> +            return;
> +        }


style nit: please use { } for the xorg_list, it's a bit dangerous otherwise


Cheers,
   Peter


> +}
> +
> +static void
> +sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
> +{
> +    DeviceIntPtr dev = (DeviceIntPtr) data;
> +
> +    remove_sync_pending(dev);
> +    wl_callback_destroy(callback);
> +}
> +
> +static const struct wl_callback_listener sync_listener = {
> +   sync_callback
> +};
> +
> +static Bool
> +keyboard_check_repeat (DeviceIntPtr dev, XkbSrvInfoPtr xkbi, unsigned key)
> +{
> +    struct xwl_seat *xwl_seat = dev->public.devicePrivate;
> +    struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
> +    struct wl_callback *callback;
> +    struct sync_pending *p;
> +
> +    xorg_list_for_each_entry(p, &xwl_seat->sync_pending, l)
> +        if (p->pending_dev == dev) {
> +            ErrorF("Key repeat discarded, Wayland compositor doesn't "
> +                   "seem to be processing events fast enough!\n");
> +
> +            return FALSE;
> +        }
> +
> +    p = xnfalloc(sizeof(struct sync_pending));
> +    p->pending_dev = dev;
> +    callback = wl_display_sync (xwl_screen->display);
> +    xorg_list_add(&p->l, &xwl_seat->sync_pending);
> +
> +    wl_callback_add_listener(callback, &sync_listener, dev);
> +
> +    return TRUE;
> +}
> +
> +static void
>  keyboard_handle_repeat_info (void *data, struct wl_keyboard *keyboard,
>                               int32_t rate, int32_t delay)
>  {
> @@ -716,6 +774,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
>                           enum wl_seat_capability caps)
>  {
>      struct xwl_seat *xwl_seat = data;
> +    DeviceIntPtr master;
>  
>      if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->wl_pointer == NULL) {
>          xwl_seat->wl_pointer = wl_seat_get_pointer(seat);
> @@ -748,12 +807,18 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
>              ActivateDevice(xwl_seat->keyboard, TRUE);
>          }
>          EnableDevice(xwl_seat->keyboard, TRUE);
> +        xwl_seat->keyboard->key->xkbInfo->checkRepeat = keyboard_check_repeat;
> +        master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
> +        if (master)
> +            master->key->xkbInfo->checkRepeat = keyboard_check_repeat;
>      } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->wl_keyboard) {
>          wl_keyboard_release(xwl_seat->wl_keyboard);
>          xwl_seat->wl_keyboard = NULL;
>  
> -        if (xwl_seat->keyboard)
> +        if (xwl_seat->keyboard) {
> +            remove_sync_pending(xwl_seat->keyboard);
>              DisableDevice(xwl_seat->keyboard, TRUE);
> +        }
>      }
>  
>      if (caps & WL_SEAT_CAPABILITY_TOUCH && xwl_seat->wl_touch == NULL) {
> @@ -814,12 +879,14 @@ create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version
>      wl_array_init(&xwl_seat->keys);
>  
>      xorg_list_init(&xwl_seat->touches);
> +    xorg_list_init(&xwl_seat->sync_pending);
>  }
>  
>  void
>  xwl_seat_destroy(struct xwl_seat *xwl_seat)
>  {
>      struct xwl_touch *xwl_touch, *next_xwl_touch;
> +    struct sync_pending *p, *npd;
>  
>      xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
>                                    &xwl_seat->touches, link_touch) {
> @@ -827,6 +894,11 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
>          free(xwl_touch);
>      }
>  
> +    xorg_list_for_each_entry_safe(p, npd, &xwl_seat->sync_pending, l) {
> +        xorg_list_del(&xwl_seat->sync_pending);
> +        free (p);
> +    }
> +
>      wl_seat_destroy(xwl_seat->seat);
>      wl_surface_destroy(xwl_seat->cursor);
>      if (xwl_seat->cursor_frame_cb)
> diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
> index 67b30cb..5c053d9 100644
> --- a/hw/xwayland/xwayland.h
> +++ b/hw/xwayland/xwayland.h
> @@ -138,6 +138,8 @@ struct xwl_seat {
>      size_t keymap_size;
>      char *keymap;
>      struct wl_surface *keyboard_focus;
> +
> +    struct xorg_list sync_pending;
>  };
>  
>  struct xwl_output {
> -- 
> 2.7.4
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
> 


More information about the xorg-devel mailing list