Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
river: handle rwm object destruction properly
If the window manager crashes river must survive.
river/Output.zig | 16 ++++++++++++----
river/Seat.zig | 11 +++++++++--
river/Window.zig | 12 ++++++++++--
river/WindowManager.zig | 15 ++++++++++-----
4 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index 9b846ab..0828ee0 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -251,7 +251,7 @@ pub fn sendDirty(output: *Output) void {
};
output.object = output_v1;
- output_v1.setHandler(*Output, handleRequest, null, output);
+ output_v1.setHandler(*Output, handleRequest, handleObjectDestroy, output);
wm_v1.sendOutput(output_v1);
break :blk output_v1;
@@ -301,13 +301,21 @@ fn handleRequestInert(
if (request == .destroy) output_v1.destroy();
}
+fn handleObjectDestroy(_: *river.OutputV1, output: *Output) void {
+ output.object = null;
+}
+
fn handleRequest(
- _: *river.OutputV1,
+ output_v1: *river.OutputV1,
request: river.OutputV1.Request,
- _: ?*Output,
+ output: *Output,
) void {
+ assert(output.object == output_v1);
switch (request) {
- .destroy => {}, // XXX send protocol error
+ .destroy => {
+ // XXX send protocol error
+ output_v1.destroy();
+ },
}
}
diff --git a/river/Seat.zig b/river/Seat.zig
index f665e42..8f9e3c0 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -299,7 +299,7 @@ pub fn sendDirty(seat: *Seat) void {
};
seat.object = seat_v1;
- seat_v1.setHandler(*Seat, handleRequest, null, seat);
+ seat_v1.setHandler(*Seat, handleRequest, handleDestroy, seat);
wm_v1.sendSeat(seat_v1);
seat.link_sent.remove();
@@ -348,6 +348,10 @@ fn handleRequestInert(
if (request == .destroy) seat_v1.destroy();
}
+fn handleDestroy(_: *river.SeatV1, seat: *Seat) void {
+ seat.object = null;
+}
+
fn handleRequest(
seat_v1: *river.SeatV1,
request: river.SeatV1.Request,
@@ -355,7 +359,10 @@ fn handleRequest(
) void {
assert(seat.object == seat_v1);
switch (request) {
- .destroy => {}, // XXX send protocol error
+ .destroy => {
+ // XXX send protocol error
+ seat_v1.destroy();
+ },
.focus_window => |args| {
const data = args.window.getUserData() orelse return;
const window: *Window = @ptrCast(@alignCast(data));
diff --git a/river/Window.zig b/river/Window.zig
index b0a14d6..35ddbbe 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -332,7 +332,7 @@ pub fn sendDirty(window: *Window) void {
return; // try again next update
};
window.object = window_v1;
- window_v1.setHandler(*Window, handleRequest, null, window);
+ window_v1.setHandler(*Window, handleRequest, handleDestroy, window);
wm_v1.sendWindow(window_v1);
server.wm.uncommitted.render_list.append(&window.node);
@@ -377,6 +377,11 @@ fn handleRequestInert(
if (request == .destroy) window_v1.destroy();
}
+fn handleDestroy(_: *river.WindowV1, window: *Window) void {
+ window.object = null;
+ window.node.makeInert();
+}
+
fn handleRequest(
window_v1: *river.WindowV1,
request: river.WindowV1.Request,
@@ -385,7 +390,10 @@ fn handleRequest(
assert(window.object == window_v1);
const uncommitted = &window.uncommitted;
switch (request) {
- .destroy => {}, // XXX send protocol error
+ .destroy => {
+ // XXX send protocol error
+ window_v1.destroy();
+ },
.close => uncommitted.closing = true,
.get_node => |args| {
if (window.node.object != null) {
diff --git a/river/WindowManager.zig b/river/WindowManager.zig
index ce0978d..6fecfdf 100644
--- a/river/WindowManager.zig
+++ b/river/WindowManager.zig
@@ -159,7 +159,7 @@ fn bind(client: *wl.Client, wm: *WindowManager, version: u32, id: u32) void {
}
wm.object = object;
- object.setHandler(*WindowManager, handleRequest, null, wm);
+ object.setHandler(*WindowManager, handleRequest, handleDestroy, wm);
}
fn handleRequestInert(
@@ -170,20 +170,25 @@ fn handleRequestInert(
if (request == .destroy) object.destroy();
}
+fn handleDestroy(_: *river.WindowManagerV1, wm: *WindowManager) void {
+ wm.object = null;
+}
+
fn handleRequest(
- object: *river.WindowManagerV1,
+ wm_v1: *river.WindowManagerV1,
request: river.WindowManagerV1.Request,
wm: *WindowManager,
) void {
- assert(wm.object == object);
+ assert(wm.object == wm_v1);
switch (request) {
.stop => {
wm.object = null;
- object.sendFinished();
- object.setHandler(?*anyopaque, handleRequestInert, null, null);
+ wm_v1.sendFinished();
+ wm_v1.setHandler(?*anyopaque, handleRequestInert, null, null);
},
.destroy => {
// XXX send protocol error
+ wm_v1.destroy();
},
.ack_update => |args| {
switch (wm.state) {