diff --git a/src/command/focus_view.zig b/src/command/focus_view.zig index fce180f..38fd531 100644 --- a/src/command/focus_view.zig +++ b/src/command/focus_view.zig @@ -2,7 +2,7 @@ const c = @import("../c.zig"); const Arg = @import("../command.zig").Arg; const Seat = @import("../seat.zig"); -const View = @import("../view.zig").View; +const View = @import("../view.zig"); const ViewStack = @import("../view_stack.zig").ViewStack; /// Focus either the next or the previous visible view, depending on the enum diff --git a/src/command/zoom.zig b/src/command/zoom.zig index 456fc7c..d3f52c3 100644 --- a/src/command/zoom.zig +++ b/src/command/zoom.zig @@ -2,7 +2,7 @@ const c = @import("../c.zig"); const Arg = @import("../command.zig").Arg; const Seat = @import("../seat.zig"); -const View = @import("../view.zig").View; +const View = @import("../view.zig"); const ViewStack = @import("../view_stack.zig").ViewStack; /// Bump the focused view to the top of the stack. If the view on the top of diff --git a/src/cursor.zig b/src/cursor.zig index f54c917..5eb4ff1 100644 --- a/src/cursor.zig +++ b/src/cursor.zig @@ -5,7 +5,7 @@ const LayerSurface = @import("layer_surface.zig"); const Log = @import("log.zig").Log; const Output = @import("output.zig"); const Seat = @import("seat.zig"); -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const CursorMode = enum { diff --git a/src/output.zig b/src/output.zig index 00cb971..e5af4c7 100644 --- a/src/output.zig +++ b/src/output.zig @@ -9,7 +9,7 @@ const Box = @import("box.zig"); const LayerSurface = @import("layer_surface.zig"); const Log = @import("log.zig").Log; const Root = @import("root.zig").Root; -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; root: *Root, diff --git a/src/render.zig b/src/render.zig index c0f73f3..2184062 100644 --- a/src/render.zig +++ b/src/render.zig @@ -5,7 +5,7 @@ const Box = @import("box.zig"); const LayerSurface = @import("layer_surface.zig"); const Output = @import("output.zig"); const Server = @import("server.zig"); -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; pub fn renderOutput(output: *Output) void { diff --git a/src/root.zig b/src/root.zig index 71aac0c..e42f0ed 100644 --- a/src/root.zig +++ b/src/root.zig @@ -7,7 +7,7 @@ const Log = @import("log.zig").Log; const Output = @import("output.zig"); const Server = @import("server.zig"); const Seat = @import("seat.zig").Seat; -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; /// Responsible for all windowing operations diff --git a/src/seat.zig b/src/seat.zig index 1b6b141..d62d5e0 100644 --- a/src/seat.zig +++ b/src/seat.zig @@ -8,7 +8,7 @@ const InputManager = @import("input_manager.zig"); const Keyboard = @import("keyboard.zig").Keyboard; const LayerSurface = @import("layer_surface.zig"); const Output = @import("output.zig"); -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const FocusTarget = union(enum) { diff --git a/src/server.zig b/src/server.zig index c2ed6a0..9aa17fd 100644 --- a/src/server.zig +++ b/src/server.zig @@ -10,7 +10,7 @@ const InputManager = @import("input_manager.zig"); const Log = @import("log.zig").Log; const Output = @import("output.zig"); const Root = @import("root.zig").Root; -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; allocator: *std.mem.Allocator, diff --git a/src/view.zig b/src/view.zig index 168dba9..ac0245a 100644 --- a/src/view.zig +++ b/src/view.zig @@ -1,4 +1,7 @@ +const Self = @This(); + const std = @import("std"); + const c = @import("c.zig"); const Box = @import("box.zig"); @@ -8,177 +11,173 @@ const Root = @import("root.zig").Root; const ViewStack = @import("view_stack.zig").ViewStack; const XdgToplevel = @import("xdg_toplevel.zig"); -pub const View = struct { - const Self = @This(); - - const ViewImpl = union(enum) { - xdg_toplevel: XdgToplevel, - }; - - /// The implementation of this view - impl: ViewImpl, - - /// The output this view is currently associated with - output: *Output, - - /// This is non-null exactly when the view is mapped - wlr_surface: ?*c.wlr_surface, - - /// If the view is floating or not - floating: bool, - - /// True if the view is currentlt focused by at lease one seat - focused: bool, - - /// The current output-relative coordinates and dimensions of the view - current_box: Box, - pending_box: ?Box, - - /// The dimensions the view would have taken if we didn't force it to tile - natural_width: u32, - natural_height: u32, - - current_tags: u32, - pending_tags: ?u32, - - pending_serial: ?u32, - - // This is what we render while a transaction is in progress - stashed_buffer: ?*c.wlr_buffer, - - pub fn init_xdg_toplevel( - self: *Self, - output: *Output, - tags: u32, - wlr_xdg_surface: *c.wlr_xdg_surface, - ) void { - self.output = output; - - self.wlr_surface = null; - - self.focused = false; - - self.current_box = Box{ - .x = 0, - .y = 0, - .height = 0, - .width = 0, - }; - self.pending_box = null; - - self.current_tags = tags; - self.pending_tags = null; - - self.pending_serial = null; - - self.stashed_buffer = null; - - self.impl = .{ .xdg_toplevel = undefined }; - self.impl.xdg_toplevel.init(self, wlr_xdg_surface); - } - - pub fn deinit(self: *Self) void { - if (self.stashed_buffer) |buffer| { - c.wlr_buffer_unref(buffer); - } - } - - pub fn needsConfigure(self: Self) bool { - if (self.pending_box) |pending_box| { - return pending_box.width != self.current_box.width or - pending_box.height != self.current_box.height; - } else { - return false; - } - } - - pub fn configure(self: Self) void { - if (self.pending_box) |pending_box| { - switch (self.impl) { - .xdg_toplevel => |xdg_toplevel| xdg_toplevel.configure(pending_box), - } - } else { - Log.Error.log("Configure called on a View with no pending box", .{}); - } - } - - pub fn sendFrameDone(self: Self) void { - var now: c.timespec = undefined; - _ = c.clock_gettime(c.CLOCK_MONOTONIC, &now); - c.wlr_surface_send_frame_done(self.wlr_surface.?, &now); - } - - pub fn dropStashedBuffer(self: *Self) void { - // TODO: log debug error - if (self.stashed_buffer) |buffer| { - c.wlr_buffer_unref(buffer); - self.stashed_buffer = null; - } - } - - pub fn stashBuffer(self: *Self) void { - // TODO: log debug error if there is already a saved buffer - if (self.wlr_surface) |wlr_surface| { - if (c.wlr_surface_has_buffer(wlr_surface)) { - _ = c.wlr_buffer_ref(wlr_surface.buffer); - self.stashed_buffer = wlr_surface.buffer; - } - } - } - - /// Set the focued bool and the active state of the view if it is a toplevel - pub fn setFocused(self: *Self, focused: bool) void { - self.focused = focused; - switch (self.impl) { - .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setActivated(focused), - } - } - - /// If true is passsed, make the view float. If false, return it to the tiled - /// layout. - pub fn setFloating(self: *Self, float: bool) void { - if (float and !self.floating) { - self.floating = true; - 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, - }; - } else if (!float and self.floating) { - self.floating = false; - } - } - - /// Move a view from one output to another, sending the required enter/leave - /// events. - pub fn sendToOutput(self: *Self, destination_output: *Output) void { - const node = @fieldParentPtr(ViewStack(View).Node, "view", self); - - self.output.views.remove(node); - destination_output.views.push(node); - - c.wlr_surface_send_leave(self.wlr_surface, self.output.wlr_output); - c.wlr_surface_send_enter(self.wlr_surface, destination_output.wlr_output); - - self.output = destination_output; - } - - pub fn close(self: Self) void { - switch (self.impl) { - .xdg_toplevel => |xdg_toplevel| xdg_toplevel.close(), - } - } - - pub fn forEachSurface( - self: Self, - iterator: c.wlr_surface_iterator_func_t, - user_data: ?*c_void, - ) void { - switch (self.impl) { - .xdg_toplevel => |xdg_toplevel| xdg_toplevel.forEachSurface(iterator, user_data), - } - } +const ViewImpl = union(enum) { + xdg_toplevel: XdgToplevel, }; + +/// The implementation of this view +impl: ViewImpl, + +/// The output this view is currently associated with +output: *Output, + +/// This is non-null exactly when the view is mapped +wlr_surface: ?*c.wlr_surface, + +/// If the view is floating or not +floating: bool, + +/// True if the view is currentlt focused by at lease one seat +focused: bool, + +/// The current output-relative coordinates and dimensions of the view +current_box: Box, +pending_box: ?Box, + +/// The dimensions the view would have taken if we didn't force it to tile +natural_width: u32, +natural_height: u32, + +current_tags: u32, +pending_tags: ?u32, + +pending_serial: ?u32, + +// This is what we render while a transaction is in progress +stashed_buffer: ?*c.wlr_buffer, + +pub fn init_xdg_toplevel( + self: *Self, + output: *Output, + tags: u32, + wlr_xdg_surface: *c.wlr_xdg_surface, +) void { + self.output = output; + + self.wlr_surface = null; + + self.focused = false; + + self.current_box = Box{ + .x = 0, + .y = 0, + .height = 0, + .width = 0, + }; + self.pending_box = null; + + self.current_tags = tags; + self.pending_tags = null; + + self.pending_serial = null; + + self.stashed_buffer = null; + + self.impl = .{ .xdg_toplevel = undefined }; + self.impl.xdg_toplevel.init(self, wlr_xdg_surface); +} + +pub fn deinit(self: *Self) void { + if (self.stashed_buffer) |buffer| { + c.wlr_buffer_unref(buffer); + } +} + +pub fn needsConfigure(self: Self) bool { + if (self.pending_box) |pending_box| { + return pending_box.width != self.current_box.width or + pending_box.height != self.current_box.height; + } else { + return false; + } +} + +pub fn configure(self: Self) void { + if (self.pending_box) |pending_box| { + switch (self.impl) { + .xdg_toplevel => |xdg_toplevel| xdg_toplevel.configure(pending_box), + } + } else { + Log.Error.log("Configure called on a View with no pending box", .{}); + } +} + +pub fn sendFrameDone(self: Self) void { + var now: c.timespec = undefined; + _ = c.clock_gettime(c.CLOCK_MONOTONIC, &now); + c.wlr_surface_send_frame_done(self.wlr_surface.?, &now); +} + +pub fn dropStashedBuffer(self: *Self) void { + // TODO: log debug error + if (self.stashed_buffer) |buffer| { + c.wlr_buffer_unref(buffer); + self.stashed_buffer = null; + } +} + +pub fn stashBuffer(self: *Self) void { + // TODO: log debug error if there is already a saved buffer + if (self.wlr_surface) |wlr_surface| { + if (c.wlr_surface_has_buffer(wlr_surface)) { + _ = c.wlr_buffer_ref(wlr_surface.buffer); + self.stashed_buffer = wlr_surface.buffer; + } + } +} + +/// Set the focued bool and the active state of the view if it is a toplevel +pub fn setFocused(self: *Self, focused: bool) void { + self.focused = focused; + switch (self.impl) { + .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setActivated(focused), + } +} + +/// If true is passsed, make the view float. If false, return it to the tiled +/// layout. +pub fn setFloating(self: *Self, float: bool) void { + if (float and !self.floating) { + self.floating = true; + 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, + }; + } else if (!float and self.floating) { + self.floating = false; + } +} + +/// Move a view from one output to another, sending the required enter/leave +/// events. +pub fn sendToOutput(self: *Self, destination_output: *Output) void { + const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); + + self.output.views.remove(node); + destination_output.views.push(node); + + c.wlr_surface_send_leave(self.wlr_surface, self.output.wlr_output); + c.wlr_surface_send_enter(self.wlr_surface, destination_output.wlr_output); + + self.output = destination_output; +} + +pub fn close(self: Self) void { + switch (self.impl) { + .xdg_toplevel => |xdg_toplevel| xdg_toplevel.close(), + } +} + +pub fn forEachSurface( + self: Self, + iterator: c.wlr_surface_iterator_func_t, + user_data: ?*c_void, +) void { + switch (self.impl) { + .xdg_toplevel => |xdg_toplevel| xdg_toplevel.forEachSurface(iterator, user_data), + } +} diff --git a/src/view_stack.zig b/src/view_stack.zig index a0eaf5e..86a3fce 100644 --- a/src/view_stack.zig +++ b/src/view_stack.zig @@ -1,4 +1,4 @@ -const View = @import("view.zig").View; +const View = @import("view.zig"); /// A specialized doubly-linked stack that allows for filtered iteration /// over the nodes. T must be View or *View. diff --git a/src/xdg_toplevel.zig b/src/xdg_toplevel.zig index 8f20af0..4c7ca2e 100644 --- a/src/xdg_toplevel.zig +++ b/src/xdg_toplevel.zig @@ -5,7 +5,7 @@ const std = @import("std"); const Box = @import("box.zig"); const Log = @import("log.zig").Log; -const View = @import("view.zig").View; +const View = @import("view.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XdgPopup = @import("xdg_popup.zig");