Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Release notes
Changelog
Elyra
Windows & multi-window

Windows & multi-window

The primary window is configured via App builder methods; additional windows can be declared at startup or opened at runtime. All windows share one event loop, one protocol handler, and one event bus (same origin, same commands).

Primary window

App::new()
    .title("My App")
    .size(900.0, 640.0)
    .min_size(420.0, 480.0)
    .resizable(true)
    .decorations(true)
    .always_on_top(false)
    .run();

Additional startup windows

use elyra::WindowConfig;

App::new()
    .window(
        WindowConfig::new("inspector")
            .title("Inspector")
            .size(360.0, 600.0)
            .path("inspector"),        // deep-link into the SPA
    )
    .run();

WindowConfig builder: new(label), title, size, min_size, resizable, decorations, always_on_top, path. path is appended to the app origin so a window can open a specific route of your frontend.

Opening windows at runtime

App binds a Windows handle into the container. Resolve it anywhere — even inside a command — to open new windows:

use elyra::{Windows, WindowConfig};

#[command]
async fn open_settings(ctx: Ctx) {
    ctx.get::<Windows>().open(
        WindowConfig::new("settings").title("Settings").path("settings"),
    );
}

Windows::open sends a request to the main-thread event loop (via an EventLoopProxy), which builds the window and webview. It returns false if the event loop has already exited.

Controlling the window from the frontend

@elyra/runtime exports appWindow (named so it doesn't clash with the global window). Actions target the focused window (or the primary one) and are applied on the main thread:

import { appWindow } from "@elyra/runtime";

appWindow.minimize();
appWindow.toggleMaximize();
appWindow.toggleFullscreen();
appWindow.setTitle("Untitled — MyApp");
appWindow.setSize(1000, 700);
appWindow.center();
appWindow.hide(); appWindow.show(); appWindow.focus();
appWindow.close(); // exits the app when it's the last window

// Live state (pushed on resize / move / focus):
const off = appWindow.onState((s) => {
  console.log(s.width, s.height, s.maximized, s.fullscreen, s.focused);
});

The same operations are available from Rust via the container-bound Windows handle (e.g. ctx.get::<Windows>().minimize(None)), which also takes an optional window label to target a specific window.

File drop

Native file drops onto the window are delivered to the frontend:

import { onFileDrop } from "@elyra/runtime";

const off = onFileDrop((paths) => {
  console.log("dropped", paths); // absolute paths
});

Remembering size & position

Opt in and the primary window's size, position, and maximized state are restored on the next launch:

App::new().title("MyApp").persist_window_state().run()

State is written to a small file under the OS config directory (~/Library/Application Support/<app>/ on macOS, %APPDATA%\<app>\ on Windows, $XDG_CONFIG_HOME/<app>/ on Linux), keyed by the About name, and saved when the window loses focus or closes.

Lifecycle

The app exits when the last window closes.

Related