[PATCH 1/4] desktop-shell: screen locking protocol

Pekka Paalanen ppaalanen at gmail.com
Mon Nov 7 07:12:31 PST 2011


Add protocol and functions for supporting screen locking, triggered by
activity timeout.

After activity timeout, compositor starts the fade to black, and then
enters SLEEPING state. At that point it calls lock() in the shell
plugin.

When input events trigger a wakeup, unlock() in the shell plugin is
called. This sends prepare_lock_surface event to the desktop-shell
client. The screen stays locked while the compositor starts fade-in.

At this point, desktop-shell client usually creates a surface for the
unlocking GUI (e.g. a password prompt), and sends it with the
set_lock_surface request. The compositor supposedly shows and allows
interaction only with the given lock surface (not yet implemented).

When desktop-shell has authenticated the user, or instead of issuing
set_lock_surface, it sends the unlock request. Upon receiving the unlock
request, the shell plugin unlocks the screen.

If desktop-shell client dies, the screen is unlocked automatically.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 clients/desktop-shell.c    |   11 ++++++-
 compositor/compositor.c    |    3 ++
 compositor/compositor.h    |    1 +
 compositor/shell.c         |   66 ++++++++++++++++++++++++++++++++++++++++++--
 protocol/desktop-shell.xml |   12 ++++++++
 5 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index b915723..7189d02 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -277,8 +277,17 @@ desktop_shell_configure(void *data,
 	}
 }
 
+static void
+desktop_shell_prepare_lock_surface(void *data,
+				   struct desktop_shell *desktop_shell)
+{
+	/* no-op for now */
+	desktop_shell_unlock(desktop_shell);
+}
+
 static const struct desktop_shell_listener listener = {
-	desktop_shell_configure
+	desktop_shell_configure,
+	desktop_shell_prepare_lock_surface
 };
 
 static void
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 642022e..43e3040 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -1336,6 +1336,9 @@ wlsc_compositor_wake(struct wlsc_compositor *compositor)
 	if (compositor->idle_inhibit)
 		return;
 
+	if (compositor->state == WLSC_COMPOSITOR_SLEEPING)
+		compositor->shell->unlock(compositor->shell);
+
 	wlsc_compositor_fade(compositor, 0.0);
 	compositor->state = WLSC_COMPOSITOR_ACTIVE;
 
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 421b80e..9c5f73d 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -163,6 +163,7 @@ struct wlsc_shell {
 			 struct wlsc_surface *es,
 			 struct wlsc_input_device *device, uint32_t time);
 	void (*lock)(struct wlsc_shell *shell);
+	void (*unlock)(struct wlsc_shell *shell);
 	void (*attach)(struct wlsc_shell *shell, struct wlsc_surface *surface);
 	void (*set_selection_focus)(struct wlsc_shell *shell,
 				    struct wl_selection *selection,
diff --git a/compositor/shell.c b/compositor/shell.c
index 7af2d86..9c79d35 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2010 Intel Corporation
+ * Copyright © 2011 Collabora, Ltd.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation for any purpose is hereby granted without fee, provided
@@ -22,6 +23,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
 #include <linux/input.h>
@@ -44,7 +46,11 @@ struct wl_shell {
 	struct {
 		struct wlsc_process process;
 		struct wl_client *client;
+		struct wl_resource *desktop_shell;
 	} child;
+
+	bool locked;
+	bool prepare_event_sent;
 };
 
 struct wlsc_move_grab {
@@ -825,9 +831,28 @@ desktop_shell_set_panel(struct wl_client *client,
 			       output->current->height);
 }
 
+static void
+desktop_shell_set_lock_surface(struct wl_client *client,
+			       struct wl_resource *resource,
+			       struct wl_resource *surface_resource)
+{
+}
+
+static void
+desktop_shell_unlock(struct wl_client *client,
+		     struct wl_resource *resource)
+{
+	struct wl_shell *shell = resource->data;
+
+	shell->locked = false;
+	shell->prepare_event_sent = false;
+}
+
 static const struct desktop_shell_interface desktop_shell_implementation = {
 	desktop_shell_set_background,
-	desktop_shell_set_panel
+	desktop_shell_set_panel,
+	desktop_shell_set_lock_surface,
+	desktop_shell_unlock
 };
 
 static void
@@ -914,8 +939,30 @@ activate(struct wlsc_shell *base, struct wlsc_surface *es,
 }
 
 static void
-lock(struct wlsc_shell *shell)
+lock(struct wlsc_shell *base)
+{
+	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+
+	shell->locked = true;
+}
+
+static void
+unlock(struct wlsc_shell *base)
 {
+	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+
+	/* If desktop-shell client has gone away, unlock immediately. */
+	if (!shell->child.desktop_shell) {
+		shell->locked = false;
+		return;
+	}
+
+	if (shell->prepare_event_sent)
+		return;
+
+	wl_resource_post_event(shell->child.desktop_shell,
+			       DESKTOP_SHELL_PREPARE_LOCK_SURFACE);
+	shell->prepare_event_sent = true;
 }
 
 static void
@@ -1014,6 +1061,15 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 }
 
 static void
+unbind_desktop_shell(struct wl_resource *resource)
+{
+	struct wl_shell *shell = resource->data;
+	shell->child.desktop_shell = NULL;
+	shell->prepare_event_sent = false;
+	free(resource);
+}
+
+static void
 bind_desktop_shell(struct wl_client *client,
 		   void *data, uint32_t version, uint32_t id)
 {
@@ -1024,8 +1080,11 @@ bind_desktop_shell(struct wl_client *client,
 					&desktop_shell_implementation,
 					id, shell);
 
-	if (client == shell->child.client)
+	if (client == shell->child.client) {
+		resource->destroy = unbind_desktop_shell;
+		shell->child.desktop_shell = resource;
 		return;
+	}
 
 	wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
 			       "permission to bind desktop_shell denied");
@@ -1048,6 +1107,7 @@ shell_init(struct wlsc_compositor *ec, char *options)
 	shell->compositor = ec;
 	shell->shell.activate = activate;
 	shell->shell.lock = lock;
+	shell->shell.unlock = unlock;
 	shell->shell.attach = attach;
 	shell->shell.set_selection_focus = wlsc_selection_set_focus;
 
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index 438773d..d099925 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -9,6 +9,12 @@
       <arg name="surface" type="object" interface="wl_surface"/>
     </request>
 
+    <request name="set_lock_surface">
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+
+    <request name="unlock"/>
+
     <!-- We'll fold most of wl_shell into this interface and then
          they'll share the configure event.  -->
     <event name="configure">
@@ -19,6 +25,12 @@
       <arg name="height" type="int"/>
     </event>
 
+    <!-- Tell the shell we want it to create and set the lock surface,
+         which is a GUI asking the user to unlock the screen. The lock
+         surface is announced with 'set_lock_surface'. Whether or not
+         the shell actually implements locking, it MUST send 'unlock'
+         request to let the normal desktop resume. -->
+    <event name="prepare_lock_surface"/>
   </interface>
 
 </protocol>
-- 
1.7.3.4



More information about the wayland-devel mailing list