aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-01-03 16:24:02 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-01-03 16:24:23 +0300
commit8e16be9e1150fed822fd671b3faf082a9b2641c0 (patch)
treefe33daa07cbbae2a3b48f5a33034a793cb21607b
parent300701f44e9d1fef38eda06fc33b34708a8c6e50 (diff)
downloadniri-8e16be9e1150fed822fd671b3faf082a9b2641c0.tar.gz
niri-8e16be9e1150fed822fd671b3faf082a9b2641c0.tar.bz2
niri-8e16be9e1150fed822fd671b3faf082a9b2641c0.zip
Allow pop-up grabs for bottom and background layers
-rw-r--r--src/handlers/xdg_shell.rs31
-rw-r--r--src/niri.rs2
2 files changed, 22 insertions, 11 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index 0d16e5f6..df8cb456 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -289,6 +289,7 @@ impl XdgShellHandler for State {
let popup = PopupKind::Xdg(surface);
let Ok(root) = find_popup_root_surface(&popup) else {
+ trace!("ignoring popup grab because no root surface");
return;
};
@@ -297,30 +298,30 @@ impl XdgShellHandler for State {
// keyboard focus being at the wrong place.
if self.niri.is_locked() {
if Some(&root) != self.niri.lock_surface_focus().as_ref() {
+ trace!("ignoring popup grab because the session is locked");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
}
} else if self.niri.screenshot_ui.is_open() {
+ trace!("ignoring popup grab because the screenshot UI is open");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
} else if let Some(output) = self.niri.layout.active_output() {
let layers = layer_map_for_output(output);
- if let Some(layer_surface) =
- layers.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)
+ if layers
+ .layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)
+ .is_none()
{
- if !matches!(layer_surface.layer(), Layer::Overlay | Layer::Top) {
- let _ = PopupManager::dismiss_popup(&root, &popup);
- return;
- }
+ // This is a grab for a regular window; check that there's no layer surface with a
+ // higher input priority.
- // FIXME: popup grabs for on-demand bottom and background layers.
- } else {
if layers.layers_on(Layer::Overlay).any(|l| {
l.cached_state().keyboard_interactivity
== wlr_layer::KeyboardInteractivity::Exclusive
|| Some(l) == self.niri.layer_shell_on_demand_focus.as_ref()
}) {
+ trace!("ignoring toplevel popup grab because the overlay layer has focus");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
}
@@ -333,28 +334,35 @@ impl XdgShellHandler for State {
|| Some(l) == self.niri.layer_shell_on_demand_focus.as_ref()
})
{
+ trace!("ignoring toplevel popup grab because the top layer has focus");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
}
let layout_focus = self.niri.layout.focus();
if Some(&root) != layout_focus.map(|win| win.toplevel().wl_surface()) {
+ trace!("ignoring toplevel popup grab because another window has focus");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
}
}
} else {
+ trace!("ignoring popup grab because no output is active");
let _ = PopupManager::dismiss_popup(&root, &popup);
return;
}
let seat = &self.niri.seat;
- let Ok(mut grab) = self
+ let mut grab = match self
.niri
.popups
.grab_popup(root.clone(), popup, seat, serial)
- else {
- return;
+ {
+ Ok(grab) => grab,
+ Err(err) => {
+ trace!("ignoring popup grab: {err:?}");
+ return;
+ }
};
let keyboard = seat.get_keyboard().unwrap();
@@ -380,6 +388,7 @@ impl XdgShellHandler for State {
&& !(pointer.has_grab(serial)
|| grab.previous_serial().map_or(true, |s| pointer.has_grab(s)));
if (can_receive_keyboard_focus && keyboard_grab_mismatches) || pointer_grab_mismatches {
+ trace!("ignoring popup grab because of current grab mismatch");
grab.ungrab(PopupUngrabStrategy::All);
return;
}
diff --git a/src/niri.rs b/src/niri.rs
index 665238ac..c8180c73 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -920,6 +920,8 @@ impl State {
// fullscreen layout window. This will need tracking in grab() to avoid handing it out
// in the first place. Or a better way to structure this code.
surface = surface.or_else(|| grab_on_layer(Layer::Top));
+ surface = surface.or_else(|| grab_on_layer(Layer::Bottom));
+ surface = surface.or_else(|| grab_on_layer(Layer::Background));
surface = surface.or_else(|| focus_on_layer(Layer::Overlay));