summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCameron Gutman <cameron.gutman@gmail.com>2021-01-19 18:20:07 -0600
committerCameron Gutman <cameron.gutman@gmail.com>2021-01-19 18:20:07 -0600
commit181cbb46879ade6cab5ed5290d0ce0b3c21e7a94 (patch)
tree3f38cbfa54556ab0fd2fa1db5071ccf244924bc7
parent0fdc520322ca5a9ba8e5c1f7fea843d1da34767d (diff)
downloadsdl-181cbb46879ade6cab5ed5290d0ce0b3c21e7a94.tar.gz
Implement keyboard grab support for Wayland
Use zwp_keyboard_shortcuts_inhibit_manager_v1 to allow SDL applications to capture system keyboard shortcuts like Alt+Tab when keyboard grab is enabled via SDL_HINT_GRAB_KEYBOARD.
-rw-r--r--src/video/wayland/SDL_waylandevents.c32
-rw-r--r--src/video/wayland/SDL_waylandevents_c.h3
-rw-r--r--src/video/wayland/SDL_waylandvideo.c6
-rw-r--r--src/video/wayland/SDL_waylandvideo.h1
-rw-r--r--src/video/wayland/SDL_waylandwindow.c9
-rw-r--r--src/video/wayland/SDL_waylandwindow.h1
-rw-r--r--wayland-protocols/keyboard-shortcuts-inhibit-unstable-v1.xml143
7 files changed, 193 insertions, 2 deletions
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 <linux/input.h>
@@ -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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="keyboard_shortcuts_inhibit_unstable_v1">
+
+ <copyright>
+ 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.
+ </copyright>
+
+ <description summary="Protocol for inhibiting the compositor keyboard shortcuts">
+ 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.
+ </description>
+
+ <interface name="zwp_keyboard_shortcuts_inhibit_manager_v1" version="1">
+ <description summary="context object for keyboard grab_manager">
+ A global interface used for inhibiting the compositor keyboard shortcuts.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the keyboard shortcuts inhibitor object">
+ Destroy the keyboard shortcuts inhibitor manager.
+ </description>
+ </request>
+
+ <request name="inhibit_shortcuts">
+ <description summary="create a new keyboard shortcuts inhibitor object">
+ 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.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_keyboard_shortcuts_inhibitor_v1"/>
+ <arg name="surface" type="object" interface="wl_surface"
+ summary="the surface that inhibits the keyboard shortcuts behavior"/>
+ <arg name="seat" type="object" interface="wl_seat"
+ summary="the wl_seat for which keyboard shortcuts should be disabled"/>
+ </request>
+
+ <enum name="error">
+ <entry name="already_inhibited"
+ value="0"
+ summary="the shortcuts are already inhibited for this surface"/>
+ </enum>
+ </interface>
+
+ <interface name="zwp_keyboard_shortcuts_inhibitor_v1" version="1">
+ <description summary="context object for keyboard shortcuts inhibitor">
+ 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.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the keyboard shortcuts inhibitor object">
+ Remove the keyboard shortcuts inhibitor from the associated wl_surface.
+ </description>
+ </request>
+
+ <event name="active">
+ <description summary="shortcuts are inhibited">
+ 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.
+ </description>
+ </event>
+
+ <event name="inactive">
+ <description summary="shortcuts are restored">
+ This event indicates that the shortcuts inhibitor is inactive,
+ normal shortcuts processing is restored by the compositor.
+ </description>
+ </event>
+ </interface>
+</protocol>