Output: use separate scene trees for layers
This commit is contained in:
parent
b38676f078
commit
f4a8d6dcc9
@ -95,7 +95,7 @@ fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurface
|
|||||||
|
|
||||||
// Remove from the output's list of layer surfaces
|
// Remove from the output's list of layer surfaces
|
||||||
const self_node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
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
|
// If the unmapped surface is focused, clear focus
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
|
@ -57,7 +57,7 @@ const State = struct {
|
|||||||
wlr_output: *wlr.Output,
|
wlr_output: *wlr.Output,
|
||||||
|
|
||||||
/// All layer surfaces on the output, indexed by the layer enum.
|
/// 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
|
/// The area left for views and other layer surfaces after applying the
|
||||||
/// exclusive zones of exclusive layer surfaces.
|
/// exclusive zones of exclusive layer surfaces.
|
||||||
@ -70,6 +70,24 @@ tree: *wlr.SceneTree,
|
|||||||
normal_content: *wlr.SceneTree,
|
normal_content: *wlr.SceneTree,
|
||||||
locked_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.
|
/// The top of the stack is the "most important" view.
|
||||||
views: ViewStack(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 tree = try server.root.scene.tree.createSceneTree();
|
||||||
|
const normal_content = try tree.createSceneTree();
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.wlr_output = wlr_output,
|
.wlr_output = wlr_output,
|
||||||
.tree = tree,
|
.tree = tree,
|
||||||
.normal_content = try tree.createSceneTree(),
|
.normal_content = normal_content,
|
||||||
.locked_content = try tree.createSceneTree(),
|
.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);
|
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.destroy.add(&self.destroy);
|
||||||
wlr_output.events.enable.add(&self.enable);
|
wlr_output.events.enable.add(&self.enable);
|
||||||
wlr_output.events.mode.add(&self.mode);
|
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});
|
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();
|
self.setTitle();
|
||||||
|
|
||||||
const ptr_node = try util.gpa.create(std.TailQueue(*Self).Node);
|
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) {
|
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 {
|
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
|
// Remove the destroyed output from root if it wasn't already removed
|
||||||
server.root.removeOutput(self);
|
server.root.removeOutput(self);
|
||||||
assert(self.views.first == null and self.views.last == null);
|
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);
|
assert(self.layouts.len == 0);
|
||||||
|
|
||||||
var it = server.root.all_outputs.first;
|
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 {
|
fn handleMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
|
||||||
const self = @fieldParentPtr(Self, "mode", listener);
|
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.arrangeLayers(.mapped);
|
||||||
self.arrangeViews();
|
self.arrangeViews();
|
||||||
server.root.startTransaction();
|
server.root.startTransaction();
|
||||||
|
@ -93,7 +93,10 @@ pub fn init(self: *Self) !void {
|
|||||||
const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self);
|
const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self);
|
||||||
errdefer transaction_timer.remove();
|
errdefer transaction_timer.remove();
|
||||||
|
|
||||||
|
// TODO get rid of this hack somehow
|
||||||
const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080);
|
const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080);
|
||||||
|
const noop_tree = try scene.tree.createSceneTree();
|
||||||
|
noop_tree.node.setEnabled(false);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.scene = scene,
|
.scene = scene,
|
||||||
.output_layout = output_layout,
|
.output_layout = output_layout,
|
||||||
@ -102,9 +105,23 @@ pub fn init(self: *Self) !void {
|
|||||||
.transaction_timer = transaction_timer,
|
.transaction_timer = transaction_timer,
|
||||||
.noop_output = .{
|
.noop_output = .{
|
||||||
.wlr_output = noop_wlr_output,
|
.wlr_output = noop_wlr_output,
|
||||||
.tree = try scene.tree.createSceneTree(),
|
.tree = noop_tree,
|
||||||
.normal_content = try scene.tree.createSceneTree(),
|
.normal_content = try noop_tree.createSceneTree(),
|
||||||
.locked_content = try scene.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 },
|
.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
|
// 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.
|
// 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();
|
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);
|
errdefer util.gpa.destroy(node);
|
||||||
const view = &node.view;
|
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();
|
errdefer tree.node.destroy();
|
||||||
|
|
||||||
try view.init(output, tree, .{ .xdg_toplevel = .{
|
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;
|
const view = &node.view;
|
||||||
|
|
||||||
// TODO actually render xwayland windows, not just an empty tree.
|
// 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.init(output, tree, .{ .xwayland_view = .{
|
||||||
.view = view,
|
.view = view,
|
||||||
|
@ -46,6 +46,11 @@ pub fn backgroundColor(
|
|||||||
if (args.len > 2) return Error.TooManyArguments;
|
if (args.len > 2) return Error.TooManyArguments;
|
||||||
|
|
||||||
server.config.background_color = try parseRgba(args[1]);
|
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(
|
pub fn borderColorFocused(
|
||||||
|
Loading…
Reference in New Issue
Block a user