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.
This commit is contained in:
Cameron Gutman
2021-01-19 18:20:07 -06:00
parent 6e97170e96
commit d789ba8332
7 changed files with 193 additions and 2 deletions

View File

@@ -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: */

View File

@@ -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: */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;