From 9ef3e012d61acf71aa495b09f0534857c7695b7e Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Tue, 15 Nov 2011 13:34:48 +0200 Subject: [PATCH] desktop-shell: screen locking protocol 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 --- clients/desktop-shell.c | 11 +++++- compositor/compositor.c | 3 ++ compositor/compositor.h | 1 + compositor/shell.c | 71 ++++++++++++++++++++++++++++++++++++-- compositor/tablet-shell.c | 6 ++++ protocol/desktop-shell.xml | 12 +++++++ 6 files changed, 100 insertions(+), 4 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index d1b1d7d4..b437ed8c 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -311,8 +311,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 eab0a373..bba12e5c 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -1334,6 +1334,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 50ccdb57..12820bf6 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -162,6 +162,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 (*map)(struct wlsc_shell *shell, struct wlsc_surface *surface, int32_t width, int32_t height); void (*configure)(struct wlsc_shell *shell, diff --git a/compositor/shell.c b/compositor/shell.c index 19362356..9d22cde3 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 #include +#include #include #include #include @@ -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 { @@ -818,9 +824,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 @@ -907,8 +932,35 @@ 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 (!shell->locked) { + wlsc_compositor_wake(shell->compositor); + return; + } + + /* 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 +1066,15 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) &shell_interface, id, shell); } +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) @@ -1025,8 +1086,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"); @@ -1049,6 +1113,7 @@ shell_init(struct wlsc_compositor *ec) shell->compositor = ec; shell->shell.activate = activate; shell->shell.lock = lock; + shell->shell.unlock = unlock; shell->shell.map = map; shell->shell.configure = configure; shell->shell.set_selection_focus = wlsc_selection_set_focus; diff --git a/compositor/tablet-shell.c b/compositor/tablet-shell.c index 504adc07..21786a2c 100644 --- a/compositor/tablet-shell.c +++ b/compositor/tablet-shell.c @@ -553,6 +553,11 @@ tablet_shell_lock(struct wlsc_shell *base) tablet_shell_set_state(shell, STATE_LOCKED); } +static void +tablet_shell_unlock(struct wlsc_shell *base) +{ +} + static void go_home(struct tablet_shell *shell) { @@ -687,6 +692,7 @@ shell_init(struct wlsc_compositor *compositor) compositor->shell = &shell->shell; shell->shell.lock = tablet_shell_lock; + shell->shell.unlock = tablet_shell_unlock; shell->shell.map = tablet_shell_map; shell->shell.configure = tablet_shell_configure; shell->shell.set_selection_focus = diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml index 438773dd..d099925f 100644 --- a/protocol/desktop-shell.xml +++ b/protocol/desktop-shell.xml @@ -9,6 +9,12 @@ + + + + + + @@ -19,6 +25,12 @@ + +