mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Allow pop-up grabs for bottom and background layers
This commit is contained in:
+20
-11
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user