Commit Graph

5 Commits

Author SHA1 Message Date
c553c4df4b themes/default: drop the inner shadows from the launcher.svg glyph
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled
In both `themes/default/branding/dark/launcher.svg` and `themes/default/branding/light/launcher.svg` the launcher glyph is built from nine cells, each with its own `filterN_diiii_4479_*`. Those filters layered four successive inner-shadow passes (`effect2..effect5_innerShadow_*`) on top of the outer drop shadow `effect1_dropShadow_*`: pairs of `feColorMatrix in="SourceAlpha"` + `feOffset` + `feGaussianBlur` + `feComposite operator="arithmetic"` + `feBlend`, with offsets `(-3.6,-3.6)`, `(1.8,1.8)`, `(0.45,0.45)` and `(1.8,1.8)` and blend modes `plus-lighter`, `overlay` and `normal` to reproduce the light-above / dark-below bevel and inner halo of the original Figma export. That is twenty-four lines per cell and nine cells per file — 216 lines per SVG, 432 in total.
This change removes those four inner-shadow passes in both files; the outer drop shadow (`effect1_dropShadow_*`), the `clipPath` with `bgblur`, the `rect` elements defining each cell and the rest of the document are kept verbatim. The launcher silhouette and its placement do not change: the icon still occupies the same `viewBox` and produces the same clip; what disappears is the specular highlight and dark inner contour of each cell, leaving flat rectangles on the background with their projected shadow. The diff is pure deletions, with no added lines, and the existing difference between the `dark` and `light` variants is preserved (only the filter identifiers differ, `_38862` versus `_38700`).
2026-05-23 00:53:13 +02:00
5ff4fa7e59 Fixed default dark theme 2026-05-14 23:49:08 +02:00
bfe27b6fef event_loop, widget, input: pointer-dwell tooltips, global drag coords, foreign-toplevel name cascade
`Button::tooltip( text )` registers a hint string that fires after a 600 ms pointer dwell. `LaidOutWidget` gains a `tooltip: Option<String>` field, `Element::tooltip()` exposes it to the input layer, and the existing pointer-hover path now calls `arm_tooltip` on hover-enter and `cancel_tooltip` on hover-leave / touch. The deadline is polled alongside `next_long_press_wakeup` in `try_run` so an idle pointer still gets a wake-up at the firing instant; on fire, `tooltip_overlay()` synthesises an `OverlaySpec` — a rounded `text_primary @ 95%` pill drawn with `bg` text — anchored above the hovered widget, flipping below or clamping inside the screen if it would clip, and pushed alongside the app's own overlays both in the redraw path and in `reconcile_overlays` so the layer surface is created the same frame the tooltip becomes visible. Pointer-only by design: touch events explicitly cancel because a tap-and-release should never linger into a hint. The `showcase` example wires `.tooltip(..)` on the three button variants as a smoke test.
The drag pipeline now reports positions in main-surface (global) coordinates instead of per-surface. `surface_offset_for( focus )` derives the top-left of an overlay surface from `SurfaceState::layer_anchor` — newly stored at `reconcile_overlays` time from `OverlaySpec::anchor` — combined with the main surface's dimensions; `on_drag_move`, `on_drop`, the synthetic move emitted on drag-promotion in `pointer.rs`, and the `pending_drag_inits` push site in `gesture::start_drag` all translate before handing coordinates to the app. The motion and release paths additionally `request_redraw()` every overlay so a dock-style drop target painted on an `Anchor::Bottom` layer surface gets repainted as the drag moves — without that, the visible drop indicator only updates when the cursor re-enters the main surface. Drops still target whichever surface fired the release; only the coordinates are unified.
`ForeignToplevelListHandler` previously read `app_id` directly via `ForeignToplevelList::info()`. Clients that never set `app_id` (some winit-windowed compositors, simple test clients) were silently invisible to crustace-style docks because the empty string fell through `unwrap_or_default()` and the dock then keyed entries off `""`. `toplevel_display_id()` cascades: prefer `app_id` for desktop-entry matching, fall back to `title` for human-readable identification, and finally to the protocol-issued `identifier` which is always present and unique per handle. Applied to both `new_toplevel` and `update_toplevel`.
`theme::system_fontdb()` lazily loads the system font database once via `OnceLock` and reuses the `Arc` for every `decode_svg_bytes` call. resvg's default `Options::fontdb` is empty, so any SVG containing `<text>` rendered with the built-in fallback font or no font at all; with the system DB attached, icons and decorative SVGs with embedded labels now resolve glyphs correctly. Cached because `load_system_fonts()` walks every font path on the system and is comfortably tens of milliseconds on a cold cache — not something to repeat per icon decode.
`themes/default/theme.json` tweaks one variant's slot palette: `surface-alt` from `@indigo/D9` to `@white/D9` and `text-primary` from `@white` to `@navy`, plus a cosmetic re-alignment of the `"value"` columns in the same slots block.
2026-05-14 22:36:17 +02:00
c3839060cc theme, event_loop: window_controls.bar_bg slot + graceful exit on compositor disconnect
`WindowControlsSpec` gains `bar_bg`, the background fill of the SSD title-bar strip the close / maximize / minimize controls sit on. Forge used to paint that strip with `palette.surface` clamped to alpha 1.0 — a hack on a translucent panel token. With a dedicated slot the theme decides directly: `@off-white` in light and a new `@window-bar-dark` shade in dark. Schema gets the matching `Option<String>` field (defaulting to `palette.surface` to keep existing themes rendering the same) and the fallback `WindowControlsSpec` seeds `Color::WHITE` so a missing theme still draws something readable.
`try_run`'s dispatch loop previously `.expect("dispatch")`-ed every calloop error. When the compositor closes the wayland socket — `wl_display.error`, forge crashing, the user logging out — the loop saw a `BrokenPipe` / `ConnectionReset` and panicked, which polluted the user's stderr with a backtrace for what is just "the session ended". The match now treats those two `IoError` kinds as a clean shutdown: it prints `Connection::protocol_error()` (the typed `wl_display.error` if the server sent one), sets `exit_requested = true`, and lets the loop drain out normally. Any other dispatch error keeps panicking — those are still genuine bugs.
2026-05-13 10:17:36 +02:00
bbab5e238d First commit. Version 0.1.0 2026-05-10 09:58:23 +02:00