xserver: Branch 'master' - 4 commits

Peter Hutterer whot at kemper.freedesktop.org
Fri Jun 3 09:35:41 UTC 2016


 hw/xwayland/xwayland-input.c |   79 ++++++++++++++++++++++++++++++++++++++++++-
 hw/xwayland/xwayland.c       |   44 +++++++++++++++++------
 hw/xwayland/xwayland.h       |    4 ++
 include/xkbsrv.h             |    6 +++
 xkb/xkbAccessX.c             |    4 +-
 5 files changed, 123 insertions(+), 14 deletions(-)

New commits:
commit 88e981e7088198fabea6c322c58f371d91578b6a
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Mar 9 10:33:50 2016 +0100

    xwayland: sync event queue to check compositor reply
    
    Read and dispatch pending Wayland events to make sure we do not miss a
    possible reply from the compositor prior to discard a key repeat.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 20dd92b..16e7155 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -560,6 +560,9 @@ keyboard_check_repeat (DeviceIntPtr dev, XkbSrvInfoPtr xkbi, unsigned key)
     struct wl_callback *callback;
     struct sync_pending *p;
 
+    /* Make sure we didn't miss a possible reply from the compositor */
+    xwl_sync_events (xwl_screen);
+
     xorg_list_for_each_entry(p, &xwl_seat->sync_pending, l) {
         if (p->pending_dev == dev) {
             ErrorF("Key repeat discarded, Wayland compositor doesn't "
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index fdc3778..8c49b0b 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -519,6 +519,13 @@ block_handler(void *data, OSTimePtr pTimeout, void *pRead)
     xwl_dispatch_events (xwl_screen);
 }
 
+void
+xwl_sync_events (struct xwl_screen *xwl_screen)
+{
+    xwl_dispatch_events (xwl_screen);
+    xwl_read_events (xwl_screen);
+}
+
 static CARD32
 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
 {
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 5c053d9..70a0492 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -155,6 +155,8 @@ struct xwl_output {
 
 struct xwl_pixmap;
 
+void xwl_sync_events (struct xwl_screen *xwl_screen);
+
 Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
 
 struct xwl_screen *xwl_screen_get(ScreenPtr screen);
commit 26ad25a0ed1d99f3cacb711793c830cb5249580e
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Mar 9 11:17:27 2016 +0100

    xwayland: refactor Wayland event handling
    
    To be able to reuse some code.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index b803ba1..fdc3778 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -462,14 +462,13 @@ static const struct wl_registry_listener registry_listener = {
 };
 
 static void
-socket_handler(int fd, int ready, void *data)
+xwl_read_events (struct xwl_screen *xwl_screen)
 {
-    struct xwl_screen *xwl_screen = data;
     int ret;
 
     ret = wl_display_read_events(xwl_screen->display);
     if (ret == -1)
-        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+        FatalError("failed to read Wayland events: %s\n", strerror(errno));
 
     xwl_screen->prepare_read = 0;
 
@@ -479,18 +478,10 @@ socket_handler(int fd, int ready, void *data)
 }
 
 static void
-wakeup_handler(void *data, int err, void *pRead)
-{
-}
-
-static void
-block_handler(void *data, OSTimePtr pTimeout, void *pRead)
+xwl_dispatch_events (struct xwl_screen *xwl_screen)
 {
-    struct xwl_screen *xwl_screen = data;
     int ret;
 
-    xwl_screen_post_damage(xwl_screen);
-
     while (xwl_screen->prepare_read == 0 &&
            wl_display_prepare_read(xwl_screen->display) == -1) {
         ret = wl_display_dispatch_pending(xwl_screen->display);
@@ -506,6 +497,28 @@ block_handler(void *data, OSTimePtr pTimeout, void *pRead)
         FatalError("failed to write to XWayland fd: %s\n", strerror(errno));
 }
 
+static void
+socket_handler(int fd, int ready, void *data)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    xwl_read_events (xwl_screen);
+}
+
+static void
+wakeup_handler(void *data, int err, void *pRead)
+{
+}
+
+static void
+block_handler(void *data, OSTimePtr pTimeout, void *pRead)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    xwl_screen_post_damage(xwl_screen);
+    xwl_dispatch_events (xwl_screen);
+}
+
 static CARD32
 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
 {
commit 239705a6feefaddf90be9541a054ebd8c8c10d81
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Mar 9 10:31:58 2016 +0100

    xwayland: add a server sync before repeating keys
    
    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>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index d186681..20dd92b 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)
 {
@@ -520,6 +525,61 @@ 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;
+        }
+    }
+}
+
+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)
 {
@@ -709,6 +769,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);
@@ -741,12 +802,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) {
@@ -807,12 +874,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) {
@@ -820,6 +889,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 {
commit fda5675f9d257d583ea0683adf863c5e1e51e30c
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Wed Mar 9 10:31:13 2016 +0100

    xkb: add hook to allow/deny AccessX key repeat
    
    The xserver generates the key repeat by itself.
    
    But when used with another server processing inputs first (e.g. a
    Wayland compositor), the other server may be busy dealing with some
    other things and not queue up key release events in time.
    
    Add a vfunc in XkbSrvInfo to possibly add a check before re-emitting a
    keypress event in the AccessX timer handler, so that the key repeat has
    a chance to be denied if the server processing the input is not ready.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 7e71089..6e4ad44 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -142,6 +142,10 @@ typedef struct _XkbFilter {
     struct _XkbFilter *next;
 } XkbFilterRec, *XkbFilterPtr;
 
+typedef Bool (*XkbSrvCheckRepeatPtr) (DeviceIntPtr dev,
+                                      struct _XkbSrvInfo * /* xkbi */ ,
+                                      unsigned /* keycode */);
+
 typedef struct _XkbSrvInfo {
     XkbStateRec prev_state;
     XkbStateRec state;
@@ -189,6 +193,8 @@ typedef struct _XkbSrvInfo {
 
     int szFilters;
     XkbFilterPtr filters;
+
+    XkbSrvCheckRepeatPtr checkRepeat;
 } XkbSrvInfoRec, *XkbSrvInfoPtr;
 
 #define	XkbSLI_IsDefault	(1L<<0)
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 892cb30..f800577 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -89,6 +89,7 @@ AccessXInit(DeviceIntPtr keybd)
     xkbi->repeatKeyTimer = NULL;
     xkbi->krgTimer = NULL;
     xkbi->beepTimer = NULL;
+    xkbi->checkRepeat = NULL;
     ctrls->repeat_delay = XkbDfltRepeatDelay;
     ctrls->repeat_interval = XkbDfltRepeatInterval;
     ctrls->debounce_delay = 300;
@@ -317,7 +318,8 @@ AccessXRepeatKeyExpire(OsTimerPtr timer, CARD32 now, void *arg)
     if (xkbi->repeatKey == 0)
         return 0;
 
-    AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE);
+    if (xkbi->checkRepeat == NULL || xkbi->checkRepeat (dev, xkbi, xkbi->repeatKey))
+        AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE);
 
     return xkbi->desc->ctrls->repeat_interval;
 }


More information about the xorg-commit mailing list