From 81f1fb934ce25567477a8deb71faf3ff4d9a9d62 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 22 Jan 2019 13:46:46 +0100 Subject: [PATCH] Implemented keyboard shortcut inhibit support. --- client/Wayland/wlfreerdp.c | 2 + uwac/include/uwac/uwac.h | 10 ++ uwac/libuwac/CMakeLists.txt | 1 + uwac/libuwac/uwac-display.c | 14 +- uwac/libuwac/uwac-input.c | 18 +++ uwac/libuwac/uwac-priv.h | 4 + uwac/libuwac/uwac-window.c | 6 +- .../keyboard-shortcuts-inhibit-unstable-v1.xml | 143 +++++++++++++++++++ uwac/protocols/xdg-decoration-unstable-v1.xml | 156 +++++++++++++++++++++ 9 files changed, 347 insertions(+), 7 deletions(-) create mode 100644 uwac/protocols/keyboard-shortcuts-inhibit-unstable-v1.xml create mode 100644 uwac/protocols/xdg-decoration-unstable-v1.xml diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 04a9c68..66f3ab1 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -273,6 +273,8 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) break; case UWAC_EVENT_KEYBOARD_ENTER: + if (instance->context->settings->GrabKeyboard) + UwacSeatInhibitShortcuts(event.keyboard_enter_leave.seat, true); if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave)) return FALSE; diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index 6a85bc7..710392a 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -494,6 +494,16 @@ UWAC_API const char *UwacSeatGetName(const UwacSeat *seat); */ UWAC_API UwacSeatId UwacSeatGetId(const UwacSeat *seat); +/** + * Inhibits or restores keyboard shortcuts. + * + * @param seat The UwacSeat to inhibit the shortcuts for + * @param inhibit Inhibit or restore keyboard shortcuts + * + * @return UWAC_SUCCESS or an appropriate error code. + */ +UWAC_API UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* seat, bool inhibit); + #ifdef __cplusplus } #endif diff --git a/uwac/libuwac/CMakeLists.txt b/uwac/libuwac/CMakeLists.txt index 255d0db..acbcb5a 100644 --- a/uwac/libuwac/CMakeLists.txt +++ b/uwac/libuwac/CMakeLists.txt @@ -39,6 +39,7 @@ endmacro() generate_protocol_file(xdg-shell) generate_protocol_file(ivi-application) generate_protocol_file(fullscreen-shell-unstable-v1) +generate_protocol_file(keyboard-shortcuts-inhibit-unstable-v1) if(FREEBSD) include_directories(${EPOLLSHIM_INCLUDE_DIR}) diff --git a/uwac/libuwac/uwac-display.c b/uwac/libuwac/uwac-display.c index ac2b49a..638aa1e 100644 --- a/uwac/libuwac/uwac-display.c +++ b/uwac/libuwac/uwac-display.c @@ -215,21 +215,25 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin { d->xdg_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); xdg_wm_base_add_listener(d->xdg_base, &xdg_wm_base_listener, d); -#if BUILD_IVI } + else if (strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) + { + d->keyboard_inhibit_manager = wl_registry_bind(registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1); + } +#if BUILD_IVI else if (strcmp(interface, "ivi_application") == 0) { d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1); + } #endif #if BUILD_FULLSCREEN_SHELL - } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) { d->fullscreen_shell = wl_registry_bind(registry, id, &zwp_fullscreen_shell_v1_interface, 1); zwp_fullscreen_shell_v1_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d); + } #endif #if 0 - } else if (strcmp(interface, "text_cursor_position") == 0) { d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1); @@ -242,7 +246,6 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin { d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1); #endif - } } static void registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) @@ -512,6 +515,9 @@ UwacReturnCode UwacCloseDisplay(UwacDisplay** pdisplay) if (display->compositor) wl_compositor_destroy(display->compositor); + if (display->keyboard_inhibit_manager) + zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(display->keyboard_inhibit_manager); + #ifdef BUILD_FULLSCREEN_SHELL if (display->fullscreen_shell) diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 16edb4b..5adb62d 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -130,6 +130,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint return; event->window = input->keyboard_focus = (UwacWindow *)wl_surface_get_user_data(surface); + event->seat = input; /* look for keys that have been released */ found = false; @@ -819,6 +820,7 @@ error_xkb_context: } void UwacSeatDestroy(UwacSeat *s) { + UwacSeatInhibitShortcuts(s, false); if (s->seat) { #ifdef WL_SEAT_RELEASE_SINCE_VERSION if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION) @@ -873,3 +875,19 @@ const char *UwacSeatGetName(const UwacSeat *seat) { UwacSeatId UwacSeatGetId(const UwacSeat *seat) { return seat->seat_id; } + +UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit) +{ + if (!s) + return UWAC_ERROR_CLOSED; + + if (s->keyboard_inhibitor) + zwp_keyboard_shortcuts_inhibitor_v1_destroy(s->keyboard_inhibitor); + if (inhibit && s->display && s->display->keyboard_inhibit_manager) + s->keyboard_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(s->display->keyboard_inhibit_manager, + s->keyboard_focus->surface, s->seat); + + if (!s->keyboard_inhibitor) + return UWAC_ERROR_INTERNAL; + return UWAC_SUCCESS; +} diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index a30c0cb..655c12f 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -28,6 +28,8 @@ #include #include #include "xdg-shell-client-protocol.h" +#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" + #ifdef BUILD_IVI #include "ivi-application-client-protocol.h" #endif @@ -86,6 +88,7 @@ struct uwac_display { struct wl_shell *shell; struct xdg_toplevel *xdg_toplevel; struct xdg_wm_base *xdg_base; + struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_inhibit_manager; #ifdef BUILD_IVI struct ivi_application *ivi_application; #endif @@ -151,6 +154,7 @@ struct uwac_seat { struct wl_keyboard *keyboard; struct wl_touch *touch; struct xkb_context *xkb_context; + struct zwp_keyboard_shortcuts_inhibitor_v1 *keyboard_inhibitor; struct { struct xkb_keymap *keymap; diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index 04927fc..694ac12 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -449,22 +449,22 @@ UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t h assert(w->xdg_surface); xdg_toplevel_add_listener(w->xdg_toplevel, &xdg_toplevel_listener, w); -#if BUILD_IVI } +#if BUILD_IVI else if (display->ivi_application) { w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface); assert(w->ivi_surface); ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w); + } #endif #if BUILD_FULLSCREEN_SHELL - } else if (display->fullscreen_shell) { zwp_fullscreen_shell_v1_present_surface(display->fullscreen_shell, w->surface, ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER, NULL); -#endif } +#endif else { w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface); diff --git a/uwac/protocols/keyboard-shortcuts-inhibit-unstable-v1.xml b/uwac/protocols/keyboard-shortcuts-inhibit-unstable-v1.xml new file mode 100644 index 0000000..2774876 --- /dev/null +++ b/uwac/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. + + + + diff --git a/uwac/protocols/xdg-decoration-unstable-v1.xml b/uwac/protocols/xdg-decoration-unstable-v1.xml new file mode 100644 index 0000000..378e8ff --- /dev/null +++ b/uwac/protocols/xdg-decoration-unstable-v1.xml @@ -0,0 +1,156 @@ + + + + Copyright © 2018 Simon Ser + + 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 interface allows a compositor to announce support for server-side + decorations. + + A window decoration is a set of window controls as deemed appropriate by + the party managing them, such as user interface components used to move, + resize and change a window's state. + + A client can use this protocol to request being decorated by a supporting + compositor. + + If compositor and client do not negotiate the use of a server-side + decoration using this protocol, clients continue to self-decorate as they + see fit. + + 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. + + + + + Destroy the decoration manager. This doesn't destroy objects created + with the manager. + + + + + + Create a new decoration object associated with the given toplevel. + + Creating an xdg_toplevel_decoration from an xdg_toplevel which has a + buffer attached or committed is a client error, and any attempts by a + client to attach or manipulate a buffer prior to the first + xdg_toplevel_decoration.configure event must also be treated as + errors. + + + + + + + + + The decoration object allows the compositor to toggle server-side window + decorations for a toplevel surface. The client can request to switch to + another mode. + + The xdg_toplevel_decoration object must be destroyed before its + xdg_toplevel. + + + + + + + + + + + Switch back to a mode without any server-side decorations at the next + commit. + + + + + + These values describe window decoration modes. + + + + + + + + Set the toplevel surface decoration mode. This informs the compositor + that the client prefers the provided decoration mode. + + After requesting a decoration mode, the compositor will respond by + emitting a xdg_surface.configure event. The client should then update + its content, drawing it without decorations if the received mode is + server-side decorations. The client must also acknowledge the configure + when committing the new content (see xdg_surface.ack_configure). + + The compositor can decide not to use the client's mode and enforce a + different mode instead. + + Clients whose decoration mode depend on the xdg_toplevel state may send + a set_mode request in response to a xdg_surface.configure event and wait + for the next xdg_surface.configure event to prevent unwanted state. + Such clients are responsible for preventing configure loops and must + make sure not to send multiple successive set_mode requests with the + same decoration mode. + + + + + + + Unset the toplevel surface decoration mode. This informs the compositor + that the client doesn't prefer a particular decoration mode. + + This request has the same semantics as set_mode. + + + + + + The configure event asks the client to change its decoration mode. The + configured state should not be applied immediately. Clients must send an + ack_configure in response to this event. See xdg_surface.configure and + xdg_surface.ack_configure for details. + + A configure event can be sent at any time. The specified mode must be + obeyed by the client. + + + + + -- 2.7.4