diff --git a/river/Cursor.zig b/river/Cursor.zig index 953b57f..810d360 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -357,7 +357,7 @@ fn updateKeyboardFocus(self: Self, result: Root.AtResult) void { self.seat.focusOutput(layer_surface.output); // If a keyboard inteactive layer surface has been clicked on, // give it keyboard focus. - if (layer_surface.wlr_layer_surface.current.keyboard_interactive == .exclusive) { + if (layer_surface.scene_layer_surface.layer_surface.current.keyboard_interactive != .none) { self.seat.setFocusRaw(.{ .layer = layer_surface }); } else { self.seat.focus(null); diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig index 1e84740..296eb9f 100644 --- a/river/LayerSurface.zig +++ b/river/LayerSurface.zig @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -const Self = @This(); +const LayerSurface = @This(); const std = @import("std"); const assert = std.debug.assert; @@ -26,125 +26,140 @@ const server = &@import("main.zig").server; const util = @import("util.zig"); const Output = @import("Output.zig"); +const SceneNodeData = @import("SceneNodeData.zig"); const log = std.log.scoped(.layer_shell); output: *Output, -wlr_layer_surface: *wlr.LayerSurfaceV1, - -box: wlr.Box = undefined, -layer: zwlr.LayerShellV1.Layer, +scene_layer_surface: *wlr.SceneLayerSurfaceV1, 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), -pub fn init(self: *Self, output: *Output, wlr_layer_surface: *wlr.LayerSurfaceV1) void { - self.* = .{ - .output = output, - .wlr_layer_surface = wlr_layer_surface, - .layer = wlr_layer_surface.current.layer, - }; - wlr_layer_surface.data = @ptrToInt(self); +pub fn create(wlr_layer_surface: *wlr.LayerSurfaceV1) error{OutOfMemory}!void { + const output = @intToPtr(*Output, wlr_layer_surface.output.?.data); + const layer_surface = try util.gpa.create(LayerSurface); + errdefer util.gpa.destroy(layer_surface); - // Set up listeners that are active for the entire lifetime of the layer surface - wlr_layer_surface.events.destroy.add(&self.destroy); - wlr_layer_surface.events.map.add(&self.map); - wlr_layer_surface.events.unmap.add(&self.unmap); - wlr_layer_surface.surface.events.commit.add(&self.commit); + const tree = output.layerSurfaceTree(wlr_layer_surface.current.layer); + const scene_layer_surface = try tree.createSceneLayerSurfaceV1(wlr_layer_surface); + + try SceneNodeData.attach(&scene_layer_surface.tree.node, .{ .layer_surface = layer_surface }); + + layer_surface.* = .{ + .output = output, + .scene_layer_surface = scene_layer_surface, + }; + wlr_layer_surface.data = @ptrToInt(layer_surface); + + wlr_layer_surface.events.destroy.add(&layer_surface.destroy); + wlr_layer_surface.events.map.add(&layer_surface.map); + wlr_layer_surface.events.unmap.add(&layer_surface.unmap); + wlr_layer_surface.surface.events.commit.add(&layer_surface.commit); // wlroots only informs us of the new surface after the first commit, // so our listener does not get called for this first commit. However, // we do want our listener called in order to send the initial configure. - handleCommit(&self.commit, wlr_layer_surface.surface); + handleCommit(&layer_surface.commit, wlr_layer_surface.surface); } -fn handleDestroy(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfaceV1) void { - const self = @fieldParentPtr(Self, "destroy", listener); +fn handleDestroy(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { + const layer_surface = @fieldParentPtr(LayerSurface, "destroy", listener); - log.debug("layer surface '{s}' destroyed", .{self.wlr_layer_surface.namespace}); + log.debug("layer surface '{s}' destroyed", .{wlr_layer_surface.namespace}); - // Remove listeners active the entire lifetime of the layer surface - self.destroy.link.remove(); - self.map.link.remove(); - self.unmap.link.remove(); - self.commit.link.remove(); + layer_surface.destroy.link.remove(); + layer_surface.map.link.remove(); + layer_surface.unmap.link.remove(); + layer_surface.commit.link.remove(); - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - util.gpa.destroy(node); + util.gpa.destroy(layer_surface); } fn handleMap(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { - const self = @fieldParentPtr(Self, "map", listener); + const layer_surface = @fieldParentPtr(LayerSurface, "map", listener); log.debug("layer surface '{s}' mapped", .{wlr_layer_surface.namespace}); - wlr_layer_surface.surface.sendEnter(wlr_layer_surface.output.?); - - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - self.output.getLayer(self.layer).append(node); - self.output.arrangeLayers(.mapped); + layer_surface.output.arrangeLayers(); + handleKeyboardInteractiveExclusive(layer_surface.output); server.root.startTransaction(); } -fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfaceV1) void { - const self = @fieldParentPtr(Self, "unmap", listener); +fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { + const layer_surface = @fieldParentPtr(LayerSurface, "unmap", listener); - log.debug("layer surface '{s}' unmapped", .{self.wlr_layer_surface.namespace}); - - // Remove from the output's list of layer surfaces - const self_node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - 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; - while (it) |node| : (it = node.next) { - const seat = &node.data; - if (seat.focused == .layer and seat.focused.layer == self) - seat.setFocusRaw(.{ .none = {} }); - } - - // This gives exclusive focus to a keyboard interactive top or overlay layer - // surface if there is one. - self.output.arrangeLayers(.mapped); - - // Ensure that focus is given to the appropriate view if there is no - // other top/overlay layer surface to grab focus. - it = server.input_manager.seats.first; - while (it) |node| : (it = node.next) { - const seat = &node.data; - seat.focus(null); - } + log.debug("layer surface '{s}' unmapped", .{wlr_layer_surface.namespace}); + layer_surface.output.arrangeLayers(); + handleKeyboardInteractiveExclusive(layer_surface.output); server.root.startTransaction(); } fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void { - const self = @fieldParentPtr(Self, "commit", listener); + const layer_surface = @fieldParentPtr(LayerSurface, "commit", listener); + const wlr_layer_surface = layer_surface.scene_layer_surface.layer_surface; - assert(self.wlr_layer_surface.output != null); + assert(wlr_layer_surface.output != null); - // If a surface is committed while it is not mapped, we may need to send a configure. - if (!self.wlr_layer_surface.mapped) { - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - self.layer = self.wlr_layer_surface.current.layer; - self.output.getLayer(self.layer).append(node); - self.output.arrangeLayers(.unmapped); - self.output.getLayer(self.layer).remove(node); - return; + // If the layer was changed, move the LayerSurface to the proper tree. + if (wlr_layer_surface.current.committed.layer) { + const tree = layer_surface.output.layerSurfaceTree(wlr_layer_surface.current.layer); + layer_surface.scene_layer_surface.tree.node.reparent(tree); } - if (@bitCast(u32, self.wlr_layer_surface.current.committed) != 0) { - // If the layer changed, move the LayerSurface to the proper list - if (self.wlr_layer_surface.current.layer != self.layer) { - const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - self.output.getLayer(self.layer).remove(node); - self.layer = self.wlr_layer_surface.current.layer; - self.output.getLayer(self.layer).append(node); - } - - self.output.arrangeLayers(.mapped); + // If a surface is committed while it is not mapped, we must send a configure. + if (!wlr_layer_surface.mapped or @bitCast(u32, wlr_layer_surface.current.committed) != 0) { + layer_surface.output.arrangeLayers(); + handleKeyboardInteractiveExclusive(layer_surface.output); server.root.startTransaction(); } } + +fn handleKeyboardInteractiveExclusive(output: *Output) void { + if (server.lock_manager.state != .unlocked) return; + + // Find the topmost layer surface in the top or overlay layers which + // requests keyboard interactivity if any. + const topmost_surface = outer: for ([_]zwlr.LayerShellV1.Layer{ .overlay, .top }) |layer| { + const tree = output.layerSurfaceTree(layer); + // Iterate in reverse to match rendering order. + var it = tree.children.iterator(.reverse); + while (it.next()) |node| { + assert(node.type == .tree); + if (@intToPtr(?*SceneNodeData, node.data)) |node_data| { + const layer_surface = node_data.data.layer_surface; + const wlr_layer_surface = layer_surface.scene_layer_surface.layer_surface; + if (wlr_layer_surface.mapped and + wlr_layer_surface.current.keyboard_interactive == .exclusive) + { + break :outer layer_surface; + } + } + } + } else null; + + var it = server.input_manager.seats.first; + while (it) |node| : (it = node.next) { + const seat = &node.data; + + // Only grab focus of seats which have the output focused + if (seat.focused_output != output) continue; + + if (topmost_surface) |to_focus| { + // If we found a surface that requires focus, grab the focus of all + // seats. + seat.setFocusRaw(.{ .layer = to_focus }); + } else if (seat.focused == .layer) { + const current_focus = seat.focused.layer.scene_layer_surface.layer_surface; + // If the seat is currently focusing an unmapped layer surface or one + // without keyboard interactivity, stop focusing that layer surface. + if (!current_focus.mapped or current_focus.current.keyboard_interactive == .none) { + seat.setFocusRaw(.{ .none = {} }); + seat.focus(null); + } + } + } +} diff --git a/river/Output.zig b/river/Output.zig index f286fef..48f16cd 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -34,9 +34,10 @@ const LayerSurface = @import("LayerSurface.zig"); const Layout = @import("Layout.zig"); const LayoutDemand = @import("LayoutDemand.zig"); const LockSurface = @import("LockSurface.zig"); +const OutputStatus = @import("OutputStatus.zig"); +const SceneNodeData = @import("SceneNodeData.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; -const OutputStatus = @import("OutputStatus.zig"); const State = struct { /// A bit field of focused tags @@ -56,9 +57,6 @@ const State = struct { wlr_output: *wlr.Output, -/// All layer surfaces on the output, indexed by the layer enum. -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. /// TODO: this should be part of the output's State @@ -226,8 +224,14 @@ pub fn create(wlr_output: *wlr.Output) !void { handleEnable(&self.enable, self.wlr_output); } -pub fn getLayer(self: *Self, layer: zwlr.LayerShellV1.Layer) *std.TailQueue(LayerSurface) { - return &self.layer_surfaces[@intCast(usize, @enumToInt(layer))]; +pub fn layerSurfaceTree(self: Self, layer: zwlr.LayerShellV1.Layer) *wlr.SceneTree { + const trees = [_]*wlr.SceneTree{ + self.layers.background, + self.layers.bottom, + self.layers.top, + self.layers.overlay, + }; + return trees[@intCast(usize, @enumToInt(layer))]; } pub fn sendViewTags(self: Self) void { @@ -305,13 +309,9 @@ pub fn arrangeViews(self: *Self) void { } } -const ArrangeLayersTarget = enum { mapped, unmapped }; - /// Arrange all layer surfaces of this output and adjust the usable area. /// Will arrange views as well if the usable area changes. -/// If target is unmapped, this function is pure aside from the -/// wlr.LayerSurfaceV1.configure() calls made on umapped layer surfaces. -pub fn arrangeLayers(self: *Self, target: ArrangeLayersTarget) void { +pub fn arrangeLayers(self: *Self) void { var full_box: wlr.Box = .{ .x = 0, .y = 0, @@ -323,186 +323,22 @@ pub fn arrangeLayers(self: *Self, target: ArrangeLayersTarget) void { // This box is modified as exclusive zones are applied var usable_box = full_box; - const layers = [_]zwlr.LayerShellV1.Layer{ .overlay, .top, .bottom, .background }; - - // Arrange all layer surfaces with exclusive zones, applying them to the - // usable box along the way. - for (layers) |layer| arrangeLayer(self.getLayer(layer).*, full_box, &usable_box, true, target); + for ([_]zwlr.LayerShellV1.Layer{ .overlay, .top, .bottom, .background }) |layer| { + const tree = self.layerSurfaceTree(layer); + var it = tree.children.iterator(.forward); + while (it.next()) |node| { + assert(node.type == .tree); + if (@intToPtr(?*SceneNodeData, node.data)) |node_data| { + node_data.data.layer_surface.scene_layer_surface.configure(&full_box, &usable_box); + } + } + } // If the the usable_box has changed, we need to rearrange the output - if (target == .mapped and !std.meta.eql(self.usable_box, usable_box)) { + if (!std.meta.eql(self.usable_box, usable_box)) { self.usable_box = usable_box; self.arrangeViews(); } - - // Arrange the layers without exclusive zones - for (layers) |layer| arrangeLayer(self.getLayer(layer).*, full_box, &usable_box, false, target); - - if (target == .unmapped) return; - - if (server.lock_manager.state != .unlocked) return; - - // Find the topmost layer surface in the top or overlay layers which - // requests keyboard interactivity if any. - const topmost_surface = outer: for (layers[0..2]) |layer| { - // Iterate in reverse order since the last layer is rendered on top - var it = self.getLayer(layer).last; - while (it) |node| : (it = node.prev) { - const layer_surface = &node.data; - if (layer_surface.wlr_layer_surface.current.keyboard_interactive == .exclusive) { - break :outer layer_surface; - } - } - } else null; - - var it = server.input_manager.seats.first; - while (it) |node| : (it = node.next) { - const seat = &node.data; - - // Only grab focus of seats which have the output focused - if (seat.focused_output != self) continue; - - if (topmost_surface) |to_focus| { - // If we found a surface that requires focus, grab the focus of all - // seats. - seat.setFocusRaw(.{ .layer = to_focus }); - } else if (seat.focused == .layer) { - // If the seat is currently focusing a layer without keyboard - // interactivity, stop focusing that layer. - if (seat.focused.layer.wlr_layer_surface.current.keyboard_interactive != .exclusive) { - seat.setFocusRaw(.{ .none = {} }); - seat.focus(null); - } - } - } -} - -/// Arrange the layer surfaces of a given layer -fn arrangeLayer( - layer: std.TailQueue(LayerSurface), - full_box: wlr.Box, - usable_box: *wlr.Box, - exclusive: bool, - target: ArrangeLayersTarget, -) void { - var it = layer.first; - while (it) |node| : (it = node.next) { - const layer_surface = &node.data; - const current_state = layer_surface.wlr_layer_surface.current; - - const desired_width = @intCast(u31, math.min(math.maxInt(u31), current_state.desired_width)); - const desired_height = @intCast(u31, math.min(math.maxInt(u31), current_state.desired_height)); - - // If the value of exclusive_zone is greater than zero, then it exclusivly - // occupies some area of the screen. - if (exclusive != (current_state.exclusive_zone > 0)) continue; - - // If the exclusive zone is set to -1, this means the the client would like - // to ignore any exclusive zones and use the full area of the output. - const bounds = if (current_state.exclusive_zone == -1) &full_box else usable_box; - - var new_box: wlr.Box = undefined; - - // Horizontal alignment - if (desired_width == 0) { - assert(current_state.anchor.right and current_state.anchor.left); - new_box.x = bounds.x + current_state.margin.left; - new_box.width = bounds.width - (current_state.margin.left + current_state.margin.right); - } else if (current_state.anchor.left == current_state.anchor.right) { - new_box.x = bounds.x + @divTrunc(bounds.width, 2) - desired_width / 2; - new_box.width = desired_width; - } else if (current_state.anchor.left) { - new_box.x = bounds.x + current_state.margin.left; - new_box.width = desired_width; - } else { - assert(current_state.anchor.right); - new_box.x = bounds.x + bounds.width - desired_width - current_state.margin.right; - new_box.width = desired_width; - } - - // Vertical alignment - if (desired_height == 0) { - assert(current_state.anchor.top and current_state.anchor.bottom); - new_box.y = bounds.y + current_state.margin.top; - new_box.height = bounds.height - (current_state.margin.top + current_state.margin.bottom); - } else if (current_state.anchor.top == current_state.anchor.bottom) { - new_box.y = bounds.y + @divTrunc(bounds.height, 2) - desired_height / 2; - new_box.height = desired_height; - } else if (current_state.anchor.top) { - new_box.y = bounds.y + current_state.margin.top; - new_box.height = desired_height; - } else { - assert(current_state.anchor.bottom); - new_box.y = bounds.y + bounds.height - desired_height - current_state.margin.bottom; - new_box.height = desired_height; - } - - // Apply the exclusive zone to the current bounds - const edges = [4]struct { - single: zwlr.LayerSurfaceV1.Anchor, - triple: zwlr.LayerSurfaceV1.Anchor, - to_increase: ?*i32, - to_decrease: *i32, - margin: i32, - }{ - .{ - .single = .{ .top = true }, - .triple = .{ .top = true, .left = true, .right = true }, - .to_increase = &usable_box.y, - .to_decrease = &usable_box.height, - .margin = current_state.margin.top, - }, - .{ - .single = .{ .bottom = true }, - .triple = .{ .bottom = true, .left = true, .right = true }, - .to_increase = null, - .to_decrease = &usable_box.height, - .margin = current_state.margin.bottom, - }, - .{ - .single = .{ .left = true }, - .triple = .{ .left = true, .top = true, .bottom = true }, - .to_increase = &usable_box.x, - .to_decrease = &usable_box.width, - .margin = current_state.margin.left, - }, - .{ - .single = .{ .right = true }, - .triple = .{ .right = true, .top = true, .bottom = true }, - .to_increase = null, - .to_decrease = &usable_box.width, - .margin = current_state.margin.right, - }, - }; - - for (edges) |edge| { - if ((std.meta.eql(current_state.anchor, edge.single) or std.meta.eql(current_state.anchor, edge.triple)) and - current_state.exclusive_zone + edge.margin > 0) - { - const delta = current_state.exclusive_zone + edge.margin; - if (edge.to_increase) |value| value.* += delta; - edge.to_decrease.* -= delta; - break; - } - } - - switch (target) { - .mapped => { - assert(layer_surface.wlr_layer_surface.mapped); - layer_surface.box = new_box; - _ = layer_surface.wlr_layer_surface.configure( - @intCast(u32, new_box.width), - @intCast(u32, new_box.height), - ); - }, - .unmapped => if (!layer_surface.wlr_layer_surface.mapped) { - _ = layer_surface.wlr_layer_surface.configure( - @intCast(u32, new_box.width), - @intCast(u32, new_box.height), - ); - }, - } - } } fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { @@ -513,7 +349,6 @@ 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.layer_surfaces) |layer| assert(layer.len == 0); assert(self.layouts.len == 0); var it = server.root.all_outputs.first; @@ -588,8 +423,7 @@ fn handleMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { background_color_rect.setSize(width, height); } - self.arrangeLayers(.mapped); - self.arrangeViews(); + self.arrangeLayers(); server.root.startTransaction(); } diff --git a/river/Root.zig b/river/Root.zig index 8711ea4..4e1e5b9 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -22,6 +22,7 @@ const assert = std.debug.assert; const mem = std.mem; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const zwlr = @import("wayland").server.zwlr; const server = &@import("main.zig").server; const util = @import("util.zig"); @@ -178,6 +179,7 @@ pub fn at(self: Self, lx: f64, ly: f64) ?AtResult { .sy = sy, .node = switch (scene_node_data.data) { .view => |view| .{ .view = view }, + .layer_surface => |layer_surface| .{ .layer_surface = layer_surface }, .lock_surface => |lock_surface| .{ .lock_surface = lock_surface }, }, }; @@ -235,9 +237,15 @@ pub fn removeOutput(self: *Self, output: *Output) void { } // Close all layer surfaces on the removed output - 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(); + for ([_]zwlr.LayerShellV1.Layer{ .overlay, .top, .bottom, .background }) |layer| { + const tree = output.layerSurfaceTree(layer); + var it = tree.children.safeIterator(.forward); + while (it.next()) |scene_node| { + assert(scene_node.type == .tree); + if (@intToPtr(?*SceneNodeData, scene_node.data)) |node_data| { + node_data.data.layer_surface.scene_layer_surface.layer_surface.destroy(); + } + } } // If any seat has the removed output focused, focus the fallback one @@ -534,7 +542,7 @@ fn processOutputConfig( self.output_layout.add(output.wlr_output, head.state.x, head.state.y); output.tree.node.setEnabled(true); output.tree.node.setPosition(head.state.x, head.state.y); - output.arrangeLayers(.mapped); + output.arrangeLayers(); } else { self.removeOutput(output); self.output_layout.remove(output.wlr_output); diff --git a/river/SceneNodeData.zig b/river/SceneNodeData.zig index 63ce09a..b0fa8ba 100644 --- a/river/SceneNodeData.zig +++ b/river/SceneNodeData.zig @@ -22,12 +22,14 @@ const wl = @import("wayland").server.wl; const util = @import("util.zig"); +const LayerSurface = @import("LayerSurface.zig"); const LockSurface = @import("LockSurface.zig"); const View = @import("View.zig"); const Data = union(enum) { view: *View, lock_surface: *LockSurface, + layer_surface: *LayerSurface, }; node: *wlr.SceneNode, diff --git a/river/Seat.zig b/river/Seat.zig index a0ac936..9796bf7 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -157,8 +157,15 @@ pub fn focus(self: *Self, _target: ?*View) void { // Views may not recieve focus while locked. if (server.lock_manager.state != .unlocked) return; - // While a layer surface is focused, views may not recieve focus - if (self.focused == .layer) return; + // While a layer surface is exclusively focused, views may not recieve focus + if (self.focused == .layer) { + const wlr_layer_surface = self.focused.layer.scene_layer_surface.layer_surface; + if (wlr_layer_surface.current.keyboard_interactive == .exclusive and + (wlr_layer_surface.current.layer == .top or wlr_layer_surface.current.layer == .overlay)) + { + return; + } + } if (target) |view| { // If the view is not currently visible, behave as if null was passed @@ -224,7 +231,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { const target_surface = switch (new_focus) { .view => |target_view| target_view.rootSurface(), .xwayland_override_redirect => |target_or| target_or.xwayland_surface.surface, - .layer => |target_layer| target_layer.wlr_layer_surface.surface, + .layer => |target_layer| target_layer.scene_layer_surface.layer_surface.surface, .lock_surface => |lock_surface| lock_surface.wlr_lock_surface.surface, .none => null, }; diff --git a/river/Server.zig b/river/Server.zig index 66dfc09..6b2243e 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -198,7 +198,6 @@ fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wl }; } -/// This event is raised when the layer_shell recieves a new surface from a client. fn handleNewLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void { const self = @fieldParentPtr(Self, "new_layer_surface", listener); @@ -206,15 +205,15 @@ fn handleNewLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_ "new layer surface: namespace {s}, layer {s}, anchor {b:0>4}, size {},{}, margin {},{},{},{}, exclusive_zone {}", .{ wlr_layer_surface.namespace, - @tagName(wlr_layer_surface.pending.layer), - @bitCast(u32, wlr_layer_surface.pending.anchor), - wlr_layer_surface.pending.desired_width, - wlr_layer_surface.pending.desired_height, - wlr_layer_surface.pending.margin.top, - wlr_layer_surface.pending.margin.right, - wlr_layer_surface.pending.margin.bottom, - wlr_layer_surface.pending.margin.left, - wlr_layer_surface.pending.exclusive_zone, + @tagName(wlr_layer_surface.current.layer), + @bitCast(u32, wlr_layer_surface.current.anchor), + wlr_layer_surface.current.desired_width, + wlr_layer_surface.current.desired_height, + wlr_layer_surface.current.margin.top, + wlr_layer_surface.current.margin.right, + wlr_layer_surface.current.margin.bottom, + wlr_layer_surface.current.margin.left, + wlr_layer_surface.current.exclusive_zone, }, ); @@ -232,13 +231,10 @@ fn handleNewLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_ wlr_layer_surface.output = output.wlr_output; } - // The layer surface will add itself to the proper list of the output on map - const output = @intToPtr(*Output, wlr_layer_surface.output.?.data); - const node = util.gpa.create(std.TailQueue(LayerSurface).Node) catch { + LayerSurface.create(wlr_layer_surface) catch { wlr_layer_surface.resource.postNoMemory(); return; }; - node.data.init(output, wlr_layer_surface); } fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {