Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Window: send dimensions event on change
river/Seat.zig | 55 +++++++++++++++++++++++++-----------------------
river/Window.zig | 20 +++++++++++++-----
river/WindowManager.zig | 2 +-
river/XdgToplevel.zig | 10 ++-------
river/XwaylandWindow.zig | 4 +---
5 files changed, 48 insertions(+), 43 deletions(-)
diff --git a/river/Seat.zig b/river/Seat.zig
index 643cd6f..d43dc79 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -238,27 +238,13 @@ pub fn queueEvent(seat: *Seat, event: Event) void {
pub fn processEvents(seat: *Seat) void {
assert(server.wm.state == .idle);
+ // Only process events while there is no pending state to be sent to the window manager.
+ // The window manager might decide to change focus or redefine keyboard/pointer bindings
+ // in response to the pending update.
var expect_frame: bool = false;
- while (seat.event_queue.readItem()) |event| {
- const pg = server.input_manager.pointer_gestures;
- switch (event) {
- .keyboard_key => |ev| ev.keyboard.processKey(&ev.key),
- .keyboard_modifiers => |ev| ev.keyboard.processModifiers(&ev.modifiers),
-
- .pointer_motion_relative => |ev| seat.cursor.processMotionRelative(&ev),
- .pointer_motion_absolute => |ev| seat.cursor.processMotionAbsolute(&ev),
- .pointer_button => |ev| seat.cursor.processButton(&ev),
- .pointer_axis => |ev| seat.cursor.processAxis(&ev),
- .pointer_frame => seat.wlr_seat.pointerNotifyFrame(),
-
- .pointer_swipe_begin => |ev| pg.sendSwipeBegin(seat.wlr_seat, ev.time_msec, ev.fingers),
- .pointer_swipe_update => |ev| pg.sendSwipeUpdate(seat.wlr_seat, ev.time_msec, ev.dx, ev.dy),
- .pointer_swipe_end => |ev| pg.sendSwipeEnd(seat.wlr_seat, ev.time_msec, ev.cancelled),
-
- .pointer_pinch_begin => |ev| pg.sendPinchBegin(seat.wlr_seat, ev.time_msec, ev.fingers),
- .pointer_pinch_update => |ev| pg.sendPinchUpdate(seat.wlr_seat, ev.time_msec, ev.dx, ev.dy, ev.scale, ev.rotation),
- .pointer_pinch_end => |ev| pg.sendPinchEnd(seat.wlr_seat, ev.time_msec, ev.cancelled),
- }
+ while (!server.wm.pending.dirty or expect_frame) {
+ const event = seat.event_queue.readItem() orelse break;
+ seat.processEvent(event);
// Don't split up pointer events grouped by a frame event
switch (event) {
@@ -268,17 +254,34 @@ pub fn processEvents(seat: *Seat) void {
.pointer_axis,
=> {
expect_frame = true;
- continue;
},
.pointer_frame => expect_frame = false,
else => assert(!expect_frame),
}
+ }
- if (server.wm.pending.dirty) {
- // Wait for feedback from the window manager before further processing.
- // The window manager might decide to change focus or redefine keyboard/pointer bindings.
- break;
- }
+ assert(!expect_frame);
+}
+
+fn processEvent(seat: *Seat, event: Event) void {
+ const pg = server.input_manager.pointer_gestures;
+ switch (event) {
+ .keyboard_key => |ev| ev.keyboard.processKey(&ev.key),
+ .keyboard_modifiers => |ev| ev.keyboard.processModifiers(&ev.modifiers),
+
+ .pointer_motion_relative => |ev| seat.cursor.processMotionRelative(&ev),
+ .pointer_motion_absolute => |ev| seat.cursor.processMotionAbsolute(&ev),
+ .pointer_button => |ev| seat.cursor.processButton(&ev),
+ .pointer_axis => |ev| seat.cursor.processAxis(&ev),
+ .pointer_frame => seat.wlr_seat.pointerNotifyFrame(),
+
+ .pointer_swipe_begin => |ev| pg.sendSwipeBegin(seat.wlr_seat, ev.time_msec, ev.fingers),
+ .pointer_swipe_update => |ev| pg.sendSwipeUpdate(seat.wlr_seat, ev.time_msec, ev.dx, ev.dy),
+ .pointer_swipe_end => |ev| pg.sendSwipeEnd(seat.wlr_seat, ev.time_msec, ev.cancelled),
+
+ .pointer_pinch_begin => |ev| pg.sendPinchBegin(seat.wlr_seat, ev.time_msec, ev.fingers),
+ .pointer_pinch_update => |ev| pg.sendPinchUpdate(seat.wlr_seat, ev.time_msec, ev.dx, ev.dy, ev.scale, ev.rotation),
+ .pointer_pinch_end => |ev| pg.sendPinchEnd(seat.wlr_seat, ev.time_msec, ev.cancelled),
}
}
diff --git a/river/Window.zig b/river/Window.zig
index 989f526..950b458 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -279,6 +279,18 @@ pub fn closing(window: *Window) void {
window.dirtyPending();
}
+pub fn setDimensions(window: *Window, width: i32, height: i32) void {
+ window.pending.box.width = width;
+ window.pending.box.height = height;
+
+ window.inflight.box.width = width;
+ window.inflight.box.height = height;
+
+ if (width != window.sent.box.width or height != window.sent.box.height) {
+ window.dirtyPending();
+ }
+}
+
pub fn setDecorationHint(window: *Window, hint: river.WindowV1.DecorationHint) void {
window.pending.decoration_hint = hint;
if (hint != window.sent.decoration_hint) {
@@ -345,7 +357,8 @@ pub fn sendDirty(window: *Window) void {
const sent = &window.sent;
// XXX send all dirty pending state
- if ((pending.box.width != sent.box.width or
+ log.debug("XXXXXXXXXXXXXX pending {any} sent {any}", .{ pending.box, sent.box });
+ if ((new or pending.box.width != sent.box.width or
pending.box.height != sent.box.height) and !pending.box.empty())
{
window_v1.sendDimensions(window.pending.box.width, window.pending.box.height);
@@ -545,10 +558,7 @@ pub fn commitTransaction(window: *Window) void {
);
}
- window.inflight.box.width = xwindow.xsurface.width;
- window.inflight.box.height = xwindow.xsurface.height;
- window.pending.box.width = xwindow.xsurface.width;
- window.pending.box.height = xwindow.xsurface.height;
+ window.setDimensions(xwindow.xsurface.width, xwindow.xsurface.height);
window.current = window.inflight;
},
diff --git a/river/WindowManager.zig b/river/WindowManager.zig
index 2535ae2..3f8fd10 100644
--- a/river/WindowManager.zig
+++ b/river/WindowManager.zig
@@ -442,7 +442,7 @@ fn commitTransaction(wm: *WindowManager) void {
if (wm.committed.dirty) {
wm.sendConfigures();
} else if (wm.pending.dirty) {
- wm.sendUpdate();
+ wm.dirtyPending();
} else {
server.input_manager.processEvents();
}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index b3063d5..db36d11 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -344,10 +344,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
});
}
- window.inflight.box.width = toplevel.geometry.width;
- window.inflight.box.height = toplevel.geometry.height;
- window.pending.box.width = toplevel.geometry.width;
- window.pending.box.height = toplevel.geometry.height;
+ window.setDimensions(toplevel.geometry.width, toplevel.geometry.height);
window.current = window.inflight;
window.updateSceneState();
} else if (old_geometry.x != toplevel.geometry.x or
@@ -369,10 +366,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
window.resizeUpdatePosition(toplevel.geometry.width, toplevel.geometry.height);
}
- window.inflight.box.width = toplevel.geometry.width;
- window.inflight.box.height = toplevel.geometry.height;
- window.pending.box.width = toplevel.geometry.width;
- window.pending.box.height = toplevel.geometry.height;
+ window.setDimensions(toplevel.geometry.width, toplevel.geometry.height);
switch (toplevel.configure_state) {
.acked => {
diff --git a/river/XwaylandWindow.zig b/river/XwaylandWindow.zig
index ca6dd85..d52775a 100644
--- a/river/XwaylandWindow.zig
+++ b/river/XwaylandWindow.zig
@@ -234,9 +234,7 @@ fn handleRequestConfigure(
return;
}
- xwindow.window.pending.box.width = event.width;
- xwindow.window.pending.box.height = event.height;
- server.wm.dirtyPending();
+ @panic("TODO");
}
fn handleSetOverrideRedirect(listener: *wl.Listener(void)) void {