From 651f701f84e46d0262a129cb9ac30537d648cb08 Mon Sep 17 00:00:00 2001 From: Hojjat Date: Thu, 10 Sep 2026 15:08:32 -0600 Subject: [PATCH] shell/focus: Don't dismiss grabbing popups of exclusive layer surfaces --- src/shell/focus/mod.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index fe8f772a..dcfd55de 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -10,7 +10,10 @@ use crate::{ use indexmap::IndexSet; use smithay::{ backend::input::InputTime, - desktop::{PopupUngrabStrategy, find_popup_root_surface, layer_map_for_output}, + desktop::{ + LayerSurface, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface, + layer_map_for_output, + }, input::{Seat, pointer::MotionEvent}, output::Output, reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface}, @@ -644,12 +647,28 @@ fn focus_target_is_valid( // If an exclusive layer shell surface exists (on any output), only exclusive // shell surfaces can have focus, on the highest layer with exclusive surfaces. + // Popups are judged by their root surface, so an exclusive surface can + // still open grabbing popups (menus, dropdowns, context menus). if let Some(layer) = exclusive_layer_surface_layer(shell) { - return if let KeyboardFocusTarget::LayerSurface(layer_surface) = target { + let is_exclusive_on_layer = |layer_surface: &LayerSurface| { let data = layer_surface.cached_state(); (data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer) - } else { - false + }; + return match target { + KeyboardFocusTarget::LayerSurface(layer_surface) => { + is_exclusive_on_layer(&layer_surface) + } + KeyboardFocusTarget::Popup(popup) => find_popup_root_surface(&popup) + .ok() + .and_then(|root| { + shell.outputs().find_map(|o| { + layer_map_for_output(o) + .layer_for_surface(&root, WindowSurfaceType::ALL) + .map(&is_exclusive_on_layer) + }) + }) + .unwrap_or(false), + _ => false, }; }