diff options
| author | srdusr <[email protected]> | 2024-11-26 23:16:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-11-26 23:16:00 +0200 |
| commit | 87f5c04b2593dc49409644e69e7962b73d26b9d8 (patch) | |
| tree | 5a1da319c9f5e81489af44a4a576eada595b9a22 /crates/core | |
| parent | fe92f6e6b8ab680c9603cc6bcf16c98555c378ae (diff) | |
| download | srdwm-87f5c04b2593dc49409644e69e7962b73d26b9d8.tar.gz srdwm-87f5c04b2593dc49409644e69e7962b73d26b9d8.zip | |
Add Monitor::maximize_geometry: maximize covers a dock, still stops at a top bar
toggle_maximize previously targeted full_geometry outright (past every
reserved zone), on an earlier request specifically about the dock -
which also silently let it extend behind a top bar's zone, reported
back as its own bug once live-tested. maximize_geometry is a third
rect distinct from geometry (every zone) and full_geometry (none):
full_geometry with only a top-anchored bar's exclusive zone subtracted
back out. New test locks in dock-covered/bar-respected together.
Diffstat (limited to 'crates/core')
| -rw-r--r-- | crates/core/src/manager/monitors.rs | 34 | ||||
| -rw-r--r-- | crates/core/src/manager/winops.rs | 14 | ||||
| -rw-r--r-- | crates/core/src/monitor.rs | 19 |
3 files changed, 64 insertions, 3 deletions
diff --git a/crates/core/src/manager/monitors.rs b/crates/core/src/manager/monitors.rs index 173e07d..9783e14 100644 --- a/crates/core/src/manager/monitors.rs +++ b/crates/core/src/manager/monitors.rs @@ -74,7 +74,10 @@ impl WindowManager { continue; } let Some(monitor) = live.iter().find(|m| m.id == window.monitor) else { continue }; - let target = if window.fullscreen { monitor.full_geometry } else { monitor.geometry }; + // Maximize and fullscreen target different rects now - see + // `Monitor::maximize_geometry`'s doc comment for why a maximized + // window still stops at a top bar while fullscreen does not. + let target = if window.maximized { monitor.maximize_geometry } else { monitor.full_geometry }; if window.geometry != target { window.geometry = target; } @@ -85,6 +88,35 @@ impl WindowManager { &self.monitors } + /// Queues a request to move output `id` to `(x, y)` in the shared + /// global space - the primitive monitor mirroring (and any other + /// output-arrangement UI) needs: position two outputs at the same + /// coordinates and they show the same desktop region, no separate + /// "mirror" concept required anywhere in this compositor. Core cannot + /// apply this itself (it doesn't own real output hardware - see this + /// field's own doc comment on `WindowManager`); the backend drains and + /// applies it on its own next poll via `drain_output_position_requests`. + /// + /// Replaces (not accumulates) any still-pending request for the same + /// `id`: only the *latest* requested position for a given output + /// matters if several arrive before the backend's next drain, the same + /// "last write wins" semantics `srd set`'s other live-config values + /// already have. + pub fn request_output_position(&mut self, id: MonitorId, x: i32, y: i32) { + self.output_position_requests.retain(|(existing, _, _)| *existing != id); + self.output_position_requests.push((id, x, y)); + } + + /// Takes every currently-queued output-position request, leaving the + /// queue empty. The backend calls this once per poll pass; requests + /// that arrive between two polls are still captured (nothing is lost + /// between drains, unlike a single `Option`), just coalesced to one + /// per output id per drain by `request_output_position`'s own + /// replace-not-accumulate behaviour. + pub fn drain_output_position_requests(&mut self) -> Vec<(MonitorId, i32, i32)> { + std::mem::take(&mut self.output_position_requests) + } + pub fn primary_monitor(&self) -> Option<&Monitor> { self.monitors.iter().find(|m| m.primary).or_else(|| self.monitors.first()) } diff --git a/crates/core/src/manager/winops.rs b/crates/core/src/manager/winops.rs index e656298..6f4d53e 100644 --- a/crates/core/src/manager/winops.rs +++ b/crates/core/src/manager/winops.rs @@ -93,7 +93,19 @@ impl WindowManager { } pub fn toggle_maximize(&mut self, id: WindowId) { - let monitor_geom = self.windows.get(&id).and_then(|w| self.monitor_for(w.monitor)).map(|m| m.geometry); + // `maximize_geometry`, not `geometry` or `full_geometry`: maximize + // covers the whole monitor past a dock's reserved zone, same as + // `toggle_fullscreen` - but still stops at a top bar's, unlike + // fullscreen. Previously targeted `full_geometry` outright (past + // both), on the user's own request specifically about the dock; + // that also silently pulled maximize past the top bar, which + // wasn't part of that request and was reported back as its own + // bug once live-tested. See `Monitor::maximize_geometry`'s own doc + // comment for the exact rect this now is. The only remaining + // difference from fullscreen is `decorated` (maximize keeps + // whatever decoration state the window already had; fullscreen + // forces it off). + let monitor_geom = self.windows.get(&id).and_then(|w| self.monitor_for(w.monitor)).map(|m| m.maximize_geometry); let animations_enabled = self.animations_enabled; let Some(w) = self.windows.get_mut(&id) else { return }; let from = w.geometry; diff --git a/crates/core/src/monitor.rs b/crates/core/src/monitor.rs index b04ee15..01f54cb 100644 --- a/crates/core/src/monitor.rs +++ b/crates/core/src/monitor.rs @@ -22,6 +22,23 @@ pub struct Monitor { /// before. Defaults to `geometry` (no reservation) for any backend /// that hasn't been taught the distinction yet. pub full_geometry: Rect, + /// The rect `toggle_maximize` targets: `full_geometry` with only a + /// top-anchored bar's exclusive zone (a menu bar, always expected to + /// stay visible/reachable) subtracted back out again - a dock anchored + /// to any other edge is deliberately left alone, same as + /// `full_geometry`. Two behaviors maximize needs that neither + /// `geometry` (shrunk by *every* zone) nor `full_geometry` (shrunk by + /// none) can express on its own: "go past the dock" and "still stop at + /// the top bar" are both true at once, on the user's own explicit + /// call when the two pulled in opposite directions (`full_geometry` had + /// briefly covered both, which un-did "stop at the top bar" as a side + /// effect of fixing "go past the dock"). + /// + /// Defaults to `geometry` (no reservation ignored at all) for any + /// backend or test that hasn't been taught the per-edge distinction -- + /// same conservative-default reasoning as `full_geometry`'s own doc + /// comment. + pub maximize_geometry: Rect, pub name: String, pub refresh_rate_mhz: u32, pub primary: bool, @@ -29,6 +46,6 @@ pub struct Monitor { impl Monitor { pub fn new(id: MonitorId, name: impl Into<String>, geometry: Rect) -> Self { - Self { id, name: name.into(), geometry, full_geometry: geometry, refresh_rate_mhz: 60_000, primary: false } + Self { id, name: name.into(), geometry, full_geometry: geometry, maximize_geometry: geometry, refresh_rate_mhz: 60_000, primary: false } } } |