1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-11 07:58:30 -04:00

fix(sway): correctly handle Sway named workspaces

- Fixes #2531
This commit is contained in:
purian23
2026-07-03 16:33:44 -04:00
parent dfe309a543
commit 7178563c2c
2 changed files with 71 additions and 28 deletions
+25 -6
View File
@@ -253,15 +253,36 @@ Item {
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
if (!screenName || SettingsData.workspaceFollowFocus) { if (!screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? swayWorkspaceKey(focusedWs) : 1;
} }
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === screenName && ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === screenName && ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? swayWorkspaceKey(focusedWs) : 1;
} }
return 1; return 1;
} }
// Sway reports num -1 for purely-named workspaces, so identity must fall back to name
function swayWorkspaceKey(ws) {
return ws.num !== -1 ? ws.num : ws.name;
}
function escapeSwayWorkspaceName(name) {
return String(name ?? "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
}
function dispatchSwayWorkspace(ws) {
if (!ws)
return;
try {
if (ws.num !== undefined && ws.num !== -1) {
I3.dispatch(`workspace number ${ws.num}`);
} else if (ws.name) {
I3.dispatch(`workspace "${escapeSwayWorkspaceName(ws.name)}"`);
}
} catch (_) {}
}
function switchWorkspace(direction) { function switchWorkspace(direction) {
const realWorkspaces = getRealWorkspaces(); const realWorkspaces = getRealWorkspaces();
if (realWorkspaces.length < 2) { if (realWorkspaces.length < 2) {
@@ -301,14 +322,12 @@ Item {
} }
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const currentWs = getCurrentWorkspace(); const currentWs = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(ws => ws.num === currentWs); const currentIndex = realWorkspaces.findIndex(ws => swayWorkspaceKey(ws) === currentWs);
const validIndex = currentIndex === -1 ? 0 : currentIndex; const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0); const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) { if (nextIndex !== validIndex) {
try { dispatchSwayWorkspace(realWorkspaces[nextIndex]);
I3.dispatch(`workspace number ${realWorkspaces[nextIndex].num}`);
} catch (_) {}
} }
} }
} }
@@ -184,25 +184,55 @@ Item {
} }
if (!root.screenName || SettingsData.workspaceFollowFocus) { if (!root.screenName || SettingsData.workspaceFollowFocus) {
return workspaces.slice().sort((a, b) => a.num - b.num).map(mapWorkspace); return workspaces.slice().sort(swayWorkspaceOrder).map(mapWorkspace);
} }
const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === root.screenName); const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === root.screenName);
return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num).map(mapWorkspace) : [ return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort(swayWorkspaceOrder).map(mapWorkspace) : [
{ {
"num": 1 "num": 1
} }
]; ];
} }
// Numbered workspaces first in ascending order; purely-named workspaces (sway reports num -1) after, by name
function swayWorkspaceOrder(a, b) {
const keyA = a.num === -1 ? Number.MAX_SAFE_INTEGER : a.num;
const keyB = b.num === -1 ? Number.MAX_SAFE_INTEGER : b.num;
if (keyA !== keyB)
return keyA - keyB;
return (a.name ?? "").localeCompare(b.name ?? "");
}
// Sway reports num -1 for purely-named workspaces, so identity must fall back to name
function swayWorkspaceKey(ws) {
return ws.num !== -1 ? ws.num : ws.name;
}
function escapeSwayWorkspaceName(name) {
return String(name ?? "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
}
function dispatchSwayWorkspace(ws) {
if (!ws)
return;
try {
if (ws.num !== undefined && ws.num !== -1) {
I3.dispatch(`workspace number ${ws.num}`);
} else if (ws.name) {
I3.dispatch(`workspace "${escapeSwayWorkspaceName(ws.name)}"`);
}
} catch (_) {}
}
function getSwayActiveWorkspace() { function getSwayActiveWorkspace() {
if (!root.screenName || SettingsData.workspaceFollowFocus) { if (!root.screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? swayWorkspaceKey(focusedWs) : 1;
} }
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === root.screenName && ws.focused === true); const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === root.screenName && ws.focused === true);
return focusedWs ? focusedWs.num : 1; return focusedWs ? swayWorkspaceKey(focusedWs) : 1;
} }
// Numbered workspaces first in id order, named (negative id) after, by name // Numbered workspaces first in id order, named (negative id) after, by name
@@ -423,7 +453,8 @@ Item {
}; };
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
placeholder = { placeholder = {
"num": -1 "num": -1,
"_placeholder": true
}; };
} else { } else {
placeholder = -1; placeholder = -1;
@@ -586,7 +617,7 @@ Item {
if (root.isMango) if (root.isMango)
return ws && ws.tag !== -1; return ws && ws.tag !== -1;
if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle)
return ws && ws.num !== -1; return ws && !ws._placeholder;
return ws !== -1; return ws !== -1;
}); });
} }
@@ -618,10 +649,7 @@ Item {
case "sway": case "sway":
case "scroll": case "scroll":
case "miracle": case "miracle":
if (data.num) dispatchSwayWorkspace(data);
try {
I3.dispatch(`workspace number ${data.num}`);
} catch (_) {}
break; break;
} }
} }
@@ -720,7 +748,7 @@ Item {
return; return;
} }
const currentIndex = realWorkspaces.findIndex(ws => ws.num === root.currentWorkspace); const currentIndex = realWorkspaces.findIndex(ws => swayWorkspaceKey(ws) === root.currentWorkspace);
const validIndex = currentIndex === -1 ? 0 : currentIndex; const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0); const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
@@ -728,9 +756,7 @@ Item {
return; return;
} }
try { dispatchSwayWorkspace(realWorkspaces[nextIndex]);
I3.dispatch(`workspace number ${realWorkspaces[nextIndex].num}`);
} catch (_) {}
} }
} }
@@ -744,7 +770,7 @@ Item {
if (root.isMango) if (root.isMango)
return (modelData?.tag !== undefined) ? (modelData.tag + 1) : ""; return (modelData?.tag !== undefined) ? (modelData.tag + 1) : "";
if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle)
return modelData?.num || ""; return (modelData?.num !== undefined && modelData.num !== -1) ? modelData.num : (modelData?.name ?? "");
return modelData - 1; return modelData - 1;
} }
@@ -759,7 +785,7 @@ Item {
} else if (root.isMango) { } else if (root.isMango) {
isPlaceholder = modelData?.tag === -1; isPlaceholder = modelData?.tag === -1;
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
isPlaceholder = modelData?.num === -1; isPlaceholder = modelData?._placeholder === true;
} else { } else {
isPlaceholder = modelData === -1; isPlaceholder = modelData === -1;
} }
@@ -1059,7 +1085,7 @@ Item {
if (root.isMango) if (root.isMango)
return !!(modelData && root.dwlActiveTags.includes(modelData.tag)); return !!(modelData && root.dwlActiveTags.includes(modelData.tag));
if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle)
return !!(modelData && modelData.num === root.currentWorkspace); return !!(modelData && root.swayWorkspaceKey(modelData) === root.currentWorkspace);
return modelData === root.currentWorkspace; return modelData === root.currentWorkspace;
} }
property bool isOccupied: { property bool isOccupied: {
@@ -1081,7 +1107,7 @@ Item {
if (root.isMango) if (root.isMango)
return !!(modelData && modelData.tag === -1); return !!(modelData && modelData.tag === -1);
if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle)
return !!(modelData && modelData.num === -1); return !!(modelData && modelData._placeholder);
return modelData === -1; return modelData === -1;
} }
property bool isHovered: mouseArea.containsMouse property bool isHovered: mouseArea.containsMouse
@@ -1397,10 +1423,8 @@ Item {
HyprlandService.focusWorkspace(root.hyprlandWorkspaceSelector(modelData)); HyprlandService.focusWorkspace(root.hyprlandWorkspaceSelector(modelData));
} else if (root.isMango && modelData?.tag !== undefined) { } else if (root.isMango && modelData?.tag !== undefined) {
MangoService.switchToTag(root.screenName, modelData.tag); MangoService.switchToTag(root.screenName, modelData.tag);
} else if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && modelData?.num) { } else if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && modelData?.num !== undefined) {
try { root.dispatchSwayWorkspace(modelData);
I3.dispatch(`workspace number ${modelData.num}`);
} catch (_) {}
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (CompositorService.isNiri) { if (CompositorService.isNiri) {