diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 691eab02a..0030166f0 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -41,6 +41,7 @@ #include "relative-pointer-unstable-v1-client-protocol.h" #include "xdg-shell-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h" +#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" #ifdef SDL_INPUT_LINUXEV #include @@ -1418,6 +1419,37 @@ int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input) return 0; } +int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input) +{ + SDL_WindowData *w = window->driverdata; + SDL_VideoData *d = input->display; + + if (!d->key_inhibitor_manager) + return -1; + + if (w->key_inhibitor) + return 0; + + w->key_inhibitor = + zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(d->key_inhibitor_manager, + w->surface, + input->seat); + + return 0; +} + +int Wayland_input_ungrab_keyboard(SDL_Window *window) +{ + SDL_WindowData *w = window->driverdata; + + if (w->key_inhibitor) { + zwp_keyboard_shortcuts_inhibitor_v1_destroy(w->key_inhibitor); + w->key_inhibitor = NULL; + } + + return 0; +} + #endif /* SDL_VIDEO_DRIVER_WAYLAND */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index a69940a7c..74ea24c5f 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -49,6 +49,9 @@ extern int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input); extern void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id); extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d); +extern int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input); +extern int Wayland_input_ungrab_keyboard(SDL_Window *window); + #endif /* SDL_waylandevents_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 2fc8297c1..73f181a1f 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -49,6 +49,7 @@ #include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h" #include "org-kde-kwin-server-decoration-manager-client-protocol.h" +#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" #define WAYLANDVID_DRIVER_NAME "wayland" @@ -393,6 +394,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id, Wayland_display_add_relative_pointer_manager(d, id); } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) { Wayland_display_add_pointer_constraints(d, id); + } else if (strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) { + d->key_inhibitor_manager = wl_registry_bind(d->registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1); } else if (strcmp(interface, "wl_data_device_manager") == 0) { d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version)); } else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) { @@ -493,6 +496,9 @@ Wayland_VideoQuit(_THIS) Wayland_display_destroy_pointer_constraints(data); Wayland_display_destroy_relative_pointer_manager(data); + if (data->key_inhibitor_manager) + zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(data->key_inhibitor_manager); + if (data->xkb_context) { WAYLAND_xkb_context_unref(data->xkb_context); data->xkb_context = NULL; diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index d5ab08164..99e3c019c 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -64,6 +64,7 @@ typedef struct { struct wl_data_device_manager *data_device_manager; struct zxdg_decoration_manager_v1 *decoration_manager; struct org_kde_kwin_server_decoration_manager *kwin_server_decoration_manager; + struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager; EGLDisplay edpy; EGLContext context; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index f776f2684..89fb40328 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -636,10 +636,15 @@ Wayland_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; - if (grabbed) + if (grabbed) { Wayland_input_confine_pointer(window, data->input); - else + + if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) + Wayland_input_grab_keyboard(window, data->input); + } else { + Wayland_input_ungrab_keyboard(window); Wayland_input_unconfine_pointer(data->input); + } } int Wayland_CreateWindow(_THIS, SDL_Window *window) diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index d9cd7999a..6e3306255 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -65,6 +65,7 @@ typedef struct { struct zwp_locked_pointer_v1 *locked_pointer; struct zxdg_toplevel_decoration_v1 *server_decoration; struct org_kde_kwin_server_decoration *kwin_server_decoration; + struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor; #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH struct qt_extended_surface *extended_surface; diff --git a/wayland-protocols/keyboard-shortcuts-inhibit-unstable-v1.xml b/wayland-protocols/keyboard-shortcuts-inhibit-unstable-v1.xml new file mode 100644 index 000000000..27748764d --- /dev/null +++ b/wayland-protocols/keyboard-shortcuts-inhibit-unstable-v1.xml @@ -0,0 +1,143 @@ + + + + + Copyright © 2017 Red Hat Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol specifies a way for a client to request the compositor + to ignore its own keyboard shortcuts for a given seat, so that all + key events from that seat get forwarded to a surface. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible + changes may be added together with the corresponding interface + version bump. + Backward incompatible changes are done by bumping the version + number in the protocol and interface names and resetting the + interface version. Once the protocol is to be declared stable, + the 'z' prefix and the version number in the protocol and + interface names are removed and the interface version number is + reset. + + + + + A global interface used for inhibiting the compositor keyboard shortcuts. + + + + + Destroy the keyboard shortcuts inhibitor manager. + + + + + + Create a new keyboard shortcuts inhibitor object associated with + the given surface for the given seat. + + If shortcuts are already inhibited for the specified seat and surface, + a protocol error "already_inhibited" is raised by the compositor. + + + + + + + + + + + + + + A keyboard shortcuts inhibitor instructs the compositor to ignore + its own keyboard shortcuts when the associated surface has keyboard + focus. As a result, when the surface has keyboard focus on the given + seat, it will receive all key events originating from the specified + seat, even those which would normally be caught by the compositor for + its own shortcuts. + + The Wayland compositor is however under no obligation to disable + all of its shortcuts, and may keep some special key combo for its own + use, including but not limited to one allowing the user to forcibly + restore normal keyboard events routing in the case of an unwilling + client. The compositor may also use the same key combo to reactivate + an existing shortcut inhibitor that was previously deactivated on + user request. + + When the compositor restores its own keyboard shortcuts, an + "inactive" event is emitted to notify the client that the keyboard + shortcuts inhibitor is not effectively active for the surface and + seat any more, and the client should not expect to receive all + keyboard events. + + When the keyboard shortcuts inhibitor is inactive, the client has + no way to forcibly reactivate the keyboard shortcuts inhibitor. + + The user can chose to re-enable a previously deactivated keyboard + shortcuts inhibitor using any mechanism the compositor may offer, + in which case the compositor will send an "active" event to notify + the client. + + If the surface is destroyed, unmapped, or loses the seat's keyboard + focus, the keyboard shortcuts inhibitor becomes irrelevant and the + compositor will restore its own keyboard shortcuts but no "inactive" + event is emitted in this case. + + + + + Remove the keyboard shortcuts inhibitor from the associated wl_surface. + + + + + + This event indicates that the shortcut inhibitor is active. + + The compositor sends this event every time compositor shortcuts + are inhibited on behalf of the surface. When active, the client + may receive input events normally reserved by the compositor + (see zwp_keyboard_shortcuts_inhibitor_v1). + + This occurs typically when the initial request "inhibit_shortcuts" + first becomes active or when the user instructs the compositor to + re-enable and existing shortcuts inhibitor using any mechanism + offered by the compositor. + + + + + + This event indicates that the shortcuts inhibitor is inactive, + normal shortcuts processing is restored by the compositor. + + + +