srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland
diff options
context:
space:
mode:
Diffstat (limited to 'crates/wayland')
-rw-r--r--crates/wayland/src/input/layers.rs12
-rw-r--r--crates/wayland/src/state/lifecycle.rs20
-rw-r--r--crates/wayland/src/udev/platform.rs2
-rw-r--r--crates/wayland/src/udev/render.rs11
-rw-r--r--crates/wayland/src/winit/nested_platform.rs4
-rw-r--r--crates/wayland/src/winit/render.rs11
6 files changed, 53 insertions, 7 deletions
diff --git a/crates/wayland/src/input/layers.rs b/crates/wayland/src/input/layers.rs
index b429fbb..4450013 100644
--- a/crates/wayland/src/input/layers.rs
+++ b/crates/wayland/src/input/layers.rs
@@ -142,7 +142,7 @@ pub(super) fn background_layer_surface_under(state: &CompState, pos: Point<f64,
/// respecting every edge here is what every mainstream desktop's own
/// maximize convention already does. Fullscreen is unaffected - it never
/// called this function, and still doesn't.
-pub(crate) fn maximize_geometry_for(output: &Output, full: srdwm_core::Rect) -> srdwm_core::Rect {
+pub(crate) fn maximize_geometry_for(output: &Output, full: srdwm_core::Rect, covers_dock: bool) -> srdwm_core::Rect {
let mut rect = full;
// `exclusive_zone`/`margin` are logical (a layer-shell client reports
// its own reservation the same way every other layer-shell geometry
@@ -162,7 +162,15 @@ pub(crate) fn maximize_geometry_for(output: &Output, full: srdwm_core::Rect) ->
rect.y += shrink;
rect.height = rect.height.saturating_sub(shrink as u32);
}
- if data.anchor.contains(Anchor::BOTTOM) && !data.anchor.contains(Anchor::TOP) {
+ // A bottom-anchored zone (a dock) is deliberately NOT subtracted
+ // when `covers_dock` is set: maximize runs to the bottom of the
+ // screen and the dock floats over it. Asked for directly - "not
+ // sure why it doesn't go all the way down past where dock would
+ // be" - and it matches the common dock convention (macOS, and any
+ // auto-hiding dock), where the dock overlays a maximized window
+ // rather than permanently shortening it. Top/left/right zones are
+ // still honoured, so a maximized window never hides the bar.
+ if data.anchor.contains(Anchor::BOTTOM) && !data.anchor.contains(Anchor::TOP) && !covers_dock {
let shrink = scaled(data.margin.bottom);
rect.height = rect.height.saturating_sub(shrink as u32);
}
diff --git a/crates/wayland/src/state/lifecycle.rs b/crates/wayland/src/state/lifecycle.rs
index 92f7d9d..163064e 100644
--- a/crates/wayland/src/state/lifecycle.rs
+++ b/crates/wayland/src/state/lifecycle.rs
@@ -131,9 +131,29 @@ impl CompState {
}
true
});
+ // The client's own declared minimum, read from the same place
+ // `resizable` above comes from. A rule's `min_size` still wins --
+ // it is applied at map time and this must not undo it - so this
+ // only ever raises the floor above the global default, never
+ // overwrites a deliberate override.
+ let declared_min = self.id_to_window.get(&id).and_then(|dw| {
+ if let Some(toplevel) = dw.toplevel() {
+ let min = smithay::wayland::compositor::with_states(toplevel.wl_surface(), |states| {
+ let mut cached = states.cached_state.get::<smithay::wayland::shell::xdg::SurfaceCachedState>();
+ cached.current().min_size
+ });
+ return (min.w > 0 && min.h > 0).then_some((min.w as u32, min.h as u32));
+ }
+ dw.x11_surface().and_then(|x| x.min_size()).and_then(|m| (m.w > 0 && m.h > 0).then_some((m.w as u32, m.h as u32)))
+ });
if let Some(win) = self.wm.borrow_mut().window_mut(id) {
win.is_dialog = is_dialog;
win.resizable = resizable;
+ if let Some(min) = declared_min {
+ if !win.min_size_from_rule {
+ win.min_size = min;
+ }
+ }
}
let show_maximize = {
let wm = self.wm.borrow();
diff --git a/crates/wayland/src/udev/platform.rs b/crates/wayland/src/udev/platform.rs
index 0ae65f7..ea2260e 100644
--- a/crates/wayland/src/udev/platform.rs
+++ b/crates/wayland/src/udev/platform.rs
@@ -830,7 +830,7 @@ impl Platform for UdevPlatform {
// deliberately *not* defaulted from `usable` the way `Monitor::
// new` alone would (see the fullscreen note below).
let full = srdwm_core::Rect::new(head.location.x, head.location.y, head.size.0 as u32, head.size.1 as u32);
- let maximize = crate::input::maximize_geometry_for(&head.output, full);
+ let maximize = crate::input::maximize_geometry_for(&head.output, full, wm.maximize_covers_dock);
let name = head.output.name();
let split = wm.monitor_split(&name);
let parts = split.map(|s| s.parts).unwrap_or(1).max(1);
diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs
index aa05529..3bd9a52 100644
--- a/crates/wayland/src/udev/render.rs
+++ b/crates/wayland/src/udev/render.rs
@@ -334,7 +334,16 @@ impl CompState {
// be_masked` degenerates to just `w.decorated` when
// masking can never succeed).
let border_curve_is_safe = w.decorated;
- if w.border_width > 0 {
+ // No border on a maximized window. A maximized window's own
+ // edges are the screen's edges, so a border has nothing to
+ // separate it from - and where maximize *does* stop short (the
+ // strip a top bar reserves) the border lands in that gap, drawn
+ // as a hard line right against the bar. Reported live with a
+ // screenshot: a 4px accent line between the bar and the window,
+ // and none anywhere else, because the left/right/bottom strips
+ // fall off-screen. Fullscreen is already borderless for the
+ // same reason, via `decorated` being cleared.
+ if w.border_width > 0 && !w.maximized {
let strips = decoration::border_strips(geom, w.border_width);
if let Some(buffer) = self.border_top_decorations.get(&id) {
let (row0, rows, shift) = decoration::border_top_visible_rows(border_curve_is_safe, w.border_width, w.corner_radius);
diff --git a/crates/wayland/src/winit/nested_platform.rs b/crates/wayland/src/winit/nested_platform.rs
index 3b762ab..b0fa529 100644
--- a/crates/wayland/src/winit/nested_platform.rs
+++ b/crates/wayland/src/winit/nested_platform.rs
@@ -117,7 +117,7 @@ impl Platform for WaylandPlatform {
let usable = srdwm_core::Rect::new(zone.loc.x, zone.loc.y, zone.size.w as u32, zone.size.h as u32);
let full_size = self.backend.window_size();
let full = srdwm_core::Rect::new(0, 0, full_size.w as u32, full_size.h as u32);
- let maximize = crate::input::maximize_geometry_for(&self.output, full);
+ let maximize = crate::input::maximize_geometry_for(&self.output, full, self.wm.borrow().maximize_covers_dock);
// Expanded into one `Monitor` per split part, exactly as
// `udev/platform.rs`'s own `monitors()` does - see the split drain
// in `poll` above for why this backend supports it at all.
@@ -149,7 +149,7 @@ impl Platform for WaylandPlatform {
// "usable, shrunk rect" `toggle_maximize` targets.
let full = self.backend.window_size();
m.full_geometry = srdwm_core::Rect::new(0, 0, full.w as u32, full.h as u32);
- m.maximize_geometry = crate::input::maximize_geometry_for(&self.output, m.full_geometry);
+ m.maximize_geometry = crate::input::maximize_geometry_for(&self.output, m.full_geometry, self.wm.borrow().maximize_covers_dock);
m.primary = true;
m
}])
diff --git a/crates/wayland/src/winit/render.rs b/crates/wayland/src/winit/render.rs
index ccc64a2..432ebba 100644
--- a/crates/wayland/src/winit/render.rs
+++ b/crates/wayland/src/winit/render.rs
@@ -313,7 +313,16 @@ impl WaylandPlatform {
// doc comment further down; that's an overlap between two
// pieces of this window's own decoration, not with its content,
// so it doesn't contradict this paragraph.)
- if w.border_width > 0 {
+ // No border on a maximized window. A maximized window's own
+ // edges are the screen's edges, so a border has nothing to
+ // separate it from - and where maximize *does* stop short (the
+ // strip a top bar reserves) the border lands in that gap, drawn
+ // as a hard line right against the bar. Reported live with a
+ // screenshot: a 4px accent line between the bar and the window,
+ // and none anywhere else, because the left/right/bottom strips
+ // fall off-screen. Fullscreen is already borderless for the
+ // same reason, via `decorated` being cleared.
+ if w.border_width > 0 && !w.maximized {
let color = crate::state::effective_border_color(w.border_color, focused == Some(id), self.wm.borrow().theme.border_inactive_dim);
let strips = decoration::border_strips(frame, w.border_width);
// Strips 0/1 (top/bottom) are rounded on their own two