srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/udev.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2024-06-20 16:08:00 +0200
committersrdusr <[email protected]>2024-06-20 16:08:00 +0200
commitab0916391532031376817ed4ab6ab234428559a2 (patch)
tree169e7799fbb6dd5d225b01ed645b1fa5cbf179de /crates/wayland/src/udev.rs
parent20cdd47b39f09aa19317d9d29fef6511b98c1233 (diff)
downloadsrdwm-ab0916391532031376817ed4ab6ab234428559a2.tar.gz
srdwm-ab0916391532031376817ed4ab6ab234428559a2.zip
Add drop shadows and shrink the resize grab margin that was eating content clicks
Two independent daily-driving gaps closed in one pass, both from MISSING.md and live user feedback: Drop shadows (general.shadows, default true). Reuses the exact "bitmap drawn outside geometry, cached like the border" technique border_strips/ render_border_top already established - decoration::shadow_bitmap rasterizes a linear alpha falloff (Chebyshev/square-ring distance, not a true blur -- no blur primitive exists without a GPU shader, and the udev backend's PixmanRenderer is software-only) from SHADOW_MAX_ALPHA (90/255, deliberately subtle) at the window's own edge down to fully transparent SHADOW_SIZE (12px) out. Cached in CompState::shadow_buffers, rebuilt at the same trigger points as border_top_decorations (redraw_decoration_buffer), for the identical damage-tracking reason: a fresh Id every frame means OutputDamageTracker never finds a previous-frame match. No shadow for a maximized or fullscreen window, matching the Hyprland/GNOME convention MISSING.md measures against. Resize grab margin: 10px -> 6px (general.resize_margin, now configurable, same call-site-count-preserving change as threading a new parameter through one indirection point: ResizeEdge::hit_test's only production caller is WindowManager::hit_test, so this didn't need touching every backend despite hit_test being shared verbatim across X11/Wayland/Windows/macOS). Reported live: ordinary clicks near any window edge - a link near a browser's edge, a button near a panel's edge - regularly registered as a resize-edge grab instead of reaching the client, not just an occasional near-miss, because the 10px band was measured inward from the client's own content rect. 6px stays comfortably grabbable while giving content back most of its edge. Verified: cargo build --workspace (all 9 crates including the windows/macos stub backends), cargo clippy --workspace (0 new warnings), cargo test across core/wayland/config/x11 (188 tests, 0 failed). Shadow rendering verified at the render-element level live in a nested session (correct geometry, alpha, buffer contents) - grim/screencopy itself turned out to route through winit.rs's separate capture_offscreen path, which only ever drew `decorations` (titlebars), never borders or shadows, so screenshots taken this way have never shown either; a real gap, not fixed in this pass.
Diffstat (limited to 'crates/wayland/src/udev.rs')
-rw-r--r--crates/wayland/src/udev.rs20
1 files changed, 20 insertions, 0 deletions
diff --git a/crates/wayland/src/udev.rs b/crates/wayland/src/udev.rs
index 96d57d5..7e7a69f 100644
--- a/crates/wayland/src/udev.rs
+++ b/crates/wayland/src/udev.rs
@@ -312,6 +312,25 @@ impl CompState {
// windows) has to agree with what `sync_geometry` mapped
// the content to, or they drift apart again.
let geom = self.window_anims.get(&id).map(crate::state::WindowAnim::current_rect).unwrap_or(w.geometry);
+ // Drawn first among this window's own decoration, and
+ // positioned from the same animated `geom` as everything
+ // else here - not `w.geometry` - for the identical
+ // reason: a shadow that stayed at the pre-tween rect
+ // while the window slid past it would look exactly as
+ // detached as the border did before that fix. Not
+ // fragment-clipped against `occluders` like the titlebar/
+ // border below: at `SHADOW_MAX_ALPHA`'s low opacity, a
+ // shadow bleeding slightly onto a window stacked in front
+ // of this one reads as a soft edge, not the hard-line
+ // bleed-through that made the titlebar/border need it.
+ if let Some(shadow) = self.shadow_buffers.get(&id) {
+ let rect = decoration::shadow_rect(geom);
+ let pos = ((rect.x - origin.x) as f64, (rect.y - origin.y) as f64);
+ match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, pos, shadow, None, None, None, Kind::Unspecified) {
+ Ok(elem) => custom_elements.push(crate::elements::OverlayElement::Memory(elem)),
+ Err(e) => log::warn!("udev: failed to import shadow buffer: {e}"),
+ }
+ }
if let Some(deco) = self.decorations.get(&id) {
// Fragment-clipped, same as the three solid border
// strips below - an *all-or-nothing* version of
@@ -996,6 +1015,7 @@ impl UdevPlatform {
dead_layer_surfaces: HashSet::new(),
decorations: HashMap::new(),
border_top_decorations: HashMap::new(),
+ shadow_buffers: HashMap::new(),
border_side_buffers: HashMap::new(),
last_synced_size: HashMap::new(),
pending: pending.clone(),