aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_input_inhibitor.h25
-rw-r--r--protocol/meson.build2
-rw-r--r--protocol/wlr-input-inhibitor-unstable-v1.xml67
-rw-r--r--types/meson.build1
-rw-r--r--types/wlr_input_inhibitor.c130
5 files changed, 225 insertions, 0 deletions
diff --git a/include/wlr/types/wlr_input_inhibitor.h b/include/wlr/types/wlr_input_inhibitor.h
new file mode 100644
index 00000000..4416c18f
--- /dev/null
+++ b/include/wlr/types/wlr_input_inhibitor.h
@@ -0,0 +1,25 @@
+#ifndef WLR_TYPES_INPUT_INHIBITOR_H
+#define WLR_TYPES_INPUT_INHIBITOR_H
+#include <wayland-server.h>
+
+struct wlr_input_inhibit_manager {
+ struct wl_global *wl_global;
+ struct wl_client *active_client;
+ struct wl_resource *active_inhibitor;
+
+ struct wl_listener display_destroy;
+
+ struct {
+ struct wl_signal activate; // struct wlr_input_inhibit_manager *
+ struct wl_signal deactivate; // struct wlr_input_inhibit_manager *
+ } events;
+
+ void *data;
+};
+
+struct wlr_input_inhibit_manager *wlr_input_inhibit_manager_create(
+ struct wl_display *display);
+void wlr_input_inhibit_manager_destroy(
+ struct wlr_input_inhibit_manager *manager);
+
+#endif
diff --git a/protocol/meson.build b/protocol/meson.build
index a41fdec3..b88b4b77 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -31,6 +31,7 @@ protocols = [
'screenshooter.xml',
'server-decoration.xml',
'wlr-layer-shell-unstable-v1.xml',
+ 'wlr-input-inhibitor-unstable-v1.xml',
]
client_protocols = [
@@ -40,6 +41,7 @@ client_protocols = [
'idle.xml',
'screenshooter.xml',
'wlr-layer-shell-unstable-v1.xml',
+ 'wlr-input-inhibitor-unstable-v1.xml',
]
wl_protos_src = []
diff --git a/protocol/wlr-input-inhibitor-unstable-v1.xml b/protocol/wlr-input-inhibitor-unstable-v1.xml
new file mode 100644
index 00000000..b62d1bb4
--- /dev/null
+++ b/protocol/wlr-input-inhibitor-unstable-v1.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_input_inhibit_unstable_v1">
+ <copyright>
+ Copyright © 2018 Drew DeVault
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="zwlr_input_inhibit_manager_v1" version="1">
+ <description summary="inhibits input events to other clients">
+ Clients can use this interface to prevent input events from being sent to
+ any surfaces but its own, which is useful for example in lock screen
+ software. It is assumed that access to this interface will be locked down
+ to whitelisted clients by the compositor.
+ </description>
+
+ <request name="get_inhibitor">
+ <description summary="inhibit input to other clients">
+ Activates the input inhibitor. As long as the inhibitor is active, the
+ compositor will not send input events to other clients.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_input_inhibitor_v1"/>
+ </request>
+
+ <enum name="error">
+ <entry name="already_inhibited" value="0" summary="an input inhibitor is already in use on the compositor"/>
+ </enum>
+ </interface>
+
+ <interface name="zwlr_input_inhibitor_v1" version="1">
+ <description summary="inhibits input to other clients">
+ While this resource exists, input to clients other than the owner of the
+ inhibitor resource will not receive input events. The client that owns
+ this resource will receive all input events normally. The compositor will
+ also disable all of its own input processing (such as keyboard shortcuts)
+ while the inhibitor is active.
+
+ The compositor may continue to send input events to selected clients,
+ such as an on-screen keyboard (via the input-method protocol).
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the input inhibitor object">
+ Destroy the inhibitor and allow other clients to receive input.
+ </description>
+ </request>
+ </interface>
+</protocol>
diff --git a/types/meson.build b/types/meson.build
index 198563b1..eda5f4e4 100644
--- a/types/meson.build
+++ b/types/meson.build
@@ -10,6 +10,7 @@ lib_wlr_types = static_library(
'wlr_idle.c',
'wlr_idle_inhibit_v1.c',
'wlr_input_device.c',
+ 'wlr_input_inhibitor.c',
'wlr_keyboard.c',
'wlr_layer_shell.c',
'wlr_linux_dmabuf.c',
diff --git a/types/wlr_input_inhibitor.c b/types/wlr_input_inhibitor.c
new file mode 100644
index 00000000..d42a5c0c
--- /dev/null
+++ b/types/wlr_input_inhibitor.c
@@ -0,0 +1,130 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include "wlr/types/wlr_input_inhibitor.h"
+#include "wlr-input-inhibitor-unstable-v1-protocol.h"
+
+static const struct zwlr_input_inhibit_manager_v1_interface inhibit_manager_implementation;
+
+static struct wlr_input_inhibit_manager *input_inhibit_manager_from_resource(
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource, &zwlr_input_inhibit_manager_v1_interface,
+ &inhibit_manager_implementation));
+ return wl_resource_get_user_data(resource);
+}
+
+static void input_inhibitor_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_input_inhibit_manager *manager =
+ input_inhibit_manager_from_resource(resource);
+ manager->active_client = NULL;
+ manager->active_inhibitor = NULL;
+ wl_resource_destroy(resource);
+ wl_signal_emit(&manager->events.deactivate, manager);
+}
+
+static struct zwlr_input_inhibitor_v1_interface input_inhibitor_implementation = {
+ .destroy = input_inhibitor_destroy,
+};
+
+static void inhibit_manager_get_inhibitor(struct wl_client *client,
+ struct wl_resource *resource, uint32_t id) {
+ struct wlr_input_inhibit_manager *manager =
+ input_inhibit_manager_from_resource(resource);
+ if (manager->active_client || manager->active_inhibitor) {
+ wl_resource_post_error(resource,
+ ZWLR_INPUT_INHIBIT_MANAGER_V1_ERROR_ALREADY_INHIBITED,
+ "this compositor already has input inhibited");
+ return;
+ }
+
+ struct wl_resource *wl_resource = wl_resource_create(client,
+ &zwlr_input_inhibitor_v1_interface,
+ wl_resource_get_version(resource), id);
+ if (!wl_resource) {
+ wl_client_post_no_memory(client);
+ }
+ wl_resource_set_implementation(wl_resource, &input_inhibitor_implementation,
+ manager, NULL);
+
+ manager->active_client = client;
+ manager->active_inhibitor = wl_resource;
+
+ wl_signal_emit(&manager->events.activate, manager);
+}
+
+static const struct zwlr_input_inhibit_manager_v1_interface inhibit_manager_implementation = {
+ .get_inhibitor = inhibit_manager_get_inhibitor
+};
+
+static void input_manager_client_destroy(struct wl_resource *resource) {
+ struct wlr_input_inhibit_manager *manager =
+ input_inhibit_manager_from_resource(resource);
+ if (manager->active_client == wl_resource_get_client(resource)) {
+ input_inhibitor_destroy(manager->active_client, resource);
+ }
+}
+
+static void inhibit_manager_bind(struct wl_client *wl_client, void *data,
+ uint32_t version, uint32_t id) {
+ struct wlr_input_inhibit_manager *manager = data;
+ assert(wl_client && manager);
+
+ struct wl_resource *wl_resource = wl_resource_create(wl_client,
+ &zwlr_input_inhibit_manager_v1_interface, version, id);
+ if (wl_resource == NULL) {
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+ wl_resource_set_implementation(wl_resource,
+ &inhibit_manager_implementation, manager,
+ input_manager_client_destroy);
+}
+
+void wlr_input_inhibit_manager_destroy(
+ struct wlr_input_inhibit_manager *manager) {
+ if (!manager) {
+ return;
+ }
+ if (manager->active_client) {
+ input_inhibitor_destroy(manager->active_client,
+ manager->active_inhibitor);
+ }
+ wl_list_remove(&manager->display_destroy.link);
+ wl_global_destroy(manager->wl_global);
+ free(manager);
+}
+
+static void handle_display_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_input_inhibit_manager *manager =
+ wl_container_of(listener, manager, display_destroy);
+ wlr_input_inhibit_manager_destroy(manager);
+}
+
+struct wlr_input_inhibit_manager *wlr_input_inhibit_manager_create(
+ struct wl_display *display) {
+ // TODO: Client destroy
+ struct wlr_input_inhibit_manager *manager =
+ calloc(1, sizeof(struct wlr_input_inhibit_manager));
+ if (!manager) {
+ return NULL;
+ }
+
+ manager->wl_global = wl_global_create(display,
+ &zwlr_input_inhibit_manager_v1_interface,
+ 1, manager, inhibit_manager_bind);
+ if (manager->wl_global == NULL){
+ wl_list_remove(&manager->display_destroy.link);
+ free(manager);
+ return NULL;
+ }
+
+ wl_signal_init(&manager->events.activate);
+ wl_signal_init(&manager->events.deactivate);
+
+ manager->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &manager->display_destroy);
+
+ return manager;
+}