srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/udev/render.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-08-15 23:22:00 +0200
committersrdusr <[email protected]>2025-08-15 23:22:00 +0200
commitcc22fe69a68e0fff027d833029aea850976488c8 (patch)
treeeb1350c24c61b5d4b30d763d64149a5c6504a925 /crates/wayland/src/udev/render.rs
parent6694a2d9946d98d5752d84b22c45879cab5c9abe (diff)
downloadsrdwm-cc22fe69a68e0fff027d833029aea850976488c8.tar.gz
srdwm-cc22fe69a68e0fff027d833029aea850976488c8.zip
Add real desktop icons plus right-click desktop/icon context menus
Closes "right-click on bare desktop" - previously a true no-op, nothing rendered above the wallpaper at all. Requested directly: a real desktop "just like windows does" - Home/Computer/Trash plus one icon per real ~/Desktop entry, individually draggable with persisted grid positions, double-click to open, right-click menus (per-icon "Open" plus "Set as Wallpaper" for image files when general.wallpaper_command is set; bare desktop "New Folder"/"Refresh"). Architecture mirrors the existing context_menu.rs/snap_flyout.rs "compositor-owned floating UI" pattern: desktop_icons.rs (data model, grid layout, filesystem scan, hit-test), desktop_icons_state.rs (JSON persistence, same shape as monitor_layout.rs), desktop_menu.rs (the new right-click menu, reusing decoration::render_context_menu's existing rasterizer), state/desktop_icons.rs (CompState glue: rescan/select/drag/ open/persist), and a new decoration::render_desktop_icon rasterizer -- hand-drawn glyphs, since no PNG/SVG decoding capability exists anywhere in this workspace. Wired into both render loops (udev and winit) above the wallpaper and below every window, and into input/pointer.rs's button/ motion handlers for selection, drag, double-click, and both menus. Four new config keys: general.desktop_icons (default true - a directly requested, purely visual feature, unlike the opt-in-while-experimental general.gpu), general.file_manager, general.desktop_icon_single_click, general.wallpaper_command (all default off/empty). Deliberately out of scope for this pass, stated up front: move-to-trash and "Empty Trash" (destructive, no confirmation-dialog primitive to gate them on yet), filesystem watching, multi-select, per-mimetype icon art, icons on any monitor but the primary one. 124 wayland-crate tests (up from 106), full workspace build and clippy clean.
Diffstat (limited to 'crates/wayland/src/udev/render.rs')
-rw-r--r--crates/wayland/src/udev/render.rs28
1 files changed, 28 insertions, 0 deletions
diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs
index 802428f..73aaa82 100644
--- a/crates/wayland/src/udev/render.rs
+++ b/crates/wayland/src/udev/render.rs
@@ -21,6 +21,12 @@ impl CompState {
// Same reason again: a native lock's capture step (below) needs
// this, and `self.wm` can't be borrowed once `self.udev` is.
let lock_blur_radius = self.wm.borrow().lock.blur_radius;
+ // Same "capture before `self.udev`'s borrow starts" reason as
+ // `cursor_status`/`cursor_buffers` above: global-space, so computed
+ // once here rather than per head, each head's own per-frame push
+ // below just re-offsets these same positions by its own `origin`.
+ self.ensure_desktop_icons();
+ let desktop_icon_render_list = self.desktop_icon_render_list();
// Captured-and-blurred backgrounds collected during the per-head
// loop below, applied via `self.capture_output` only after it
// ends - `self.udev`'s mutable borrow is held for the whole loop
@@ -323,6 +329,15 @@ impl CompState {
Err(e) => log::warn!("udev: failed to import snap flyout buffer: {e}"),
}
}
+ // The desktop-icon/bare-desktop right-click menu, if open --
+ // same "topmost but never hides the cursor" placement.
+ if let (Some(menu), Some(buffer)) = (self.desktop_menu.as_ref(), self.desktop_menu_buffer.as_ref()) {
+ let pos = ((menu.pos.0 - origin.x) as f64, (menu.pos.1 - origin.y) as f64);
+ match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, pos, buffer, None, None, None, Kind::Unspecified) {
+ Ok(elem) => custom_elements.push(crate::elements::OverlayElement::Memory(elem)),
+ Err(e) => log::warn!("udev: failed to import desktop menu buffer: {e}"),
+ }
+ }
// Popups next: always above every window's own content,
// matching this codebase's long-standing behavior from
// before content moved into this same `custom_elements`
@@ -903,6 +918,19 @@ impl CompState {
}
occluders.push(frame);
}
+ // Real desktop icons - above the wallpaper, below every
+ // window: pushed after the windows loop above (so nothing
+ // here can occlude a real window) but before the
+ // background-layer push just below (so the wallpaper still
+ // shows through everywhere an icon doesn't draw). See
+ // `desktop_icons.rs`'s own module doc comment.
+ for (pos, buffer) in &desktop_icon_render_list {
+ let pos = ((pos.0 - origin.x) as f64, (pos.1 - origin.y) as f64);
+ match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, pos, buffer, None, None, None, Kind::Unspecified) {
+ Ok(elem) => custom_elements.push(crate::elements::OverlayElement::Memory(elem)),
+ Err(e) => log::warn!("udev: failed to import desktop icon buffer: {e}"),
+ }
+ }
// Background/bottom layer-shell (wallpaper engines) last --
// bottommost, matching smithay's own `space_render_elements`
// ordering, which this whole custom loop now replaces.