[PATCH v3 xserver] xwayland: Add grab protocol support

Olivier Fourdan ofourdan at redhat.com
Wed Jul 12 09:51:08 UTC 2017


The keyboard grabbing protocol for Xwayland is included in
wayland-protocol 1.9.

Update the wayland-protocol required version in both configure and meson
builds and add support for this new protocol in Xwayland.

Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 v2: Remove break after return statement (Peter's review)
 v3: Update wayland-protocol requirement in both configure.ac and
     meson.build now that wayland-protocol 1.9 was released with the
     protocol definition.

 configure.ac                 |  2 +-
 hw/xwayland/Makefile.am      |  7 +++-
 hw/xwayland/xwayland-input.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland.c       |  2 +-
 hw/xwayland/xwayland.h       |  5 ++-
 meson.build                  |  2 +-
 6 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index e202770..8d3c3b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2353,7 +2353,7 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes])
 
 dnl Xwayland DDX
 
-XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.5 $LIBDRM epoxy"
+XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.9 $LIBDRM epoxy"
 if test "x$XF86VIDMODE" = xyes; then
 	XWAYLANDMODULES="$XWAYLANDMODULES $VIDMODEPROTO"
 fi
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 7eda9be..c14b95b 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -57,7 +57,9 @@ Xwayland_built_sources +=					\
 	pointer-constraints-unstable-v1-client-protocol.h	\
 	pointer-constraints-unstable-v1-protocol.c		\
 	tablet-unstable-v2-client-protocol.h			\
-	tablet-unstable-v2-protocol.c
+	tablet-unstable-v2-protocol.c				\
+	xwayland-keyboard-grab-unstable-v1-protocol.c		\
+	xwayland-keyboard-grab-unstable-v1-client-protocol.h
 
 nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
 CLEANFILES = $(Xwayland_built_sources)
@@ -83,6 +85,9 @@ pointer-constraints-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)
 tablet-unstable-v2-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 tablet-unstable-v2-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
+xwayland-keyboard-grab-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
+	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
+xwayland-keyboard-grab-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
 	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
 
 %-protocol.c : %.xml
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index c5bb381..92e530d 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -1016,6 +1016,85 @@ static const struct wl_touch_listener touch_listener = {
     touch_handle_cancel
 };
 
+static struct xwl_seat *
+find_matching_seat(DeviceIntPtr device)
+{
+    DeviceIntPtr dev;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+        if (dev->deviceProc == xwl_keyboard_proc &&
+            device == GetMaster(dev, MASTER_KEYBOARD))
+                return (struct xwl_seat *) dev->public.devicePrivate;
+
+    return NULL;
+}
+
+static void
+release_grab(struct xwl_seat *xwl_seat)
+{
+    if (xwl_seat->keyboard_grab)
+        zwp_xwayland_keyboard_grab_v1_destroy(xwl_seat->keyboard_grab);
+    xwl_seat->keyboard_grab = NULL;
+}
+
+static void
+set_grab(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window)
+{
+    struct xwl_screen *xwl_screen;
+
+    if (!xwl_window)
+        return;
+
+    /* We already have a grab */
+    if (xwl_seat->keyboard_grab)
+        release_grab (xwl_seat);
+
+    xwl_screen = xwl_seat->xwl_screen;
+    if (xwl_screen->wp_grab)
+        xwl_seat->keyboard_grab =
+            zwp_xwayland_keyboard_grab_manager_v1_grab_keyboard(xwl_screen->wp_grab,
+                                                                xwl_window->surface,
+                                                                xwl_seat->seat);
+}
+
+static void
+xwl_keyboard_activate_grab(DeviceIntPtr device, GrabPtr grab, TimeStamp time, Bool passive)
+{
+    struct xwl_seat *xwl_seat = device->public.devicePrivate;
+
+    /* We are not interested in passive grabs */
+    if (!passive) {
+        /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */
+        if (xwl_seat == NULL)
+            xwl_seat = find_matching_seat(device);
+        if (xwl_seat)
+            set_grab(xwl_seat, xwl_window_from_window(grab->window));
+    }
+
+    ActivateKeyboardGrab(device, grab, time, passive);
+}
+
+static void
+xwl_keyboard_deactivate_grab(DeviceIntPtr device)
+{
+    struct xwl_seat *xwl_seat = device->public.devicePrivate;
+
+    /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */
+    if (xwl_seat == NULL)
+        xwl_seat = find_matching_seat(device);
+    if (xwl_seat)
+        release_grab (xwl_seat);
+
+    DeactivateKeyboardGrab(device);
+}
+
+static void
+setup_keyboard_grab_handler (DeviceIntPtr device)
+{
+    device->deviceGrab.ActivateGrab = xwl_keyboard_activate_grab;
+    device->deviceGrab.DeactivateGrab = xwl_keyboard_deactivate_grab;
+}
+
 static DeviceIntPtr
 add_device(struct xwl_seat *xwl_seat,
            const char *driver, DeviceProc device_proc)
