diff options
| author | srdusr <[email protected]> | 2025-09-10 11:24:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-09-10 11:24:00 +0200 |
| commit | 5ee627928d0cb017e59d796c71793c35d5b65d33 (patch) | |
| tree | 3285a7df82a04b178fb41fae220d60fe1dd38bd7 /crates/wayland/src/decoration | |
| parent | 4a55182ce17fd4474f8be1e8819a41b7ccd11045 (diff) | |
| download | srdwm-5ee627928d0cb017e59d796c71793c35d5b65d33.tar.gz srdwm-5ee627928d0cb017e59d796c71793c35d5b65d33.zip | |
Wayland backend: desktop icons v2, menu rebuild, layer-shell/scale fixes,
XWayland stability, GPU rendering, and multi-cursor Phase 2
The bulk of a multi-session shift's real work landed in crates/wayland.
Full root-cause/verification narrative for every item below lives in
docs/TODO.md (each has its own dated entry); this is the summary:
Desktop shell:
- Real desktop icons v2 (state/desktop_icons.rs, desktop_icons.rs):
fixed origin-baked-before-the-bar-connects, fixed-icon sort order, and
a proper Rename/Delete-to-Trash menu (window_memory.rs backs the
rename-persistence side). Rubber-band marquee multi-select.
- icon_theme.rs: real freedesktop icon-theme lookup (inherits chain,
hicolor fallback) rendering actual theme SVGs via resvg/tiny-skia,
replacing the hand-drawn placeholder glyphs.
- Context/desktop menus (decoration.rs, desktop_menu.rs, state/menu.rs)
rebuilt to match the project's own AGS panel styling: rounded floating
panel, tinted-fill row highlight, real separators, a much fuller
titlebar window-menu action set.
Layer-shell / multi-monitor:
- Layer-shell hit-testing and render positioning (input/pointer.rs,
udev/render.rs's element placement) now correctly convert LayerMap's
logical geometry into physical pixels on a fractionally-scaled output
- root cause of a bottom-anchored dock being unclickable and
unpainted while a top-anchored bar on the same output worked.
udev/outputs.rs's relayout_outputs gained the same physical/logical
split for cross-output positioning, now backed by a real unit test
(next_logical_x) built from the original measured incident numbers.
- state/geometry.rs: a window's border/decoration no longer briefly
clips when moved between differently-scaled monitors mid-drag.
XWayland / stability:
- xwayland.rs, udev/session.rs, udev/platform.rs: fixed a 100%-
reproducible cold-start XKEYBOARD crash-loop (XWayland's own stdin
inherited a real, already-owned VT; env passthrough and idle-callback
spawn timing were both real, independent gaps) that had silently taken
down all X11-app support and the global-menu registrar every session.
- state/toplevel.rs, state/lifecycle.rs: XWayland dialog detection via
WM_TRANSIENT_FOR, not just a native xdg_toplevel parent.
Rendering:
- udev/render.rs, decoration.rs: real GPU (GBM+EGL+DrmCompositor)
window-content and cursor rendering on the udev backend, falling back
to the untouched Pixman path automatically on any init failure.
- decoration/tests.rs, state/mod.rs: rounded-corner/border fixes for
interactive resize lag and cross-monitor moves.
Multi-cursor Phase 2 (virtual_pointer.rs, new; state/mod.rs, udev/
platform.rs, winit/nested_platform.rs): pins a zwlr_virtual_pointer_
unstable_v1 object to a specific window, bypassing the shared seat/
focus/pointer_pos path entirely via hand-rolled wl_pointer.enter/motion/
button/frame/leave against every WlPointer the target client has bound
(PointerHandle::client_pointers). Lets an agent operate one window while
a human uses another, genuinely simultaneously, with zero client
cooperation and no second wl_seat (confirmed a dead end: real clients
only ever bind the first seat advertised).
Full workspace build/test/clippy clean.
Diffstat (limited to 'crates/wayland/src/decoration')
| -rw-r--r-- | crates/wayland/src/decoration/tests.rs | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/crates/wayland/src/decoration/tests.rs b/crates/wayland/src/decoration/tests.rs index c8eb9b2..5cbc12f 100644 --- a/crates/wayland/src/decoration/tests.rs +++ b/crates/wayland/src/decoration/tests.rs @@ -813,14 +813,26 @@ fn context_menu_highlighted_row_has_a_different_background_than_the_rest() { } #[test] -fn context_menu_border_is_opaque_at_every_edge() { +fn context_menu_panel_is_opaque_in_the_middle_but_rounded_at_the_corners() { + // Reported live: the old hard-square panel with a single 1px border + // read as "squished... not at all polished" next to this project's own + // AGS reference (`GlobalMenu/style.scss`'s `popover box.menu-list`, + // flat rows with no border, only the panel itself rounded). A real + // rounded corner means the exact corner pixel is now transparent, not + // opaque - the opposite of what this test used to assert - while an + // edge's midpoint (away from any corner's curve) and the panel's own + // interior stay fully opaque either way. let items = [("Close", false)]; let buf = render_context_menu(100, 28, &items, (0, 0, 0), (0xff, 0xff, 0xff), (0, 0, 0), (0x99, 0x99, 0x99)); let alpha_at = |x: usize, y: usize| buf[(y * 100 + x) * 4 + 3]; - assert_eq!(alpha_at(0, 0), 255); - assert_eq!(alpha_at(99, 0), 255); - assert_eq!(alpha_at(0, 27), 255); - assert_eq!(alpha_at(99, 27), 255); + assert_eq!(alpha_at(0, 0), 0, "the exact corner pixel is now outside the rounded curve, not a hard square"); + // 2px in from the flat top/bottom edges, at the midpoint (far enough + // from either corner's own curve, and past this helper's own ~1px + // antialiasing band around every edge - see `fill_rounded_rect`'s + // shared smoothstep construction, not specific to this test). + assert_eq!(alpha_at(50, 2), 255, "just inside the flat top edge, away from either corner, is opaque"); + assert_eq!(alpha_at(50, 25), 255, "just inside the flat bottom edge is opaque"); + assert_eq!(alpha_at(50, 14), 255, "the panel's interior stays opaque"); } #[test] @@ -845,6 +857,21 @@ fn snap_flyout_border_is_opaque_at_every_outer_edge() { } #[test] +fn render_desktop_icon_actually_draws_something_visible_for_every_kind() { + // Reported live: desktop icons construct and push correctly (confirmed + // via a live diagnostic: non-empty element list, correct position, + // no import error) but nothing visible shows up on screen - this + // isolates whether the rasterizer itself is the problem, offline, + // without needing a live compositor round-trip to check. + use crate::desktop_icons::IconKind; + for kind in [IconKind::Home, IconKind::Computer, IconKind::Trash, IconKind::Folder, IconKind::File] { + let buf = render_desktop_icon(88, 88, kind, "Test", false, (74, 144, 226), (240, 240, 240), (100, 100, 100), None); + let opaque_pixels = buf.chunks_exact(4).filter(|px| px[3] > 0).count(); + assert!(opaque_pixels > 100, "{kind:?} drew only {opaque_pixels} non-transparent pixels out of {}", buf.len() / 4); + } +} + +#[test] fn snap_flyout_has_an_internal_grid_line_between_columns() { let labels = ["A", "B", "C", "D", "E", "F"]; let (cell_w, cell_h) = (90, 60); |