mirror of
https://github.com/swaywm/sway.git
synced 2024-12-25 14:36:23 +01:00
WIP: add protocol for clients to request to be shown over the lock screen
This commit is contained in:
parent
fdc4318ac6
commit
d87ce180b3
13 changed files with 211 additions and 19 deletions
|
@ -13,6 +13,7 @@ struct sway_layer_surface {
|
|||
struct wl_listener node_destroy;
|
||||
struct wl_listener new_popup;
|
||||
|
||||
bool show_over_lockscreen;
|
||||
bool mapped;
|
||||
|
||||
struct wlr_scene_tree *popups;
|
||||
|
|
4
include/sway/lockscreen-overlay.h
Normal file
4
include/sway/lockscreen-overlay.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include <wayland-server-core.h>
|
||||
|
||||
struct sway_lockscreen_overlay;
|
||||
struct sway_lockscreen_overlay *sway_lockscreen_overlay_create(struct wl_display *display);
|
|
@ -97,6 +97,8 @@ struct sway_server {
|
|||
struct wl_listener manager_destroy;
|
||||
} session_lock;
|
||||
|
||||
struct sway_lockscreen_overlay *lockscreen_overlay;
|
||||
|
||||
struct wlr_output_power_manager_v1 *output_power_manager_v1;
|
||||
struct wl_listener output_power_manager_set_mode;
|
||||
struct wlr_input_method_manager_v2 *input_method;
|
||||
|
|
38
protocols/kde-lockscreen-overlay-v1.xml
Normal file
38
protocols/kde-lockscreen-overlay-v1.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="kde_lockscreen_overlay_v1">
|
||||
<copyright><![CDATA[
|
||||
SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
]]></copyright>
|
||||
|
||||
<interface name="kde_lockscreen_overlay_v1" version="1">
|
||||
<description summary="Allow surfaces over the lockscreen">
|
||||
Allows a client to request a surface to be visible when the system is locked.
|
||||
|
||||
This is meant to be used for specific high urgency cases like phone calls or alarms.
|
||||
|
||||
Warning! The protocol described in this file is a desktop environment
|
||||
implementation detail. Regular clients must not use this protocol.
|
||||
Backward incompatible changes may be added without bumping the major
|
||||
version of the extension.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_surface_state" value="0" summary="the client provided an invalid surface state"/>
|
||||
</enum>
|
||||
|
||||
<request name="allow">
|
||||
<description summary="Tell about which surface could be raised above the lockscreen">
|
||||
Informs the compositor that the surface could be shown when the screen is locked. This request should be called while the surface is unmapped.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="Destroy the kde_lockscreen_overlay_v1">
|
||||
This won't affect the surface previously marked with the allow request.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -18,6 +18,7 @@ protocols = [
|
|||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'idle.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
'kde-lockscreen-overlay-v1.xml',
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/layers.h"
|
||||
#include "sway/lock.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
|
@ -54,7 +55,7 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
|
|||
}
|
||||
|
||||
static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
|
||||
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) {
|
||||
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive, bool locked) {
|
||||
struct wlr_scene_node *node;
|
||||
wl_list_for_each(node, &tree->children, link) {
|
||||
struct sway_layer_surface *surface = scene_descriptor_try_get(node,
|
||||
|
@ -64,6 +65,17 @@ static void arrange_surface(struct sway_output *output, const struct wlr_box *fu
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!surface->show_over_lockscreen) {
|
||||
wlr_scene_node_set_enabled(node, !locked);
|
||||
/* wlr_scene_node_set_enabled(node, true); */
|
||||
if (locked) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// TODO: not sure why this is required
|
||||
wlr_scene_node_set_enabled(node, true);
|
||||
}
|
||||
|
||||
if (!surface->scene->layer_surface->initialized) {
|
||||
continue;
|
||||
}
|
||||
|
@ -82,19 +94,26 @@ void arrange_layers(struct sway_output *output) {
|
|||
&usable_area.width, &usable_area.height);
|
||||
const struct wlr_box full_area = usable_area;
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true);
|
||||
bool locked = server.session_lock.lock;
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false);
|
||||
if (locked) {
|
||||
sway_log(SWAY_INFO, "arranging locked layout");
|
||||
}
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true, locked);
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false, locked);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false, locked);
|
||||
|
||||
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
|
||||
sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
|
||||
output->usable_area = usable_area;
|
||||
arrange_locks();
|
||||
arrange_output(output);
|
||||
} else {
|
||||
arrange_popups(root->layers.popup);
|
||||
|
|
|
@ -623,13 +623,22 @@ void arrange_popups(struct wlr_scene_tree *popups) {
|
|||
|
||||
static void arrange_root(struct sway_root *root) {
|
||||
struct sway_container *fs = root->fullscreen_global;
|
||||
bool locked = server.session_lock.lock;
|
||||
|
||||
wlr_scene_node_set_enabled(&root->layers.shell_background->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.shell_bottom->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.tiling->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.floating->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.tiling->node, !fs && !locked);
|
||||
wlr_scene_node_set_enabled(&root->layers.floating->node, !fs && !locked);
|
||||
wlr_scene_node_set_enabled(&root->layers.shell_top->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.fullscreen->node, !fs);
|
||||
wlr_scene_node_set_enabled(&root->layers.fullscreen->node, !fs && !locked);
|
||||
wlr_scene_node_set_enabled(&root->layers.fullscreen_global->node, !locked);
|
||||
#if WLR_HAS_XWAYLAND
|
||||
wlr_scene_node_set_enabled(&root->layers.unmanaged->node, !locked);
|
||||
#endif
|
||||
|
||||
if (server.session_lock.lock) {
|
||||
sway_log(SWAY_INFO, "arranging locked layout");
|
||||
}
|
||||
|
||||
// hide all contents in the scratchpad
|
||||
for (int i = 0; i < root->scratchpad->length; i++) {
|
||||
|
|
|
@ -1068,7 +1068,20 @@ void seat_configure_xcursor(struct sway_seat *seat) {
|
|||
bool seat_is_input_allowed(struct sway_seat *seat,
|
||||
struct wlr_surface *surface) {
|
||||
if (server.session_lock.lock) {
|
||||
return sway_session_lock_has_surface(server.session_lock.lock, surface);
|
||||
if (sway_session_lock_has_surface(server.session_lock.lock, surface)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_layer_surface_v1 *layer_surface =
|
||||
wlr_layer_surface_v1_try_from_wlr_surface(surface);
|
||||
struct sway_layer_surface *layer =
|
||||
layer_surface ? layer_surface->data : NULL;
|
||||
|
||||
if (layer && layer->show_over_lockscreen) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
24
sway/lock.c
24
sway/lock.c
|
@ -4,10 +4,12 @@
|
|||
#include "log.h"
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/input/keyboard.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/layers.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/lock.h"
|
||||
|
||||
struct sway_session_lock_output {
|
||||
|
@ -79,13 +81,13 @@ static void handle_surface_destroy(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
static void lock_output_reconfigure(struct sway_session_lock_output *output) {
|
||||
int width = output->output->width;
|
||||
int height = output->output->height;
|
||||
struct wlr_box usable_area = output->output->usable_area;
|
||||
|
||||
wlr_scene_rect_set_size(output->background, width, height);
|
||||
wlr_scene_node_set_position(&output->tree->node, usable_area.x, usable_area.y);
|
||||
wlr_scene_rect_set_size(output->background, usable_area.width, usable_area.height);
|
||||
|
||||
if (output->surface) {
|
||||
wlr_session_lock_surface_v1_configure(output->surface, width, height);
|
||||
wlr_session_lock_surface_v1_configure(output->surface, usable_area.width, usable_area.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,6 +236,9 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
|
|||
struct sway_output *output = root->outputs->items[i];
|
||||
arrange_layers(output);
|
||||
}
|
||||
|
||||
arrange_root();
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
static void handle_abandon(struct wl_listener *listener, void *data) {
|
||||
|
@ -295,8 +300,17 @@ static void handle_session_lock(struct wl_listener *listener, void *data) {
|
|||
sway_lock->destroy.notify = handle_abandon;
|
||||
wl_signal_add(&lock->events.destroy, &sway_lock->destroy);
|
||||
|
||||
wlr_session_lock_v1_send_locked(lock);
|
||||
server.session_lock.lock = sway_lock;
|
||||
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *output = root->outputs->items[i];
|
||||
arrange_layers(output);
|
||||
}
|
||||
|
||||
arrange_root();
|
||||
transaction_commit_dirty();
|
||||
|
||||
wlr_session_lock_v1_send_locked(lock);
|
||||
}
|
||||
|
||||
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
87
sway/lockscreen-overlay.c
Normal file
87
sway/lockscreen-overlay.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include "sway/lockscreen-overlay.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/layers.h"
|
||||
|
||||
#include "kde-lockscreen-overlay-v1-protocol.h"
|
||||
#include "log.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
|
||||
struct sway_lockscreen_overlay {
|
||||
};
|
||||
|
||||
static void kde_lockscreen_overlay_allow(struct wl_client *client,
|
||||
struct wl_resource *resource, struct wl_resource *surface) {
|
||||
sway_log(SWAY_ERROR, "at %s:%d", __func__, __LINE__);
|
||||
|
||||
struct wlr_surface *overlay_surface = wlr_surface_from_resource(surface);
|
||||
// TODO: send a protocol error for each of these checks?
|
||||
if (!overlay_surface) {
|
||||
sway_log(SWAY_ERROR, "No overlay surface found");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_layer_surface_v1 *wlr_layer_surface =
|
||||
wlr_layer_surface_v1_try_from_wlr_surface(overlay_surface);
|
||||
if (!wlr_layer_surface) {
|
||||
sway_log(SWAY_ERROR, "no wlr_layer surface found");
|
||||
return;
|
||||
}
|
||||
|
||||
struct sway_layer_surface *layer_surface = wlr_layer_surface->data;
|
||||
if (!layer_surface) {
|
||||
sway_log(SWAY_ERROR, "no sway_layer surface found");
|
||||
return;
|
||||
}
|
||||
|
||||
layer_surface->show_over_lockscreen = true;
|
||||
|
||||
arrange_layers(layer_surface->output);
|
||||
arrange_root();
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
static void kde_lockscreen_overlay_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct kde_lockscreen_overlay_v1_interface impl = {
|
||||
.allow = kde_lockscreen_overlay_allow,
|
||||
.destroy = kde_lockscreen_overlay_destroy,
|
||||
};
|
||||
|
||||
static void lockscreen_overlay_bind(
|
||||
struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id
|
||||
) {
|
||||
struct sway_lockscreen_overlay *overlay = data;
|
||||
|
||||
struct wl_resource *resource = wl_resource_create(client,
|
||||
&kde_lockscreen_overlay_v1_interface, version, id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation(resource, &impl, overlay, NULL);
|
||||
}
|
||||
|
||||
struct sway_lockscreen_overlay *sway_lockscreen_overlay_create(struct wl_display *display) {
|
||||
struct sway_lockscreen_overlay *overlay = calloc(1, sizeof(*overlay));
|
||||
|
||||
wl_global_create(
|
||||
display,
|
||||
&kde_lockscreen_overlay_v1_interface, 1,
|
||||
overlay, lockscreen_overlay_bind
|
||||
);
|
||||
|
||||
return overlay;
|
||||
}
|
|
@ -6,6 +6,7 @@ sway_sources = files(
|
|||
'ipc-json.c',
|
||||
'ipc-server.c',
|
||||
'lock.c',
|
||||
'lockscreen-overlay.c',
|
||||
'main.c',
|
||||
'realtime.c',
|
||||
'scene_descriptor.c',
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "sway/server.h"
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/tree/root.h"
|
||||
#include "sway/lockscreen-overlay.h"
|
||||
|
||||
#if WLR_HAS_XWAYLAND
|
||||
#include <wlr/xwayland/shell.h>
|
||||
|
@ -352,6 +353,8 @@ bool server_init(struct sway_server *server) {
|
|||
wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION);
|
||||
server->foreign_toplevel_manager =
|
||||
wlr_foreign_toplevel_manager_v1_create(server->wl_display);
|
||||
server->lockscreen_overlay =
|
||||
sway_lockscreen_overlay_create(server->wl_display);
|
||||
|
||||
sway_session_lock_init();
|
||||
|
||||
|
|
|
@ -50,10 +50,10 @@ struct sway_root *root_create(struct wl_display *wl_display) {
|
|||
#if WLR_HAS_XWAYLAND
|
||||
root->layers.unmanaged = alloc_scene_tree(root->layer_tree, &failed);
|
||||
#endif
|
||||
root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed);
|
||||
root->layers.shell_overlay = alloc_scene_tree(root->layer_tree, &failed);
|
||||
root->layers.popup = alloc_scene_tree(root->layer_tree, &failed);
|
||||
root->layers.seat = alloc_scene_tree(root->layer_tree, &failed);
|
||||
root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed);
|
||||
|
||||
if (!failed && !scene_descriptor_assign(&root->layers.seat->node,
|
||||
SWAY_SCENE_DESC_NON_INTERACTIVE, (void *)1)) {
|
||||
|
|
Loading…
Reference in a new issue