srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/decoration
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-09-10 11:24:00 +0200
committersrdusr <[email protected]>2025-09-10 11:24:00 +0200
commit5ee627928d0cb017e59d796c71793c35d5b65d33 (patch)
tree3285a7df82a04b178fb41fae220d60fe1dd38bd7 /crates/wayland/src/decoration
parent4a55182ce17fd4474f8be1e8819a41b7ccd11045 (diff)
downloadsrdwm-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.rs37
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);