Only store mapped views in the view stack
This commit is contained in:
parent
b2f172e91b
commit
5bec8f4fcb
6 changed files with 32 additions and 44 deletions
|
@ -147,15 +147,6 @@ pub fn getRenderer(self: Self) *c.wlr_renderer {
|
|||
return c.river_wlr_backend_get_renderer(self.wlr_output.backend);
|
||||
}
|
||||
|
||||
/// Add a new view to the output. arrangeViews() will be called by the view
|
||||
/// when it is mapped. The surface argument must be a c.wlr_xdg_surface or
|
||||
/// c.wlr_xwayland_surface (if xwayland is enabled)
|
||||
pub fn addView(self: *Self, surface: var) !void {
|
||||
const node = try self.root.server.allocator.create(ViewStack(View).Node);
|
||||
node.view.init(self, self.current_focused_tags, surface);
|
||||
self.views.push(node);
|
||||
}
|
||||
|
||||
/// Add a newly created layer surface to the output.
|
||||
pub fn addLayerSurface(self: *Self, wlr_layer_surface: *c.wlr_layer_surface_v1) !void {
|
||||
const layer = wlr_layer_surface.client_pending.layer;
|
||||
|
|
|
@ -190,7 +190,10 @@ fn handleNewXdgSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v
|
|||
|
||||
Log.Debug.log("New xdg_toplevel", .{});
|
||||
|
||||
self.input_manager.default_seat.focused_output.addView(wlr_xdg_surface) catch unreachable;
|
||||
// The View will add itself to the output's view stack on map
|
||||
const output = self.input_manager.default_seat.focused_output;
|
||||
const node = self.allocator.create(ViewStack(View).Node) catch unreachable;
|
||||
node.view.init(output, output.current_focused_tags, wlr_xdg_surface);
|
||||
}
|
||||
|
||||
/// This event is raised when the layer_shell recieves a new surface from a client.
|
||||
|
@ -261,5 +264,9 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(
|
|||
"New xwayland surface: title '{}', class '{}'",
|
||||
.{ wlr_xwayland_surface.title, wlr_xwayland_surface.class },
|
||||
);
|
||||
self.input_manager.default_seat.focused_output.addView(wlr_xwayland_surface) catch unreachable;
|
||||
|
||||
// The View will add itself to the output's view stack on map
|
||||
const output = self.input_manager.default_seat.focused_output;
|
||||
const node = self.allocator.create(ViewStack(View).Node) catch unreachable;
|
||||
node.view.init(output, output.current_focused_tags, wlr_xwayland_surface);
|
||||
}
|
||||
|
|
17
src/View.zig
17
src/View.zig
|
@ -105,7 +105,7 @@ pub fn init(
|
|||
} else unreachable;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
pub fn deinit(self: Self) void {
|
||||
if (self.stashed_buffer) |buffer| {
|
||||
c.wlr_buffer_unref(buffer);
|
||||
}
|
||||
|
@ -227,6 +227,10 @@ pub fn surfaceAt(self: Self, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_surfa
|
|||
pub fn map(self: *Self) void {
|
||||
const root = self.output.root;
|
||||
|
||||
// Add the view to the stack of its output
|
||||
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
|
||||
self.output.views.push(node);
|
||||
|
||||
// Focus the newly mapped view. Note: if a seat is focusing a different output
|
||||
// it will continue to do so.
|
||||
var it = root.server.input_manager.seats.first;
|
||||
|
@ -252,5 +256,16 @@ pub fn unmap(self: *Self) void {
|
|||
seat.handleViewUnmap(self);
|
||||
}
|
||||
|
||||
// Remove the view from its output's stack
|
||||
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
|
||||
self.output.views.remove(node);
|
||||
|
||||
root.arrange();
|
||||
}
|
||||
|
||||
/// Destory the view and free the ViewStack node holding it.
|
||||
pub fn destroy(self: *const Self) void {
|
||||
self.deinit();
|
||||
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
|
||||
self.output.root.server.allocator.destroy(node);
|
||||
}
|
||||
|
|
|
@ -110,10 +110,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||
c.wl_list_remove(&self.listen_map.link);
|
||||
c.wl_list_remove(&self.listen_unmap.link);
|
||||
|
||||
// Remove the view from the stack
|
||||
const node = @fieldParentPtr(ViewStack(View).Node, "view", self.view);
|
||||
output.views.remove(node);
|
||||
output.root.server.allocator.destroy(node);
|
||||
self.view.destroy();
|
||||
}
|
||||
|
||||
/// Called when the xdg surface is mapped, or ready to display on-screen.
|
||||
|
|
|
@ -108,17 +108,13 @@ pub fn surfaceAt(self: Self, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_surfa
|
|||
/// Called when the xwayland surface is destroyed
|
||||
fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
|
||||
const output = self.view.output;
|
||||
|
||||
// Remove listeners that are active for the entire lifetime of the view
|
||||
c.wl_list_remove(&self.listen_destroy.link);
|
||||
c.wl_list_remove(&self.listen_map.link);
|
||||
c.wl_list_remove(&self.listen_unmap.link);
|
||||
|
||||
// Remove the view from the stack
|
||||
const node = @fieldParentPtr(ViewStack(View).Node, "view", self.view);
|
||||
output.views.remove(node);
|
||||
output.root.server.allocator.destroy(node);
|
||||
self.view.destroy();
|
||||
}
|
||||
|
||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
||||
|
|
|
@ -92,7 +92,7 @@ pub fn ViewStack(comptime T: type) type {
|
|||
/// This function is horribly ugly, but it's well tested below.
|
||||
pub fn next(self: *Iterator) ?*Node {
|
||||
while (self.it) |node| : (self.it = if (self.reverse) node.prev else node.next) {
|
||||
if (node.view.wlr_surface != null and if (self.pending)
|
||||
if (if (self.pending)
|
||||
if (node.view.pending_tags) |pending_tags|
|
||||
self.tags & pending_tags != 0
|
||||
else
|
||||
|
@ -109,7 +109,6 @@ pub fn ViewStack(comptime T: type) type {
|
|||
|
||||
/// Returns an iterator starting at the passed node and filtered by
|
||||
/// checking the passed tags against the current tags of each view.
|
||||
/// Unmapped views are skipped.
|
||||
pub fn iterator(start: ?*Node, tags: u32) Iterator {
|
||||
return Iterator{
|
||||
.it = start,
|
||||
|
@ -121,7 +120,6 @@ pub fn ViewStack(comptime T: type) type {
|
|||
|
||||
/// Returns a reverse iterator starting at the passed node and filtered by
|
||||
/// checking the passed tags against the current tags of each view.
|
||||
/// Unmapped views are skipped.
|
||||
pub fn reverseIterator(start: ?*Node, tags: u32) Iterator {
|
||||
return Iterator{
|
||||
.it = start,
|
||||
|
@ -133,8 +131,7 @@ pub fn ViewStack(comptime T: type) type {
|
|||
|
||||
/// Returns an iterator starting at the passed node and filtered by
|
||||
/// checking the passed tags against the pending tags of each view.
|
||||
/// If a view has no pending tags, the current tags are used. Unmapped
|
||||
/// views are skipped.
|
||||
/// If a view has no pending tags, the current tags are used.
|
||||
pub fn pendingIterator(start: ?*Node, tags: u32) Iterator {
|
||||
return Iterator{
|
||||
.it = start,
|
||||
|
@ -285,51 +282,36 @@ test "iteration (View)" {
|
|||
var views: ViewStack(View) = undefined;
|
||||
views.init();
|
||||
|
||||
// Pretty nice hack for testing: we don't actually need a wlr_surface here,
|
||||
// but we need the iteration function to thing that the view has a non-null
|
||||
// wlr_surface. So, just cast an integer to a pointer to get an arbitrary
|
||||
// but non-null value. Use 8 so the alignment checks out.
|
||||
|
||||
const one_a_pb = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(one_a_pb);
|
||||
one_a_pb.view.wlr_surface = @intToPtr(*c.wlr_surface, 8);
|
||||
one_a_pb.view.current_tags = 1 << 0;
|
||||
one_a_pb.view.pending_tags = 1 << 1;
|
||||
|
||||
const two_a = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(two_a);
|
||||
two_a.view.wlr_surface = @intToPtr(*c.wlr_surface, 8);
|
||||
two_a.view.current_tags = 1 << 0;
|
||||
two_a.view.pending_tags = null;
|
||||
|
||||
const three_b_pa = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(three_b_pa);
|
||||
three_b_pa.view.wlr_surface = @intToPtr(*c.wlr_surface, 8);
|
||||
three_b_pa.view.current_tags = 1 << 1;
|
||||
three_b_pa.view.pending_tags = 1 << 0;
|
||||
|
||||
const four_b = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(four_b);
|
||||
four_b.view.wlr_surface = @intToPtr(*c.wlr_surface, 8);
|
||||
four_b.view.current_tags = 1 << 1;
|
||||
four_b.view.pending_tags = null;
|
||||
|
||||
const five_b = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(five_b);
|
||||
five_b.view.wlr_surface = @intToPtr(*c.wlr_surface, 8);
|
||||
five_b.view.current_tags = 1 << 1;
|
||||
five_b.view.pending_tags = null;
|
||||
|
||||
const unmapped_1 = try allocator.create(ViewStack(View).Node);
|
||||
defer allocator.destroy(unmapped_1);
|
||||
unmapped_1.view.wlr_surface = null;
|
||||
|
||||
views.push(three_b_pa); // {3}
|
||||
views.push(one_a_pb); // {1, 3}
|
||||
views.push(unmapped_1); // {u, 1, 3}
|
||||
views.push(four_b); // {4, u, 1, 3}
|
||||
views.push(five_b); // {5, 4, u, 1, 3}
|
||||
views.push(two_a); // {2, 5, 4, u, 1, 3}
|
||||
views.push(four_b); // {4, 1, 3}
|
||||
views.push(five_b); // {5, 4, 1, 3}
|
||||
views.push(two_a); // {2, 5, 4, 1, 3}
|
||||
|
||||
// Iteration over all tags
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue