Only store mapped views in the view stack
This commit is contained in:
parent
b2f172e91b
commit
5bec8f4fcb
@ -147,15 +147,6 @@ pub fn getRenderer(self: Self) *c.wlr_renderer {
|
|||||||
return c.river_wlr_backend_get_renderer(self.wlr_output.backend);
|
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.
|
/// Add a newly created layer surface to the output.
|
||||||
pub fn addLayerSurface(self: *Self, wlr_layer_surface: *c.wlr_layer_surface_v1) !void {
|
pub fn addLayerSurface(self: *Self, wlr_layer_surface: *c.wlr_layer_surface_v1) !void {
|
||||||
const layer = wlr_layer_surface.client_pending.layer;
|
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", .{});
|
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.
|
/// 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 '{}'",
|
"New xwayland surface: title '{}', class '{}'",
|
||||||
.{ wlr_xwayland_surface.title, wlr_xwayland_surface.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;
|
} else unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: Self) void {
|
||||||
if (self.stashed_buffer) |buffer| {
|
if (self.stashed_buffer) |buffer| {
|
||||||
c.wlr_buffer_unref(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 {
|
pub fn map(self: *Self) void {
|
||||||
const root = self.output.root;
|
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
|
// Focus the newly mapped view. Note: if a seat is focusing a different output
|
||||||
// it will continue to do so.
|
// it will continue to do so.
|
||||||
var it = root.server.input_manager.seats.first;
|
var it = root.server.input_manager.seats.first;
|
||||||
@ -252,5 +256,16 @@ pub fn unmap(self: *Self) void {
|
|||||||
seat.handleViewUnmap(self);
|
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();
|
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_map.link);
|
||||||
c.wl_list_remove(&self.listen_unmap.link);
|
c.wl_list_remove(&self.listen_unmap.link);
|
||||||
|
|
||||||
// Remove the view from the stack
|
self.view.destroy();
|
||||||
const node = @fieldParentPtr(ViewStack(View).Node, "view", self.view);
|
|
||||||
output.views.remove(node);
|
|
||||||
output.root.server.allocator.destroy(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xdg surface is mapped, or ready to display on-screen.
|
/// 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
|
/// Called when the xwayland surface is destroyed
|
||||||
fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
|
const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
|
||||||
const output = self.view.output;
|
|
||||||
|
|
||||||
// Remove listeners that are active for the entire lifetime of the view
|
// 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_destroy.link);
|
||||||
c.wl_list_remove(&self.listen_map.link);
|
c.wl_list_remove(&self.listen_map.link);
|
||||||
c.wl_list_remove(&self.listen_unmap.link);
|
c.wl_list_remove(&self.listen_unmap.link);
|
||||||
|
|
||||||
// Remove the view from the stack
|
self.view.destroy();
|
||||||
const node = @fieldParentPtr(ViewStack(View).Node, "view", self.view);
|
|
||||||
output.views.remove(node);
|
|
||||||
output.root.server.allocator.destroy(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
/// 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.
|
/// This function is horribly ugly, but it's well tested below.
|
||||||
pub fn next(self: *Iterator) ?*Node {
|
pub fn next(self: *Iterator) ?*Node {
|
||||||
while (self.it) |node| : (self.it = if (self.reverse) node.prev else node.next) {
|
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|
|
if (node.view.pending_tags) |pending_tags|
|
||||||
self.tags & pending_tags != 0
|
self.tags & pending_tags != 0
|
||||||
else
|
else
|
||||||
@ -109,7 +109,6 @@ pub fn ViewStack(comptime T: type) type {
|
|||||||
|
|
||||||
/// Returns an iterator starting at the passed node and filtered by
|
/// Returns an iterator starting at the passed node and filtered by
|
||||||
/// checking the passed tags against the current tags of each view.
|
/// checking the passed tags against the current tags of each view.
|
||||||
/// Unmapped views are skipped.
|
|
||||||
pub fn iterator(start: ?*Node, tags: u32) Iterator {
|
pub fn iterator(start: ?*Node, tags: u32) Iterator {
|
||||||
return Iterator{
|
return Iterator{
|
||||||
.it = start,
|
.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
|
/// Returns a reverse iterator starting at the passed node and filtered by
|
||||||
/// checking the passed tags against the current tags of each view.
|
/// checking the passed tags against the current tags of each view.
|
||||||
/// Unmapped views are skipped.
|
|
||||||
pub fn reverseIterator(start: ?*Node, tags: u32) Iterator {
|
pub fn reverseIterator(start: ?*Node, tags: u32) Iterator {
|
||||||
return Iterator{
|
return Iterator{
|
||||||
.it = start,
|
.it = start,
|
||||||
@ -133,8 +131,7 @@ pub fn ViewStack(comptime T: type) type {
|
|||||||
|
|
||||||
/// Returns an iterator starting at the passed node and filtered by
|
/// Returns an iterator starting at the passed node and filtered by
|
||||||
/// checking the passed tags against the pending tags of each view.
|
/// checking the passed tags against the pending tags of each view.
|
||||||
/// If a view has no pending tags, the current tags are used. Unmapped
|
/// If a view has no pending tags, the current tags are used.
|
||||||
/// views are skipped.
|
|
||||||
pub fn pendingIterator(start: ?*Node, tags: u32) Iterator {
|
pub fn pendingIterator(start: ?*Node, tags: u32) Iterator {
|
||||||
return Iterator{
|
return Iterator{
|
||||||
.it = start,
|
.it = start,
|
||||||
@ -285,51 +282,36 @@ test "iteration (View)" {
|
|||||||
var views: ViewStack(View) = undefined;
|
var views: ViewStack(View) = undefined;
|
||||||
views.init();
|
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);
|
const one_a_pb = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(one_a_pb);
|
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.current_tags = 1 << 0;
|
||||||
one_a_pb.view.pending_tags = 1 << 1;
|
one_a_pb.view.pending_tags = 1 << 1;
|
||||||
|
|
||||||
const two_a = try allocator.create(ViewStack(View).Node);
|
const two_a = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(two_a);
|
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.current_tags = 1 << 0;
|
||||||
two_a.view.pending_tags = null;
|
two_a.view.pending_tags = null;
|
||||||
|
|
||||||
const three_b_pa = try allocator.create(ViewStack(View).Node);
|
const three_b_pa = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(three_b_pa);
|
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.current_tags = 1 << 1;
|
||||||
three_b_pa.view.pending_tags = 1 << 0;
|
three_b_pa.view.pending_tags = 1 << 0;
|
||||||
|
|
||||||
const four_b = try allocator.create(ViewStack(View).Node);
|
const four_b = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(four_b);
|
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.current_tags = 1 << 1;
|
||||||
four_b.view.pending_tags = null;
|
four_b.view.pending_tags = null;
|
||||||
|
|
||||||
const five_b = try allocator.create(ViewStack(View).Node);
|
const five_b = try allocator.create(ViewStack(View).Node);
|
||||||
defer allocator.destroy(five_b);
|
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.current_tags = 1 << 1;
|
||||||
five_b.view.pending_tags = null;
|
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(three_b_pa); // {3}
|
||||||
views.push(one_a_pb); // {1, 3}
|
views.push(one_a_pb); // {1, 3}
|
||||||
views.push(unmapped_1); // {u, 1, 3}
|
views.push(four_b); // {4, 1, 3}
|
||||||
views.push(four_b); // {4, u, 1, 3}
|
views.push(five_b); // {5, 4, 1, 3}
|
||||||
views.push(five_b); // {5, 4, u, 1, 3}
|
views.push(two_a); // {2, 5, 4, 1, 3}
|
||||||
views.push(two_a); // {2, 5, 4, u, 1, 3}
|
|
||||||
|
|
||||||
// Iteration over all tags
|
// Iteration over all tags
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user