Diese Seite wurde maschinell übersetzt und kann Fehler enthalten. Das englische Original lesen

Dokumentation

Linux

NSH-Apps laufen auch unter Linux. Das Linux-Backend rendert sie mit GTK-4-Widgets und setzt den Text mit Pango; der Core, der reaktive Graph, der Renderer, das Taffy-Layout und die nativen Module sind dieselben wie unter iOS und Android, sodass eine App überall läuft. Unter Linux ist os() Os::Linux (platform.os ist "linux" in TSX), und die desktop={{…}}-Props von TSX gelten. Der Fenstertitel, eine eigene Titelleiste der App, die Menüleiste und Kontextmenüs stammen von nsh_core::element::desktop in Rust (Desktop-Titelleisten) und von nsh/desktop in TSX.

#Voraussetzungen

  • GTK 4.14 oder neuer. Um den Runner einer Rust-App oder die Linux-Runtime von NSH zu bauen (aus einem Checkout oder mit cargo xtask dist on Linux) you need their development packages and clang: libgtk-4-dev clang unter Debian und Ubuntu (ab 24.04), gtk4 clang unter Arch, gtk4-devel clang unter Fedora.
  • WebKitGTK 6.0 (2.40 oder neuer) für Web Views: libwebkitgtk-6.0-dev unter Debian und Ubuntu, webkitgtk-6.0 unter Arch, webkitgtk6.0-devel unter Fedora, um die Runtime zu bauen. Der Entwicklungs-Host und der Release-Runner verwenden sie standardmäßig, daher benötigen paketierte Apps WebKitGTK 6.0 dort, wo sie laufen (libwebkitgtk-6.0-4 unter Debian und Ubuntu; GNOME-Desktops bringen es mit). cargo xtask dist auf einem Rechner ohne die Entwicklungsdateien baut eine Runtime, deren Web Views Platzhalter sind und deren Apps nur GTK benötigen.
  • GStreamer-Plugins für die Videoformate, die Ihre App abspielt (GTK spielt Video über GStreamer ab).

#Eine App ausführen

Unter Linux öffnet nsh run die App in einem GTK-Fenster. Eine Rust-App wird aus ihrem Verzeichnis gestartet:

nsh run                        # --target linux is the default on Linux

nsh baut einen Debug-Runner mit Ihrem Crate und öffnet die App, wobei ihre Logs (log::info! und die übrigen) im Terminal erscheinen; bei einer Änderung am Rust-Code des Crates wird der Runner neu gebaut und die App neu gestartet. cargo run startet dasselbe Root aus dem src/main.rs des Crates, das nsh init --template rust schreibt: run_app mit AppSource::Rust.

Eine TSX-App benennt ihren Einstiegspunkt und öffnet sich standardmäßig in einem Fenster von 390×844, mit Hot Reload, Logs im Terminal und dem Fehler-Overlay wie auf den anderen Zielplattformen:

nsh run App.tsx

In einem Checkout baut nsh run zuerst den Entwicklungs-Host (nsh-linux-host); die unter Linux erstellte Distribution liefert ihn in runtime/linux/ mit. Strg+C schließt das Fenster, und das Schließen des Fensters beendet nsh run. Der Host führt auch ein gebautes Bundle eigenständig aus:

nsh build my-app --release -o build
dist/nsh/runtime/linux/nsh-linux-host --bundle build/bundle.nshc --window-size 1024x768   # in a checkout: target/debug/nsh-linux-host

--window-size ist die Standardgröße des Fensters (TSX-Apps); Tiling-Fenstermanager können dem Fenster eine andere Größe geben.

#Paketierung

nsh package --target linux [--run]           # a Rust app, from its directory
nsh package App.tsx --target linux [--run]   # a TSX app

Schreibt ein Verzeichnis und dasselbe als Archiv:

