From a71c39b8648f000ac2b867d358205e72018bde50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
Date: Tue, 17 Apr 2018 15:51:21 +0200
Subject: [PATCH] lockscreen: limit input to shell using input-inhibitor

---
 protocol/wlr-input-inhibitor-unstable-v1.xml | 67 ++++++++++++++++++++
 src/meson.build                              |  1 +
 src/phosh.c                                  | 26 ++++++--
 3 files changed, 87 insertions(+), 7 deletions(-)
 create mode 100644 protocol/wlr-input-inhibitor-unstable-v1.xml

diff --git a/protocol/wlr-input-inhibitor-unstable-v1.xml b/protocol/wlr-input-inhibitor-unstable-v1.xml
new file mode 100644
index 0000000..b62d1bb
--- /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/src/meson.build b/src/meson.build
index 18db653..673283f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -21,6 +21,7 @@ wl_protos = [
   '/'.join([wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml']),
   '../protocol/idle.xml',
   '../protocol/phosh-mobile-shell.xml',
+  '../protocol/wlr-input-inhibitor-unstable-v1.xml',
   '../protocol/wlr-layer-shell-unstable-v1.xml',
 ]
 wl_proto_deps = []
diff --git a/src/phosh.c b/src/phosh.c
index d8022f3..63b6e2f 100644
--- a/src/phosh.c
+++ b/src/phosh.c
@@ -21,6 +21,7 @@
 #include "idle-client-protocol.h"
 #include "phosh-mobile-shell-client-protocol.h"
 #include "wlr-layer-shell-unstable-v1-client-protocol.h"
+#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
 
 #include "phosh.h"
 #include "background.h"
@@ -52,6 +53,8 @@ typedef struct
   struct phosh_mobile_shell *mshell;
   struct zwlr_layer_shell_v1 *layer_shell;
   struct org_kde_kwin_idle *idle_manager;
+  struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager;
+  struct zwlr_input_inhibitor_v1 *input_inhibitor;
   struct wl_output *output;
 
   GdkDisplay *gdk_display;
@@ -122,9 +125,9 @@ lockscreen_unlock_cb (PhoshShell *self, PhoshLockscreen *window)
   zwlr_layer_surface_v1_destroy(priv->lockscreen->layer_surface);
   g_free (priv->lockscreen);
   priv->lockscreen = NULL;
-#if 0
-  phosh_mobile_shell_unlock(priv->mshell);
-#endif
+
+  zwlr_input_inhibitor_v1_destroy(priv->input_inhibitor);
+  priv->input_inhibitor = NULL;
 }
 
 
@@ -239,6 +242,9 @@ lockscreen_create (PhoshShell *self)
   lockscreen = g_malloc0 (sizeof *lockscreen);
   lockscreen->window = phosh_lockscreen_new ();
 
+  priv->input_inhibitor =
+    zwlr_input_inhibit_manager_v1_get_inhibitor(priv->input_inhibit_manager);
+
   gdk_window = gtk_widget_get_window (lockscreen->window);
   gdk_wayland_window_set_use_custom_surface (gdk_window);
 
@@ -452,6 +458,12 @@ registry_handle_global (void *data,
 #if 0 /* FIXME: this breaks GTK+ input since GTK+ binds it as well */
     priv->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
 #endif
+  } else if (!strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name)) {
+    priv->input_inhibit_manager = wl_registry_bind(
+      registry,
+      name,
+      &zwlr_input_inhibit_manager_v1_interface,
+      1);
   }
 }
 
@@ -536,12 +548,12 @@ phosh_shell_constructed (GObject *object)
 
   /* Wait until we have been notified about the compositor,
    * shell, and shell helper objects */
-  if (!priv->output || !priv->layer_shell || !priv->idle_manager)
+  if (!priv->output || !priv->layer_shell || !priv->idle_manager || !priv->input_inhibit_manager)
     wl_display_roundtrip (priv->display);
-  if (!priv->output || !priv->layer_shell || !priv->idle_manager) {
+  if (!priv->output || !priv->layer_shell || !priv->idle_manager || !priv->input_inhibit_manager) {
       g_error ("Could not find needed globals\n"
-               "output: %p, layer_shell: %p, seat: %p\n",
-               priv->output, priv->mshell, priv->idle_manager);
+               "output: %p, layer_shell: %p, seat: %p, inhibit: %p\n",
+               priv->output, priv->mshell, priv->idle_manager, priv->input_inhibit_manager);
   }
 
   env_setup ();
-- 
GitLab