diff --git a/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml b/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml index 79533929f..5220f660f 100644 --- a/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml +++ b/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml @@ -253,6 +253,16 @@ Item { return ws.id > 0 ? ws.id : "name:" + (ws.name ?? ""); } + // A hotplug can leave the workspace→monitor mapping stale so nothing matches this screen; + // show what the monitor itself reports rather than a fabricated workspace "1" (#3133) + function hyprlandMonitorWorkspaces(workspaces) { + const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === root.screenName); + if (monitorWorkspaces.length > 0) + return monitorWorkspaces.sort(hyprlandWorkspaceOrder); + const active = Hyprland.monitors?.values?.find(m => m.name === root.screenName)?.activeWorkspace; + return active ? [active] : []; + } + function getHyprlandWorkspaces() { const workspaces = Hyprland.workspaces?.values || []; if (workspaces.length === 0) { @@ -284,13 +294,7 @@ Item { if (!root.screenName || SettingsData.workspaceFollowFocus) { filtered = filtered.slice().sort(hyprlandWorkspaceOrder); } else { - const monitorWorkspaces = filtered.filter(ws => ws.monitor?.name === root.screenName); - filtered = monitorWorkspaces.length > 0 ? monitorWorkspaces.sort(hyprlandWorkspaceOrder) : [ - { - id: 1, - name: "1" - } - ]; + filtered = hyprlandMonitorWorkspaces(filtered); } if (!SettingsData.showOccupiedWorkspacesOnly) { diff --git a/quickshell/Services/CompositorService.qml b/quickshell/Services/CompositorService.qml index c77b9f72a..9baa85d7d 100644 --- a/quickshell/Services/CompositorService.qml +++ b/quickshell/Services/CompositorService.qml @@ -221,6 +221,10 @@ Singleton { enabled: isHyprland function onRawEvent(event) { + if (event.name === "monitoraddedv2" || event.name === "monitorremoved") { + root.refreshHyprlandMonitorLayout(); + return; + } if (event.name === "openwindow" || event.name === "closewindow" || event.name === "movewindow" || event.name === "movewindowv2" || event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activewindow" || event.name === "activewindowv2" || event.name === "changefloatingmode" || event.name === "fullscreen" || event.name === "moveintogroup" || event.name === "moveoutofgroup" || event.name === "activespecial") { try { Hyprland.refreshToplevels(); @@ -690,9 +694,19 @@ Singleton { target: Quickshell function onScreensChanged() { root._recomputeFrameBlocked(); + root.refreshHyprlandMonitorLayout(); } } + // Workspace moves can land before Hyprland announces the monitor and before the Wayland + // output reaches us, so re-read both models once the screen set settles (#3133) + function refreshHyprlandMonitorLayout() { + if (!isHyprland) + return; + Hyprland.refreshMonitors(); + Hyprland.refreshWorkspaces(); + } + function _screenForName(screenOrName) { if (screenOrName && typeof screenOrName !== "string") return screenOrName;