Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
river: implement river_window_v1.hide
Also ensure proposed dimensions are sent to the window even if the
window is hidden or if the dimensions are redundant.
river/Window.zig | 12 ++++++------
river/WindowManager.zig | 4 ++--
river/XdgToplevel.zig | 5 +++--
rivercompat/PointerBinding.zig | 9 ++++-----
rivercompat/Seat.zig | 27 +++++++++++++++++++++++++--
rivercompat/XkbBinding.zig | 7 ++++---
6 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/river/Window.zig b/river/Window.zig
index 462ebfb..1af33e3 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -675,6 +675,12 @@ pub fn configure(window: *Window) bool {
.resizing = false, // XXX
};
+ const track_configure = switch (window.impl) {
+ .toplevel => |*toplevel| toplevel.configure(committed.proposed != null),
+ .xwayland => |*xwindow| xwindow.configure(),
+ .none => unreachable,
+ };
+
// Ensure a dimensions event is sent if the window manager has proposed dimensions
// even if the actual dimensions commited by the window do not change.
if (committed.proposed != null) {
@@ -683,12 +689,6 @@ pub fn configure(window: *Window) bool {
committed.proposed = null;
}
- const track_configure = switch (window.impl) {
- .toplevel => |*toplevel| toplevel.configure(),
- .xwayland => |*xwindow| xwindow.configure(),
- .none => unreachable,
- };
-
if (track_configure and window.mapped) {
window.saveSurfaceTree();
window.sendFrameDone();
diff --git a/river/WindowManager.zig b/river/WindowManager.zig
index 3f8fd10..763ac3b 100644
--- a/river/WindowManager.zig
+++ b/river/WindowManager.zig
@@ -421,8 +421,8 @@ fn commitTransaction(wm: *WindowManager) void {
window.tree.node.reparent(server.scene.layers.wm);
window.tree.node.raiseToTop();
- window.tree.node.setEnabled(true);
- window.popup_tree.node.setEnabled(true);
+ window.tree.node.setEnabled(!window.current.hidden);
+ window.popup_tree.node.setEnabled(!window.current.hidden);
},
}
}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 840eed7..5466438 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -116,7 +116,8 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
}
/// Send a configure event, applying the inflight state of the window.
-pub fn configure(toplevel: *XdgToplevel) bool {
+/// If force is true, a configure will always be sent but not necessarily tracked.
+pub fn configure(toplevel: *XdgToplevel, force: bool) bool {
switch (toplevel.configure_state) {
.idle, .timed_out, .timed_out_acked => {},
.inflight, .acked, .committed => unreachable,
@@ -130,7 +131,7 @@ pub fn configure(toplevel: *XdgToplevel) bool {
const inflight = &toplevel.window.inflight;
const current = &toplevel.window.current;
- if (!toplevel.needsConfigure()) {
+ if (!force and !toplevel.needsConfigure()) {
// If no new configure is required, continue to track a timed out configure
// from the previous transaction if any.
switch (toplevel.configure_state) {
diff --git a/rivercompat/PointerBinding.zig b/rivercompat/PointerBinding.zig
index 5cdf0fb..2d51a3b 100644
--- a/rivercompat/PointerBinding.zig
+++ b/rivercompat/PointerBinding.zig
@@ -29,17 +29,20 @@ const gpa = std.heap.c_allocator;
seat: *Seat,
pointer_binding_v1: *river.PointerBindingV1,
+action: Seat.Action,
pub fn create(
seat: *Seat,
button: u32,
modifiers: river.SeatV1.Modifiers,
+ action: Seat.Action,
) void {
const pointer_binding_v1 = seat.seat_v1.getPointerBinding(button, modifiers) catch @panic("OOM");
const binding = gpa.create(PointerBinding) catch @panic("OOM");
binding.* = .{
.seat = seat,
.pointer_binding_v1 = pointer_binding_v1,
+ .action = action,
};
pointer_binding_v1.setListener(*PointerBinding, handleEvent, binding);
pointer_binding_v1.enable();
@@ -48,11 +51,7 @@ pub fn create(
fn handleEvent(pointer_binding_v1: *river.PointerBindingV1, event: river.PointerBindingV1.Event, binding: *PointerBinding) void {
assert(binding.pointer_binding_v1 == pointer_binding_v1);
switch (event) {
- .pressed => {
- if (binding.seat.focused) |window| {
- window.window_v1.close();
- }
- },
+ .pressed => binding.seat.execute(binding.action),
.released => {},
}
}
diff --git a/rivercompat/Seat.zig b/rivercompat/Seat.zig
index bd90e29..938414a 100644
--- a/rivercompat/Seat.zig
+++ b/rivercompat/Seat.zig
@@ -48,8 +48,10 @@ pub fn create(wm: *WindowManager, seat_v1: *river.SeatV1) void {
seat_v1.setListener(*Seat, handleEvent, seat);
- XkbBinding.create(seat, xkb.Keysym.n, .{ .mod4 = true });
- PointerBinding.create(seat, c.BTN_RIGHT, .{ .mod4 = true });
+ XkbBinding.create(seat, xkb.Keysym.n, .{ .mod4 = true }, .focus_next);
+ XkbBinding.create(seat, xkb.Keysym.h, .{ .mod4 = true }, .hide_focused);
+ XkbBinding.create(seat, xkb.Keysym.s, .{ .mod4 = true }, .show_all);
+ PointerBinding.create(seat, c.BTN_RIGHT, .{ .mod4 = true }, .close_focused);
}
pub fn focus(seat: *Seat, target: ?*Window) void {
@@ -93,3 +95,24 @@ fn handleEvent(seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *Seat) v
},
}
}
+
+pub const Action = enum {
+ focus_next,
+ close_focused,
+ hide_focused,
+ show_all,
+};
+
+pub fn execute(seat: *Seat, action: Action) void {
+ switch (action) {
+ .focus_next => seat.focusNext(),
+ .close_focused => if (seat.focused) |window| window.window_v1.close(),
+ .hide_focused => if (seat.focused) |window| window.window_v1.hide(),
+ .show_all => {
+ var it = seat.wm.windows.iterator(.forward);
+ while (it.next()) |window| {
+ window.window_v1.show();
+ }
+ },
+ }
+}
diff --git a/rivercompat/XkbBinding.zig b/rivercompat/XkbBinding.zig
index 6bdf856..0abbf2b 100644
--- a/rivercompat/XkbBinding.zig
+++ b/rivercompat/XkbBinding.zig
@@ -29,17 +29,20 @@ const gpa = std.heap.c_allocator;
seat: *Seat,
xkb_binding_v1: *river.XkbBindingV1,
+action: Seat.Action,
pub fn create(
seat: *Seat,
keysym: u32,
modifiers: river.SeatV1.Modifiers,
+ action: Seat.Action,
) void {
const xkb_binding_v1 = seat.seat_v1.getXkbBinding(keysym, modifiers) catch @panic("OOM");
const binding = gpa.create(XkbBinding) catch @panic("OOM");
binding.* = .{
.seat = seat,
.xkb_binding_v1 = xkb_binding_v1,
+ .action = action,
};
xkb_binding_v1.setListener(*XkbBinding, handleEvent, binding);
xkb_binding_v1.enable();
@@ -48,9 +51,7 @@ pub fn create(
fn handleEvent(xkb_binding_v1: *river.XkbBindingV1, event: river.XkbBindingV1.Event, binding: *XkbBinding) void {
assert(binding.xkb_binding_v1 == xkb_binding_v1);
switch (event) {
- .pressed => {
- binding.seat.focusNext();
- },
+ .pressed => binding.seat.execute(binding.action),
.released => {},
}
}