Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
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 {