Veshell 0.1.4 (beta).
Features
-
File chooser portal (#147). Veshell now owns
org.freedesktop.impl.portal.FileChooser, so Open and Save dialogs from sandboxed apps — a download in Brave, Save As, Open File — are answered by the shell's own file explorer, drawn inside the requesting window like a native dialog. The requesting app is resolved through a new xdg-foreign exporter (v1 and v2), so the dialog lands on the right window and monitor instead of the focused one. The xdg-foreign importer is tracked in #146. -
Caps Lock remapping (#142). A new
keyboard.capsLocksetting maps Caps Lock to Control, to Escape, swaps it with Escape, or disables it. It is applied as an xkb option in the seat keymap, so the shell and forwarded clients agree, and a hand-edited value falls back todefaultinstead of failing the settings load. -
Several bindings per action, and standardised navigation (#139, fixes #133). A hotkey can now be bound to more than one chord (
Super+WandSuper+Up), with a key-capture field in the settings list editor; the shipped defaults include the WASD family and the arrow keys.Super+Shift+W/Smoves the selected tileable between workspace rows and follows it there (#134). Navigation is now contextual — the screen owns the vertical axis, the workspace the horizontal one, the overview its result list — and Activate/Dismiss reuse Flutter's own intents, so the shell's keys drive focused widgets and overlays. Moving tileables and workspaces across screens is tracked in #141.
Fixes
-
Blank, unclosable ephemeral windows (#129, closes #128). A tile whose launch never produced a window rendered an empty card with a dead close button and stayed until the compositor restarted. It now shows the launch's execution logs with a close button, closing a tile with no window removes it, and removing a tile cancels its pending launch (the
systemd-rununit is stopped through the cgroup, not just the supervisor). -
Launching from a display manager on Fedora Atomic (#131). The systemd unit passes
--session, butmainnever read it, so a login manager leakingDISPLAYorWAYLAND_DISPLAYsent Veshell to the nested winit backend.--sessionnow forces the DRM backend, and the initial primary-GPU acquisition is retried for up to five seconds instead of panicking while the greeter still holds DRM master. -
Abort on a parentless subsurface (#135). Destroying a
wl_subsurfacecould leave the surface with the subsurface role while its parent was already gone. The unconditional unwrap panicked inside a Wayland request handler, where the panic cannot unwind — so the whole compositor aborted. -
Icons with an unsupported
font-weightrender again (#136).vector_graphics_compileraccepts onlynormal,boldand the round hundreds, so an icon carrying e.g.596threw during compilation and came out blank. The weight is now snapped to the nearest supported value, after CSS inlining, at every SVG entry point. -
Windows attaching as dialogs of the wrong app (#137).
activatedBywas recorded from the token's declared opener or the currently focused surface, which turned "declared nothing" into "whatever was focused". A second browser restoring its session could therefore attach as a dialog of the first. Only a declared opener is recorded now. -
Launch-burst settle widened to 150 ms (#138). A launch burst is detected by quiet time; a session-restoring browser can map its windows slightly further apart, and the late window then attaches as a dialog of whatever it claimed (#128). The threshold is now named and raised, deliberately modestly.
-
Leaked platform-event subscriptions (#140). Six providers — the auto-disposed meta-window drag and resize state among them — subscribed to the platform event stream in
buildwithout cancelling. A late event then wrote to a disposed notifier and threw during a frame. Every subscription now cancels on dispose. -
Persistence silently dropping writes (#143).
writeFileAtomicallyused a fixed$path.tmpand a fire-and-forget debounce, so a second flush could delete and rename the temp file the first was still using; because the cache was updated before the write, state then stopped persisting without a further error. Flushes are serialized per path and treated as best-effort. -
Notification routing left in an error state (#144). The read-tracker closed notifications through the manager inside a listener on the routing provider, re-invalidating that provider during its own refresh and tripping Riverpod's same-frame guard, which left the routing providers in an error state. The writes are deferred to a microtask.
-
A window stolen from the tile that gathered it (#145). The "waiting" bonus is a gather signal, but it also decided settled ownership, so a sibling still gathering outranked the clicked tile by ~100 points — the window ping-ponged between tiles and each emptied tile reopened its app. Redistribution now ignores the bonus.
Channels
Arch: veshell / veshell-bin / veshell-git on the AUR · Fedora: COPR · openSUSE, Debian and Ubuntu: OBS · NixOS: the flake.
Internal: the shell is now reformatted with the pinned SDK and the format is enforced in CI (#130).