Implement the keyboard shortcuts inhibitor protocol
parent
1ca82ce2e2
commit
4fc5eb6d06
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "keyboard-shortcuts-inhibit-unstable-v1.h"
|
||||
|
||||
struct shortcuts_inhibitor {
|
||||
//TODO add the inhibitor toggle key to the struct ?
|
||||
struct zwp_keyboard_shortcuts_inhibit_manager_v1* manager;
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1* inhibitor;
|
||||
|
||||
struct wl_surface* surface;
|
||||
struct wl_seat* seat;
|
||||
};
|
||||
|
||||
struct shortcuts_inhibitor* inhibitor_new(struct zwp_keyboard_shortcuts_inhibit_manager_v1*);
|
||||
void inhibitor_destroy(struct shortcuts_inhibitor*);
|
||||
bool inhibitor_init(struct shortcuts_inhibitor*, struct wl_surface*, struct wl_seat*);
|
||||
|
||||
bool inhibitor_is_inhibited(const struct shortcuts_inhibitor*);
|
||||
void inhibitor_inhibit(struct shortcuts_inhibitor*);
|
||||
void inhibitor_release(struct shortcuts_inhibitor*);
|
||||
void inhibitor_toggle(struct shortcuts_inhibitor*);
|
|
@ -69,6 +69,7 @@ sources = [
|
|||
'src/vnc.c',
|
||||
'src/strlcpy.c',
|
||||
'src/evdev-to-qnum.c',
|
||||
'src/inhibitor.c',
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
|
|
|
@ -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>
|
|
@ -15,6 +15,7 @@ wayland_scanner_client = generator(
|
|||
|
||||
client_protocols = [
|
||||
'xdg-shell.xml',
|
||||
'keyboard-shortcuts-inhibit-unstable-v1.xml',
|
||||
]
|
||||
|
||||
client_protos_src = []
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "inhibitor.h"
|
||||
#include <stdio.h>
|
||||
|
||||
struct shortcuts_inhibitor* inhibitor_new(struct zwp_keyboard_shortcuts_inhibit_manager_v1* manager)
|
||||
{
|
||||
struct shortcuts_inhibitor* self = calloc(1, sizeof(*self));
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
self->manager = manager;
|
||||
self->inhibitor = NULL;
|
||||
self->surface = NULL;
|
||||
self->seat = NULL;
|
||||
return self;
|
||||
}
|
||||
|
||||
bool inhibitor_init(struct shortcuts_inhibitor* self, struct wl_surface* surface,
|
||||
struct wl_seat* seat)
|
||||
{
|
||||
if ( self->surface != NULL || self->seat != NULL)
|
||||
return false;
|
||||
|
||||
self->surface = surface;
|
||||
self->seat = seat;
|
||||
return true;
|
||||
}
|
||||
|
||||
void inhibitor_destroy(struct shortcuts_inhibitor* self)
|
||||
{
|
||||
if (self->inhibitor)
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy(self->inhibitor);
|
||||
if (self->manager)
|
||||
zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(self->manager);
|
||||
}
|
||||
|
||||
bool inhibitor_is_inhibited(const struct shortcuts_inhibitor* self)
|
||||
{
|
||||
return self->inhibitor != NULL;
|
||||
}
|
||||
|
||||
void inhibitor_inhibit(struct shortcuts_inhibitor* self)
|
||||
{
|
||||
// The compositor does not support the wlr shortcuts inhibitor protocol
|
||||
if (self->manager == NULL)
|
||||
return;
|
||||
if (!inhibitor_is_inhibited(self))
|
||||
self->inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(
|
||||
self->manager, self->surface, self->seat);
|
||||
}
|
||||
|
||||
void inhibitor_release(struct shortcuts_inhibitor* self)
|
||||
{
|
||||
if (inhibitor_is_inhibited(self)) {
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy(self->inhibitor);
|
||||
self->inhibitor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void inhibitor_toggle(struct shortcuts_inhibitor* self)
|
||||
{
|
||||
if (inhibitor_is_inhibited(self)) {
|
||||
inhibitor_release(self);
|
||||
} else {
|
||||
inhibitor_inhibit(self);
|
||||
}
|
||||
}
|
19
src/main.c
19
src/main.c
|
@ -29,6 +29,7 @@
|
|||
#include <wayland-client.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include "inhibitor.h"
|
||||
#include "pixman.h"
|
||||
#include "xdg-shell.h"
|
||||
#include "shm.h"
|
||||
|
@ -61,8 +62,10 @@ struct wl_compositor* wl_compositor = NULL;
|
|||
struct wl_shm* wl_shm = NULL;
|
||||
static struct xdg_wm_base* xdg_wm_base;
|
||||
static struct wl_list seats;
|
||||
static struct zwp_keyboard_shortcuts_inhibit_manager_v1* keyboard_shortcuts_inhibitor;
|
||||
struct pointer_collection* pointers;
|
||||
struct keyboard_collection* keyboards;
|
||||
struct shortcuts_inhibitor* inhibitor;
|
||||
|
||||
static enum wl_shm_format wl_shm_format;
|
||||
static bool have_format = false;
|
||||
|
@ -103,6 +106,10 @@ static void registry_add(void* data, struct wl_registry* registry, uint32_t id,
|
|||
xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
|
||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||
wl_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) == 0) {
|
||||
keyboard_shortcuts_inhibitor = wl_registry_bind(registry, id,
|
||||
&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
|
||||
inhibitor = inhibitor_new(keyboard_shortcuts_inhibitor);
|
||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||
struct wl_seat* wl_seat;
|
||||
wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, 5);
|
||||
|
@ -312,6 +319,7 @@ static void xdg_surface_configure(void* data, struct xdg_surface* surface,
|
|||
struct window* w = data;
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
window_configure(w);
|
||||
inhibitor_init(inhibitor, w->wl_surface, seat_first(&seats)->wl_seat);
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
|
@ -436,6 +444,17 @@ void on_keyboard_event(struct keyboard_collection* collection,
|
|||
// TODO handle multiple symbols
|
||||
xkb_keysym_t symbol = xkb_state_key_get_one_sym(keyboard->state, key);
|
||||
|
||||
if (symbol == XKB_KEY_F12) {
|
||||
if (!is_pressed) {
|
||||
inhibitor_toggle(inhibitor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (inhibitor->manager != NULL && !inhibitor_is_inhibited(inhibitor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char name[256];
|
||||
xkb_keysym_get_name(symbol, name, sizeof(name));
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
#include <wayland-cursor.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
#include "inhibitor.h"
|
||||
#include "pointer.h"
|
||||
|
||||
#define STEP_SIZE 15.0
|
||||
|
||||
extern struct wl_shm* wl_shm;
|
||||
extern struct wl_compositor* wl_compositor;
|
||||
extern struct shortcuts_inhibitor* inhibitor;
|
||||
|
||||
static struct wl_cursor_theme* pointer_load_cursor_theme(void)
|
||||
{
|
||||
|
@ -69,6 +71,7 @@ void pointer_destroy(struct pointer* self)
|
|||
if (self->cursor_theme)
|
||||
wl_cursor_theme_destroy(self->cursor_theme);
|
||||
wl_surface_destroy(self->cursor_surface);
|
||||
inhibitor_destroy(inhibitor);
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
@ -162,6 +165,7 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer,
|
|||
pointer->serial = serial;
|
||||
|
||||
pointer_update_cursor(pointer);
|
||||
inhibitor_inhibit(inhibitor);
|
||||
}
|
||||
|
||||
static void pointer_leave(void* data, struct wl_pointer* wl_pointer,
|
||||
|
@ -173,8 +177,7 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer,
|
|||
assert(pointer);
|
||||
|
||||
pointer->serial = serial;
|
||||
|
||||
// Do nothing?
|
||||
inhibitor_release(inhibitor);
|
||||
}
|
||||
|
||||
static void pointer_motion(void* data, struct wl_pointer* wl_pointer,
|
||||
|
|
Loading…
Reference in New Issue