.nsh/out/<Name>/
  <Name>                 the executable: a Rust app's own runner, built with its crate; nsh's release runner for TSX
  nsh/bundle.nshc        a TSX app, compiled
  nsh/assets/…           the assets it imports (a Rust crate's `assets!()` too)
  nsh/app.json           the window title and the application id
  <id>.desktop           a desktop entry (StartupWMClass is the id)
  <id>.png               the icon, when nsh.json names one
.nsh/out/<Name>.tar.gz

Die ausführbare Datei findet nsh/ neben sich (ein symbolischer Link darauf, etwa in ~/.local/bin, funktioniert ebenfalls). GTK 4, Pango und WebKitGTK 6.0 müssen dort installiert sein, wo die App läuft. Um die App im Launcher eines Desktops anzuzeigen, legen Sie die ausführbare Datei (oder einen Link) in den PATH, die .desktop-Datei in ~/.local/share/applications und das Icon in ein Icon-Theme-Verzeichnis. --run startet die App nach dem Paketieren.

#In eine GTK-App einbetten

Das Crate nsh-platform-linux (aus dem NSH-Repository) gibt einer Rust-GTK-App AppView: eine NSH-Engine als GTK-Widget. Jede AppView ist unabhängig; mehrere können gleichzeitig laufen. Sie führt ein Rust-Root aus, die Root-Komponente Ihres Crates:

use std::rc::Rc;
use nsh_platform_linux::{gtk4 as gtk, set_ui_sets, AppOptions, AppView, Root};
use gtk::prelude::*;

fn main() -> gtk::glib::ExitCode {
    // Once, before the first view: the UI sets the apps import (NSH's and your crate's).
    set_ui_sets(vec![nsh_base::registry(), my_app::registry()]);
    let app = gtk::Application::builder().application_id("com.example.host").build();
    app.connect_activate(|app| {
        let window = gtk::ApplicationWindow::builder().application(app).default_width(390).default_height(844).build();
        let view = AppView::new(AppOptions::default());
        // register native components here, before loading
        view.load(Root::of::<my_app::App>().into());
        window.set_child(Some(&view.widget()));
        // The window keeps the view; closing it stops the app.
        let keep = std::cell::RefCell::new(Some(Rc::clone(&view)));
        window.connect_destroy(move |_| if let Some(view) = keep.take() { view.stop() });
        window.present();
    });
    app.run()
}

Root::tokens gibt dem Root sein Theme, und Root::app_id die ID, unter der seine Daten gespeichert werden. Ein TSX-Bundle, das nsh build geschrieben hat, wird in dieselbe View geladen, wobei asset_base auf sein assets-Verzeichnis gesetzt ist:

use nsh_platform_linux::{AppOptions, AppView, AssetBase, Bundle};

let view = AppView::new(AppOptions {
    asset_base: Some(AssetBase::Directory("app/assets".into())),
    ..AppOptions::default()
});
let code = std::fs::read_to_string("app/bundle.js").expect("bundle");
view.load(Bundle::source(code).into());

AppView::load ersetzt, was zuvor lief; stop beendet die App. asset_base teilt ihr mit, wo asset:/-URIs aufgelöst werden (AssetBase::Directory oder AssetBase::Http). Bytecode-Bundles (bundle.nshc) werden mit unsafe { Bundle::bytecode(bytes) } geladen: QuickJS-Bytecode ist vertrauenswürdige Eingabe, laden Sie ihn daher nur aus den Dateien Ihrer eigenen App. Ein eigenständiges Fenster ist nsh_platform_linux::run_app(source, options), mit AppSource::Rust(root) oder AppSource::Bundle(bundle).

AppOptions::cache (oder AppView::set_cache für die als Nächstes geladenen Apps) legt fest, wo die Apps ihre Caches und die heruntergeladenen Bilder ablegen und wie viel jede davon behält (CacheOptions: standardmäßig das Cache-Verzeichnis des Systems und 256 MiB für Bilder).

AppView::set_locale(Some(locale)) und AppView::set_font_scale(Some(scale)) geben der App Ihre App-Sprache und Ihre Textgröße anstelle der des Systems (None folgt wieder dem System): locale(), Intl, fontScale() und Text folgen sofort (Gerät und Umgebung).

AppView::set_theme_overrides(Some(json)) legt die Marke Ihrer App über das Theme der App: eine Theme-Datei im Format von nsh.json aus "theme", deren Tokens im hellen und im dunklen Modus Vorrang vor den gleichnamigen Tokens der App haben, während die übrigen der App erhalten bleiben; Klassen wie bg-primary werden sofort neu gestylt, und später geladene Apps starten damit (None gibt der App ihr eigenes Theme zurück; eine Datei, die sich nicht parsen lässt, ist ein Fehler und ändert nichts).

Native Komponenten werden mit AppView::register_component registriert; siehe Native Komponenten. set_ui_sets(sets) legt die UI-Sets fest, die jede Engine bereitstellt: die von NSH (nsh_base::registry()) und die Ihrer Crates (my_app::registry(), das #[native_module] erzeugt), sodass das TSX, das eine View lädt, auch Ihre Rust-Komponenten und -Module importiert.

#Was unter Linux anders ist

Die Umgebung ist die eines Desktops: Der Safe Area und die Tastaturhöhe sind 0, idiom() ist der Desktop (platform.idiom ist "desktop"), os_version() (platform.version) ist die Haupt- und Nebenversion des Kernels, und der Dark Mode folgt live der Einstellung des Desktops (über das XDG-Settings-Portal). Siehe Gerät und Umgebung.

#Tastatur

Tasten Aktion
Return In einem Input, was submitBehavior festlegt: absenden (onSubmit), absenden und das Feld verlassen oder eine neue Zeile (mehrzeilige Eingaben)
Shift+Return, Alt+Return Eine neue Zeile in einer mehrzeiligen Eingabe, deren Return absendet (Strg+Return sendet ab)
Tab, Shift+Tab Das nächste / vorherige Feld in Bildschirmreihenfolge, innerhalb des neuesten Dialogs
Escape Verlässt das fokussierte Feld; andernfalls hebt es eine Textauswahl auf, dann schließt es den neuesten Dialog oder geht zurück
Alt+Links, Zurück-Taste, Zurück-Maustaste Zurückgehen (auch aus einem Feld)
Strg+Pfeiltasten, Pos1 / Ende, mit Shift; Strg+Rückschritt / Entf In einem Feld wortweise und zeilenweise bewegen, auswählen und löschen, wie in jeder GTK-App
Strg+Z, Strg+Shift+Z, Strg+X / C / V / A Rückgängig, Wiederholen, Ausschneiden, Kopieren, Einfügen, Alles auswählen (ein masked-Feld verweigert Ausschneiden und Kopieren); Strg+A / Strg+C wählen auswählbaren Text aus und kopieren ihn
Pfeiltasten; Bild auf / ab, Leertaste, Shift+Leertaste; Pos1 / Ende Scrollen die Scroll View um die fokussierte View oder unter der Maus um eine Zeile, eine Seite, zum Anfang / Ende (nicht, solange ein Feld den Fokus hat)
Strg+W, F11, Strg+Q Fenster schließen, Vollbild, Beenden (nsh package- und nsh run-Apps)
Strg+R Lädt den neuesten Build neu (nsh run)

Die eigenen Shortcuts der App (keymap) sind ein fensterweiter Shortcut-Controller; Strg+Q und F11 können nicht belegt werden.

Shortcuts funktionieren mit jedem Tastaturlayout (auf einem kyrillischen oder griechischen ist Strg+C die Taste, die auf einem US-Layout C tippt). Ein Return, das die Komposition einer Eingabemethode (Chinesisch, Japanisch, …) bestätigt, sendet nie ab. onKeyPress meldet, was React Native meldet: den eingegebenen Text, "Enter", "Backspace" und "Escape"; eingefügter Text wird nicht gemeldet.

Web Views sind WebKitGTK-Seiten, die innerhalb der Views von NSH gezeichnet werden: Sheets, Dialoge, Toasts und nachfolgende Views werden über einer Seite gezeichnet, und übergeordnete Views beschneiden sie und blenden sie aus. Ihre Website-Daten (Cookies, Storage, Cache) werden pro App gespeichert, unter ~/.local/share/<app id>/webkit und ~/.cache/<app id>/webkit. Die Capability webview gilt auch für die Seiten von Frames: Ein iframe eines Hosts, der Ihrer App nicht gewährt wurde, bleibt leer. Escape in einer Seite verlässt sie, wie in einem Textfeld (sofern die Seite es nicht selbst verwendet); Alt+Links und die Zurück-Maustaste gehen in der Seite zurück, solange sie einen Verlauf hat.

Nicht unterstützt:

  • Video rate: GTK spielt nur in normaler Geschwindigkeit ab. onEnd kommt nur bei Videos, die nicht in einer Schleife laufen.
  • Zoomende Scroll Views (zoomTo, die Zoom-Props).
  • mixBlendMode und backdropFilter (die Hintergrundfarbe wird weiterhin gezeichnet); borderCurve: "continuous" zeichnet runde Ecken.
  • Input Accessory Views und die Statusleiste (kein Desktop-Äquivalent).
  • Barrierefreiheit: accessible-Gruppierung, benutzerdefinierte accessibilityActions; stattdessen werden Live Regions angesagt.

#Siehe auch