From 54e12efcaedb0f73fbc0a64fd169a55ea79a7fb3 Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Mon, 1 Jun 2026 14:26:20 +0200 Subject: [PATCH] quickshell: fix workspace highlight drift and unstable sort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sliding active indicator positioned itself via Repeater.itemAt(), which returns null mid-rebuild; the fallback then stranded it at the top (looked like workspace 1 was active while the font correctly showed another). Cells are uniform, so compute the indicator's y arithmetically from the index instead. Also make monitorWsData's sort deterministic: numbered workspaces ascending, then named ones (e.g. joplin) alphabetically — parseInt alone yields NaN and an unstable order for named workspaces. --- dot_config/quickshell/bar/Workspaces.qml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dot_config/quickshell/bar/Workspaces.qml b/dot_config/quickshell/bar/Workspaces.qml index ad880a3..7bd7b52 100644 --- a/dot_config/quickshell/bar/Workspaces.qml +++ b/dot_config/quickshell/bar/Workspaces.qml @@ -31,7 +31,16 @@ Item { if (ws.monitor && ws.monitor.name === monitorName) data.push({ id: ws.id, name: ws.name }); } - data.sort((a, b) => parseInt(a.name) - parseInt(b.name)); + // Numbered workspaces first (ascending), then named ones (e.g. "joplin") + // alphabetically. parseInt-only sort is unstable for non-numeric names. + data.sort((a, b) => { + let na = parseInt(a.name), nb = parseInt(b.name); + let aNum = !isNaN(na), bNum = !isNaN(nb); + if (aNum && bNum) return na - nb; + if (aNum) return -1; + if (bNum) return 1; + return a.name.localeCompare(b.name); + }); return data; } @@ -85,10 +94,11 @@ Item { } return Math.max(0, Math.min(root.activeWsId - 1, root.wsCount - 1)); } - property var targetItem: wsRepeater.itemAt(targetIndex) - + // Position arithmetically from the index — cells are uniform, so this + // avoids depending on Repeater.itemAt() (which returns null mid-rebuild + // and stranded the indicator at the top). x: (container.width - width) / 2 - y: targetItem ? targetItem.y + wsCol.y : container.padding + y: container.padding + targetIndex * (root.cellSize + wsCol.spacing) width: root.cellSize height: root.cellSize radius: Shared.Theme.radiusSmall