#!/bin/bash # Läuft INNERHALB des Debian-Rootfs, aufgerufen von 01-s1-plasma-mobile.sh. # Direkt aufrufen ergibt keinen Sinn — die Umgebung kommt vom äußeren Skript. set -uo pipefail GPU_PROFIL="${HPOS_GPU_PROFIL:-virgl}" BREITE="${HPOS_BREITE:-1080}" HOEHE="${HPOS_HOEHE:-2340}" echo "── Debian-Seite: Plasma Mobile ──" export DEBIAN_FRONTEND=noninteractive export DISPLAY=:0 export XDG_RUNTIME_DIR=/tmp/hpos-runtime export PULSE_SERVER=127.0.0.1 export LANG=de_DE.UTF-8 mkdir -p "$XDG_RUNTIME_DIR" && chmod 700 "$XDG_RUNTIME_DIR" # Plasma Mobile ist Touch-first: ohne diese Variablen kommt eine Desktop-Skalierung # heraus, die auf einem Telefon unbedienbar ist. export QT_QPA_PLATFORM=wayland export QT_QUICK_CONTROLS_MOBILE=1 export PLASMA_PLATFORM=phone export KDE_FULL_SESSION=true # Ohne gesetztes Cursor-Thema meldet KWin 'Failed to load cursor theme "default"' # und zeichnet gar keinen Mauszeiger. export XCURSOR_THEME=breeze_cursors export XCURSOR_SIZE=24 # Im Container immer virpipe, unabhängig vom Profil. Der Vulkan-Treiber liegt in # Termux' Verzeichnis und ist hier drinnen nicht erreichbar — Zink hätte also # nichts, worauf es aufsetzen könnte. Der schnelle Pfad (Zink auf Turnip) wird # eine Ebene tiefer genutzt, vom virgl-Server auf der Termux-Seite. export GALLIUM_DRIVER=virpipe export MESA_GL_VERSION_OVERRIDE=4.3 export MESA_GLES_VERSION_OVERRIDE=3.2 echo " GPU-Profil: $GPU_PROFIL (im Container über virpipe)" # ── Pakete ─────────────────────────────────────────────────────────────────── # Bewusst ohne empfohlene Pakete: sonst zieht Plasma Mobile eine komplette # Desktop-Umgebung samt Drucksystem mit, was auf einem Telefon nur Platz kostet. if ! command -v kwin_wayland >/dev/null 2>&1; then echo "── Installiere Plasma Mobile (einmalig, gut 1 GB) ──" apt-get update -qq # Bewusst OHNE --no-install-recommends: bei KDE stecken die QML-Module # traditionell in den Empfehlungen, nicht in den harten Abhängigkeiten. # Ohne sie ist die Shell formal installiert, aber innen hohl — plasmashell # lädt sie dann nicht und fällt wortlos auf die Voreinstellung zurück. # Für einen Machbarkeitsbeweis ist ein paar hundert MB zu viel das kleinere # Übel gegenüber einem Fehlschlag aus dem falschen Grund. apt-get install -y \ plasma-mobile plasma-nano kwin-wayland plasma-workspace maliit-keyboard \ xdg-desktop-portal-kde qtwayland5 libqt5waylandclient5 \ || echo " ! Paketinstallation unvollständig — Details oben" fi for b in kwin_wayland plasmashell; do if command -v "$b" >/dev/null 2>&1; then echo " ✓ $b vorhanden" else echo " ✗ $b fehlt"; fi done # ── Welche Shell? ──────────────────────────────────────────────────────────── # Ohne gültiges Shell-Paket startet plasmashell klaglos, meldet nur beiläufig # "starting invalid corona" und zeichnet dann nichts. Von außen sieht das aus wie # ein Fehlschlag des Compositors und ist keiner. # # In Debian liefert ausgerechnet 'plasma-mobile' KEINE Shell mit, sondern nur # QML-Module und KWin-Skripte. Die Shell steckt in 'plasma-nano' und heißt # org.kde.plasma.nano. Der Name org.kde.plasma.mobileshell aus den KDE-Quellen # existiert in Debian nicht. Deshalb wird nachgesehen statt geraten. shell_suchen() { local kandidat for kandidat in org.kde.plasma.mobileshell org.kde.plasma.phoneshell \ org.kde.plasma.nano org.kde.plasma.desktop; do if [ -d "/usr/share/plasma/shells/$kandidat" ]; then printf '%s' "$kandidat" return 0 fi done return 1 } echo "── Verfügbare Plasma-Shells ──" if [ -d /usr/share/plasma/shells ]; then ls -1 /usr/share/plasma/shells/ 2>/dev/null | sed 's/^/ /' [ -z "$(ls -A /usr/share/plasma/shells/ 2>/dev/null)" ] && echo " (leer)" else echo " (Verzeichnis /usr/share/plasma/shells fehlt)" fi SHELL_PAKET="$(shell_suchen || true)" if [ -z "$SHELL_PAKET" ]; then echo " ! Keine Shell gefunden — versuche plasma-nano nachzuinstallieren." apt-get install -y --no-install-recommends plasma-nano plasma-mobile 2>&1 \ | tail -5 | sed 's/^/ /' SHELL_PAKET="$(shell_suchen || true)" fi if [ -n "$SHELL_PAKET" ]; then echo " ✓ Shell: $SHELL_PAKET" else echo " ✗ Weiterhin keine Plasma-Shell — plasmashell hat nichts zu zeichnen." echo " Prüfen: dpkg -L plasma-nano | grep shells" echo " Ohne Shell ist Versuch A zum Scheitern verurteilt; XFCE zeigt dann," echo " ob wenigstens X-Server und GPU tragen." fi # ── GPU-Nachweis, bevor der Desktop startet ────────────────────────────────── # Wenn hier schon nichts kommt, ist ein Fehlschlag von Plasma keine Aussage über # Plasma, sondern über den GPU-Pfad. Deshalb vorher messen. echo "── Anzeige und GPU prüfen ──" # Erst der X-Server. Wenn schon der nicht erreichbar ist, sagt jeder GL-Test # darunter nichts aus. if timeout 15 xdpyinfo >/tmp/hpos-xdpy.txt 2>&1; then grep -E '^(name of display|version number|dimensions)' /tmp/hpos-xdpy.txt \ | head -3 | sed 's/^/ /' echo " ✓ X-Server erreichbar" else echo " ✗ X-Server NICHT erreichbar — das wäre die Wurzel allen Übels:" head -3 /tmp/hpos-xdpy.txt | sed 's/^/ /' fi # Jeden GL-Weg einzeln und mit Rückgabewert prüfen. Stürzt glxinfo ab, kommt die # Meldung von der Shell und nicht vom Programm — sie ginge in einer # Kommandoersetzung verloren, und die Ausgabe wäre einfach leer. Genau das ist # vorher passiert und sah aus wie 'kein Treiber gefunden'. gl_test() { local name="$1"; shift local aus rc aus=$(env "$@" timeout 25 glxinfo -B 2>&1); rc=$? if printf '%s' "$aus" | grep -qi 'OpenGL renderer'; then printf '%s\n' "$aus" | grep -Ei 'OpenGL (renderer|version)' | sed 's/^/ /' echo " ✓ $name" return 0 fi echo " ✗ $name — Rückgabewert $rc$([ "$rc" -gt 128 ] && echo ' (abgestürzt oder abgebrochen)')" if [ -n "$aus" ]; then printf '%s\n' "$aus" | head -4 | sed 's/^/ /' else echo " (keine Ausgabe)" fi return 1 } # Ist der virgl-Socket überhaupt da? Fehlt er, hängt der Client bis zum Zeitlimit # (Rückgabewert 124) statt eine Fehlermeldung zu liefern. if ls /tmp/.virgl_test* >/dev/null 2>&1; then echo " ✓ virgl-Socket sichtbar: $(ls /tmp/.virgl_test* 2>/dev/null | tr '\n' ' ')" else echo " ! Kein virgl-Socket unter /tmp — der Container sieht den Server nicht." echo " (Termux legt ihn in sein tmp; proot-distro bindet das über --shared-tmp.)" fi if gl_test "OpenGL über virgl" GALLIUM_DRIVER=virpipe; then GL_WEG=virgl export GALLIUM_DRIVER=virpipe else # Hier war ein Denkfehler: schlugen beide Prüfungen fehl, wurde der # Software-Pfad NICHT gesetzt — ausgerechnet dann nicht, wenn er am nötigsten # ist. Und glxinfo taugt ohnehin nicht als Richter: unter Termux-X11 # scheitert es an X_GetImage mit BadMatch, weil es Pixel zurücklesen will. # Das sagt etwas über glxinfo, nichts über OpenGL. # # Deshalb: Prüfungen nur zur Information, und im Zweifel immer den # Software-Pfad. KWin und QtQuick haben je einen, der die GL-Ebene ganz umgeht. gl_test "OpenGL in Software (llvmpipe)" LIBGL_ALWAYS_SOFTWARE=1 || true GL_WEG=software unset GALLIUM_DRIVER export LIBGL_ALWAYS_SOFTWARE=1 export KWIN_COMPOSE=Q # KWin: QPainter statt OpenGL export QT_QUICK_BACKEND=software export QMLSCENE_DEVICE=softwarecontext echo " → Weiter mit Software-Rendering (KWin QPainter, QtQuick software)." echo " Träge, aber für S1 ausreichend: die Frage ist, OB es läuft." echo " Ein scheiterndes glxinfo schließt das nicht aus — es prüft anders." fi echo " Verwendeter Weg: $GL_WEG" # ── D-Bus ──────────────────────────────────────────────────────────────────── if [ ! -e /run/dbus/system_bus_socket ]; then mkdir -p /run/dbus dbus-daemon --system --fork 2>/dev/null && echo " ✓ System-D-Bus gestartet" \ || echo " ! System-D-Bus nicht gestartet (ohne logind oft verschmerzbar)" fi # ── Versuch A: KWin genestet im X11-Backend ────────────────────────────────── # Das ist die eigentliche Wette. In diesem Modus braucht KWin weder DRM noch Seat. echo "" echo "── Versuch A: kwin_wayland --x11-display ──" echo " Umgebung: GL_WEG=$GL_WEG KWIN_COMPOSE=${KWIN_COMPOSE:-(nicht gesetzt)}" echo " QT_QUICK_BACKEND=${QT_QUICK_BACKEND:-(nicht gesetzt)}" LOGA=/tmp/hpos-s1-versuchA.log # Die lange Optionsform statt '-p': kurze Formen ändern sich zwischen den # Plasma-Fassungen leichter als lange, und eine unbekannte Kurzoption wird still # ignoriert statt bemängelt. Genau das ist der Verdacht. # # Und statt einen Namen zu raten, werden die vorhandenen Shells der Reihe nach # ausprobiert. 'invalid corona' im Protokoll ist das Abbruchkriterium — es sagt, # dass plasmashell nichts zeichnen wird, ohne dass man hinschauen muss. beenden_versuch() { [ -n "${PID_A:-}" ] && kill "$PID_A" 2>/dev/null pkill -x kwin_wayland 2>/dev/null pkill -x plasmashell 2>/dev/null sleep 3 } starte_mit_shell() { local shell="$1" : >"$LOGA" dbus-run-session -- kwin_wayland \ --x11-display "$DISPLAY" \ --width "$BREITE" --height "$HOEHE" \ --xwayland \ -- plasmashell ${shell:+--shell-plugin "$shell"} \ >"$LOGA" 2>&1 & PID_A=$! sleep 25 kill -0 "$PID_A" 2>/dev/null || return 1 grep -q 'invalid corona' "$LOGA" && return 2 return 0 } KANDIDATEN="$SHELL_PAKET" for w in org.kde.plasma.mobileshell org.kde.plasma.nano; do case " $KANDIDATEN " in *" $w "*) ;; *) KANDIDATEN="$KANDIDATEN $w" ;; esac done ERFOLG=0 for shell in $KANDIDATEN; do [ -d "/usr/share/plasma/shells/$shell" ] || continue echo "" echo " → Versuche Shell: $shell" starte_mit_shell "$shell" case $? in 0) echo " ✓ läuft, und plasmashell meldet keine ungültige Shell." ERFOLG=1; break ;; 2) echo " ✗ 'invalid corona' — diese Shell trägt nicht." grep 'invalid corona' "$LOGA" | tail -1 | sed 's/^/ /' beenden_versuch ;; *) echo " ✗ Prozess sofort beendet." tail -n 15 "$LOGA" | sed 's/^/ /' ;; esac done if [ "$ERFOLG" = 1 ] && kill -0 "$PID_A" 2>/dev/null; then echo "" echo " ✓ Versuch A läuft — jetzt in die Termux:X11-App wechseln und schauen." echo " Verwendete Shell: $shell" echo " Beenden mit: pkill -x kwin_wayland" echo " Protokoll: $LOGA" tail -n 20 "$LOGA" 2>/dev/null | sed 's/^/ /' exit 0 fi if kill -0 "${PID_A:-0}" 2>/dev/null; then # Läuft noch, aber keine Shell hat getragen: KWin steht, plasmashell zeichnet # nichts. Das ist ein Teilerfolg und soll auch so benannt werden — der # Compositor ist der schwierige Teil, die Shell der austauschbare. echo "" echo " ! KWin läuft, aber keine der vorhandenen Shells ließ sich laden." echo " Der Compositor ist damit bewiesen, die Shell nicht." echo " Nächster Schritt von Hand, zeigt die eigentliche Ursache:" echo " plasmashell --shell-plugin org.kde.plasma.mobileshell" echo " Protokoll: $LOGA" tail -n 20 "$LOGA" 2>/dev/null | sed 's/^/ /' exit 0 fi echo " ✗ Versuch A beendet. Letzte Zeilen:" tail -n 40 "$LOGA" 2>/dev/null | sed 's/^/ /' # ── Versuch B: die von Debian mitgelieferte Sitzung ────────────────────────── # Startet KWin selbst und wählt sein Backend eigenständig. Weniger Kontrolle, # aber manchmal weiß das Distributionsskript etwas, das wir nicht wissen. echo "" echo "── Versuch B: startplasmamobile ──" if command -v startplasmamobile >/dev/null 2>&1; then LOGB=/tmp/hpos-s1-versuchB.log KWIN_COMPOSE=O2 dbus-run-session -- startplasmamobile >"$LOGB" 2>&1 & PID_B=$! sleep 25 if kill -0 "$PID_B" 2>/dev/null; then echo " ✓ Versuch B läuft — in die Termux:X11-App wechseln." tail -n 25 "$LOGB" 2>/dev/null | sed 's/^/ /' exit 0 fi echo " ✗ Versuch B beendet. Letzte Zeilen:" tail -n 40 "$LOGB" 2>/dev/null | sed 's/^/ /' else echo " ! startplasmamobile nicht vorhanden" fi # ── Rückfallebene: XFCE, damit der Abend nicht umsonst war ─────────────────── # Beweist zumindest, dass X-Server und GPU-Pfad tragen. Damit ist ein Fehlschlag # von S1 eindeutig Plasma zuzuordnen und nicht der Umgebung. echo "" echo "── Rückfallebene: XFCE zur Gegenprobe ──" if ! command -v startxfce4 >/dev/null 2>&1; then apt-get install -y --no-install-recommends xfce4 xfce4-terminal >/dev/null 2>&1 \ || echo " ! XFCE-Installation fehlgeschlagen" fi if command -v startxfce4 >/dev/null 2>&1; then dbus-run-session -- startxfce4 >/tmp/hpos-s1-xfce.log 2>&1 & sleep 12 if pgrep -f xfwm4 >/dev/null 2>&1; then echo " ✓ XFCE läuft. S1 ist gescheitert, aber X-Server und GPU-Pfad tragen." echo " → Im Protokoll als 'S1 gescheitert, XFCE-Profil wird Hauptweg' vermerken." else echo " ✗ Auch XFCE startet nicht — dann liegt es an X-Server oder GPU, nicht an Plasma." fi fi exit 1