git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit2adeb0fb90ac55c8cb1fc3e4fc03b9b937f6ecc8
parent23842fb811
authorIsaac Freund <[email protected]>
date2020-05-17 17:06
Make XdgPopup work with non-XdgToplevel parents

The idea is to use the same struct for layer shell popups.

 src/XdgPopup.zig    | 37 +++++++++++++++++++++++--------------
 src/XdgToplevel.zig |  6 +++---
 2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/src/XdgPopup.zig b/src/XdgPopup.zig
index afc01b3..b4ee56c 100644
--- a/src/XdgPopup.zig
+++ b/src/XdgPopup.zig
@@ -21,10 +21,14 @@ const std = @import("std");
 
 const c = @import("c.zig");
 
-const XdgToplevel = @import("XdgToplevel.zig");
+const Box = @import("Box.zig");
+const Output = @import("Output.zig");
 
-/// The toplevel this popup is a child of
-xdg_toplevel: *XdgToplevel,
+/// The output this popup is displayed on.
+output: *Output,
+
+/// Box of the parent of this popup tree. Needed to unconstrain child popups.
+parent_box: *const Box,
 
 /// The corresponding wlroots object
 wlr_xdg_popup: *c.wlr_xdg_popup,
@@ -32,15 +36,20 @@ wlr_xdg_popup: *c.wlr_xdg_popup,
 listen_destroy: c.wl_listener,
 listen_new_popup: c.wl_listener,
 
-pub fn init(self: *Self, xdg_toplevel: *XdgToplevel, wlr_xdg_popup: *c.wlr_xdg_popup) void {
-    self.xdg_toplevel = xdg_toplevel;
+pub fn init(
+    self: *Self,
+    output: *Output,
+    parent_box: *const Box,
+    wlr_xdg_popup: *c.wlr_xdg_popup,
+) void {
+    self.output = output;
+    self.parent_box = parent_box;
     self.wlr_xdg_popup = wlr_xdg_popup;
 
-    // The output box relative to the toplevel parent of the popup
-    const output = xdg_toplevel.view.output;
+    // The output box relative to the parent of the popup
     var box = c.wlr_output_layout_get_box(output.root.wlr_output_layout, output.wlr_output).*;
-    box.x -= xdg_toplevel.view.current_box.x;
-    box.y -= xdg_toplevel.view.current_box.y;
+    box.x -= parent_box.x;
+    box.y -= parent_box.y;
     c.wlr_xdg_popup_unconstrain_from_box(wlr_xdg_popup, &box);
 
     // Setup listeners
@@ -53,21 +62,21 @@ pub fn init(self: *Self, xdg_toplevel: *XdgToplevel, wlr_xdg_popup: *c.wlr_xdg_p
 
 fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
     const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
-    const server = self.xdg_toplevel.view.output.root.server;
+    const allocator = self.output.root.server.allocator;
 
     c.wl_list_remove(&self.listen_destroy.link);
     c.wl_list_remove(&self.listen_new_popup.link);
 
-    server.allocator.destroy(self);
+    allocator.destroy(self);
 }
 
 /// Called when a new xdg popup is requested by the client
 fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
     const self = @fieldParentPtr(Self, "listen_new_popup", listener.?);
     const wlr_xdg_popup = @ptrCast(*c.wlr_xdg_popup, @alignCast(@alignOf(*c.wlr_xdg_popup), data));
-    const server = self.xdg_toplevel.view.output.root.server;
+    const allocator = self.output.root.server.allocator;
 
     // This will free itself on destroy
-    var xdg_popup = server.allocator.create(Self) catch unreachable;
-    xdg_popup.init(self.xdg_toplevel, wlr_xdg_popup);
+    var xdg_popup = allocator.create(Self) catch unreachable;
+    xdg_popup.init(self.output, self.parent_box, wlr_xdg_popup);
 }
diff --git a/src/XdgToplevel.zig b/src/XdgToplevel.zig
index 95fee3e..b3806db 100644
--- a/src/XdgToplevel.zig
+++ b/src/XdgToplevel.zig
@@ -193,9 +193,9 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
 fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
     const self = @fieldParentPtr(Self, "listen_new_popup", listener.?);
     const wlr_xdg_popup = @ptrCast(*c.wlr_xdg_popup, @alignCast(@alignOf(*c.wlr_xdg_popup), data));
-    const server = self.view.output.root.server;
+    const allocator = self.view.output.root.server.allocator;
 
     // This will free itself on destroy
-    var xdg_popup = server.allocator.create(XdgPopup) catch unreachable;
-    xdg_popup.init(self, wlr_xdg_popup);
+    var xdg_popup = allocator.create(XdgPopup) catch unreachable;
+    xdg_popup.init(self.view.output, &self.view.current_box, wlr_xdg_popup);
 }