Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
XdgPopup: fix TODO panic
Actually (re)position popups rather than crashing.
river/WindowManager.zig | 1 +
river/XdgPopup.zig | 53 +++++++++++++++++++++++++++++--------------------
2 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/river/WindowManager.zig b/river/WindowManager.zig
index c8abd94..4c1e74b 100644
--- a/river/WindowManager.zig
+++ b/river/WindowManager.zig
@@ -431,6 +431,7 @@ fn renderFinish(wm: *WindowManager) void {
.window => |window| {
window.renderFinish();
window.tree.node.reparent(server.scene.layers.wm);
+ window.popup_tree.node.reparent(server.scene.layers.popups);
if (window.wm_requested.fullscreen != null) {
found_fullscreen = true;
window.tree.node.raiseToTop();
diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig
index 833cd41..3026347 100644
--- a/river/XdgPopup.zig
+++ b/river/XdgPopup.zig
@@ -28,7 +28,7 @@ const SceneNodeData = @import("SceneNodeData.zig");
const log = std.log.scoped(.xdg_popup);
-wlr_xdg_popup: *wlr.XdgPopup,
+wlr_popup: *wlr.XdgPopup,
/// The root of the surface tree, i.e. the Window's popup_tree
root: *wlr.SceneTree,
@@ -41,7 +41,7 @@ reposition: wl.Listener(void) = .init(handleReposition),
// TODO check if popup is set_reactive and reposition on parent movement.
pub fn create(
- wlr_xdg_popup: *wlr.XdgPopup,
+ wlr_popup: *wlr.XdgPopup,
root: *wlr.SceneTree,
parent: *wlr.SceneTree,
) error{OutOfMemory}!void {
@@ -49,15 +49,15 @@ pub fn create(
errdefer util.gpa.destroy(xdg_popup);
xdg_popup.* = .{
- .wlr_xdg_popup = wlr_xdg_popup,
+ .wlr_popup = wlr_popup,
.root = root,
- .tree = try parent.createSceneXdgSurface(wlr_xdg_popup.base),
+ .tree = try parent.createSceneXdgSurface(wlr_popup.base),
};
- wlr_xdg_popup.events.destroy.add(&xdg_popup.destroy);
- wlr_xdg_popup.base.surface.events.commit.add(&xdg_popup.commit);
- wlr_xdg_popup.base.events.new_popup.add(&xdg_popup.new_popup);
- wlr_xdg_popup.events.reposition.add(&xdg_popup.reposition);
+ wlr_popup.events.destroy.add(&xdg_popup.destroy);
+ wlr_popup.base.surface.events.commit.add(&xdg_popup.commit);
+ wlr_popup.base.events.new_popup.add(&xdg_popup.new_popup);
+ wlr_popup.events.reposition.add(&xdg_popup.reposition);
}
fn handleDestroy(listener: *wl.Listener(void)) void {
@@ -74,20 +74,20 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
const xdg_popup: *XdgPopup = @fieldParentPtr("commit", listener);
- if (xdg_popup.wlr_xdg_popup.base.initial_commit) {
+ if (xdg_popup.wlr_popup.base.initial_commit) {
handleReposition(&xdg_popup.reposition);
}
}
-fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
+fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_popup: *wlr.XdgPopup) void {
const xdg_popup: *XdgPopup = @fieldParentPtr("new_popup", listener);
XdgPopup.create(
- wlr_xdg_popup,
+ wlr_popup,
xdg_popup.root,
xdg_popup.tree,
) catch {
- wlr_xdg_popup.resource.postNoMemory();
+ wlr_popup.resource.postNoMemory();
return;
};
}
@@ -95,20 +95,31 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.Xdg
fn handleReposition(listener: *wl.Listener(void)) void {
const xdg_popup: *XdgPopup = @fieldParentPtr("reposition", listener);
- const output = switch (SceneNodeData.fromNode(&xdg_popup.root.node).?.data) {
- .window => |_| @panic("TODO"),
- else => unreachable,
- };
-
- var box: wlr.Box = undefined;
- server.om.output_layout.getBox(output.wlr_output, &box);
-
var root_lx: c_int = undefined;
var root_ly: c_int = undefined;
_ = xdg_popup.root.node.coords(&root_lx, &root_ly);
+ const wlr_output = switch (SceneNodeData.fromNode(&xdg_popup.root.node).?.data) {
+ .window => |_| blk: {
+ var lx: f64 = undefined;
+ var ly: f64 = undefined;
+ server.om.output_layout.closestPoint(
+ null,
+ @as(f64, @floatFromInt(root_lx + xdg_popup.wlr_popup.scheduled.geometry.x)),
+ @as(f64, @floatFromInt(root_ly + xdg_popup.wlr_popup.scheduled.geometry.y)),
+ &lx,
+ &ly,
+ );
+ break :blk server.om.output_layout.outputAt(lx, ly).?;
+ },
+ .shell_surface, .lock_surface, .override_redirect => unreachable,
+ };
+
+ var box: wlr.Box = undefined;
+ server.om.output_layout.getBox(wlr_output, &box);
+
box.x -= root_lx;
box.y -= root_ly;
- xdg_popup.wlr_xdg_popup.unconstrainFromBox(&box);
+ xdg_popup.wlr_popup.unconstrainFromBox(&box);
}