@@ -1104,6 +1183,8 @@ release_relative_pointer(struct xwl_seat *xwl_seat)
 static void
 init_keyboard(struct xwl_seat *xwl_seat)
 {
+    DeviceIntPtr master;
+
     xwl_seat->wl_keyboard = wl_seat_get_keyboard(xwl_seat->seat);
     wl_keyboard_add_listener(xwl_seat->wl_keyboard,
                              &keyboard_listener, xwl_seat);
@@ -1115,6 +1196,10 @@ init_keyboard(struct xwl_seat *xwl_seat)
     }
     EnableDevice(xwl_seat->keyboard, TRUE);
     xwl_seat->keyboard->key->xkbInfo->checkRepeat = keyboard_check_repeat;
+
+    master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
+    if (master)
+        setup_keyboard_grab_handler(master);
 }
 
 static void
@@ -1172,6 +1257,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
     if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->wl_keyboard == NULL) {
         init_keyboard(xwl_seat);
     } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->wl_keyboard) {
+        release_grab(xwl_seat);
         release_keyboard(xwl_seat);
     }
 
@@ -1271,6 +1357,7 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
 
     release_tablet_manager_seat(xwl_seat);
 
+    release_grab(xwl_seat);
     wl_seat_destroy(xwl_seat->seat);
     xwl_cursor_release(&xwl_seat->cursor);
     wl_array_release(&xwl_seat->keys);
@@ -2311,6 +2398,16 @@ init_pointer_constraints(struct xwl_screen *xwl_screen,
 }
 
 static void
+init_keyboard_grab(struct xwl_screen *xwl_screen,
+                   uint32_t id, uint32_t version)
+{
+    xwl_screen->wp_grab =
+         wl_registry_bind(xwl_screen->registry, id,
+                          &zwp_xwayland_keyboard_grab_manager_v1_interface,
+                          1);
+}
+
+static void
 input_handler(void *data, struct wl_registry *registry, uint32_t id,
               const char *interface, uint32_t version)
 {
@@ -2325,6 +2422,8 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
         init_pointer_constraints(xwl_screen, id, version);
     } else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
         init_tablet_manager(xwl_screen, id, version);
+    } else if (strcmp(interface, "zwp_xwayland_keyboard_grab_manager_v1") == 0) {
+        init_keyboard_grab(xwl_screen, id, version);
     }
 }
 
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 551443f..cb929ca 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -234,7 +234,7 @@ xwl_close_screen(ScreenPtr screen)
     return screen->CloseScreen(screen);
 }
 
-static struct xwl_window *
+struct xwl_window *
 xwl_window_from_window(WindowPtr window)
 {
     struct xwl_window *xwl_window;
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 0668770..6d3edf3 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -45,6 +45,7 @@
 #include "relative-pointer-unstable-v1-client-protocol.h"
 #include "pointer-constraints-unstable-v1-client-protocol.h"
 #include "tablet-unstable-v2-client-protocol.h"
+#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
 
 struct xwl_screen {
     int width;
@@ -80,7 +81,7 @@ struct xwl_screen {
     struct wl_shell *shell;
     struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
     struct zwp_pointer_constraints_v1 *pointer_constraints;
-
+    struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
     uint32_t serial;
 
 #define XWL_FORMAT_ARGB8888 (1 << 0)
@@ -188,6 +189,7 @@ struct xwl_seat {
     struct xorg_list tablets;
     struct xorg_list tablet_tools;
     struct xorg_list tablet_pads;
+    struct zwp_xwayland_keyboard_grab_v1 *keyboard_grab;
 };
 
 struct xwl_tablet {
@@ -307,6 +309,7 @@ RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
 void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
 struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
 
+struct xwl_window *xwl_window_from_window(WindowPtr window);
 
 Bool xwl_shm_create_screen_resources(ScreenPtr screen);
 PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
diff --git a/meson.build b/meson.build
index 79da237..a36ae9d 100644
--- a/meson.build
+++ b/meson.build
@@ -98,7 +98,7 @@ if (host_machine.system() != 'darwin' and
 
         xwayland_dep = [
             dependency('wayland-client', version: '>= 1.3.0', required: xwayland_required),
-            dependency('wayland-protocols', version: '>= 1.5.0', required: xwayland_required),
+            dependency('wayland-protocols', version: '>= 1.9.0', required: xwayland_required),
             dependency('libdrm', version: '>= 2.3.1', required: xwayland_required),
             dependency('epoxy', required: xwayland_required),
         ]
-- 
2.9.4



More information about the wayland-devel mailing list