git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitbb58eb9e16642a140a6721a3053dd36d638ab536
parentd53737e656
authorIsaac Freund <[email protected]>
date2025-08-04 20:17
Window: send (un)maximize/minimize_requsted

 river/Window.zig      | 17 +++++++++++++++++
 river/XdgToplevel.zig | 22 ++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/river/Window.zig b/river/Window.zig
index 03b293f..ea760cd 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -143,6 +143,12 @@ wm_scheduled: struct {
     decoration_hint: river.WindowV1.DecorationHint = .only_supports_csd,
     /// Set back to no_request at the end of each update sequence
     fullscreen_requested: FullscreenRequest = .no_request,
+    maximize_requested: enum {
+        no_request,
+        maximize,
+        unmaximize,
+    } = .no_request,
+    minimize_requested: bool = false,
     dirty_app_id: bool = false,
     dirty_title: bool = false,
     pointer_move_requested: ?*Seat = null,
@@ -386,6 +392,7 @@ pub fn manageStart(window: *Window) void {
                 window_v1.sendDecorationHint(window.wm_scheduled.decoration_hint);
                 sent.decoration_hint = scheduled.decoration_hint;
             }
+
             switch (scheduled.fullscreen_requested) {
                 .no_request => {},
                 .fullscreen => |output_hint| {
@@ -398,6 +405,16 @@ pub fn manageStart(window: *Window) void {
                 .exit => window_v1.sendExitFullscreenRequested(),
             }
             scheduled.fullscreen_requested = .no_request;
+            switch (scheduled.maximize_requested) {
+                .no_request => {},
+                .maximize => window_v1.sendMaximizeRequested(),
+                .unmaximize => window_v1.sendUnmaximizeRequested(),
+            }
+            scheduled.maximize_requested = .no_request;
+            if (scheduled.minimize_requested) {
+                window_v1.sendMinimizeRequested();
+            }
+            scheduled.minimize_requested = false;
 
             if (new or scheduled.dirty_app_id) {
                 window_v1.sendAppId(window.getAppId());
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index a93aa87..6ff71c0 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -66,6 +66,8 @@ unmap: wl.Listener(void) = .init(handleUnmap),
 commit: wl.Listener(*wlr.Surface) = .init(handleCommit),
 new_popup: wl.Listener(*wlr.XdgPopup) = .init(handleNewPopup),
 request_fullscreen: wl.Listener(void) = .init(handleRequestFullscreen),
+request_maximize: wl.Listener(void) = .init(handleRequestMaximize),
+request_minimize: wl.Listener(void) = .init(handleRequestMinimize),
 request_move: wl.Listener(*wlr.XdgToplevel.event.Move) = .init(handleRequestMove),
 request_resize: wl.Listener(*wlr.XdgToplevel.event.Resize) = .init(handleRequestResize),
 set_title: wl.Listener(void) = .init(handleSetTitle),
@@ -106,6 +108,8 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
     wlr_toplevel.base.surface.events.commit.add(&toplevel.commit);
     wlr_toplevel.base.events.new_popup.add(&toplevel.new_popup);
     wlr_toplevel.events.request_fullscreen.add(&toplevel.request_fullscreen);
+    wlr_toplevel.events.request_maximize.add(&toplevel.request_maximize);
+    wlr_toplevel.events.request_minimize.add(&toplevel.request_minimize);
     wlr_toplevel.events.request_move.add(&toplevel.request_move);
     wlr_toplevel.events.request_resize.add(&toplevel.request_resize);
     wlr_toplevel.events.set_title.add(&toplevel.set_title);
@@ -229,6 +233,8 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
     toplevel.commit.link.remove();
     toplevel.new_popup.link.remove();
     toplevel.request_fullscreen.link.remove();
+    toplevel.request_maximize.link.remove();
+    toplevel.request_minimize.link.remove();
     toplevel.request_move.link.remove();
     toplevel.request_resize.link.remove();
     toplevel.set_title.link.remove();
@@ -378,6 +384,22 @@ fn handleRequestFullscreen(listener: *wl.Listener(void)) void {
     server.wm.dirtyWindowing();
 }
 
+fn handleRequestMaximize(listener: *wl.Listener(void)) void {
+    const toplevel: *XdgToplevel = @fieldParentPtr("request_maximize", listener);
+    if (toplevel.wlr_toplevel.requested.maximized) {
+        toplevel.window.wm_scheduled.maximize_requested = .maximize;
+    } else {
+        toplevel.window.wm_scheduled.maximize_requested = .unmaximize;
+    }
+    server.wm.dirtyWindowing();
+}
+
+fn handleRequestMinimize(listener: *wl.Listener(void)) void {
+    const toplevel: *XdgToplevel = @fieldParentPtr("request_minimize", listener);
+    toplevel.window.wm_scheduled.minimize_requested = true;
+    server.wm.dirtyWindowing();
+}
+
 fn handleRequestMove(
     listener: *wl.Listener(*wlr.XdgToplevel.event.Move),
     event: *wlr.XdgToplevel.event.Move,