From 07f1da32409464d8a772c46e5ce1b77748a8ec30 Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Sun, 6 Aug 2023 23:56:19 +0530 Subject: [PATCH] stash Signed-off-by: Shinyzenith --- next/Server.zig | 23 ++++++- next/desktop/LayerSurface.zig | 114 ++++++++++++++++++++++++++++++++++ next/desktop/Output.zig | 29 ++++++++- next/desktop/OutputLayout.zig | 2 +- 4 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 next/desktop/LayerSurface.zig diff --git a/next/Server.zig b/next/Server.zig index 2e775a8..0b10607 100644 --- a/next/Server.zig +++ b/next/Server.zig @@ -22,6 +22,7 @@ const Cursor = @import("input/Cursor.zig"); const DecorationManager = @import("desktop/DecorationManager.zig"); const InputManager = @import("input/InputManager.zig"); const Keyboard = @import("input/Keyboard.zig"); +const LayerSurface = @import("desktop/LayerSurface.zig"); const Output = @import("desktop/Output.zig"); const OutputLayout = @import("desktop/OutputLayout.zig"); const Seat = @import("input/Seat.zig"); @@ -380,13 +381,15 @@ fn newXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgS }; } else { log.err("No focused wlr_output found. Skipping xdg_toplevel.", .{}); + xdg_surface.resource.destroy(); return; } } } // This callback is called when a new layer surface is created. -pub fn newLayerSurface(_: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { +pub fn newLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { + const self = @fieldParentPtr(Self, "new_layer_surface", listener); log.debug("Signal: wlr_layer_shell_new_surface", .{}); log.debug( "New layer surface: namespace {s}, layer {s}, anchor {b:0>4}, size {},{}, margin {},{},{},{}, exclusive_zone {}", @@ -403,7 +406,23 @@ pub fn newLayerSurface(_: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: wlr_layer_surface.pending.exclusive_zone, }, ); - // TODO: Finish this. + + if (wlr_layer_surface.output == null) { + const output = self.seat.focused_output orelse { + log.err("No focused output found for surface: {s}", .{wlr_layer_surface.namespace}); + wlr_layer_surface.destroy(); + return; + }; + + log.debug("Null output layer surface assigned to output: {s}", .{output.wlr_output.name}); + wlr_layer_surface.output = output.wlr_output; + } + + LayerSurface.init(wlr_layer_surface) catch { + log.err("Failed to allocate memory", .{}); + wlr_layer_surface.resource.postNoMemory(); + return; + }; } // This callback is called when a new xwayland surface is created. diff --git a/next/desktop/LayerSurface.zig b/next/desktop/LayerSurface.zig new file mode 100644 index 0000000..d781c1c --- /dev/null +++ b/next/desktop/LayerSurface.zig @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD 2-Clause "Simplified" License +// +// next/desktop/LayerSurface.zig +// +// Created by: Aakash Sen Sharma, August 2023 +// Copyright: (C) 2023, Aakash Sen Sharma & Contributors + +const Self = @This(); + +const allocator = @import("../utils/allocator.zig").allocator; +const log = std.log.scoped(.LayerSurface); +const server = &@import("../next.zig").server; +const std = @import("std"); + +const wl = @import("wayland").server.wl; +const wlr = @import("wlroots"); + +const Output = @import("Output.zig"); + +output: *Output, +mapped: bool = false, + +wlr_layer_surface: *wlr.LayerSurfaceV1, +scene_layer_surface: *wlr.SceneLayerSurfaceV1, +scene_tree: *wlr.SceneTree, +popup_scene_tree: *wlr.SceneTree, + +destroy: wl.Listener(*wlr.LayerSurfaceV1) = wl.Listener(*wlr.LayerSurfaceV1).init(handleDestroy), +map: wl.Listener(*wlr.LayerSurfaceV1) = wl.Listener(*wlr.LayerSurfaceV1).init(handleMap), +unmap: wl.Listener(*wlr.LayerSurfaceV1) = wl.Listener(*wlr.LayerSurfaceV1).init(handleUnmap), +commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit), +//new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup), + +pub fn init(wlr_layer_surface: *wlr.LayerSurfaceV1) error{OutOfMemory}!void { + const layer_surface_output = @intToPtr(*Output, wlr_layer_surface.output.?.data); + + const self = try allocator.create(Self); + errdefer allocator.destroy(self); + + var layer_tree: *wlr.SceneTree = undefined; + switch (wlr_layer_surface.current.layer) { + .background => { + layer_tree = server.layer_bg; + }, + .bottom => { + layer_tree = server.layer_bottom; + }, + .top => { + layer_tree = server.layer_top; + }, + .overlay => { + layer_tree = server.layer_overlay; + }, + else => {}, + } + + const scene_layer_surface = try layer_tree.createSceneLayerSurfaceV1(wlr_layer_surface); + const popup_scene_tree = try layer_tree.createSceneTree(); + wlr_layer_surface.surface.data = @ptrToInt(popup_scene_tree); + + self.* = .{ + .output = layer_surface_output, + .wlr_layer_surface = wlr_layer_surface, + .scene_layer_surface = scene_layer_surface, + .scene_tree = scene_layer_surface.tree, + .popup_scene_tree = popup_scene_tree, + }; + + self.scene_tree.node.data = @ptrToInt(self); + + wlr_layer_surface.data = @ptrToInt(self); + + wlr_layer_surface.events.destroy.add(&self.destroy); + wlr_layer_surface.events.map.add(&self.map); + wlr_layer_surface.events.unmap.add(&self.unmap); + + handleCommit(&self.commit, wlr_layer_surface.surface); + + // Temporarily set layers state to pending so we can arrange it easily. + const previous_state = wlr_layer_surface.current; + wlr_layer_surface.current = wlr_layer_surface.pending; + self.mapped = true; + //TODO: arrangelayers. + wlr_layer_surface.current = previous_state; +} + +fn handleMap(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { + const self = @fieldParentPtr(Self, "map", listener); + log.debug("Signal: wlr_layer_surface_v1_map", .{}); + log.debug("Layer surface '{s}' mapped", .{wlr_layer_surface.namespace}); + + _ = self; +} + +fn handleUnmap(_: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfaceV1) void {} +fn handleDestroy(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfaceV1) void { + const self = @fieldParentPtr(Self, "destroy", listener); + log.debug("Signal: wlr_layer_surface_v1_destroy", .{}); + + self.destroy.link.remove(); + self.map.link.remove(); + self.unmap.link.remove(); + + //TODO: Destroy all popups here. + + allocator.destroy(self); +} + +fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void { + const self = @fieldParentPtr(Self, "commit", listener); + log.debug("Signal: wlr_surface_commit", .{}); + + _ = self; +} diff --git a/next/desktop/Output.zig b/next/desktop/Output.zig index 9dd926e..00f9870 100644 --- a/next/desktop/Output.zig +++ b/next/desktop/Output.zig @@ -26,6 +26,7 @@ pub const WallpaperMode = enum { }; server: *Server, +usable_box: wlr.Box, // The output space remaining after respecting layer-shelll exclusive zones. wlr_output: *wlr.Output, @@ -67,9 +68,19 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void { //TODO: self.wlr_output.enableAdaptiveSync(true); if config states it. + var width: c_int = undefined; + var height: c_int = undefined; + self.wlr_output.effectiveResolution(&width, &height); + self.* = .{ .server = server, .wlr_output = wlr_output, + .usable_box = .{ + .x = 0, + .y = 0, + .width = width, + .height = height, + }, }; self.wlr_output.data = @ptrToInt(&self); @@ -96,7 +107,7 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void { } // If focused_output is null, we become the new focused_output :) - if (self.server.seat.focused_output) |_| {} else { + if (self.server.seat.focused_output == null) { self.server.seat.focusOutput(self); } } @@ -251,3 +262,19 @@ pub fn getName(self: *Self) []const u8 { const name = self.wlr_output.name; return std.mem.span(name); } + +pub fn arrangeLayers(self: *Self) void { + var box: wlr.Box = .{ + .x = 0, + .y = 0, + .width = undefined, + .height = undefined, + }; + self.wlr_output.effectiveResolution(&box.width, &box.height); + + var usable_box = box; + + //TODO: Finish this. + + self.usable_box = usable_box; +} diff --git a/next/desktop/OutputLayout.zig b/next/desktop/OutputLayout.zig index 5df12f5..12a9dd4 100644 --- a/next/desktop/OutputLayout.zig +++ b/next/desktop/OutputLayout.zig @@ -41,7 +41,7 @@ fn layoutChange(listener: *wl.Listener(*wlr.OutputLayout), _: *wlr.OutputLayout) // Everytime an output is resized / added / removed, we redo wallpaper rendering. // This is probably not efficient but without it in nested sessions, if wlr_output is resized, the wallpaper doesn't get resized accordingly. for (self.server.outputs.items) |output| { - if (self.server.seat.focused_output) |_| {} else { + if (self.server.seat.focused_output == null) { self.server.seat.focusOutput(output); }