From daa08d23aab019b441b2fa9158698830cb1640ac Mon Sep 17 00:00:00 2001 From: lkn Date: Tue, 23 Jun 2026 22:44:38 +0200 Subject: [PATCH] add ext-session-lock-v1 protocol support Enables screen locker clients (swaylock, waylock) to lock the session. On lock: confirms locked state to client. On new_surface: configures lock surface to cover the output and adds it to the scene overlay layer. On unlock: clears locked state. --- src/Makefile | 17 +++++- src/Makefile.am | 1 + src/backend/wayland/wl_extensions.c | 11 ++++ src/backend/wayland/wl_session_lock.c | 81 +++++++++++++++++++++++++++ src/backend/wayland/wl_types.h | 8 +++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/backend/wayland/wl_session_lock.c diff --git a/src/Makefile b/src/Makefile index bb2775d..0add850 100644 --- a/src/Makefile +++ b/src/Makefile @@ -157,6 +157,7 @@ am__append_7 = \ backend/wayland/wl_handlers.c \ backend/wayland/wl_icon.c \ backend/wayland/wl_kaboom.c \ + backend/wayland/wl_session_lock.c \ backend/wayland/wl_virtual_pointer.c \ backend/wayland/wl_input_fwd.c @@ -246,7 +247,7 @@ am__wmaker_SOURCES_DIST = GNUstep.h WindowMaker.h actions.c actions.h \ backend/wayland/wl_layout_sync.c backend/wayland/wl_xdg.c \ backend/wayland/wl_dock.c backend/wayland/wl_layer_shell.c \ backend/wayland/wl_handlers.c backend/wayland/wl_icon.c \ - backend/wayland/wl_kaboom.c \ + backend/wayland/wl_kaboom.c backend/wayland/wl_session_lock.c \ backend/wayland/wl_virtual_pointer.c \ backend/wayland/wl_input_fwd.c misc.c xmodifier.c \ backend/wayland/wl_xdisplay.c backend/wayland/wl_xwayland.c @@ -307,6 +308,7 @@ am__objects_7 = backend/wayland/wl_backend.$(OBJEXT) \ backend/wayland/wl_handlers.$(OBJEXT) \ backend/wayland/wl_icon.$(OBJEXT) \ backend/wayland/wl_kaboom.$(OBJEXT) \ + backend/wayland/wl_session_lock.$(OBJEXT) \ backend/wayland/wl_virtual_pointer.$(OBJEXT) \ backend/wayland/wl_input_fwd.$(OBJEXT) am__objects_8 = misc.$(OBJEXT) \ @@ -413,6 +415,7 @@ am__depfiles_remade = ./$(DEPDIR)/actions.Po ./$(DEPDIR)/appicon.Po \ backend/wayland/$(DEPDIR)/wl_icccm.Po \ backend/wayland/$(DEPDIR)/wl_icon.Po \ backend/wayland/$(DEPDIR)/wl_input_fwd.Po \ + backend/wayland/$(DEPDIR)/wl_kaboom.Po \ backend/wayland/$(DEPDIR)/wl_keyboard.Po \ backend/wayland/$(DEPDIR)/wl_layer_shell.Po \ backend/wayland/$(DEPDIR)/wl_layout_sync.Po \ @@ -424,6 +427,7 @@ am__depfiles_remade = ./$(DEPDIR)/actions.Po ./$(DEPDIR)/appicon.Po \ backend/wayland/$(DEPDIR)/wl_popup.Po \ backend/wayland/$(DEPDIR)/wl_props.Po \ backend/wayland/$(DEPDIR)/wl_screen.Po \ + backend/wayland/$(DEPDIR)/wl_session_lock.Po \ backend/wayland/$(DEPDIR)/wl_shm.Po \ backend/wayland/$(DEPDIR)/wl_signalfd.Po \ backend/wayland/$(DEPDIR)/wl_stacking.Po \ @@ -1010,6 +1014,11 @@ backend/wayland/wl_handlers.$(OBJEXT): \ backend/wayland/$(DEPDIR)/$(am__dirstamp) backend/wayland/wl_icon.$(OBJEXT): backend/wayland/$(am__dirstamp) \ backend/wayland/$(DEPDIR)/$(am__dirstamp) +backend/wayland/wl_kaboom.$(OBJEXT): backend/wayland/$(am__dirstamp) \ + backend/wayland/$(DEPDIR)/$(am__dirstamp) +backend/wayland/wl_session_lock.$(OBJEXT): \ + backend/wayland/$(am__dirstamp) \ + backend/wayland/$(DEPDIR)/$(am__dirstamp) backend/wayland/wl_virtual_pointer.$(OBJEXT): \ backend/wayland/$(am__dirstamp) \ backend/wayland/$(DEPDIR)/$(am__dirstamp) @@ -1115,6 +1124,7 @@ include backend/wayland/$(DEPDIR)/wl_handlers.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_icccm.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_icon.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_input_fwd.Po # am--include-marker +include backend/wayland/$(DEPDIR)/wl_kaboom.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_keyboard.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_layer_shell.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_layout_sync.Po # am--include-marker @@ -1126,6 +1136,7 @@ include backend/wayland/$(DEPDIR)/wl_pointer_motion.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_popup.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_props.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_screen.Po # am--include-marker +include backend/wayland/$(DEPDIR)/wl_session_lock.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_shm.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_signalfd.Po # am--include-marker include backend/wayland/$(DEPDIR)/wl_stacking.Po # am--include-marker @@ -1400,6 +1411,7 @@ distclean: distclean-am -rm -f backend/wayland/$(DEPDIR)/wl_icccm.Po -rm -f backend/wayland/$(DEPDIR)/wl_icon.Po -rm -f backend/wayland/$(DEPDIR)/wl_input_fwd.Po + -rm -f backend/wayland/$(DEPDIR)/wl_kaboom.Po -rm -f backend/wayland/$(DEPDIR)/wl_keyboard.Po -rm -f backend/wayland/$(DEPDIR)/wl_layer_shell.Po -rm -f backend/wayland/$(DEPDIR)/wl_layout_sync.Po @@ -1411,6 +1423,7 @@ distclean: distclean-am -rm -f backend/wayland/$(DEPDIR)/wl_popup.Po -rm -f backend/wayland/$(DEPDIR)/wl_props.Po -rm -f backend/wayland/$(DEPDIR)/wl_screen.Po + -rm -f backend/wayland/$(DEPDIR)/wl_session_lock.Po -rm -f backend/wayland/$(DEPDIR)/wl_shm.Po -rm -f backend/wayland/$(DEPDIR)/wl_signalfd.Po -rm -f backend/wayland/$(DEPDIR)/wl_stacking.Po @@ -1554,6 +1567,7 @@ maintainer-clean: maintainer-clean-am -rm -f backend/wayland/$(DEPDIR)/wl_icccm.Po -rm -f backend/wayland/$(DEPDIR)/wl_icon.Po -rm -f backend/wayland/$(DEPDIR)/wl_input_fwd.Po + -rm -f backend/wayland/$(DEPDIR)/wl_kaboom.Po -rm -f backend/wayland/$(DEPDIR)/wl_keyboard.Po -rm -f backend/wayland/$(DEPDIR)/wl_layer_shell.Po -rm -f backend/wayland/$(DEPDIR)/wl_layout_sync.Po @@ -1565,6 +1579,7 @@ maintainer-clean: maintainer-clean-am -rm -f backend/wayland/$(DEPDIR)/wl_popup.Po -rm -f backend/wayland/$(DEPDIR)/wl_props.Po -rm -f backend/wayland/$(DEPDIR)/wl_screen.Po + -rm -f backend/wayland/$(DEPDIR)/wl_session_lock.Po -rm -f backend/wayland/$(DEPDIR)/wl_shm.Po -rm -f backend/wayland/$(DEPDIR)/wl_signalfd.Po -rm -f backend/wayland/$(DEPDIR)/wl_stacking.Po diff --git a/src/Makefile.am b/src/Makefile.am index 332eefc..298aab8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -249,6 +249,7 @@ wmaker_SOURCES += \ backend/wayland/wl_handlers.c \ backend/wayland/wl_icon.c \ backend/wayland/wl_kaboom.c \ + backend/wayland/wl_session_lock.c \ backend/wayland/wl_virtual_pointer.c \ backend/wayland/wl_input_fwd.c endif diff --git a/src/backend/wayland/wl_extensions.c b/src/backend/wayland/wl_extensions.c index cf897c0..af85313 100644 --- a/src/backend/wayland/wl_extensions.c +++ b/src/backend/wayland/wl_extensions.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -485,6 +486,16 @@ wl_protocols_init(void) wwarning("wl_backend: xdg-decoration-manager created"); } + /* ext-session-lock-v1: screen locker support (swaylock, waylock) */ + extern void handle_session_lock_new_lock(struct wl_listener *listener, void *data); + wl_state.session_lock_mgr = wlr_session_lock_manager_v1_create(wl_state.display); + if (wl_state.session_lock_mgr) { + wl_state.session_lock_new_lock_listener.notify = handle_session_lock_new_lock; + wl_signal_add(&wl_state.session_lock_mgr->events.new_lock, + &wl_state.session_lock_new_lock_listener); + wwarning("wl_backend: session-lock-v1 created"); + } + wlr_renderer_init_wl_shm(wl_state.renderer, wl_state.display); /* wl_output global is created in handle_backend_new_output. */ diff --git a/src/backend/wayland/wl_session_lock.c b/src/backend/wayland/wl_session_lock.c new file mode 100644 index 0000000..6fec975 --- /dev/null +++ b/src/backend/wayland/wl_session_lock.c @@ -0,0 +1,81 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include "wl_types.h" + +static void handle_lock_new_surface(struct wl_listener *listener, void *data) +{ + struct wlr_session_lock_surface_v1 *lock_surface = data; + (void)listener; + + struct wlr_output *output = lock_surface->output; + if (!output) return; + + /* Configure lock surface to cover the full output */ + wlr_session_lock_surface_v1_configure(lock_surface, + output->width, output->height); + + /* Create scene node for the lock surface above everything */ + struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY] + ? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree; + wlr_scene_subsurface_tree_create(parent, lock_surface->surface); +} + +static void handle_lock_unlock(struct wl_listener *listener, void *data) +{ + (void)listener; (void)data; + wl_state.session_locked = false; + wl_state.active_lock = NULL; + wl_list_remove(&wl_state.session_lock_unlock_listener.link); + wl_list_init(&wl_state.session_lock_unlock_listener.link); + wl_list_remove(&wl_state.session_lock_destroy_listener.link); + wl_list_init(&wl_state.session_lock_destroy_listener.link); + wl_list_remove(&wl_state.session_lock_new_surface_listener.link); + wl_list_init(&wl_state.session_lock_new_surface_listener.link); +} + +static void handle_lock_destroy(struct wl_listener *listener, void *data) +{ + (void)listener; (void)data; + /* Lock client died without unlocking — keep locked state. + * A new lock client can connect and take over. */ + wl_state.active_lock = NULL; + wl_list_remove(&wl_state.session_lock_unlock_listener.link); + wl_list_init(&wl_state.session_lock_unlock_listener.link); + wl_list_remove(&wl_state.session_lock_destroy_listener.link); + wl_list_init(&wl_state.session_lock_destroy_listener.link); + wl_list_remove(&wl_state.session_lock_new_surface_listener.link); + wl_list_init(&wl_state.session_lock_new_surface_listener.link); +} + +void handle_session_lock_new_lock(struct wl_listener *listener, void *data) +{ + (void)listener; + struct wlr_session_lock_v1 *lock = data; + + if (wl_state.active_lock) { + wlr_session_lock_v1_destroy(lock); + return; + } + + wl_state.active_lock = lock; + wl_state.session_locked = true; + + wl_state.session_lock_new_surface_listener.notify = handle_lock_new_surface; + wl_signal_add(&lock->events.new_surface, + &wl_state.session_lock_new_surface_listener); + + wl_state.session_lock_unlock_listener.notify = handle_lock_unlock; + wl_signal_add(&lock->events.unlock, + &wl_state.session_lock_unlock_listener); + + wl_state.session_lock_destroy_listener.notify = handle_lock_destroy; + wl_signal_add(&lock->events.destroy, + &wl_state.session_lock_destroy_listener); + + wlr_session_lock_v1_send_locked(lock); +} diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index d454433..be42bb4 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -313,6 +313,14 @@ struct wl_compositor_state { struct wl_listener virtual_pointer_new_listener; struct wlr_xdg_foreign_registry *xdg_foreign_registry; struct wlr_xdg_foreign_v2 *xdg_foreign_v2; + /* Session lock (ext-session-lock-v1) */ + struct wlr_session_lock_manager_v1 *session_lock_mgr; + struct wlr_session_lock_v1 *active_lock; + struct wl_listener session_lock_new_lock_listener; + struct wl_listener session_lock_unlock_listener; + struct wl_listener session_lock_destroy_listener; + struct wl_listener session_lock_new_surface_listener; + bool session_locked; /* Phase 29 axis listeners (headless pointer + real nested pointer). */ struct wl_listener pointer_axis_listener; struct wl_listener real_pointer_axis_listener;