From 8728791c93ecf6f19d8a928c60407a813ec77e9b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 26 Jul 2026 20:30:52 -0700 Subject: [PATCH] Build only the module list the bar is showing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The center section declares both an anchored and an unanchored arrangement and shows whichever fits, but a hidden ModuleList is still a loaded Loader. With a center anchor set — the default — every center module was therefore mounted twice for the life of the session: two IPC handlers registered for the same target, two clocks ticking, two of every timer and network fetch behind them, one set of which nothing could reach. Co-Authored-By: Claude Opus 5 (1M context) --- shell/plugins/bar/Bar.qml | 6 ++++++ test/shell.d/bar-test.sh | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/shell/plugins/bar/Bar.qml b/shell/plugins/bar/Bar.qml index 4d7202cc..daf243c0 100644 --- a/shell/plugins/bar/Bar.qml +++ b/shell/plugins/bar/Bar.qml @@ -1321,6 +1321,12 @@ Item { property string region: "" visible: entries.length > 0 + // A hidden list must not build its modules. The center section declares + // both an anchored and an unanchored arrangement and shows whichever + // fits, so leaving the other one loaded mounts every center module + // twice — two IPC handlers registered for the same target, two clocks + // ticking, two of every timer and fetch behind them. + active: visible && entries.length > 0 sourceComponent: root.vertical ? verticalModuleList : horizontalModuleList width: item ? item.implicitWidth : 0 height: item ? item.implicitHeight : 0 diff --git a/test/shell.d/bar-test.sh b/test/shell.d/bar-test.sh index 7a40ea9b..5bd64d5e 100644 --- a/test/shell.d/bar-test.sh +++ b/test/shell.d/bar-test.sh @@ -19,6 +19,14 @@ const fs = require('fs') const bar = requireFromRoot('shell/plugins/bar/BarModel.js') const barSource = fs.readFileSync(root + '/shell/plugins/bar/Bar.qml', 'utf8') +// The center section declares two arrangements and shows one; the hidden one +// must not build its modules or every center widget exists twice. +const moduleList = barSource.slice(barSource.indexOf('component ModuleList'), barSource.indexOf('component ModuleSlot')) +assert( + /active: visible && entries\.length > 0/.test(moduleList), + 'bar builds only the module list it is showing' +) + // A center module is mounted twice — drawn copy plus zero-size placeholder — // and the order they register in is not stable across a live reconfiguration, // so panel routing has to pick the one that is actually on screen.