view: introduce state struct to simplify code

The state struct holds all of the state that is double-buffered and
applied through transactions. This more explicit handling simplifies
much of the code, and will allow for easier implementation of new
feature such as fullscreen.
This commit is contained in:
Isaac Freund
2020-06-27 22:43:15 +02:00
parent 89d0fb012d
commit c04112b81a
12 changed files with 105 additions and 124 deletions

View File

@ -41,6 +41,18 @@ const Mode = enum {
float,
};
const State = struct {
/// The output-relative coordinates and dimensions of the view. The
/// surface itself may have other dimensions which are stored in the
/// surface_box member.
box: Box,
/// The tags of the view, as a bitmask
tags: u32,
mode: Mode,
};
const SavedBuffer = struct {
wlr_buffer: *c.wlr_buffer,
box: Box,
@ -56,19 +68,15 @@ output: *Output,
/// This is non-null exactly when the view is mapped
wlr_surface: ?*c.wlr_surface,
/// The current mode of the view
mode: Mode,
/// True if the view is currently focused by at least one seat
focused: bool,
/// The current output-relative coordinates and dimensions of the view. The
/// surface itself may have other dimensions which are stored in the
/// surface_box member.
current_box: Box,
/// The double-buffered state of the view
current: State,
pending: State,
/// Pending dimensions of the view during a transaction
pending_box: ?Box,
/// The serial sent with the currently pending configure event
pending_serial: ?u32,
/// The currently commited geometry of the surface. The x/y may be negative if
/// for example the client has decided to draw CSD shadows a la GTK.
@ -85,29 +93,24 @@ saved_buffers: std.ArrayList(SavedBuffer),
natural_width: u32,
natural_height: u32,
current_tags: u32,
pending_tags: ?u32,
pending_serial: ?u32,
pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void {
self.output = output;
self.wlr_surface = null;
self.mode = .layout;
self.focused = false;
self.current_box = Box{
.x = 0,
.y = 0,
.height = 0,
.width = 0,
self.current = .{
.box = .{
.x = 0,
.y = 0,
.height = 0,
.width = 0,
},
.tags = tags,
.mode = .layout,
};
self.pending_box = null;
self.current_tags = tags;
self.pending_tags = null;
self.pending = self.current;
self.pending_serial = null;
@ -135,13 +138,9 @@ pub fn needsConfigure(self: Self) bool {
}
pub fn configure(self: Self) void {
if (self.pending_box) |pending_box| {
switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.configure(pending_box),
.xwayland_view => |xwayland_view| xwayland_view.configure(pending_box),
}
} else {
log.err(.transaction, "configure called on a View with no pending box", .{});
switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.configure(self.pending.box),
.xwayland_view => |xwayland_view| xwayland_view.configure(self.pending.box),
}
}
@ -190,7 +189,8 @@ fn saveBuffersIterator(
}
}
/// Set the focued bool and the active state of the view if it is a toplevel
/// Set the focused bool and the active state of the view if it is a toplevel
/// TODO: This is insufficient for multi-seat, probably need a focus counter.
pub fn setFocused(self: *Self, focused: bool) void {
self.focused = focused;
switch (self.impl) {
@ -199,30 +199,6 @@ pub fn setFocused(self: *Self, focused: bool) void {
}
}
/// Set the mode of the view to the given mode
pub fn setMode(self: *Self, mode: Mode) void {
switch (self.mode) {
.layout => switch (mode) {
.layout => {},
.float => {
self.mode = .float;
self.pending_box = Box{
.x = std.math.max(0, @divTrunc(@intCast(i32, self.output.usable_box.width) -
@intCast(i32, self.natural_width), 2)),
.y = std.math.max(0, @divTrunc(@intCast(i32, self.output.usable_box.height) -
@intCast(i32, self.natural_height), 2)),
.width = self.natural_width,
.height = self.natural_height,
};
},
},
.float => switch (mode) {
.float => {},
.layout => self.mode = .layout,
},
}
}
/// Move a view from one output to another, sending the required enter/leave
/// events.
pub fn sendToOutput(self: *Self, destination_output: *Output) void {