vike
Desktop app

Workspaces

The multi-window desktop — arrangement, the minimized-window rail, the menu bar, and how a chart layout is persisted to workspace.json and named layouts without ever bricking startup.

The desktop workspace is crates/vike-app-core/src/workspace/mod.rs: multi-window management, arrangement and layout persistence, split by concern into state (per-window state and the window chrome loop), arrange (cascade, tile, grid, maximize and restore), persist (the chart layout as JSON), menu (the menu bar, command emission only) and rail (the left rail of minimized windows). It is egui-only and free of app content — tool-window view state lives elsewhere — which is what let it move out of the GUI shell into a crate CI tests.

Windows

crates/vike-app-core/src/workspace/state.rs says how a window behaves: each is a floating egui::Window, egui owns the live geometry so the user can drag and resize, and the app reads the rectangle back each frame. An arrange or maximize action forces geometry for a single frame through pending and then releases it. A freshly opened or restored window is pinned to its intended size for OPEN_PIN_FRAMES — eight frames — because an unpinned window would otherwise auto-shrink to its content over the first few frames. WinKind names the twelve kinds and WinKind::LAUNCHERS the nine in the launcher row; The desktop app lists them.

WinState carries window chrome plus chart content: symbol, interval, the data venue the live bar feed subscribes to (DEFAULT_VENUE is "binance", the value that keeps every pre-feature path byte-identical), the picked instrument's asset class for feed routing, style, indicators, scale, invert, chart options, pane fractions, the sync group, the order-flow toggles and the compare series. The chart key it builds, series_key, spells a non-Binance series as venue:SYMBOL@interval and a Binance one bare. Build that key by hand and drop the venue, and every non-Binance series lands in the Binance-shaped slot — which is why series_key exists as one function rather than a format string repeated at each call site.

Tool-window view state is deliberately not in WinState. crates/vike-app-core/src/tools.rs's ToolView is the per-window state for the tool windows (selection, filters, page, expiry, the order-ticket out-slots), owned by the app keyed by window id and taken out of the map around each draw; ToolData is the fetch-thread-owned data behind News, Calendar and Options.

Arrange, menu, rail

crates/vike-app-core/src/workspace/arrange.rs's Arrange offers Cascade, TileH, TileV, Grid, MinimizeAll and RestoreAll, plus per-window maximize and restore. Its naming is explicit: Tile Horizontal is full-width rows stacked vertically; Tile Vertical is full-height columns side by side. Arranging never draws — it writes one-frame pending rectangles that the window loop consumes next frame.

crates/vike-app-core/src/workspace/menu.rs is pure command emission: menu_bar returns a MenuResult of the actions chosen this frame and the app applies them. File holds New chart window, Open and Save Workspace, Save layout as…, the Load layout and Delete layout submenus, Export chart image… and Exit; View holds Timezone; Window holds the six arrange actions and Toggle left panel. crates/vike-app-core/src/workspace/rail.rs draws the left rail as vertical tabs, one per minimized window, sized to their rotated text; clicking a tab restores its window. New windows land in a cascade slot decided by crates/vike-app-core/src/window_spawn.rs, which also builds the window's state and names the live subscriptions it needs before it can paint.

What is persisted

crates/vike-app-core/src/workspace/persist.rs captures chart windows only. Its header lists the scope: symbol, interval, style, geometry, minimized and maximized state, follow-live flags, the price-scale mode, the flattened ChartOptions, the per-pane heights, and per-indicator parameters and per-line colour and width. WinSnap also carries the venue, the asset class, the invert flag, pane membership and order, the sync group, the CVD, profile and tick-size order-flow settings, and the compare series with their panes and axis pins. Tool windows are launcher-recreatable and carry runtime state, so they are skipped. Workspace adds the globals: the display timezone, the order-flow backfill hours (default 2.0), the GPU candle-layer toggle (default off) and the indicator favourites.

The file is $VIKE_WORKSPACE, else <state_dir>/workspace.json, where the state directory is VIKE_STATE_ROOT or the project's settings/state. It is loaded automatically at startup when present — skipped under VIKE_SHOT so QA captures stay deterministic — and written only by an explicit File → Save Workspace. save_path returns an error, never a different location, when no state directory resolves, and the caller surfaces it: a save that silently landed elsewhere would be found by nothing.

A corrupt or old file never bricks startup

load_from treats an unparseable file as "no saved workspace" with a warning and falls back to the default layout. VERSION is 2 and a v1 file still loads: ChartOptions is flattened with a struct-level default, so every colour and flag absent from an old file takes its custom default rather than a type-zero, and every later field is #[serde(default)]. Pane keys written under the old Osc spelling are accepted through a serde alias, because a parse error on one entry would reset the whole saved workspace.

Named layouts

The single workspace.json stays the default, auto-loaded layout. Any number of named layouts can be saved as layouts/<name>.json beside it — same schema, same forward-compatibility — driven by save_layout, load_layout, delete_layout and list_layouts. sanitize_layout_name maps a user-entered name to a safe filename stem (alphanumerics, dash, underscore and space survive; everything else becomes an underscore), and the stem is the displayed name. last_layout.txt remembers the layout last loaded or saved-as so a restart can reopen it; a stale pointer to a deleted layout is ignored. base_dir is one base for the layouts directory, the pointer file and the backend registry's backends.json, so the family can never half-move when $VIKE_WORKSPACE relocates it.

Which windows a fresh launch opens is crates/vike-app-core/src/startup.rs's plan: a restored workspace (a named layout is preferred over workspace.json when one was last active), one of the QA capture tool windows, or the default BTCUSDT chart — and, for each, which feeds must be ensured before it can paint.

On this page