View: refactor initialization

This anytype parameter is a wart that's been around for far too long.
This commit is contained in:
Isaac Freund 2022-05-29 15:59:46 +02:00
parent 6ef97eea24
commit 960afa89ec
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
5 changed files with 63 additions and 52 deletions

View File

@ -33,9 +33,9 @@ const LayoutManager = @import("LayoutManager.zig");
const Output = @import("Output.zig");
const Root = @import("Root.zig");
const StatusManager = @import("StatusManager.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
const XdgToplevel = @import("XdgToplevel.zig");
const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
const XwaylandView = @import("XwaylandView.zig");
const IdleInhibitorManager = @import("IdleInhibitorManager.zig");
const log = std.log.scoped(.server);
@ -187,13 +187,12 @@ fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wl
log.debug("new xdg_toplevel", .{});
// The View will add itself to the output's view stack on map
const output = self.input_manager.defaultSeat().focused_output;
const node = util.gpa.create(ViewStack(View).Node) catch {
XdgToplevel.create(output, xdg_surface) catch {
log.err("out of memory", .{});
xdg_surface.resource.postNoMemory();
return;
};
node.view.init(output, xdg_surface);
}
/// This event is raised when the layer_shell recieves a new surface from a client.
@ -239,25 +238,24 @@ fn handleNewLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_
node.data.init(output, wlr_layer_surface);
}
fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), wlr_xwayland_surface: *wlr.XwaylandSurface) void {
fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {
const self = @fieldParentPtr(Self, "new_xwayland_surface", listener);
if (wlr_xwayland_surface.override_redirect) {
log.debug("new unmanaged xwayland surface", .{});
// The unmanged surface will add itself to the list of unmanaged views
// in Root when it is mapped.
const node = util.gpa.create(std.TailQueue(XwaylandUnmanaged).Node) catch return;
node.data.init(wlr_xwayland_surface);
return;
}
log.debug(
"new xwayland surface: title '{s}', class '{s}'",
.{ wlr_xwayland_surface.title, wlr_xwayland_surface.class },
"new xwayland surface: title='{s}', class='{s}', override redirect={}",
.{ xwayland_surface.title, xwayland_surface.class, xwayland_surface.override_redirect },
);
// The View will add itself to the output's view stack on map
const output = self.input_manager.defaultSeat().focused_output;
const node = util.gpa.create(ViewStack(View).Node) catch return;
node.view.init(output, wlr_xwayland_surface);
if (xwayland_surface.override_redirect) {
_ = XwaylandUnmanaged.create(xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
} else {
const output = self.input_manager.defaultSeat().focused_output;
_ = XwaylandView.create(output, xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
}
}

View File

@ -74,7 +74,7 @@ const SavedBuffer = struct {
};
/// The implementation of this view
impl: Impl = undefined,
impl: Impl,
/// The output this view is currently associated with
output: *Output,
@ -102,7 +102,7 @@ surface_box: Box = undefined,
saved_surface_box: Box = undefined,
/// These are what we render while a transaction is in progress
saved_buffers: std.ArrayList(SavedBuffer),
saved_buffers: std.ArrayListUnmanaged(SavedBuffer) = .{},
/// The floating dimensions the view, saved so that they can be restored if the
/// view returns to floating mode.
@ -126,26 +126,18 @@ foreign_close: wl.Listener(*wlr.ForeignToplevelHandleV1) =
request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
pub fn init(self: *Self, output: *Output, surface: anytype) void {
pub fn init(self: *Self, output: *Output, impl: Impl) void {
const initial_tags = blk: {
const tags = output.current.tags & output.spawn_tagmask;
break :blk if (tags != 0) tags else output.current.tags;
};
self.* = .{
.impl = impl,
.output = output,
.current = .{ .tags = initial_tags },
.pending = .{ .tags = initial_tags },
.saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa),
};
if (@TypeOf(surface) == *wlr.XdgSurface) {
self.impl = .{ .xdg_toplevel = undefined };
self.impl.xdg_toplevel.init(self, surface);
} else if (build_options.xwayland and @TypeOf(surface) == *wlr.XwaylandSurface) {
self.impl = .{ .xwayland_view = undefined };
self.impl.xwayland_view.init(self, surface);
} else unreachable;
}
/// If saved buffers of the view are currently in use by a transaction,
@ -159,7 +151,7 @@ pub fn destroy(self: *Self) void {
// around until the current transaction completes. This function will be
// called again in Root.commitTransaction()
if (self.saved_buffers.items.len == 0) {
self.saved_buffers.deinit();
self.saved_buffers.deinit(util.gpa);
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
util.gpa.destroy(node);
@ -237,19 +229,19 @@ pub fn dropSavedBuffers(self: *Self) void {
pub fn saveBuffers(self: *Self) void {
assert(self.saved_buffers.items.len == 0);
self.saved_surface_box = self.surface_box;
self.forEachSurface(*std.ArrayList(SavedBuffer), saveBuffersIterator, &self.saved_buffers);
self.forEachSurface(*std.ArrayListUnmanaged(SavedBuffer), saveBuffersIterator, &self.saved_buffers);
}
fn saveBuffersIterator(
surface: *wlr.Surface,
surface_x: c_int,
surface_y: c_int,
saved_buffers: *std.ArrayList(SavedBuffer),
saved_buffers: *std.ArrayListUnmanaged(SavedBuffer),
) callconv(.C) void {
if (surface.buffer) |buffer| {
var source_box: wlr.FBox = undefined;
surface.getBufferSourceBox(&source_box);
saved_buffers.append(.{
saved_buffers.append(util.gpa, .{
.client_buffer = buffer,
.surface_box = .{
.x = surface_x,

View File

@ -25,6 +25,7 @@ const server = &@import("main.zig").server;
const util = @import("util.zig");
const Box = @import("Box.zig");
const Output = @import("Output.zig");
const Seat = @import("Seat.zig");
const Subsurface = @import("Subsurface.zig");
const View = @import("View.zig");
@ -62,8 +63,17 @@ request_resize: wl.Listener(*wlr.XdgToplevel.event.Resize) =
set_title: wl.Listener(*wlr.XdgSurface) = wl.Listener(*wlr.XdgSurface).init(handleSetTitle),
set_app_id: wl.Listener(*wlr.XdgSurface) = wl.Listener(*wlr.XdgSurface).init(handleSetAppId),
pub fn init(self: *Self, view: *View, xdg_surface: *wlr.XdgSurface) void {
self.* = .{ .view = view, .xdg_surface = xdg_surface };
/// The View will add itself to the output's view stack on map
pub fn create(output: *Output, xdg_surface: *wlr.XdgSurface) error{OutOfMemory}!void {
const node = try util.gpa.create(ViewStack(View).Node);
const view = &node.view;
view.init(output, .{ .xdg_toplevel = .{
.view = view,
.xdg_surface = xdg_surface,
} });
const self = &node.view.impl.xdg_toplevel;
xdg_surface.data = @ptrToInt(self);
// Add listeners that are active over the view's entire lifetime

View File

@ -47,7 +47,12 @@ set_override_redirect: wl.Listener(*wlr.XwaylandSurface) =
// Listeners that are only active while mapped
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
pub fn init(self: *Self, xwayland_surface: *wlr.XwaylandSurface) void {
/// The unmanged surface will add itself to the list of unmanaged views
/// in Root when it is mapped.
pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!*Self {
const node = try util.gpa.create(std.TailQueue(Self).Node);
const self = &node.data;
self.* = .{ .xwayland_surface = xwayland_surface };
// Add listeners that are active over the the entire lifetime
@ -55,6 +60,8 @@ pub fn init(self: *Self, xwayland_surface: *wlr.XwaylandSurface) void {
xwayland_surface.events.destroy.add(&self.destroy);
xwayland_surface.events.map.add(&self.map);
xwayland_surface.events.unmap.add(&self.unmap);
return self;
}
fn handleRequestConfigure(
@ -135,15 +142,13 @@ fn handleSetOverrideRedirect(
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
handleDestroy(&self.destroy, xwayland_surface);
// The View will add itself to the output's view stack on map
const output = server.input_manager.defaultSeat().focused_output;
const node = util.gpa.create(ViewStack(View).Node) catch {
const xwayland_view = XwaylandView.create(output, xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
node.view.init(output, xwayland_surface);
if (xwayland_surface.mapped) {
XwaylandView.handleMap(&node.view.impl.xwayland_view.map, xwayland_surface);
XwaylandView.handleMap(&xwayland_view.map, xwayland_surface);
}
}

View File

@ -27,6 +27,7 @@ const server = &@import("main.zig").server;
const util = @import("util.zig");
const Box = @import("Box.zig");
const Output = @import("Output.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
const XdgPopup = @import("XdgPopup.zig");
@ -63,12 +64,18 @@ request_fullscreen: wl.Listener(*wlr.XwaylandSurface) =
request_minimize: wl.Listener(*wlr.XwaylandSurface.event.Minimize) =
wl.Listener(*wlr.XwaylandSurface.event.Minimize).init(handleRequestMinimize),
pub fn init(self: *Self, view: *View, xwayland_surface: *wlr.XwaylandSurface) void {
self.* = .{
/// The View will add itself to the output's view stack on map
pub fn create(output: *Output, xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!*Self {
const node = try util.gpa.create(ViewStack(View).Node);
const view = &node.view;
view.init(output, .{ .xwayland_view = .{
.view = view,
.xwayland_surface = xwayland_surface,
.last_set_fullscreen_state = xwayland_surface.fullscreen,
};
} });
const self = &node.view.impl.xwayland_view;
xwayland_surface.data = @ptrToInt(self);
// Add listeners that are active over the view's entire lifetime
@ -76,6 +83,8 @@ pub fn init(self: *Self, view: *View, xwayland_surface: *wlr.XwaylandSurface) vo
xwayland_surface.events.map.add(&self.map);
xwayland_surface.events.unmap.add(&self.unmap);
xwayland_surface.events.request_configure.add(&self.request_configure);
return self;
}
pub fn needsConfigure(self: Self) bool {
@ -283,16 +292,13 @@ fn handleSetOverrideRedirect(
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
handleDestroy(&self.destroy, xwayland_surface);
// The unmanged surface will add itself to the list of unmanaged views
// in Root when it is mapped.
const node = util.gpa.create(std.TailQueue(XwaylandUnmanaged).Node) catch {
const unmanaged = XwaylandUnmanaged.create(xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
node.data.init(xwayland_surface);
if (xwayland_surface.mapped) {
XwaylandUnmanaged.handleMap(&node.data.map, xwayland_surface);
XwaylandUnmanaged.handleMap(&unmanaged.map, xwayland_surface);
}
}