srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/state/mod.rs
AgeCommit message (Collapse)AuthorFilesLines
2026-07-27Hide a window only when srdwm knows it has not drawn, not when a lookup says sosrdusr1-18/+27
Regression I introduced two commits ago, reported live: "I can click close where the button would normally be and it does close, but it is still invisible." The gate that stops an empty frame being drawn before a client paints asked the renderer, from inside the render loop, whether a window's surface had a buffer attached right now - and treated "no" as "do not draw". That question is only meaningful for a native xdg-shell toplevel. An XWayland window's surface state does not describe it the same way, so the answer came back no on every frame and the window was never drawn again, while srdwm's own hit-testing carried on working perfectly: an invisible window that still takes clicks, which is a worse failure than the empty frame it was meant to prevent. Inverted to the fail-safe direction. `new_managed_window` - the one path that creates a native toplevel - puts the window into `awaiting_first_buffer`, and `commit` takes it out on the first commit that carries a buffer. The render and capture paths test that set and nothing else. A window is now hidden only when srdwm itself put it there, so no window whose plumbing works differently can be hidden by a lookup that did not apply to it: the XWayland map path never touches the set, and neither can anything else. The buffer question still gets asked, but only in `commit`, about a surface it was just handed, where it is the right question. Verified both halves: an ordinary spawn still shows no frame before content (26 captured frames with content, 0 without), and the only way into the set is one line in one function.
2026-07-23Do not draw a window before its client has painted anythingsrdusr1-1/+22
Reported as "before a window spawns, the border corners look funny". A toplevel is placed, sized and decorated the moment its role is created, which is well before the client draws. srdwm was rendering it from that moment, so what appeared first was an empty frame: border, titlebar and shadow standing around bare desktop, at the guessed 800x600 placeholder size, with nothing inside. When the real buffer arrived the frame snapped to the real size. Measured in a nested session, capturing a cold terminal's spawn with grim: four consecutive captured frames spanning 540ms showed a complete red border with zero client content inside it, at 642px outer height, which then settled at 610 - a jump of exactly one TITLEBAR_HEIGHT. After this change the same capture has no such frame at all: every frame that shows a border shows content in it, and the height does not change afterward. Two parts: - Nothing is drawn for a window that has never committed a buffer. All five paths that draw a frame agree on this - both udev render loops (Pixman and GPU), the winit render loop, and both screencopy paths, so a screenshot cannot show a frame the screen does not. - The open-slide starts at the first commit that carries a buffer rather than at role creation. A cold terminal took ~800ms to paint, long enough for the whole tween to finish against the empty frame, so the window simply appeared, already at rest, with no animation at all. It now animates where it can actually be seen. The answer latches once true (windows_shown_once), so a window that has legitimately shown something is never hidden again by this however its buffer state changes. A window that cannot be resolved to a surface counts as drawable, deliberately: this hides a window only on positive evidence that it has never drawn, so nothing whose surface plumbing works differently - an XWayland window - can be hidden by a lookup that did not apply to it. Same shape, and the same reason, as sync_layer_visibility's own has_buffer branch, which layer surfaces have had all along. 533 tests pass, clippy clean.
2026-05-15Fix the maximize border on the path that actually runs, and three spawn faultssrdusr1-0/+6
The maximize border was still drawn because the earlier fix landed on the wrong branch. udev/render.rs has three border blocks: the SRDWM_GPU=1 path at the top and two Pixman ones below. The patch replaced the first match in the file, which is the GPU branch a real DRM session never runs. All four sites across both backends are now gated on !maximized. The verification had failed twice for a separate reason: winit/capture.rs did not draw border strips at all, so a screenshot could never answer "is there a border here" and the control passed for the wrong reason. Border strips are now drawn into that pass as solid fills - corner rounding is not reproduced, so a capture is not pixel-exact at the corners, but presence, position, thickness and colour are. With that closed the test has a real control: unmaximized gives 6 accent pixels at x=800..805, exactly the configured border_width, and maximized gives none at the right edge or along the top row. That proves the winit path; the Pixman path is the same change at two more sites and is not separately confirmed on screen. Windows spawning as squares, partly off-screen, and always on the left were all SmartPlacement::grid. It returned size.min(cell), shrinking every window to its grid cell whatever size it asked for; it scanned cells in reading order and took the first free one, which is the leftmost; and nothing clamped the result, so a window larger than its cell could hang off the edge with its border out of view. The cell now decides only where a window goes, the scan starts from a rotating cell, and both grid and cascade clamp into the usable area. Four tests, one per reported symptom. 525 tests pass, clippy clean.
2026-04-27Build the eight asks recovered from the previous session's transcriptsrdusr1-0/+7
The punch list was not the whole record. These are the owner's own typed requests, read back out of the previous session's transcript rather than guessed at, then each checked against the code before being treated as open. Three they suspected were already done really were: dialogs already had a Close-only titlebar, inactive dimming already existed, and the corner resize hitbox had already been tuned. Snap layouts on drag, asked for twice. Edge snapping worked but committed silently on release with nothing shown first, so there was no way to know it would happen or where. A translucent drop-target preview now follows the drag, and throwing the pointer at a monitor's top edge drops down the existing six-cell grid to aim at. The preview calls the same snap_zone that end_drag does, so the two cannot disagree. Two defects found by screenshot before landing: moving down onto the flyout closed it, and its labels overflowed at a fixed cell width - the same "text goes out of view" fault already fixed once for the context menu. New File now offers real types, chosen by extension, with the de-duplication counter placed before the extension so the file stays what it says it is. Refresh re-reads init.lua and fires a new srd.on("refresh") handler instead of only re-scanning the icon grid. What refresh means beyond srdwm's own config stays the config's decision. general.config_reload_on_write (default on) applies an edited config on save, via an mtime sweep rather than an inotify watch: no new dependency, same behaviour on every target, and unaffected by editors that write through a temp file. A real bug behind "what happens when our config fails": you lost every keybinding. do_reload cleared the binding, handler and repeat tables before re-executing and never restored them, so a syntax error left neither the old config nor the new one, and the only key still working was the reload combo nobody thinks to press. The tables are now restored on any failure and config errors reach notify-send, not just the log. srd.lock() and a default Mod4+Ctrl+l binding: the built-in lock screen could not be reached from Lua at all. Native rather than shelling out, because a lock key that shells out fails silently when the binary is not on PATH. Default bindings added for srd.window.move and a dynamic/tiling toggle, both of which existed with no way to reach them, plus srd.layout.get() so the toggle reads the live workspace rather than the configured default. Dialogs open centred, and are excluded from remembered geometry in both directions - that table is keyed by app_id, which a dialog shares with the window that spawned it, so dialogs inherited an unrelated position and size and then overwrote it with their own. theme.decorations.title_bar.button_mode (dynamic by default, or fixed) drops the Maximize button on a window whose client pinned min == max size, where pressing it can do nothing. Maximize is removed from the slot list rather than skipped in place on both the render and hit-test sides, so the remaining buttons close the gap identically; three tests pin that agreement, which is what fails silently when it drifts. Also: the nested backend's screencopy pass now draws both menus, the flyout and the drag preview. Four investigations in one day started from a screenshot missing a tier, so that pass carries an explicit list of what it still omits and the on-screen loop points at it. 512 tests pass, clippy clean.
2026-01-30Fix a real regression: dynamic-mode windows lost their shadow via ↵srdusr1-9/+12
toggle_floating The tiled-shadow-tint fix earlier today gated the shadow on Window::floating alone. arrange_workspace only reads floating under the "tiling" layout, so every window on this project's own default "dynamic" layout starts, and stays, floating: false - the gate misread that as "tiled, no shadow" regardless of which layout was actually running, so shadows silently vanished under dynamic mode entirely, recoverable only by pressing Super+S (toggle_floating), which then looked like that key toggles a tint rather than floating. Fixed by checking the workspace's own layout name first: a window is only "currently tiled" when its workspace runs "tiling" AND it hasn't opted out via floating. DecorationSignature's floating field is now currently_tiled, since a layout switch changes this for every window on a workspace without touching any of their own floating fields. Also disabled general.shadows in the user's own config per direct request - never asked for, on by default, and a real problem for color-accuracy work regardless of how correctly it renders otherwise. Also fixed both context menus (titlebar and desktop) silently truncating labels past a fixed 170px width with no indication - widened dynamically to each menu's own real widest label via a new measure_text_width helper.
2025-12-03Stop giving tiled windows a shadow that lands on their neighboursrdusr1-0/+9
Diagnosed by a peer session (dotfiles-1a): SHADOW_SIZE is 24px, and a tiling layout with a small gap_inner (as little as 1px live) leaves the shadow nowhere to fall except onto the adjacent tile, darkening it by up to SHADOW_MAX_ALPHA (~35%) on whichever side is unfocused. Not a content tint or an opacity rule - verified against the actual rasteriser and the live rule set before accepting the diagnosis. A drop shadow separates a window from what's behind it; tiled windows are coplanar and adjacent by construction, with nothing behind them to separate from. redraw_decoration_buffer's shadow gate now requires w.floating in addition to the existing !maximized/!fullscreen checks. DecorationSignature gained a floating field so toggling floating on its own invalidates the decoration cache instead of waiting for an unrelated field to force a rebuild. Live-verified in a nested compositor: two tiled windows show a clean shared edge with no gradient bleeding across; floating a window still detaches it from the tile group with its shadow intact; shadows still toggle globally both ways.
2025-12-01Let a new window pick its own size instead of forcing a guessed placeholdersrdusr1-0/+8
Root-caused "windows spawn small and square, not remembering placement or size": new_managed_window hardcoded a fresh toplevel's geometry to 800x632 before the client had said anything about its own preferred size, and sync_geometry forced that guess onto the client's very first xdg_toplevel::configure unconditionally. Per xdg-shell, size: None on that first configure is how every mainstream compositor lets a client pick its own natural size instead; this one never did, so every app converged on the same placeholder rectangle regardless of what it would have chosen. Window::size_is_provisional marks a size that really was just the guess (not a remembered geometry, a rule's explicit geometry action, or a maximize/phone-mode fill, none of which are guesses). sync_geometry sends size: None for such a window's first configure; a new adopt_provisional_size, called from the commit handler, adopts the client's own real first size into Window::geometry the moment it commits one, clamping only position so a bigger-than-guessed window can't hang off its monitor's edge. Live-verified in a nested compositor: a zenity dialog now renders at its own compact natural size instead of being stretched to the old guess.
2025-09-28Fix multi-selected desktop icons only ever dragging one at a timesrdusr1-11/+5
Reported live: "try move desktop items all at once somewhere else" didn't work. Two compounding bugs, both real: CompState:: desktop_icon_drag only ever tracked one icon id, and the click handler that starts a drag unconditionally collapsed any existing multi- selection down to just the grabbed icon before the drag even began. desktop_icon_drag is now Option<DesktopIconDrag> (crates/wayland/src/ desktop_icons.rs, new type): a grab offset, the grabbed icon's own live position, and a members list - every currently-selected icon (the grabbed one included), each a fixed offset from the grabbed icon's own top-left at drag start, so the group moves as one rigid unit. input/pointer.rs's click handler now only resets to single-selection when the grabbed icon isn't already part of the current selection -- grabbing one inside an existing multi-selection keeps the whole group selected and dragging, matching Windows/GNOME/macOS/KDE convention. end_desktop_icon_drag snaps every dragged icon to its own nearest free grid cell independently, tracking newly-claimed cells across the group so two icons landing near each other never claim the same one. Full workspace build/test/clippy clean, built and installed. Not unit- testable (this module has no CompState test fixture for its own selection/drag logic, an already-documented, accepted gap) - needs a live drag to confirm.
2025-09-10Wayland backend: desktop icons v2, menu rebuild, layer-shell/scale fixes,srdusr1-0/+27
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.
2025-08-17Fix desktop icons v1 regressions: bar overlap, wrong order; add proper menussrdusr1-0/+8
Live testing found v1 genuinely broken, not just rough: 1. Icons weren't rendering reliably at all - ensure_desktop_icons only ever computed the grid's origin once, on whichever render pass happened to be first. AGS's own top bar registers its exclusive zone after that first pass, so origin got permanently baked in at the pre-bar geometry. Confirmed live via a temporary diagnostic log. Fixed by re-deriving origin from the primary monitor's current geometry on every call instead of just the first. 2. Fixed icons (Home/Computer/Trash) always sorted before real files -- confirmed wrong via direct question. The whole list now sorts alphabetically by label, case-insensitive, fixed icons included. 3. "Set as Wallpaper" was the wrong feature: removed entirely (DesktopMenuAction::SetWallpaper, general.wallpaper_command, is_image_path). The user wants that handled by their real file manager once opened, not reimplemented here. Also adds real menu functionality per "where are all the options": Rename (inline text edit, new CompState::renaming_icon field and keyboard redirect mirroring NativeLock::password's existing precedent), Delete (moves to ~/.local/share/Trash per the freedesktop.org spec, new trash.rs module, same-filesystem case, no confirmation - this is the reversible move-to-trash, not a permanent delete), Empty Trash on the Trash icon, and Open Terminal Here / Open in File Manager on the bare-desktop menu (new general.terminal config key). 133 wayland-crate tests (up from 106), full workspace build and clippy clean.
2025-08-15Add real desktop icons plus right-click desktop/icon context menussrdusr1-0/+33
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.
2025-08-09Fix interactive-resize border/shadow lag without the OOB risk that sank the ↵srdusr1-0/+14
first attempt effective_frame_of now returns the live drag target while a window is being interactively resized (same change as the reverted first attempt), but two things make it safe this time instead of reintroducing the out-of-bounds texture sample that reversion was for: - Every src crop rect built from a window's frame width in udev/render.rs and winit/render.rs (titlebar, top border strip, bottom border strip) is now clamped against DecorationSignature's own recorded width/ border_width - the bitmap's actual last-built size - before reaching MemoryRenderBufferRenderElement::from_buffer, which does not itself validate src against the real texture size. This is a structural floor independent of timing, not a repeat of the previous unsafe approach. - handle_pointer_position now calls redraw_decoration_buffer once per resize motion event (throttled to 60Hz via a new CompState::resize_redraw_at), closing the lag at its source instead of only catching up on the next real client commit. This also fixes the shadow bitmap's identical commit-vs-live-position gap for free, since redraw_decoration_buffer rebuilds all three bitmaps together. Updates the TODO.md entry for this bug with the full before/after.
2025-02-18Fix clippy warnings surfaced by the mergesrdusr1-1/+1
Pre-existing issues in the uncommitted rust-rewrite work (unused imports, over-arity glyph-drawing functions, a couple of complex inline types, or_insert_with(T::default) instead of or_default(), and one unsimplified test-only arithmetic expression), plus two imports left unused by switching to or_default(). None of these are behavior changes. Full workspace build + clippy -D warnings + test suite (378 tests) all green after this.
2025-02-15Checkpoint: preserve all uncommitted rust-rewrite worktree worksrdusr1-19/+132
Safety commit before reconciling this worktree with main, which has diverged with its own separate fixes today. Nothing here is reviewed or curated yet - this exists purely so none of this work can be lost to a git operation, disk issue, or worktree cleanup while that reconciliation happens.
2025-02-13Implement the Wayland implicit pointer grabsrdusr1-0/+29
Every pointer motion event re-ran the same popup/layer/content hit-test from scratch and delivered focus to whatever it found right now - there was no notion of "a button is held, keep delivering to the surface that received the press" at all, which is standard, expected Wayland compositor behavior (every real compositor does this; it's how dragging, text selection, and scrollbar-thumb dragging all stay coherent even when the pointer briefly leaves the widget's bounds mid-gesture). Without it, a real human's hand drifting even slightly outside the pressed surface mid-drag - trivially easy during a fast, non-perfectly- straight mouse motion - sent that client an unrequested `leave` event in the middle of its own gesture. GTK's drag recognizers (a GtkHeaderBar's move-the-window gesture, concretely) treat a mid-gesture leave as "this isn't coherent, abort," which reads as "dragging this window by its title bar does nothing at all" - live-reproduced this work on Nemo, and consistent with move_request never having fired once all session despite real attempts. pointer_button_grab captures the (surface, origin) resolved on a button press once the held-button count goes from 0 to 1, and every event under the grab - motion or button, this press's or a later one overlapping it - is delivered there instead of wherever a fresh hit-test lands, until every held button is back up.
2025-02-06Fix layer surfaces spuriously hiding/re-showing on their own realizationsrdusr1-0/+21
sync_layer_visibility could not tell a real hide (null-buffer commit on an already-visible surface) apart from a layer-shell client's ordinary realization sequence (commit with no buffer -> configure -> ack-commit with no buffer again -> attach real content): both look like "committed, no buffer" from has_buffer alone. Every layer surface's first realization was spuriously unmapped and immediately remapped, doubling LayerMap arrange() passes on every single popup open. Live-reproduced via an AGS peer session: a full-monitor click-outside-to- close popup surface came back from a hit-test with geometry wider than the real output after several open/close cycles on a wl_surface GTK had reused across role destroy/recreate, and sat in the Top layer above every real window with no input region set - silently swallowing clicks meant for windows, dropdowns, and CSD title bars alike. layer_surfaces_shown_once now gates the hide path on a surface having actually shown a buffer at least once, and is cleared in layer_destroyed so a reused wl_surface's next role starts clean rather than inheriting the previous role's flag.
2024-12-24Accumulate wayland-crate additions: capture rendering, focus/Space sync, VT ↵srdusr1-5/+109
resume, plumbing Bundles the remaining wayland-crate changes built up here, touching both backends (udev and winit) and the shared input/rendering code: - udev/capture.rs: off-screen Pixman render of an arbitrary (not necessarily on-screen) workspace's window content to a PPM file -- what crates/core's capture-request queue drives, for a workspace switcher's thumbnail previews. wlr-screencopy structurally can't do this (it can only see what an output is presenting), which is why this exists as a separate render path rather than reusing it. - input::focus_window now also raises the window in smithay's own Space, not just core's stacking order - Space is what actually renders on top and what pointer hit-testing reads, so any focus path that skipped this (an IPC "focus" dispatch, concretely) left a window genuinely focused while still rendering, and receiving clicks, underneath whatever was already topmost. Both backends' poll loops now re-sync this after any IPC mutation. - udev/session.rs's VT-switch resume fix (drains a stale pending page flip before reasserting CRTCs) already has its own earlier, cleanly isolated commit - not duplicated here. - Assorted decoration/cursor/rounded-corners/output-management/ screencopy/XWayland changes and their cross-backend wiring. Coarser than the repo's usual one-purpose-per-commit convention, deliberately - see the core-crate sweep commit's own message for why.
2024-08-23Round the bottom border strip's corners to match the topsrdusr1-0/+3
MISSING.md listed the border frame's bottom/left/right strips as staying square while the top one (and the titlebar above it) rounds -- "unrelated to client content rounding... not attempted." The left/ right strips genuinely can't participate (border_strips' geometry has them span only the height between the top and bottom strips, no corner to round), but the bottom strip is exactly the same shape as the top one and had no reason left to stay square. decoration::render_border_bottom mirrors render_border_top exactly (round_bottom_corners mirrors round_top_corners), cached the same way in a new border_bottom_decorations map, and drawn in both render loops via the same all-or-nothing occlusion check the top strip already uses - pulled out of the left/right strips' per-fragment occlusion splitting into its own dedicated bitmap path, matching top's existing trade-off (cropping a rounded bitmap's source rect per fragment is real extra work for a strip this thin) rather than inventing a new one. One real bug caught before it shipped: round_bottom_corners' corner- centre math (height - r - 1) panics on unsigned underflow whenever the radius clamp lands on the strip's own full height (a real, common case - a 2px-thick test strip hits it immediately). Fixed by computing the centre as a signed offset instead, mirroring how the existing dx/dy distance math already avoids the same class of issue.
2024-08-20Send tiled xdg_toplevel state so GTK stops reserving its own shadowsrdusr1-0/+1
No configure this compositor ever sent set any xdg_toplevel::State bit at all - confirmed by grepping the whole crate, zero hits before this. GTK4 (Firefox concretely) reads the tiled bits to decide whether to reserve an invisible client-side shadow margin around its own content, independent of server- vs client-side decoration; with none ever sent it always assumed "floating, might need a shadow" and kept reserving one. That margin sits inside the committed buffer but is functionally invisible, so this compositor's own border - drawn at the full geometry, margin included, since nothing here knew the margin existed - ended up visibly offset from where the client's real chrome began. Root-caused from a live screenshot: Firefox's srdwm-drawn border sat clearly up-and-left of its actual toolbar, not framing it. Reported as "border is not with the window at start" and, more generally, borders never feeling like part of the window they're drawn around - which this is: decoration and content genuinely disagreeing about where the window's edge is. Sets all four Tiled* bits unconditionally on every xdg_toplevel configure - the same technique river/dwl use, telling every window it's flush against something and should skip its own shadow regardless of whether it's in a literal tiling layout, which is the outcome actually wanted here: this compositor draws the frame, nothing else should also be reserving room for one. Not visually verified against a live client yet - this needs an actual GTK app rendering under a restarted session to confirm the shadow margin is really gone, which no offline test can substitute for.
2024-08-03Fix doc-comment file references left stale by today's six module splitssrdusr1-1/+1
~17 comments across the codebase still pointed at udev.rs/winit.rs/ state.rs by their old flat-file names after those became udev/, winit/, state/ directories - found while auditing what this work rushed, since the split verification (function/struct-name diffing, full test suite) checked structural correctness but never comment accuracy. Updated each to either the specific new file (e.g. "see state.rs's REPEAT_DELAY" -> "see state/mod.rs's REPEAT_DELAY", "udev.rs's monitors()" -> "udev/platform.rs's monitors()") or the bare module name where the reference was already generic ("the udev/winit backends", not a specific location).
2024-07-30Split crates/wayland/src/state.rs (1276 lines) into state/srdusr1-0/+551
Pure reorganization, no behavior change - verified by diffing the function-name and struct-name sets before/after (both identical) plus a full cargo test pass. mod.rs keeps ClientState/OutputEntry/CompState/ WindowAnim/RepeatState's definitions, the key-repeat impl, and the output-lookup impl (all small and tightly coupled to the type definitions), plus mod declarations. The one large impl CompState block (previously ~600 lines) splits by concern: - lifecycle.rs: new_managed_window, set_decorated_from_mode, redraw_decoration_buffer, remove_window. - layers.rs: ensure_layer_initial_configure. - focus.rs: set_keyboard_focus, set_window_activated. - menu.rs: open/close/run_context_menu_action, is_double_click. - geometry.rs: raise_pinned, sync_geometry. - tick.rs: tick_dirty_broadcasts, tick_animations, resync_stacking_order. - toplevel.rs: the with_toplevel_title/app_id/sync_toplevel_metadata free functions. - tests.rs: unsplit, same reasoning as every other split this pass. CompState's fields were already pub(crate) (this crate's existing convention, unlike core's/config's plain-private), so no field- visibility changes were needed - only resync_stacking_order (called from geometry.rs, defined in tick.rs) needed bumping from private to pub(crate), matching that same convention.