aboutsummaryrefslogtreecommitdiff
path: root/src/server.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.zig')
-rw-r--r--src/server.zig44
1 files changed, 41 insertions, 3 deletions
diff --git a/src/server.zig b/src/server.zig
index 54d3efe..7206341 100644
--- a/src/server.zig
+++ b/src/server.zig
@@ -11,8 +11,10 @@ pub const Server = struct {
listen_new_output: c.wl_listener,
- xdg_shell: *c.wlr_xdg_shell,
- new_xdg_surface: c.wl_listener,
+ wlr_xdg_shell: *c.wlr_xdg_shell,
+ listen_new_xdg_surface: c.wl_listener,
+
+ // Must stay ordered bottom to top
views: std.ArrayList(View),
pub fn init(allocator: *std.mem.Allocator) !@This() {
@@ -57,6 +59,17 @@ pub const Server = struct {
// Setup a listener for new outputs
server.listen_new_output = handle_new_output;
c.wl_signal_add(&server.wlr_backend.*.events.new_output, &server.listen_new_output);
+
+ // Set up our list of views and the xdg-shell. The xdg-shell is a Wayland
+ // protocol which is used for application windows.
+ // https://drewdevault.com/2018/07/29/Wayland-shells.html
+ server.views = std.ArrayList(View).init(std.heap.c_allocator);
+ server.wlr_xdg_shell = c.wlr_xdg_shell_create(server.wl_display) orelse
+ return error.CantCreateWlrXdgShell;
+ server.listen_new_xdg_surface.notify = handle_new_xdg_surface;
+ c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &server.listen_new_xdg_surface);
+
+ return server;
}
/// Free allocated memory and clean up
@@ -120,6 +133,31 @@ pub const Server = struct {
var wlr_output = @ptrCast(*c.wlr_output, @alignCast(@alignOf(*c.wlr_output), data));
// TODO: Handle failure
- server.outputs.append(Output.init(server, wlr_output) orelse return);
+ server.outputs.append(Output.init(server, wlr_output) catch unreachable);
+ }
+
+ fn handle_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
+ // This event is raised when wlr_xdg_shell receives a new xdg surface from a
+ // client, either a toplevel (application window) or popup.
+ var server = @fieldParentPtr(Server, "listen_new_xdg_surface", listener);
+ var wlr_xdg_surface = @ptrCast(*c.wlr_xdg_surface, @alignCast(@alignOf(*c.wlr_xdg_surface), data));
+
+ if (wlr_xdg_surface.role != c.enum_wlr_xdg_surface_role.WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
+ return;
+ }
+
+ // Init a View to handle this surface
+ server.*.views.append(View.init(server, wlr_xdg_surface)) catch unreachable;
+ }
+
+ /// Finds the top most view under the output layout coordinates lx, ly
+ /// returns the view if found, and a pointer to the wlr_surface as well as the surface coordinates
+ pub fn desktop_view_at(self: *@This(), lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) ?*View {
+ for (server.*.views.span()) |*view| {
+ if (view.is_at(lx, ly, surface, sx, sy)) {
+ return view;
+ }
+ }
+ return null;
}
};