github free-explorers/veshell v0.1.4

4 hours ago

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.capsLock setting 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 to default instead 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+W and Super+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/S moves 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-run unit is stopped through the cgroup, not just the supervisor).

  • Launching from a display manager on Fedora Atomic (#131). The systemd unit passes --session, but main never read it, so a login manager leaking DISPLAY or WAYLAND_DISPLAY sent Veshell to the nested winit backend. --session now 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_subsurface could 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-weight render again (#136). vector_graphics_compiler accepts only normal, bold and the round hundreds, so an icon carrying e.g. 596 threw 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). activatedBy was 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 build without 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). writeFileAtomically used a fixed $path.tmp and 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).

Don't miss a new veshell release

NewReleases is sending notifications on new releases.