mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Allow pop-up grabs for bottom and background layers
This commit is contained in:
+19
-10
@@ -289,6 +289,7 @@ impl XdgShellHandler for State {
|
|||||||
|
|
||||||
let popup = PopupKind::Xdg(surface);
|
let popup = PopupKind::Xdg(surface);
|
||||||
let Ok(root) = find_popup_root_surface(&popup) else {
|
let Ok(root) = find_popup_root_surface(&popup) else {
|
||||||
|
trace!("ignoring popup grab because no root surface");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -297,30 +298,30 @@ impl XdgShellHandler for State {
|
|||||||
// keyboard focus being at the wrong place.
|
// keyboard focus being at the wrong place.
|
||||||
if self.niri.is_locked() {
|
if self.niri.is_locked() {
|
||||||
if Some(&root) != self.niri.lock_surface_focus().as_ref() {
|
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);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if self.niri.screenshot_ui.is_open() {
|
} else if self.niri.screenshot_ui.is_open() {
|
||||||
|
trace!("ignoring popup grab because the screenshot UI is open");
|
||||||
let _ = PopupManager::dismiss_popup(&root, &popup);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
} else if let Some(output) = self.niri.layout.active_output() {
|
} else if let Some(output) = self.niri.layout.active_output() {
|
||||||
let layers = layer_map_for_output(output);
|
let layers = layer_map_for_output(output);
|
||||||
|
|
||||||
if let Some(layer_surface) =
|
if layers
|
||||||
layers.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)
|
.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)
|
||||||
|
.is_none()
|
||||||
{
|
{
|
||||||
if !matches!(layer_surface.layer(), Layer::Overlay | Layer::Top) {
|
// This is a grab for a regular window; check that there's no layer surface with a
|
||||||
let _ = PopupManager::dismiss_popup(&root, &popup);
|
// higher input priority.
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: popup grabs for on-demand bottom and background layers.
|
|
||||||
} else {
|
|
||||||
if layers.layers_on(Layer::Overlay).any(|l| {
|
if layers.layers_on(Layer::Overlay).any(|l| {
|
||||||
l.cached_state().keyboard_interactivity
|
l.cached_state().keyboard_interactivity
|
||||||
== wlr_layer::KeyboardInteractivity::Exclusive
|
== wlr_layer::KeyboardInteractivity::Exclusive
|
||||||
|| Some(l) == self.niri.layer_shell_on_demand_focus.as_ref()
|
|| 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);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -333,28 +334,35 @@ impl XdgShellHandler for State {
|
|||||||
|| Some(l) == self.niri.layer_shell_on_demand_focus.as_ref()
|
|| 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);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout_focus = self.niri.layout.focus();
|
let layout_focus = self.niri.layout.focus();
|
||||||
if Some(&root) != layout_focus.map(|win| win.toplevel().wl_surface()) {
|
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);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
trace!("ignoring popup grab because no output is active");
|
||||||
let _ = PopupManager::dismiss_popup(&root, &popup);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let seat = &self.niri.seat;
|
let seat = &self.niri.seat;
|
||||||
let Ok(mut grab) = self
|
let mut grab = match self
|
||||||
.niri
|
.niri
|
||||||
.popups
|
.popups
|
||||||
.grab_popup(root.clone(), popup, seat, serial)
|
.grab_popup(root.clone(), popup, seat, serial)
|
||||||
else {
|
{
|
||||||
|
Ok(grab) => grab,
|
||||||
|
Err(err) => {
|
||||||
|
trace!("ignoring popup grab: {err:?}");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let keyboard = seat.get_keyboard().unwrap();
|
let keyboard = seat.get_keyboard().unwrap();
|
||||||
@@ -380,6 +388,7 @@ impl XdgShellHandler for State {
|
|||||||
&& !(pointer.has_grab(serial)
|
&& !(pointer.has_grab(serial)
|
||||||
|| grab.previous_serial().map_or(true, |s| pointer.has_grab(s)));
|
|| grab.previous_serial().map_or(true, |s| pointer.has_grab(s)));
|
||||||
if (can_receive_keyboard_focus && keyboard_grab_mismatches) || pointer_grab_mismatches {
|
if (can_receive_keyboard_focus && keyboard_grab_mismatches) || pointer_grab_mismatches {
|
||||||
|
trace!("ignoring popup grab because of current grab mismatch");
|
||||||
grab.ungrab(PopupUngrabStrategy::All);
|
grab.ungrab(PopupUngrabStrategy::All);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -920,6 +920,8 @@ impl State {
|
|||||||
// fullscreen layout window. This will need tracking in grab() to avoid handing it out
|
// 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.
|
// 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::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));
|
surface = surface.or_else(|| focus_on_layer(Layer::Overlay));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user