fix: check layer map for root popup surface

This commit is contained in:
Ashley Wulber 2025-07-31 14:10:34 -04:00 committed by Victoria Brekenfeld
parent a409770df7
commit e1aa8f7cb4
2 changed files with 68 additions and 40 deletions

View file

@ -42,7 +42,9 @@ impl WlrLayerShellHandler for State {
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
self.common.shell.read().unconstrain_popup(&popup);
if popup.send_configure().is_ok() {
if let Err(err) = popup.send_configure() {
tracing::warn!("Unable to configure popup. {err:?}",);
} else {
self.common
.popups
.track_popup(PopupKind::from(popup))

View file

@ -4,11 +4,12 @@ use crate::{
shell::{focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, PendingWindow},
utils::prelude::*,
};
use smithay::desktop::layer_map_for_output;
use smithay::{
delegate_xdg_shell,
desktop::{
find_popup_root_surface, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab,
PopupUngrabStrategy,
PopupUngrabStrategy, WindowSurfaceType,
},
input::{pointer::Focus, Seat},
output::Output,
@ -63,7 +64,9 @@ impl XdgShellHandler for State {
// let other shells deal with their popups
self.common.shell.read().unconstrain_popup(&surface);
if surface.send_configure().is_ok() {
if let Err(err) = surface.send_configure() {
warn!("Unable to configure popup. {err:?}",);
} else {
self.common
.popups
.track_popup(PopupKind::from(surface))
@ -75,52 +78,75 @@ impl XdgShellHandler for State {
fn grab(&mut self, surface: PopupSurface, seat: WlSeat, serial: Serial) {
let seat = Seat::from_resource(&seat).unwrap();
let kind = PopupKind::Xdg(surface);
let maybe_root = find_popup_root_surface(&kind)
.ok()
.and_then(|root| self.common.shell.read().element_for_surface(&root).cloned());
let maybe_root = find_popup_root_surface(&kind).ok();
if maybe_root.is_none() {
tracing::warn!("No root surface found for popup grab.");
return;
}
let maybe_root: Option<KeyboardFocusTarget> = maybe_root.and_then(|root| {
let shell = self.common.shell.read();
shell
.element_for_surface(&root)
.map(|r| r.clone().into())
.or_else(|| {
shell.outputs().find_map(|o| {
layer_map_for_output(o)
.layer_for_surface(&root, WindowSurfaceType::ALL)
.cloned()
.map(KeyboardFocusTarget::LayerSurface)
})
})
});
if let Some(root) = maybe_root {
let target = root.into();
let ret = self.common.popups.grab_popup(target, kind, &seat, serial);
if let Ok(mut grab) = ret {
if let Some(keyboard) = seat.get_keyboard() {
if keyboard.is_grabbed()
&& !(keyboard.has_grab(serial)
|| keyboard.has_grab(grab.previous_serial().unwrap_or(serial)))
{
grab.ungrab(PopupUngrabStrategy::All);
return;
match ret {
Ok(mut grab) => {
if let Some(keyboard) = seat.get_keyboard() {
if keyboard.is_grabbed()
&& !(keyboard.has_grab(serial)
|| keyboard.has_grab(grab.previous_serial().unwrap_or(serial)))
{
grab.ungrab(PopupUngrabStrategy::All);
return;
}
Shell::set_focus(
self,
grab.current_grab().as_ref(),
&seat,
Some(serial),
false,
);
keyboard.set_grab(self, PopupKeyboardGrab::new(&grab), serial);
}
Shell::set_focus(
self,
grab.current_grab().as_ref(),
&seat,
Some(serial),
false,
);
keyboard.set_grab(self, PopupKeyboardGrab::new(&grab), serial);
}
if let Some(pointer) = seat.get_pointer() {
if pointer.is_grabbed()
&& !(pointer.has_grab(serial)
|| pointer
.has_grab(grab.previous_serial().unwrap_or_else(|| grab.serial())))
{
grab.ungrab(PopupUngrabStrategy::All);
return;
if let Some(pointer) = seat.get_pointer() {
if pointer.is_grabbed()
&& !(pointer.has_grab(serial)
|| pointer.has_grab(
grab.previous_serial().unwrap_or_else(|| grab.serial()),
))
{
grab.ungrab(PopupUngrabStrategy::All);
return;
}
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
}
pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep);
}
seat.user_data()
.insert_if_missing(|| PopupGrabData::new(None));
seat.user_data()
.get::<PopupGrabData>()
.unwrap()
.set(Some(grab));
seat.user_data()
.insert_if_missing(|| PopupGrabData::new(None));
seat.user_data()
.get::<PopupGrabData>()
.unwrap()
.set(Some(grab));
}
Err(err) => {
tracing::warn!("Failed to grab popup: {:?}", err);
}
}
} else {
tracing::warn!("No root for grab.");
}
}