bring modal or floating windows to front

This commit is contained in:
2026-08-21 23:32:29 +02:00
parent f60dd06e7e
commit 97b27f1f4c
3 changed files with 117 additions and 9 deletions
+42
View File
@@ -75,6 +75,11 @@ pending_close: bool = false,
/// Bumped whenever the window takes focus, giving a cheap "most recently
/// focused" ordering without maintaining dwm's second linked list.
focus_serial: u64 = 0,
/// Where this window's family of parents and children sits in the floating
/// stack, and how far down that family the window is. Recomputed each render
/// sequence; see `Wm.computeStacking`.
stack_serial: u64 = 0,
stack_depth: u32 = 0,
/// Cleared once the window has had its one chance at taking focus as it maps.
wants_initial_focus: bool = true,
@@ -105,6 +110,38 @@ pub fn getNode(self: *Window) ?*river.NodeV1 {
return self.node;
}
/// The window at the top of this window's parent chain, and how many parents
/// away it is. A window with no parent is its own root, at depth zero.
///
/// The protocol promises the parent links form a tree, but a client that
/// breaks that promise must not hang the compositor, so the walk is bounded.
pub fn ancestry(self: *Window) struct { root: *Window, depth: u32 } {
var root = self;
var depth: u32 = 0;
while (root.parent) |p| {
if (depth >= max_parent_depth) break;
root = p;
depth += 1;
}
return .{ .root = root, .depth = depth };
}
/// Whether this window belongs to a window that is currently fullscreen. Such
/// a dialog has to be drawn above the fullscreen layer: its parent covers the
/// whole output, and everything below it with it.
pub fn hasFullscreenAncestor(self: *Window) bool {
var next = self.parent;
var depth: u32 = 0;
while (next) |p| : (depth += 1) {
if (depth >= max_parent_depth) break;
if (p.fullscreen and p.visible and !p.closed) return true;
next = p.parent;
}
return false;
}
const max_parent_depth = 32;
/// Clamp a proposed size to the window's advertised limits. These are hints,
/// but respecting them avoids pointless configure round-trips with windows
/// that will refuse the size anyway.
@@ -215,6 +252,11 @@ fn onEvent(_: *river.WindowV1, event: river.WindowV1.Event, self: *Window) void
if (config.float_children and self.parent != null and !self.floating_forced) {
self.floating = true;
}
// A parent may be set after the window has already been mapped and
// laid out — Vivado's dialogs do exactly that — so the change of
// both float state and stacking has to be arranged for.
self.wm.needsManage();
self.wm.ipcDirty();
},
.fullscreen_requested => |ev| {