From 43c15a401566ff7a069f48faab2227fcbb903d9f Mon Sep 17 00:00:00 2001 From: husamemad Date: Tue, 28 Jul 2026 13:18:48 +0300 Subject: [PATCH 1/2] =?UTF-8?q?Stop=20stranding=20the=20Launching=E2=80=A6?= =?UTF-8?q?=20OSD=20when=20a=20second=20app=20is=20launched?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shell/services/AppLibrary.qml | 6 +++++- test/shell.d/app-search-test.sh | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/shell/services/AppLibrary.qml b/shell/services/AppLibrary.qml index 35a3a65c..09d51eee 100644 --- a/shell/services/AppLibrary.qml +++ b/shell/services/AppLibrary.qml @@ -150,11 +150,15 @@ Item { try { return ToplevelManager.toplevels.values.length } catch (e) { return 0 } } + // launchOsdOpen tracks whether the OSD is on screen, not which launch put it + // there, so a new launch must not clear it: the OSD is shown with duration 0, + // and only closeLaunchFeedback() takes it down. Dropping the flag here would + // orphan an OSD left over from the previous launch, and the timer restarts + // below discard the timeout that was its last chance to close. function beginLaunchFeedback(name) { root.launchSerial++ root.launchToplevelCount = root.toplevelCount() root.launchActiveToplevel = ToplevelManager.activeToplevel - root.launchOsdOpen = false root.launchOsdMessage = "Launching " + String(name || "application") + "…" launchDelay.restart() launchTimeout.restart() diff --git a/test/shell.d/app-search-test.sh b/test/shell.d/app-search-test.sh index 44c13bc8..99e7678c 100644 --- a/test/shell.d/app-search-test.sh +++ b/test/shell.d/app-search-test.sh @@ -121,6 +121,13 @@ assert( 'app library prefers indexed app icons over ambiguous themed icons' ) +const beginLaunchMatch = appLibraryQml.match(/function beginLaunchFeedback\(name\) \{([\s\S]*?)\n \}/) +assert(beginLaunchMatch, 'app library beginLaunchFeedback function exists') +assert( + !beginLaunchMatch[1].includes('root.launchOsdOpen = false'), + 'app library keeps owning an OSD a previous launch left on screen' +) + const openMatch = menuQml.match(/function openExistingMenu\(initialMenu\) \{([\s\S]*?)\n \}/) assert(openMatch, 'menu openExistingMenu function exists') assert( From 3914c65147452a7f4ade56ddea81fbe28cb5c160 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 28 Jul 2026 07:41:45 -0700 Subject: [PATCH 2/2] Document the launch OSD flag where it lives Co-Authored-By: Claude Opus 5 (1M context) --- shell/services/AppLibrary.qml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/shell/services/AppLibrary.qml b/shell/services/AppLibrary.qml index 09d51eee..ef9456f4 100644 --- a/shell/services/AppLibrary.qml +++ b/shell/services/AppLibrary.qml @@ -26,6 +26,9 @@ Item { property int launchSerial: 0 property int launchToplevelCount: 0 property var launchActiveToplevel: null + // True while the launch OSD is on screen. It outlives the launch that opened + // it: the OSD shows with duration 0, so only closeLaunchFeedback() takes it + // down. property bool launchOsdOpen: false property string launchOsdMessage: "" @@ -150,11 +153,6 @@ Item { try { return ToplevelManager.toplevels.values.length } catch (e) { return 0 } } - // launchOsdOpen tracks whether the OSD is on screen, not which launch put it - // there, so a new launch must not clear it: the OSD is shown with duration 0, - // and only closeLaunchFeedback() takes it down. Dropping the flag here would - // orphan an OSD left over from the previous launch, and the timer restarts - // below discard the timeout that was its last chance to close. function beginLaunchFeedback(name) { root.launchSerial++ root.launchToplevelCount = root.toplevelCount()