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

commitfd1562b8db892abce998c74b06e320f0e3c7e757
parent51627ef806
authorLucas Galante <[email protected]>
date2026-09-18 13:01
feat(status): `adjust` topic — "on"/"off" as window-adjust mode comes and goes

Pushed from refresh_adjust_held and set_mode, so it follows
window_adjust_active() exactly (overview, or Super held, injected or
real). The desktop grid subscribes to show resize handles on its pinned
images in step with the windows' handles: it never holds keyboard
focus, so it cannot read the modifier state for itself.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

 WORKSPACE.md                 |  6 ++++--
 src/server/status_server.rs  | 13 ++++++++++++-
 src/server/window_manager.rs |  5 +++++
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/WORKSPACE.md b/WORKSPACE.md
index 177f8bb..32209a7 100644
--- a/WORKSPACE.md
+++ b/WORKSPACE.md
@@ -80,7 +80,7 @@ ccebuild install cce-mail  # just one package (what each crate's `make install`
 ccebuild restart            # restart user services left on a replaced binary
 ccebuild status             # built-vs-installed drift, AND running-vs-installed
 ccebuild prune              # target/ artifacts of crates cargo no longer knows
-ccebuild install-system     # the root-owned binaries (needs sudo)
+ccebuild install-system     # the root-owned binaries, units, PAM stacks (one sudo prompt; --dry-run to preview)
 ```
 
 The full deploy loop is `ccebuild install && ccebuild restart`. `ccebuild` derives
@@ -289,7 +289,9 @@ Clients and compositor communicate over Unix sockets keyed by `$WAYLAND_DISPLAY`
   `ccectl` binary (in `cce-compositor/`) is the CLI client; run `ccectl` with no args for the
   command list.
 - **Status**: `/tmp/cce-status-{WAYLAND_DISPLAY}.sock` — subscribe to `layout` /
-  `title` / `modifiers` / `dismiss` / `backdrop <app_id>` and receive push updates.
+  `title` / `modifiers` / `adjust` / `dismiss` / `backdrop <app_id>` and receive push
+  updates. `adjust` is "on"/"off" as window-adjust mode (overview, or Super
+  held) comes and goes — what `cce-grid` keys its image resize handles on.
   This feeds `cce-status-interface` (the status bar). `backdrop` is the odd one
   out: it takes the asking segment's app_id and reports what that segment is
   composited over, which is the one thing a Wayland client can never see for
diff --git a/src/server/status_server.rs b/src/server/status_server.rs
index 6f16b44..f122c14 100644
--- a/src/server/status_server.rs
+++ b/src/server/status_server.rs
@@ -2,7 +2,7 @@
 //
 // Runs in a dedicated thread. cce-status connects to
 // /tmp/cce-status-{WAYLAND_DISPLAY}.sock, sends a subscription line
-// ("layout", "title", "modifiers", or "dismiss") and receives lines whenever the status changes.
+// ("layout", "title", "modifiers", "adjust", or "dismiss") and receives lines whenever the status changes.
 //
 // The main loop sends updates through an mpsc channel. The server thread
 // owns the socket and handles all I/O independently of the Wayland event loop.
@@ -24,6 +24,12 @@ pub struct StatusUpdate {
     pub title_text: String,
     /// Plain text for modifiers subscriber
     pub modifiers_text: String,
+    /// "on" while window-adjust mode is active (overview, or Super held —
+    /// `WindowManager::window_adjust_active`), else "off". The desktop grid
+    /// subscribes to show its own resize handles on the pinned images in
+    /// step with the windows' handles; it never holds keyboard focus, so
+    /// it cannot read the modifier state for itself.
+    pub adjust_text: String,
     /// What each status segment is composited OVER, by app_id — see
     /// [`crate::backdrop`]. Unlike the other topics this one is
     /// per-subscriber: a segment gets only its own entry, since the whole
@@ -54,6 +60,8 @@ enum Subscription {
     Layout,
     Title,
     Modifiers,
+    /// `adjust` — "on"/"off" as window-adjust mode comes and goes.
+    Adjust,
     /// One-shot menu-dismiss events only — never receives state pushes.
     Dismiss,
     /// `backdrop <app_id>` — what THIS segment is composited over, so it can
@@ -75,6 +83,7 @@ impl Subscription {
             "layout" => Subscription::Layout,
             "title" => Subscription::Title,
             "modifiers" => Subscription::Modifiers,
+            "adjust" => Subscription::Adjust,
             "dismiss" => Subscription::Dismiss,
             _ => Subscription::Unknown,
         }
@@ -424,6 +433,7 @@ fn format_for_subscription(sub: &Subscription, update: &StatusUpdate) -> String
         Subscription::Layout => update.layout_text.clone(),
         Subscription::Title => update.title_text.clone(),
         Subscription::Modifiers => update.modifiers_text.clone(),
+        Subscription::Adjust => update.adjust_text.clone(),
         Subscription::Backdrop(app_id) => {
             // A segment the compositor has no sample for (not mapped yet, or
             // its app_id does not match a window) is told so explicitly
@@ -512,6 +522,7 @@ pub unsafe fn build_status_update(wm: &crate::window_manager::WindowManager) ->
         layout_text,
         title_text,
         modifiers_text,
+        adjust_text: if wm.window_adjust_active() { "on" } else { "off" }.to_string(),
         // Measured in the render pass (see `Output::measure_status_backdrops`)
         // because that is where the frame's grid geometry already lives;
         // here it is only carried.
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 39bd136..a0ca407 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -2155,6 +2155,8 @@ impl WindowManager {
         }
         self.mode = mode;
         self.arm_border_fade();
+        // The `adjust` status topic follows window_adjust_active().
+        self.update_status();
     }
 
     /// Overview, or Super held: the focused window shows its frame and
@@ -2188,6 +2190,9 @@ impl WindowManager {
         }
         self.adjust_held = held;
         self.arm_border_fade();
+        // The `adjust` status topic: the desktop grid shows its image
+        // handles in step with the windows'.
+        self.update_status();
         let now = crate::util::msec_timestamp();
         let mut curr_seat = (*seats_list).next;
         while curr_seat != seats_list {