Commit Graph
5 Commits
Author SHA1 Message Date
aiongg f8a83e8204 craft-window: window list, cascade placement, Window menu and viewports for apps with one window per document 2026-10-25 19:09:54 +00:00
aiongg 271594c081 window: the title bar's empty area takes no keyboard focus (#334) 2026-10-25 14:36:07 -04:00
skylar taylor-barrick e5da4a7a68 M0: reconcile shared UI and updater changes with egui 0.37 2026-10-25 17:07:55 +01:00
aiongg e9824219c7 window: title_bar module for app-drawn title bars (#316)
* window: title_bar module for app-drawn title bars

The empty part of an app's top strip moves the window on drag and follows
the macOS title-bar double-click setting. A control on the strip or an
in-window Order::Middle panel over it (floating docks, egui::Window) keeps
its own drag: window_movable is false there and, on macOS, sync_movable
sets NSWindow.movable from it. No gesture acts on the window in full
screen.

* window: empty_area returns the empty area's response
2026-10-25 09:49:44 -04:00
Dylan M. Taylor 1f805378d4 feat(window): shared craft-window crate for consistent window decorations (#217)
* feat(window): shared crate deciding who draws the window frame

Add craft-window, which decides whether the desktop or the app draws the
window frame (titlebar, borders, window buttons) and applies it to an
egui ViewportBuilder. This fixes the drift where some Craft apps drew
their own titlebar on KDE while others kept KWin's.

The rule: macOS, Windows and X11 keep the desktop frame; a Wayland
compositor with zxdg_decoration_manager_v1 (KDE, Sway, Hyprland, COSMIC)
keeps its frame; one without it (GNOME) leaves the frame to the app.
<PREFIX>_TITLEBAR=app|system|desktop overrides. When the app draws the
frame, the decision carries the window-button Layout from GNOME's
button-layout so the app's header bar matches the desktop's order.

Decision logic only; drawing the buttons stays in each app. Extracted and
generalized from pdfcraft's decorations.rs. forbid(unsafe_code); default
build has no egui dependency (egui feature adds decorate()).

* style(window): rustfmt the Wayland probe and Dispatch impl

cargo fmt --check failed CI: collapse the thread-spawn builder chain and
the Dispatch::event signature onto the lines rustfmt wants (verified with
rustfmt 1.98 against the workspace rustfmt.toml).

* fix(window): address review — WAYLAND_SOCKET, bounded gsettings, checkout creds

- Skip the Wayland probe when WAYLAND_SOCKET is set: connect_to_env would
  take ownership of the inherited fd and unset the variable, closing the
  descriptor winit needs. Keep the desktop frame instead.
- Run the gsettings button-layout lookup behind the same 500 ms bounded
  worker as the Wayland probe, so a stalled gsettings can't block startup.
  Factored the worker into a shared bounded() helper.
- window.yml: set persist-credentials: false on checkout so the token
  isn't left in .git/config while cargo runs dependency build scripts.
- README: document the socket guard and the bounded gsettings lookup.

Verified with rustfmt 1.98 and clippy -D warnings (both feature sets).

* fix(window): reap the gsettings child on timeout; document probe tradeoffs

Follow-up to review: the button-layout lookup now spawns gsettings with
piped output, reads it on a worker, and kills+reaps the child whether it
finishes or times out — so a stalled gsettings leaves neither a blocked
process nor a parked worker (it is a one-shot startup call).

Also document, on the Wayland probe, that an inherited WAYLAND_SOCKET
(rare; normal launches get WAYLAND_DISPLAY) deliberately falls back to the
desktop frame to protect winit's connection — the same frame an app that
doesn't probe would get, a safe default rather than a regression.

Verified: rustfmt 1.98 clean, clippy -D warnings clean (default + egui),
tests pass.
2026-10-21 05:35:20 -04:00