[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 xorg-devel
mailing list