Add cosmic-session-lock-layer-v1 protocol

https://github.com/pop-os/cosmic-protocols/pull/88
This commit is contained in:
Ian Douglas Scott 2026-08-28 13:14:21 -07:00 • committed by Jeremy Soller
parent f9e02f4321
commit a7349b72e3
7 changed files with 339 additions and 85 deletions

View file

@ -2,12 +2,15 @@ use crate::{
shell::{CosmicSurface, MinimizedWindow, Shell, Trigger, element::CosmicMapped},
state::{Common, State},
utils::prelude::*,
wayland::handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
wayland::{
handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
protocols::session_lock_layer::layer_show_on_lock,
},
};
use indexmap::IndexSet;
use smithay::{
backend::input::InputTime,
desktop::{PopupUngrabStrategy, layer_map_for_output},
desktop::{PopupUngrabStrategy, find_popup_root_surface, layer_map_for_output},
input::{Seat, pointer::MotionEvent},
output::Output,
reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface},
@ -627,8 +630,15 @@ fn focus_target_is_valid(
output: &Output,
target: KeyboardFocusTarget,
) -> bool {
// If a session lock is active, only lock surfaces can be focused
// If a session lock is active, only lock surfaces and lock layers can be focused
if shell.session_lock.is_some() {
if let KeyboardFocusTarget::LayerSurface(layer) = &target {
return layer_show_on_lock(layer.wl_surface());
} else if let KeyboardFocusTarget::Popup(popup) = &target
&& let Ok(root) = find_popup_root_surface(popup)
{
return layer_show_on_lock(&root);
}
return matches!(target, KeyboardFocusTarget::LockSurface(_));
}

View file

@ -22,7 +22,7 @@ use crate::{
prelude::OutputExt,
quirks::{WORKSPACE_OVERVIEW_NAMESPACE, workspace_overview_is_open},
},
wayland::protocols::workspace::WorkspaceHandle,
wayland::protocols::{session_lock_layer::layer_show_on_lock, workspace::WorkspaceHandle},
};
pub enum Stage<'a> {
@ -89,7 +89,92 @@ fn render_input_order_internal<R: 'static>(
// Session Lock
if let Some(session_lock) = &shell.session_lock {
return callback(Stage::SessionLock(session_lock.surfaces.get(output)));
for (layer, popup, location) in layer_popups(output, Layer::Overlay, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Overlay, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
for (layer, popup, location) in layer_popups(output, Layer::Top, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Top, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
callback(Stage::SessionLock(session_lock.surfaces.get(output)))?;
for (layer, popup, location) in layer_popups(output, Layer::Bottom, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, popup, location) in layer_popups(output, Layer::Background, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Bottom, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Background, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
return ControlFlow::Continue(());
}
// Overlay-level layer shell

View file

@ -19,7 +19,10 @@ use crate::{
utils,
wayland::{
handlers::data_device::{self, get_dnd_icon},
protocols::workspace::{State as WState, WorkspaceCapabilities},
protocols::{
session_lock_layer::layer_show_on_lock,
workspace::{State as WState, WorkspaceCapabilities},
},
},
};
use cosmic_comp_config::{
@ -2049,11 +2052,24 @@ impl Shell {
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
if let Some(session_lock) = &self.session_lock {
return session_lock
if let Some((output, _)) = session_lock
.surfaces
.iter()
.find(|(_, v)| v.wl_surface() == surface)
.map(|(k, _)| k);
{
return Some(output);
}
for o in self.outputs() {
let map = layer_map_for_output(o);
if let Some(layer_surface) = map.layer_for_surface(surface, WindowSurfaceType::ALL)
{
if layer_show_on_lock(layer_surface.wl_surface()) {
return Some(o);
} else {
return None;
}
}
}
}
self.outputs()