From 2b790a8a71024034fe3c2c2c67251d899c77882f Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Mon, 2 Nov 2026 21:20:18 -0500 Subject: [PATCH] fix(runtime): keep the Linux desktop installed across a runtime update (#2021) * fix(runtime): keep the Linux desktop installed across a runtime update A runtime update replaces the whole runtime tree, and the desktop pack is built against one runtime, so every update removed the installed desktop. Since the runtime started updating by itself, this happened without the user doing anything: the next Open showed "Install & open" and downloaded the whole desktop again. When the desktop was installed before the update, the same update job now installs the new runtime's desktop pack right after the runtime, with the update's progress. If that install fails, the runtime update still counts as done and Open offers the install as before. A repair from the session no longer installs the desktop a second time when the runtime install already did. * fix(runtime): roll back a failed desktop restore after a runtime update If putting the desktop back fails after its archive started unpacking, the install journal stayed behind, and every later launch, Steam included, tried to resume it and stopped when that failed. The update now rolls back the partial desktop with the desktop removal, which restores the runtime's own files and clears the journal. Open then offers the desktop install as before. Whether the desktop was installed is now checked on its own, so a repair of a damaged runtime also restores it. * fix(session): do not install the desktop again after resuming it Opening the desktop with an interrupted desktop install resumed that install and then installed the desktop a second time. The second install is now skipped when the resume already completed the desktop. --- .../com/droiddeck/launcher/SessionActivity.kt | 3 +- .../runtime/LinuxRuntimeInstaller.java | 30 +++++++++++++++++-- tools/ubuntu/README.md | 3 +- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt index fb344c194..f20ea7a7a 100644 --- a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt +++ b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt @@ -1944,7 +1944,8 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { } if (problem == null) SessionEvents.record("package.ready") else failedComponent = "package" } - if (problem == null && desktop && !SessionState.stopRequested) { + if (problem == null && desktop && !SessionState.stopRequested && + !((runtime || resume) && com.droiddeck.launcher.runtime.DesktopCatalog.desktopInstalled(this))) { if (activeInstallWorker === worker) SessionState.installing = "desktop" SessionEvents.transition(SessionPhase.INSTALLING_RUNTIME, "desktop.installing", mapOf("component" to "desktop")) problem = installDesktop() diff --git a/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntimeInstaller.java b/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntimeInstaller.java index 50fb07355..21a40a92a 100644 --- a/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntimeInstaller.java +++ b/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntimeInstaller.java @@ -130,7 +130,8 @@ public final class LinuxRuntimeInstaller { } if (!owner) return join(job, listener); try { - job.ok = installOnce(context.getApplicationContext(), release, new ProgressListener() { + Context app = context.getApplicationContext(); + ProgressListener progress = new ProgressListener() { @Override public void onProgress(String stage, int percent) { onProgress(Step.OTHER, stage, percent); } @@ -141,7 +142,10 @@ public final class LinuxRuntimeInstaller { job.percent = percent; for (ProgressListener l : job.listeners) l.onProgress(step, stage, percent); } - }); + }; + boolean desktop = DesktopCatalog.INSTANCE.desktopInstalled(app); + job.ok = installOnce(app, release, progress); + if (job.ok && desktop) keepDesktop(app, progress); return job.ok; } finally { synchronized (JOB_LOCK) { @@ -151,6 +155,28 @@ public final class LinuxRuntimeInstaller { } } + private static void keepDesktop(Context context, ProgressListener progress) { + String problem; + try { + problem = DesktopCatalog.INSTANCE.install(context, DesktopCatalog.INSTANCE.desktopEntry(context), progress); + } catch (RuntimeException e) { + problem = e.toString(); + } + if (problem == null) { + Log.i(TAG, "desktop installed again for the new runtime"); + return; + } + Log.w(TAG, "desktop not installed again for the new runtime: " + problem); + boolean started = false; + for (DesktopCatalog.Entry entry : DesktopCatalog.INSTANCE.interrupted(context)) { + if (DesktopCatalog.DESKTOP_ID.equals(entry.getId())) started = true; + } + if (!started) return; + String undone = DesktopCatalog.INSTANCE.removeDesktop(context, progress); + if (undone == null) Log.i(TAG, "rolled back the partial desktop install"); + else Log.w(TAG, "could not roll back the partial desktop install: " + undone); + } + public static boolean isInstalling() { synchronized (JOB_LOCK) { return running != null && !running.removal && !running.maintenance; diff --git a/tools/ubuntu/README.md b/tools/ubuntu/README.md index ceea395c5..85001fe67 100644 --- a/tools/ubuntu/README.md +++ b/tools/ubuntu/README.md @@ -29,7 +29,8 @@ Steam on the desktop). The app installs it into `files/linuxfs` and runs it unde - The desktop pack's `usr/share/droiddeck/desktop/files.tsv.gz` lists each path the desktop added (N), changed (C) or removed (R), and `originals/` keeps the runtime's copies of changed and removed files. Removing the desktop restores those and deletes the added files the user has not changed; - a runtime update replaces the tree, and the desktop is downloaded again when it is next opened. + a runtime update replaces the tree, so when the desktop was installed the update installs the new + runtime's desktop pack right after it. At run time: