This commit is contained in:
2025-06-29 19:31:25 +09:00
68 changed files with 1298 additions and 1002 deletions

View File

@ -97,8 +97,6 @@ power_manager_set_mode: wl.Listener(*wlr.OutputPowerManagerV1.event.SetMode) =
wl.Listener(*wlr.OutputPowerManagerV1.event.SetMode).init(handlePowerManagerSetMode),
gamma_control_manager: *wlr.GammaControlManagerV1,
gamma_control_set_gamma: wl.Listener(*wlr.GammaControlManagerV1.event.SetGamma) =
wl.Listener(*wlr.GammaControlManagerV1.event.SetGamma).init(handleSetGamma),
/// A list of all outputs
all_outputs: wl.list.Head(Output, .all_link),
@ -117,12 +115,17 @@ transaction_timeout: *wl.EventSource,
pending_state_dirty: bool = false,
pub fn init(root: *Root) !void {
const output_layout = try wlr.OutputLayout.create();
const output_layout = try wlr.OutputLayout.create(server.wl_server);
errdefer output_layout.destroy();
const scene = try wlr.Scene.create();
errdefer scene.tree.node.destroy();
const gamma_control_manager = try wlr.GammaControlManagerV1.create(server.wl_server);
scene.setGammaControlManagerV1(gamma_control_manager);
if (server.linux_dmabuf) |linux_dmabuf| scene.setLinuxDmabufV1(linux_dmabuf);
const interactive_content = try scene.tree.createSceneTree();
const drag_icons = try scene.tree.createSceneTree();
const hidden_tree = try scene.tree.createSceneTree();
@ -131,9 +134,6 @@ pub fn init(root: *Root) !void {
const outputs = try interactive_content.createSceneTree();
const override_redirect = if (build_options.xwayland) try interactive_content.createSceneTree();
const presentation = try wlr.Presentation.create(server.wl_server, server.backend);
scene.setPresentation(presentation);
const event_loop = server.wl_server.getEventLoop();
const transaction_timeout = try event_loop.addTimer(*Root, handleTransactionTimeout, root);
errdefer transaction_timeout.remove();
@ -166,11 +166,11 @@ pub fn init(root: *Root) !void {
.all_outputs = undefined,
.active_outputs = undefined,
.presentation = presentation,
.presentation = try wlr.Presentation.create(server.wl_server, server.backend, 2),
.xdg_output_manager = try wlr.XdgOutputManagerV1.create(server.wl_server, output_layout),
.output_manager = try wlr.OutputManagerV1.create(server.wl_server),
.power_manager = try wlr.OutputPowerManagerV1.create(server.wl_server),
.gamma_control_manager = try wlr.GammaControlManagerV1.create(server.wl_server),
.gamma_control_manager = gamma_control_manager,
.transaction_timeout = transaction_timeout,
};
root.hidden.pending.focus_stack.init();
@ -190,10 +190,14 @@ pub fn init(root: *Root) !void {
root.output_manager.events.@"test".add(&root.manager_test);
root.output_layout.events.change.add(&root.layout_change);
root.power_manager.events.set_mode.add(&root.power_manager_set_mode);
root.gamma_control_manager.events.set_gamma.add(&root.gamma_control_set_gamma);
}
pub fn deinit(root: *Root) void {
root.manager_apply.link.remove();
root.manager_test.link.remove();
root.layout_change.link.remove();
root.power_manager_set_mode.link.remove();
root.output_layout.destroy();
root.transaction_timeout.remove();
}
@ -326,7 +330,7 @@ pub fn deactivateOutput(root: *Root, output: *Output) void {
var it = tree.children.safeIterator(.forward);
while (it.next()) |scene_node| {
assert(scene_node.type == .tree);
if (@as(?*SceneNodeData, @ptrFromInt(scene_node.data))) |node_data| {
if (@as(?*SceneNodeData, @alignCast(@ptrCast(scene_node.data)))) |node_data| {
node_data.data.layer_surface.wlr_layer_surface.destroy();
}
}
@ -416,6 +420,9 @@ pub fn activateOutput(root: *Root, output: *Output) void {
}
assert(root.fallback_pending.focus_stack.empty());
assert(root.fallback_pending.wm_stack.empty());
// Enforce map-to-output configuration for the newly active output.
server.input_manager.reconfigureDevices();
}
/// Trigger asynchronous application of pending state for all outputs and views.
@ -673,24 +680,12 @@ fn commitTransaction(root: *Root) void {
while (focus_stack_it.next()) |view| {
assert(view.inflight.output == output);
if (view.current.output != view.inflight.output or
(output.current.fullscreen == view and output.inflight.fullscreen != view))
{
if (view.inflight.float) {
view.tree.node.reparent(output.layers.float);
} else {
view.tree.node.reparent(output.layers.layout);
}
view.popup_tree.node.reparent(output.layers.popups);
}
if (view.current.float != view.inflight.float) {
if (view.inflight.float) {
view.tree.node.reparent(output.layers.float);
} else {
view.tree.node.reparent(output.layers.layout);
}
if (view.inflight.float) {
view.tree.node.reparent(output.layers.float);
} else {
view.tree.node.reparent(output.layers.layout);
}
view.popup_tree.node.reparent(output.layers.popups);
view.commitTransaction();
@ -703,15 +698,13 @@ fn commitTransaction(root: *Root) void {
}
}
if (output.inflight.fullscreen != output.current.fullscreen) {
if (output.inflight.fullscreen) |view| {
assert(view.inflight.output == output);
assert(view.current.output == output);
view.tree.node.reparent(output.layers.fullscreen);
}
output.current.fullscreen = output.inflight.fullscreen;
output.layers.fullscreen.node.setEnabled(output.current.fullscreen != null);
if (output.inflight.fullscreen) |view| {
assert(view.inflight.output == output);
assert(view.current.output == output);
view.tree.node.reparent(output.layers.fullscreen);
}
output.current.fullscreen = output.inflight.fullscreen;
output.layers.fullscreen.node.setEnabled(output.current.fullscreen != null);
output.status.handleTransactionCommit(output);
}
@ -743,7 +736,7 @@ fn commitTransaction(root: *Root) void {
// We need this listener to deal with outputs that have their position auto-configured
// by the wlr_output_layout.
fn handleLayoutChange(listener: *wl.Listener(*wlr.OutputLayout), _: *wlr.OutputLayout) void {
const root = @fieldParentPtr(Root, "layout_change", listener);
const root: *Root = @fieldParentPtr("layout_change", listener);
root.handleOutputConfigChange() catch std.log.err("out of memory", .{});
}
@ -778,7 +771,7 @@ fn handleManagerApply(
listener: *wl.Listener(*wlr.OutputConfigurationV1),
config: *wlr.OutputConfigurationV1,
) void {
const root = @fieldParentPtr(Root, "manager_apply", listener);
const root: *Root = @fieldParentPtr("manager_apply", listener);
defer config.destroy();
std.log.scoped(.output_manager).info("applying output configuration", .{});
@ -792,7 +785,7 @@ fn handleManagerTest(
listener: *wl.Listener(*wlr.OutputConfigurationV1),
config: *wlr.OutputConfigurationV1,
) void {
const root = @fieldParentPtr(Root, "manager_test", listener);
const root: *Root = @fieldParentPtr("manager_test", listener);
defer config.destroy();
root.processOutputConfig(config, .test_only);
@ -812,7 +805,7 @@ fn processOutputConfig(
var it = config.heads.iterator(.forward);
while (it.next()) |head| {
const wlr_output = head.state.output;
const output: *Output = @ptrFromInt(wlr_output.data);
const output: *Output = @alignCast(@ptrCast(wlr_output.data));
var proposed_state = wlr.Output.State.init();
head.state.apply(&proposed_state);
@ -864,7 +857,7 @@ fn handlePowerManagerSetMode(
event: *wlr.OutputPowerManagerV1.event.SetMode,
) void {
// The output may have been destroyed, in which case there is nothing to do
const output = @as(?*Output, @ptrFromInt(event.output.data)) orelse return;
const output: *Output = @alignCast(@ptrCast(event.output.data orelse return));
std.log.debug("client requested dpms {s} for output {s}", .{
@tagName(event.mode),
@ -895,16 +888,3 @@ fn handlePowerManagerSetMode(
output.updateLockRenderStateOnEnableDisable();
}
fn handleSetGamma(
_: *wl.Listener(*wlr.GammaControlManagerV1.event.SetGamma),
event: *wlr.GammaControlManagerV1.event.SetGamma,
) void {
// The output may have been destroyed, in which case there is nothing to do
const output = @as(?*Output, @ptrFromInt(event.output.data)) orelse return;
std.log.debug("client requested to set gamma", .{});
output.gamma_dirty = true;
output.wlr_output.scheduleFrame();
}