125 lines
4.2 KiB
Python
125 lines
4.2 KiB
Python
import argparse
|
|
import os
|
|
import sys
|
|
|
|
|
|
# parse_args: function definition for ScanSlicer behavior.
|
|
def parse_args(argv=None):
|
|
parser = argparse.ArgumentParser(
|
|
prog="scanslicer",
|
|
description="ScanSlicer Qt UI (Wayland/X11)",
|
|
)
|
|
parser.add_argument(
|
|
"path",
|
|
nargs="?",
|
|
help="Optional input directory containing images",
|
|
)
|
|
parser.add_argument(
|
|
"--backend",
|
|
choices=("auto", "wayland", "x11"),
|
|
default="auto",
|
|
help="Display backend selection (default: auto)",
|
|
)
|
|
return parser.parse_args(argv)
|
|
|
|
|
|
# _detect_backend_from_qpa_env: function definition for ScanSlicer behavior.
|
|
def _detect_backend_from_qpa_env():
|
|
qpa_value = os.environ.get("QT_QPA_PLATFORM", "").strip().lower()
|
|
if not qpa_value:
|
|
return None
|
|
|
|
tokens = [token.strip() for token in qpa_value.split(";") if token.strip()]
|
|
for token in tokens:
|
|
if token == "wayland":
|
|
return "wayland"
|
|
if token in ("xcb", "x11"):
|
|
return "x11"
|
|
return None
|
|
|
|
|
|
# resolve_runtime_backend: function definition for ScanSlicer behavior.
|
|
def resolve_runtime_backend(backend):
|
|
if backend in ("wayland", "x11"):
|
|
return backend
|
|
|
|
env_backend = _detect_backend_from_qpa_env()
|
|
if env_backend is not None:
|
|
return env_backend
|
|
|
|
session_type = os.environ.get("XDG_SESSION_TYPE", "").strip().lower()
|
|
if session_type == "wayland":
|
|
return "wayland"
|
|
if session_type == "x11":
|
|
return "x11"
|
|
|
|
runtime_dir = os.environ.get("XDG_RUNTIME_DIR", "").strip()
|
|
wayland_display = os.environ.get("WAYLAND_DISPLAY", "").strip()
|
|
if runtime_dir and wayland_display and os.path.exists(os.path.join(runtime_dir, wayland_display)):
|
|
return "wayland"
|
|
|
|
if os.environ.get("DISPLAY", "").strip():
|
|
return "x11"
|
|
|
|
# Fall back to Wayland when auto-detection has no clear signal.
|
|
return "wayland"
|
|
|
|
|
|
# configure_qt_backend: function definition for ScanSlicer behavior.
|
|
def configure_qt_backend(backend):
|
|
if backend == "wayland":
|
|
os.environ["QT_QPA_PLATFORM"] = "wayland"
|
|
# Prevent accidental X11/XWayland routing in mixed environments.
|
|
os.environ.pop("DISPLAY", None)
|
|
elif backend == "x11":
|
|
os.environ["QT_QPA_PLATFORM"] = "xcb"
|
|
else:
|
|
raise RuntimeError(f"Unsupported backend '{backend}'.")
|
|
|
|
is_appimage = bool(os.environ.get("APPIMAGE"))
|
|
|
|
# In sandboxed desktop runtimes (Flatpak/Snap), prefer portal integration
|
|
# for file dialogs and desktop services.
|
|
sandboxed = bool(
|
|
os.environ.get("FLATPAK_ID")
|
|
or os.environ.get("SNAP")
|
|
)
|
|
if sandboxed:
|
|
os.environ.setdefault("QT_QPA_PLATFORMTHEME", "xdgdesktopportal")
|
|
elif is_appimage:
|
|
# AppImage is not a strict sandbox and some portal backends can emit:
|
|
# "Connection already associated with an application ID".
|
|
# Prefer GTK theme integration and avoid forced portal registration.
|
|
os.environ.setdefault("QT_QPA_PLATFORMTHEME", "gtk3")
|
|
os.environ.setdefault("QT_NO_XDG_DESKTOP_PORTAL", "1")
|
|
|
|
# In containers, prefer GTK platform theme so Qt can follow host theme
|
|
# settings when available (for example dark/light mode).
|
|
if os.path.exists("/.dockerenv"):
|
|
os.environ.setdefault("QT_QPA_PLATFORMTHEME", "gtk3")
|
|
|
|
|
|
# validate_wayland_environment: function definition for ScanSlicer behavior.
|
|
def validate_wayland_environment():
|
|
runtime_dir = os.environ.get("XDG_RUNTIME_DIR", "").strip()
|
|
display_name = os.environ.get("WAYLAND_DISPLAY", "").strip()
|
|
if not runtime_dir or not display_name:
|
|
raise RuntimeError(
|
|
"Missing Wayland runtime environment. "
|
|
"Set XDG_RUNTIME_DIR and WAYLAND_DISPLAY."
|
|
)
|
|
|
|
socket_path = os.path.join(runtime_dir, display_name)
|
|
if not os.path.exists(socket_path):
|
|
raise RuntimeError(
|
|
f"Wayland socket not found: {socket_path}"
|
|
)
|
|
|
|
|
|
# validate_x11_environment: function definition for ScanSlicer behavior.
|
|
def validate_x11_environment():
|
|
display_name = os.environ.get("DISPLAY", "").strip()
|
|
if not display_name:
|
|
raise RuntimeError(
|
|
"Missing X11 runtime environment. Set DISPLAY or use --backend wayland."
|
|
)
|