feat(linux): native build path + Linux-specific launcher optimizations

- X-Plane auto-detection now finds Steam (native + Flatpak), /opt and
  external-drive SteamLibrary installs, not just ~/ and macOS/Windows paths.
- Close-to-background minimizes on Linux instead of hiding to tray, so the app
  is never stranded on desktops without a tray (e.g. vanilla GNOME).
- Disable WebKitGTK's DMABUF renderer on Linux to avoid black/blank windows on
  some GPU/driver combos (overridable via the env var).
- Launcher font stack gains Linux UI/mono fallbacks (Cantarell/Ubuntu/Noto).
- scripts/build.sh: Docker-free Linux AppImage build — repack the cockpit into
  the prebuilt bundle for web-only changes; recompile natively for code changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-05 01:33:19 +02:00
parent b9241e60c8
commit 55ea7fdcc8
4 changed files with 162 additions and 12 deletions
+56 -9
View File
@@ -66,30 +66,71 @@ fn suggest_port(start: u16) -> u16 {
start
}
// A directory is an X-Plane 12 root iff it holds Resources/default data.
fn is_xplane_root(p: &std::path::Path) -> bool {
p.join("Resources").join("default data").is_dir()
}
#[tauri::command]
fn default_xplane_path() -> Option<String> {
let home = std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.unwrap_or_default();
let candidates = [
let user = std::env::var("USER")
.or_else(|_| std::env::var("USERNAME"))
.unwrap_or_default();
let mut candidates = vec![
// Generic / cross-platform
format!("{home}/X-Plane 12"),
format!("{home}/Desktop/X-Plane 12"),
format!("{home}/Games/X-Plane 12"),
// Steam on Linux — native, plus the Flatpak Steam sandbox path
format!("{home}/.steam/steam/steamapps/common/X-Plane 12"),
format!("{home}/.local/share/Steam/steamapps/common/X-Plane 12"),
format!("{home}/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/X-Plane 12"),
// System-wide (Linux)
"/opt/X-Plane 12".to_string(),
// macOS
"/Applications/X-Plane 12".to_string(),
// Windows
"C:/X-Plane 12".to_string(),
"D:/X-Plane 12".to_string(),
];
// Secondary/external drives: Steam libraries on extra disks usually mount
// under /media/$USER, /run/media/$USER or /mnt. Probe each mounted volume
// for the standard SteamLibrary layout (and a bare "X-Plane 12" folder).
for base in [
format!("/media/{user}"),
format!("/run/media/{user}"),
"/mnt".to_string(),
] {
if let Ok(entries) = std::fs::read_dir(&base) {
for vol in entries.flatten().map(|e| e.path()) {
candidates.push(
vol.join("SteamLibrary/steamapps/common/X-Plane 12")
.to_string_lossy()
.into_owned(),
);
candidates.push(
vol.join("steamapps/common/X-Plane 12")
.to_string_lossy()
.into_owned(),
);
candidates.push(vol.join("X-Plane 12").to_string_lossy().into_owned());
}
}
}
candidates
.into_iter()
.find(|c| PathBuf::from(c).join("Resources").join("default data").is_dir())
.find(|c| is_xplane_root(&PathBuf::from(c)))
}
#[tauri::command]
fn valid_xplane_path(path: String) -> bool {
!path.is_empty()
&& PathBuf::from(&path)
.join("Resources")
.join("default data")
.is_dir()
!path.is_empty() && is_xplane_root(&PathBuf::from(&path))
}
#[tauri::command]
@@ -225,11 +266,17 @@ pub fn run() {
build_tray(app.handle())?;
Ok(())
})
// Closing the window hides it instead of quitting, so the server keeps
// serving tablets in the background. Quit from the tray.
// Closing the window keeps the app alive so the server keeps serving
// tablets in the background. On macOS/Windows the tray icon is always
// reachable, so fully hide. On Linux many desktops (notably vanilla
// GNOME) show no tray at all, so hiding would strand the app with no way
// back — minimize instead, keeping it in the taskbar while it runs.
.on_window_event(|window, event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
api.prevent_close();
#[cfg(target_os = "linux")]
let _ = window.minimize();
#[cfg(not(target_os = "linux"))]
let _ = window.hide();
}
})
+9
View File
@@ -2,5 +2,14 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
// WebKitGTK's DMABUF renderer shows a black/blank window on a number of Linux
// GPU/driver combinations (notably Nvidia and older Mesa). This launcher is a
// simple control panel, so favour reliability over GPU compositing: disable
// the DMABUF renderer unless the user has already set the variable themselves.
#[cfg(target_os = "linux")]
if std::env::var_os("WEBKIT_DISABLE_DMABUF_RENDERER").is_none() {
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
}
xplane_cockpit_lib::run()
}