From ac61aedae946938079cdc10b0a7e19636ad87ac0 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Wed, 22 Mar 2017 10:21:02 +0100 Subject: wayland: add shortcut inhibitor support This adds support for the shortcut inhibitor protocol in gdk/wayland backend. A shortcut inhibitor request is issued from the gdk wayland backend for both the older, deprecated API gdk_device_grab() and the new gdk seat API gdk_seat_grab(), but only if the requested capability is for the keyboard only. https://bugzilla.gnome.org/show_bug.cgi?id=783343 --- configure.ac | 2 +- gdk/wayland/Makefile.am | 2 ++ gdk/wayland/gdkdevice-wayland.c | 15 +++++++++++- gdk/wayland/gdkdisplay-wayland.c | 6 +++++ gdk/wayland/gdkdisplay-wayland.h | 2 ++ gdk/wayland/gdkprivate-wayland.h | 5 ++++ gdk/wayland/gdkwindow-wayland.c | 51 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 49c59d7ed0..301310219e 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ m4_define([cairo_required_version], [1.14.0]) m4_define([gdk_pixbuf_required_version], [2.30.0]) m4_define([introspection_required_version], [1.39.0]) m4_define([wayland_required_version], [1.9.91]) -m4_define([wayland_protocols_required_version], [1.7]) +m4_define([wayland_protocols_required_version], [1.9]) m4_define([mirclient_required_version], [0.22.0]) m4_define([mircookie_required_version], [0.17.0]) m4_define([epoxy_required_version], [1.0]) diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am index d4983cf2a5..408bf7be5c 100644 --- a/gdk/wayland/Makefile.am +++ b/gdk/wayland/Makefile.am @@ -31,6 +31,8 @@ BUILT_SOURCES = \ gtk-primary-selection-protocol.c \ tablet-unstable-v2-client-protocol.h \ tablet-unstable-v2-protocol.c \ + keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h \ + keyboard-shortcuts-inhibit-unstable-v1-protocol.c \ gtk-shell-client-protocol.h \ gtk-shell-protocol.c diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 011fe30e2d..e1bccc606d 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -757,6 +757,8 @@ gdk_wayland_device_grab (GdkDevice *device, if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { /* Device is a keyboard */ + gdk_wayland_window_inhibit_shortcuts (window, + gdk_device_get_seat (device)); return GDK_GRAB_SUCCESS; } else @@ -813,6 +815,9 @@ gdk_wayland_device_ungrab (GdkDevice *device, if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) { /* Device is a keyboard */ + if (prev_focus) + gdk_wayland_window_restore_shortcuts (prev_focus, + gdk_device_get_seat (device)); } else { @@ -4756,6 +4761,10 @@ gdk_wayland_seat_grab (GdkSeat *seat, _gdk_display_get_next_serial (display), evtime, FALSE); + + /* Inhibit shortcuts if the seat grab is for the keyboard only */ + if (capabilities == GDK_SEAT_CAPABILITY_KEYBOARD) + gdk_wayland_window_inhibit_shortcuts (window, seat); } if (wayland_seat->tablets && @@ -4827,7 +4836,11 @@ gdk_wayland_seat_ungrab (GdkSeat *seat) grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_keyboard); if (grab) - grab->serial_end = grab->serial_start; + { + grab->serial_end = grab->serial_start; + if (grab->window) + gdk_wayland_window_restore_shortcuts (grab->window, seat); + } } if (wayland_seat->touch_master) diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 0baa2de21c..8f8c1ddc9a 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -451,6 +451,12 @@ gdk_registry_handle_global (void *data, wl_registry_bind (display_wayland->wl_registry, id, &zxdg_importer_v1_interface, 1); } + else if (strcmp (interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) + { + display_wayland->keyboard_shortcuts_inhibit = + wl_registry_bind (display_wayland->wl_registry, id, + &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1); + } else handled = FALSE; diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 1270405e11..3f53108a15 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,7 @@ struct _GdkWaylandDisplay struct zwp_tablet_manager_v2 *tablet_manager; struct zxdg_exporter_v1 *xdg_exporter; struct zxdg_importer_v1 *xdg_importer; + struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; GList *async_roundtrips; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 96c1536710..09590b81b3 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -281,4 +281,9 @@ void gdk_wayland_seat_set_global_cursor (GdkSeat *seat, struct wl_output *gdk_wayland_window_get_wl_output (GdkWindow *window); +void gdk_wayland_window_inhibit_shortcuts (GdkWindow *window, + GdkSeat *gdk_seat); +void gdk_wayland_window_restore_shortcuts (GdkWindow *window, + GdkSeat *gdk_seat); + #endif /* __GDK_PRIVATE_WAYLAND_H__ */ diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index dbaf7e08a1..1b42371a46 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -204,6 +204,7 @@ struct _GdkWindowImplWayland } exported; struct zxdg_imported_v1 *imported_transient_for; + GHashTable *shortcuts_inhibitors; }; struct _GdkWindowImplWaylandClass @@ -668,6 +669,7 @@ _gdk_wayland_display_create_window_impl (GdkDisplay *display, impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL); window->impl = GDK_WINDOW_IMPL (impl); impl->wrapper = GDK_WINDOW (window); + impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL); if (window->width > 65535) { @@ -968,6 +970,8 @@ gdk_window_impl_wayland_finalize (GObject *object) g_clear_pointer (&impl->input_region, cairo_region_destroy); g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy); + g_hash_table_destroy (impl->shortcuts_inhibitors); + G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object); } @@ -4163,3 +4167,50 @@ gdk_wayland_window_set_transient_for_exported (GdkWindow *window, return TRUE; } + +static struct zwp_keyboard_shortcuts_inhibitor_v1 * +gdk_wayland_window_get_inhibitor (GdkWindowImplWayland *impl, + struct wl_seat *seat) +{ + return g_hash_table_lookup (impl->shortcuts_inhibitors, seat); +} + +void +gdk_wayland_window_inhibit_shortcuts (GdkWindow *window, + GdkSeat *gdk_seat) +{ + GdkWindowImplWayland *impl= GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); + struct wl_surface *surface = impl->display_server.wl_surface; + struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat); + struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor; + + if (display->keyboard_shortcuts_inhibit == NULL) + return; + + if (gdk_wayland_window_get_inhibitor (impl, seat)) + return; /* Already inhibitted */ + + inhibitor = + zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts ( + display->keyboard_shortcuts_inhibit, surface, seat); + + g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor); +} + +void +gdk_wayland_window_restore_shortcuts (GdkWindow *window, + GdkSeat *gdk_seat) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat); + struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor; + + inhibitor = gdk_wayland_window_get_inhibitor (impl, seat); + if (inhibitor == NULL) + return; /* Not inhibitted */ + + zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor); + g_hash_table_remove (impl->shortcuts_inhibitors, seat); +} + -- cgit v1.2.1