Output: use separate scene trees for layers
This commit is contained in:
		| @ -95,7 +95,7 @@ fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurface | ||||
|  | ||||
|     // Remove from the output's list of layer surfaces | ||||
|     const self_node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); | ||||
|     self.output.layers[@intCast(usize, @enumToInt(self.layer))].remove(self_node); | ||||
|     self.output.layer_surfaces[@intCast(usize, @enumToInt(self.layer))].remove(self_node); | ||||
|  | ||||
|     // If the unmapped surface is focused, clear focus | ||||
|     var it = server.input_manager.seats.first; | ||||
|  | ||||
| @ -57,7 +57,7 @@ const State = struct { | ||||
| wlr_output: *wlr.Output, | ||||
|  | ||||
| /// All layer surfaces on the output, indexed by the layer enum. | ||||
| layers: [4]std.TailQueue(LayerSurface) = [1]std.TailQueue(LayerSurface){.{}} ** 4, | ||||
| layer_surfaces: [4]std.TailQueue(LayerSurface) = [1]std.TailQueue(LayerSurface){.{}} ** 4, | ||||
|  | ||||
| /// The area left for views and other layer surfaces after applying the | ||||
| /// exclusive zones of exclusive layer surfaces. | ||||
| @ -70,6 +70,24 @@ tree: *wlr.SceneTree, | ||||
| normal_content: *wlr.SceneTree, | ||||
| locked_content: *wlr.SceneTree, | ||||
|  | ||||
| layers: struct { | ||||
|     background_color_rect: *wlr.SceneRect, | ||||
|     /// Background layer shell layer | ||||
|     background: *wlr.SceneTree, | ||||
|     /// Bottom layer shell layer | ||||
|     bottom: *wlr.SceneTree, | ||||
|     /// Tiled and floating views | ||||
|     views: *wlr.SceneTree, | ||||
|     /// Top layer shell layer | ||||
|     top: *wlr.SceneTree, | ||||
|     /// Fullscreen views | ||||
|     fullscreen: *wlr.SceneTree, | ||||
|     /// Overlay layer shell layer | ||||
|     overlay: *wlr.SceneTree, | ||||
|     /// Xdg popups, Xwayland override redirect windows | ||||
|     popups: *wlr.SceneTree, | ||||
| }, | ||||
|  | ||||
| /// The top of the stack is the "most important" view. | ||||
| views: ViewStack(View) = .{}, | ||||
|  | ||||
| @ -146,16 +164,44 @@ pub fn create(wlr_output: *wlr.Output) !void { | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     var width: c_int = undefined; | ||||
|     var height: c_int = undefined; | ||||
|     wlr_output.effectiveResolution(&width, &height); | ||||
|  | ||||
|     const tree = try server.root.scene.tree.createSceneTree(); | ||||
|     const normal_content = try tree.createSceneTree(); | ||||
|  | ||||
|     self.* = .{ | ||||
|         .wlr_output = wlr_output, | ||||
|         .tree = tree, | ||||
|         .normal_content = try tree.createSceneTree(), | ||||
|         .normal_content = normal_content, | ||||
|         .locked_content = try tree.createSceneTree(), | ||||
|         .usable_box = undefined, | ||||
|         .layers = .{ | ||||
|             .background_color_rect = try normal_content.createSceneRect( | ||||
|                 width, | ||||
|                 height, | ||||
|                 &server.config.background_color, | ||||
|             ), | ||||
|             .background = try normal_content.createSceneTree(), | ||||
|             .bottom = try normal_content.createSceneTree(), | ||||
|             .views = try normal_content.createSceneTree(), | ||||
|             .top = try normal_content.createSceneTree(), | ||||
|             .fullscreen = try normal_content.createSceneTree(), | ||||
|             .overlay = try normal_content.createSceneTree(), | ||||
|             .popups = try normal_content.createSceneTree(), | ||||
|         }, | ||||
|         .usable_box = .{ | ||||
|             .x = 0, | ||||
|             .y = 0, | ||||
|             .width = width, | ||||
|             .height = height, | ||||
|         }, | ||||
|     }; | ||||
|     wlr_output.data = @ptrToInt(self); | ||||
|  | ||||
|     _ = try self.layers.fullscreen.createSceneRect(width, height, &[_]f32{ 0, 0, 0, 1.0 }); | ||||
|     self.layers.fullscreen.node.setEnabled(false); | ||||
|  | ||||
|     wlr_output.events.destroy.add(&self.destroy); | ||||
|     wlr_output.events.enable.add(&self.enable); | ||||
|     wlr_output.events.mode.add(&self.mode); | ||||
| @ -171,14 +217,6 @@ pub fn create(wlr_output: *wlr.Output) !void { | ||||
|             std.log.scoped(.cursor).err("failed to load xcursor theme at scale {}", .{wlr_output.scale}); | ||||
|     } | ||||
|  | ||||
|     self.usable_box = .{ | ||||
|         .x = 0, | ||||
|         .y = 0, | ||||
|         .width = undefined, | ||||
|         .height = undefined, | ||||
|     }; | ||||
|     self.wlr_output.effectiveResolution(&self.usable_box.width, &self.usable_box.height); | ||||
|  | ||||
|     self.setTitle(); | ||||
|  | ||||
|     const ptr_node = try util.gpa.create(std.TailQueue(*Self).Node); | ||||
| @ -189,7 +227,7 @@ pub fn create(wlr_output: *wlr.Output) !void { | ||||
| } | ||||
|  | ||||
| pub fn getLayer(self: *Self, layer: zwlr.LayerShellV1.Layer) *std.TailQueue(LayerSurface) { | ||||
|     return &self.layers[@intCast(usize, @enumToInt(layer))]; | ||||
|     return &self.layer_surfaces[@intCast(usize, @enumToInt(layer))]; | ||||
| } | ||||
|  | ||||
| pub fn sendViewTags(self: Self) void { | ||||
| @ -475,7 +513,7 @@ fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { | ||||
|     // Remove the destroyed output from root if it wasn't already removed | ||||
|     server.root.removeOutput(self); | ||||
|     assert(self.views.first == null and self.views.last == null); | ||||
|     for (self.layers) |layer| assert(layer.len == 0); | ||||
|     for (self.layer_surfaces) |layer| assert(layer.len == 0); | ||||
|     assert(self.layouts.len == 0); | ||||
|  | ||||
|     var it = server.root.all_outputs.first; | ||||
| @ -538,6 +576,18 @@ fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { | ||||
|  | ||||
| fn handleMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { | ||||
|     const self = @fieldParentPtr(Self, "mode", listener); | ||||
|  | ||||
|     { | ||||
|         var width: c_int = undefined; | ||||
|         var height: c_int = undefined; | ||||
|         self.wlr_output.effectiveResolution(&width, &height); | ||||
|         self.layers.background_color_rect.setSize(width, height); | ||||
|  | ||||
|         var it = self.layers.fullscreen.children.iterator(.forward); | ||||
|         const background_color_rect = @fieldParentPtr(wlr.SceneRect, "node", it.next().?); | ||||
|         background_color_rect.setSize(width, height); | ||||
|     } | ||||
|  | ||||
|     self.arrangeLayers(.mapped); | ||||
|     self.arrangeViews(); | ||||
|     server.root.startTransaction(); | ||||
|  | ||||
| @ -93,7 +93,10 @@ pub fn init(self: *Self) !void { | ||||
|     const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self); | ||||
|     errdefer transaction_timer.remove(); | ||||
|  | ||||
|     // TODO get rid of this hack somehow | ||||
|     const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080); | ||||
|     const noop_tree = try scene.tree.createSceneTree(); | ||||
|     noop_tree.node.setEnabled(false); | ||||
|     self.* = .{ | ||||
|         .scene = scene, | ||||
|         .output_layout = output_layout, | ||||
| @ -102,9 +105,23 @@ pub fn init(self: *Self) !void { | ||||
|         .transaction_timer = transaction_timer, | ||||
|         .noop_output = .{ | ||||
|             .wlr_output = noop_wlr_output, | ||||
|             .tree = try scene.tree.createSceneTree(), | ||||
|             .normal_content = try scene.tree.createSceneTree(), | ||||
|             .locked_content = try scene.tree.createSceneTree(), | ||||
|             .tree = noop_tree, | ||||
|             .normal_content = try noop_tree.createSceneTree(), | ||||
|             .locked_content = try noop_tree.createSceneTree(), | ||||
|             .layers = .{ | ||||
|                 .background_color_rect = try noop_tree.createSceneRect( | ||||
|                     0, | ||||
|                     0, | ||||
|                     &server.config.background_color, | ||||
|                 ), | ||||
|                 .background = try noop_tree.createSceneTree(), | ||||
|                 .bottom = try noop_tree.createSceneTree(), | ||||
|                 .views = try noop_tree.createSceneTree(), | ||||
|                 .top = try noop_tree.createSceneTree(), | ||||
|                 .fullscreen = try noop_tree.createSceneTree(), | ||||
|                 .overlay = try noop_tree.createSceneTree(), | ||||
|                 .popups = try noop_tree.createSceneTree(), | ||||
|             }, | ||||
|             .usable_box = .{ .x = 0, .y = 0, .width = 0, .height = 0 }, | ||||
|         }, | ||||
|     }; | ||||
| @ -218,7 +235,7 @@ pub fn removeOutput(self: *Self, output: *Output) void { | ||||
|     } | ||||
|  | ||||
|     // Close all layer surfaces on the removed output | ||||
|     for (output.layers) |*layer| { | ||||
|     for (output.layer_surfaces) |*layer| { | ||||
|         // Destroying the layer surface will cause it to be removed from this list. | ||||
|         while (layer.first) |layer_node| layer_node.data.wlr_layer_surface.destroy(); | ||||
|     } | ||||
|  | ||||
| @ -63,7 +63,7 @@ pub fn create(output: *Output, xdg_toplevel: *wlr.XdgToplevel) error{OutOfMemory | ||||
|     errdefer util.gpa.destroy(node); | ||||
|     const view = &node.view; | ||||
|  | ||||
|     const tree = try output.normal_content.createSceneXdgSurface(xdg_toplevel.base); | ||||
|     const tree = try output.layers.views.createSceneXdgSurface(xdg_toplevel.base); | ||||
|     errdefer tree.node.destroy(); | ||||
|  | ||||
|     try view.init(output, tree, .{ .xdg_toplevel = .{ | ||||
|  | ||||
| @ -68,7 +68,7 @@ pub fn create(output: *Output, xwayland_surface: *wlr.XwaylandSurface) error{Out | ||||
|     const view = &node.view; | ||||
|  | ||||
|     // TODO actually render xwayland windows, not just an empty tree. | ||||
|     const tree = try output.tree.createSceneTree(); | ||||
|     const tree = try output.layers.views.createSceneTree(); | ||||
|  | ||||
|     view.init(output, tree, .{ .xwayland_view = .{ | ||||
|         .view = view, | ||||
|  | ||||
| @ -46,6 +46,11 @@ pub fn backgroundColor( | ||||
|     if (args.len > 2) return Error.TooManyArguments; | ||||
|  | ||||
|     server.config.background_color = try parseRgba(args[1]); | ||||
|     var it = server.root.all_outputs.first; | ||||
|     while (it) |node| : (it = node.next) { | ||||
|         const output = node.data; | ||||
|         output.layers.background_color_rect.setColor(&server.config.background_color); | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn borderColorFocused( | ||||
|  | ||||
		Reference in New Issue
	
	Block a user