srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core/src
AgeCommit message (Collapse)AuthorFilesLines
2024-05-14Draw a cursor, handle the lid, and everything a real config needssrdusr3-12/+324
Groundwork for actually daily-driving this: porting the user's Hyprland config exposed what srdwm couldn't yet express, and testing on a bare TTY exposed something worse. A visible mouse cursor. Nothing drew a pointer at all - on a bare TTY the mouse was simply invisible. It hid because the nested backend runs inside another compositor, which draws a cursor over srdwm's window; only the DRM backend, i.e. the actual session path, was affected. A built-in arrow is now composited above everything on the output the pointer is on. It's a reviewable ASCII bitmap rather than an XCursor theme: a cursor that is always present beats a prettier one that sometimes isn't, the same reasoning as decoration.rs's font fallback. Client-set cursor surfaces and named shapes are still not rendered, so an app asking for an I-beam gets the arrow. Lid switch. libinput switch events are handled and surfaced to config as srd.on("lid_closed"/"lid_open", fn), so closing the lid can lock and suspend instead of doing nothing. Config-driven additions, each needed by a binding in the ported config and none of which existed: fullscreen (Window.fullscreen was a dead field -- declared, never read or written), directional window move that swaps with the neighbour and reorders the stack so tiling follows, focus cycling, modifier+drag to move/resize anywhere in a window rather than only by the titlebar, modifier+scroll to change workspace, and 8 XF86 media/power keysyms taken from the system's own XF86keysym.h. The keysym tables are hand-maintained in both directions and a key missing from either fails silently, so a round-trip test now covers every one the configs bind. Verified in the QEMU VM: a bare-TTY screendump shows a recognisable arrow at the pointer position (113 white fill + 58 black outline pixels at screen centre, where the pointer starts).
2024-04-12udev: connector hotplug, and rescue windows on an unplugged monitorsrdusr2-0/+181
Monitors were probed once at startup, so plugging or unplugging one while srdwm was running went unnoticed. A UdevBackend event source now watches for the kernel's `change` uevent and reconciles the head list against a fresh connector probe - forcing a re-probe rather than trusting cached status, since on a hotplug the cache is exactly what has gone stale. Removing a head tears down everything it owned: the wl_output global, its place in the Space, its DRM framebuffers and dumb buffers (dropping the Rust structs alone leaks the kernel-side objects, which matters when a cable is plugged repeatedly), and any lock surface for it - otherwise confirm_lock_if_presented would wait forever on a monitor that no longer exists. New connectors go through the same bring_up_head path as startup, so a monitor plugged in later is set up identically to one present at boot. Heads are then repositioned left-to-right, since removing one shifts the rest, and layer maps re-arranged so bars follow their moved output. set_monitors rehomes windows stranded by the change, and main.rs re-queries the whole monitor list on MonitorAdded/MonitorRemoved rather than applying the single monitor in the event, because the others' positions move too. The rehoming had a bug that unit tests missed and live testing caught. It originally keyed off Window::monitor, but that field records the monitor a window was *assigned* at creation, not where it is: add_window always sets it from the primary monitor, so a window placed on the second monitor by a rule - or dragged there - still reads monitor == 0. The field-only check saw a valid id, skipped the window, and left it at coordinates that no longer existed: invisible and unreachable. Found by unplugging a monitor out from under a real xterm and watching it vanish from both heads. It now keys off geometry, with a regression test that fails against the old logic. Verified in the QEMU VM, booting with one connector and toggling the second at runtime: plug in -> head added and rendering at its own resolution; unplug -> head removed cleanly; and an xterm at global x=1500 survived its monitor being unplugged, reappearing at x=680 (= min(1500, 1280-600)) with its size intact. Writing to /sys/class/drm/<connector>/status changes the connector but emits no uevent on this kernel, so the signal the kernel would send is synthesized with `udevadm trigger`; the whole reaction path is genuinely exercised.
2024-04-02Add window rules, real config validation, and a Wayland DRM/udev backendsrdusr4-4/+279
- srd.rule(): match windows by title/class, apply floating/maximized/ workspace/geometry/decoration actions on creation (crates/core/src/rules.rs) - srd.validate_config()/srd.debug.*: real range/format checks and status/profiling helpers, replacing the always-true stub - Wayland titlebar text rendering via fontdue, unit-tested without a display (crates/wayland/src/decoration.rs) - Wayland precise keybinding matching, replacing the "any Super-held key" heuristic, sharing the keysym table with X11 (moved to crates/core/src/keysyms.rs) - Wayland DRM/udev backend (crates/wayland/src/udev.rs): runs as the real compositor on a bare TTY via libseat/libinput/KMS, software rendering via Pixman + dumb buffers (no GBM/EGL required) - srdwm_platform::detect() fix, found via VM testing: a bare TTY with no DISPLAY/WAYLAND_DISPLAY now correctly resolves to Wayland instead of an X11 backend that can never work there - XWayland integration groundwork (crates/wayland/src/xwayland.rs): spawn, X11Wm, and full XwmHandler event routing into the same WindowManager/ Space pipeline as native clients. Windows don't render yet - a real glamor-vs-software-renderer conflict in XWayland's own fallback path, root-caused via WAYLAND_DEBUG tracing and documented in docs/IMPLEMENTATION_STATUS.md rather than worked around blind. All verified live in an isolated QEMU VM: X11 backend shows two decorated, correctly-tiled xterms with real title text; the DRM/udev Wayland backend opens the GPU, initializes input, and scans out a rendered frame via KMS page-flip.
2024-04-02Rewrite srdwm in Rust: working X11 and Wayland backends, Lua configsrdusr9-0/+1471
The C++ prototype (moved to legacy-cpp/) was mostly a design skeleton: X11 and Windows backends were partially real, Wayland created the wlroots object graph but never wired a single event listener, macOS was stub except monitor enumeration, and the Lua engine's srd.bind() stored a key-combo string but never the actual closure. See docs/PRIOR_ART.md for the full audit. This replaces it with a Cargo workspace: - srdwm-core: platform-independent window/workspace/monitor state, a real master-stack tiling layout, and SmartPlacement grid/cascade/ snap-to-edge placement - fixing several bugs in the C++ version (hardcoded 2-column grid, cascade that never cascaded, snap-to-edge that always returned a fixed rect). 35 unit tests. - srdwm-config: the srd Lua API via mlua, implementing the surface docs/DEFAULTS.md always documented but the C++ engine never actually built (srd.window.close()/focus(direction), srd.workspace.next(), real keybinding closures, require("srd") support). 10 unit tests. - srdwm-x11: a real reparenting WM with a drawn title bar (buttons, drag, resize), verified live under Xephyr - frame placement and client offset match srdwm-core's computed geometry exactly, and the decoration renders correctly on screen. - srdwm-wayland: a from-scratch smithay compositor (the C++ version had nothing working to port from) - runs via the winit backend, tracks xdg-shell toplevels through the same WindowManager and hit-testing code X11 uses, verified to start/render/run without crashing. Decorations are solid-color (no text yet); see docs/IMPLEMENTATION_STATUS.md for exact scope. - srdwm-windows / srdwm-macos: structured, cfg-gated designs informed by komorebi/glazewm and yabai/AeroSpace respectively (see docs/PRIOR_ART.md), honestly marked as unbuilt/unverified since this sandbox has no Windows or macOS target.