1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

Feat/niri workspace names (#1396)

* dankbar: show niri workspace names

Keep labels aligned with niri indices and live renames.

* dankbar: prefix named workspaces with index

Use workspace index toggle to show index: name labels.

* workspaces: change size conditions for workspace names

---------

Co-authored-by: bbedward <bbedward@gmail.com>
This commit is contained in:
Kamil Chmielewski
2026-01-21 16:43:55 +01:00
committed by GitHub
parent 417bf37515
commit fd2c6a0784
3 changed files with 161 additions and 56 deletions

View File

@@ -46,11 +46,24 @@ Item {
function getRealWorkspaces() {
if (CompositorService.isNiri) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
return NiriService.getCurrentOutputWorkspaceNumbers();
const fallbackWorkspaces = [
{
"id": 1,
"idx": 0,
"name": ""
},
{
"id": 2,
"idx": 1,
"name": ""
}
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === barWindow.screenName).map(ws => ws.idx + 1);
return workspaces.length > 0 ? workspaces : [1, 2];
];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
const currentWorkspaces = NiriService.getCurrentOutputWorkspaces();
return currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces;
}
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === barWindow.screenName);
return workspaces.length > 0 ? workspaces : fallbackWorkspaces;
} else if (CompositorService.isHyprland) {
const workspaces = Hyprland.workspaces?.values || [];
@@ -118,7 +131,7 @@ Item {
return NiriService.getCurrentWorkspaceNumber();
}
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === barWindow.screenName && ws.is_active);
return activeWs ? activeWs.idx + 1 : 1;
return activeWs ? activeWs.idx : 1;
} else if (CompositorService.isHyprland) {
const monitors = Hyprland.monitors?.values || [];
const currentMonitor = monitors.find(monitor => monitor.name === barWindow.screenName);
@@ -151,12 +164,16 @@ Item {
if (CompositorService.isNiri) {
const currentWs = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(ws => ws === currentWs);
const currentIndex = realWorkspaces.findIndex(ws => ws && ws.idx === currentWs);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
NiriService.switchToWorkspace(realWorkspaces[nextIndex] - 1);
const nextWorkspace = realWorkspaces[nextIndex];
if (!nextWorkspace || nextWorkspace.idx === undefined) {
return;
}
NiriService.switchToWorkspace(nextWorkspace.idx);
}
} else if (CompositorService.isHyprland) {
const currentWs = getCurrentWorkspace();

View File

@@ -199,6 +199,7 @@ Item {
let targetWorkspaceId;
if (CompositorService.isNiri) {
if (!ws || typeof ws !== "object") {
const wsNumber = typeof ws === "number" ? ws : -1;
if (wsNumber <= 0) {
return [];
@@ -208,6 +209,12 @@ Item {
return [];
}
targetWorkspaceId = workspace.id;
} else {
if (ws.id === undefined || ws.id === -1 || ws.idx === -1) {
return [];
}
targetWorkspaceId = ws.id;
}
} else if (CompositorService.isHyprland) {
targetWorkspaceId = ws.id !== undefined ? ws.id : ws;
} else if (CompositorService.isDwl) {
@@ -300,6 +307,12 @@ Item {
"active": false,
"hidden": true
};
} else if (CompositorService.isNiri) {
placeholder = {
"id": -1,
"idx": -1,
"name": ""
};
} else if (CompositorService.isHyprland) {
placeholder = {
"id": -1,
@@ -324,28 +337,52 @@ Item {
function getNiriWorkspaces() {
if (NiriService.allWorkspaces.length === 0) {
return [1, 2];
return [
{
"id": 1,
"idx": 0,
"name": ""
},
{
"id": 2,
"idx": 1,
"name": ""
}
];
}
const fallbackWorkspaces = [
{
"id": 1,
"idx": 0,
"name": ""
},
{
"id": 2,
"idx": 1,
"name": ""
}
];
let workspaces;
if (!root.screenName || SettingsData.workspaceFollowFocus) {
workspaces = NiriService.getCurrentOutputWorkspaceNumbers();
const currentWorkspaces = NiriService.getCurrentOutputWorkspaces();
workspaces = currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces;
} else {
const displayWorkspaces = NiriService.allWorkspaces.filter(ws => ws.output === root.screenName).map(ws => ws.idx + 1);
workspaces = displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2];
const displayWorkspaces = NiriService.allWorkspaces.filter(ws => ws.output === root.screenName);
workspaces = displayWorkspaces.length > 0 ? displayWorkspaces : fallbackWorkspaces;
}
workspaces = workspaces.slice().sort((a, b) => a.idx - b.idx);
if (!SettingsData.showOccupiedWorkspacesOnly) {
return workspaces;
}
return workspaces.filter(wsNum => {
const workspace = NiriService.allWorkspaces.find(w => w.idx + 1 === wsNum && w.output === root.effectiveScreenName);
if (!workspace)
return false;
if (workspace.is_active)
return workspaces.filter(ws => {
if (ws.is_active)
return true;
return NiriService.windows?.some(win => win.workspace_id === workspace.id) ?? false;
return NiriService.windows?.some(win => win.workspace_id === ws.id) ?? false;
});
}
@@ -359,7 +396,7 @@ Item {
}
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === root.screenName && ws.is_active);
return activeWs ? activeWs.idx + 1 : 1;
return activeWs ? activeWs.idx : 1;
}
function getDwlTags() {
@@ -473,6 +510,8 @@ Item {
return root.workspaceList.filter(ws => {
if (useExtWorkspace)
return ws && (ws.id !== "" || ws.name !== "") && !ws.hidden;
if (CompositorService.isNiri)
return ws && ws.idx !== -1;
if (CompositorService.isHyprland)
return ws && ws.id !== -1;
if (CompositorService.isDwl)
@@ -480,6 +519,7 @@ Item {
if (CompositorService.isSway || CompositorService.isScroll)
return ws && ws.num !== -1;
return ws !== -1;
});
}
@@ -506,7 +546,7 @@ Item {
return;
}
const currentIndex = realWorkspaces.findIndex(ws => ws === root.currentWorkspace);
const currentIndex = realWorkspaces.findIndex(ws => ws && ws.idx === root.currentWorkspace);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
@@ -514,7 +554,11 @@ Item {
return;
}
NiriService.switchToWorkspace(realWorkspaces[nextIndex] - 1);
const nextWorkspace = realWorkspaces[nextIndex];
if (!nextWorkspace || nextWorkspace.idx === undefined) {
return;
}
NiriService.switchToWorkspace(nextWorkspace.idx);
} else if (CompositorService.isHyprland) {
const realWorkspaces = getRealWorkspaces();
if (realWorkspaces.length < 2) {
@@ -565,10 +609,26 @@ Item {
}
}
function getWorkspaceIndexFallback(modelData, index) {
if (root.useExtWorkspace)
return index + 1;
if (CompositorService.isNiri)
return (modelData?.idx !== undefined && modelData?.idx !== -1) ? modelData.idx : "";
if (CompositorService.isHyprland)
return modelData?.id || "";
if (CompositorService.isDwl)
return (modelData?.tag !== undefined) ? (modelData.tag + 1) : "";
if (CompositorService.isSway || CompositorService.isScroll)
return modelData?.num || "";
return modelData - 1;
}
function getWorkspaceIndex(modelData, index) {
let isPlaceholder;
if (root.useExtWorkspace) {
isPlaceholder = modelData?.hidden === true;
} else if (CompositorService.isNiri) {
isPlaceholder = modelData?.idx === -1;
} else if (CompositorService.isHyprland) {
isPlaceholder = modelData?.id === -1;
} else if (CompositorService.isDwl) {
@@ -582,26 +642,28 @@ Item {
if (isPlaceholder)
return index + 1;
let workspaceName = "";
if (SettingsData.showWorkspaceName) {
let workspaceName = modelData?.name;
workspaceName = modelData?.name ?? "";
if (workspaceName && workspaceName !== "") {
if (root.isVertical) {
return workspaceName.charAt(0);
workspaceName = workspaceName.charAt(0);
}
return workspaceName;
} else {
workspaceName = "";
}
}
if (root.useExtWorkspace)
return index + 1;
if (CompositorService.isHyprland)
return modelData?.id || "";
if (CompositorService.isDwl)
return (modelData?.tag !== undefined) ? (modelData.tag + 1) : "";
if (CompositorService.isSway || CompositorService.isScroll)
return modelData?.num || "";
return modelData - 1;
if (workspaceName) {
if (SettingsData.showWorkspaceIndex) {
const indexLabel = getWorkspaceIndexFallback(modelData, index);
return indexLabel ? `${indexLabel}: ${workspaceName}` : workspaceName;
}
return workspaceName;
}
return getWorkspaceIndexFallback(modelData, index);
}
readonly property bool hasNativeWorkspaceSupport: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl || CompositorService.isSway || CompositorService.isScroll
@@ -747,6 +809,8 @@ Item {
property bool isActive: {
if (root.useExtWorkspace)
return (modelData?.id || modelData?.name) === root.currentWorkspace;
if (CompositorService.isNiri)
return !!(modelData && modelData.idx === root.currentWorkspace);
if (CompositorService.isHyprland)
return !!(modelData && modelData.id === root.currentWorkspace);
if (CompositorService.isDwl)
@@ -769,6 +833,8 @@ Item {
property bool isPlaceholder: {
if (root.useExtWorkspace)
return !!(modelData && modelData.hidden);
if (CompositorService.isNiri)
return !!(modelData && modelData.idx === -1);
if (CompositorService.isHyprland)
return !!(modelData && modelData.id === -1);
if (CompositorService.isDwl)
@@ -800,6 +866,10 @@ Item {
readonly property real baseWidth: root.isVertical ? (SettingsData.showWorkspaceApps ? widgetHeight * 0.7 : widgetHeight * 0.5) : (isActive ? root.widgetHeight * 1.05 : root.widgetHeight * 0.7)
readonly property real baseHeight: root.isVertical ? (isActive ? root.widgetHeight * 1.05 : root.widgetHeight * 0.7) : (SettingsData.showWorkspaceApps ? widgetHeight * 0.7 : widgetHeight * 0.5)
readonly property bool hasWorkspaceName: SettingsData.showWorkspaceName && modelData?.name && modelData.name !== ""
readonly property bool workspaceNamesEnabled: SettingsData.showWorkspaceName && CompositorService.isNiri
readonly property real contentImplicitWidth: (hasWorkspaceName || loadedHasIcon) ? (appIconsLoader.item?.contentWidth ?? 0) : 0
readonly property real contentImplicitHeight: (workspaceNamesEnabled || loadedHasIcon) ? (appIconsLoader.item?.contentHeight ?? 0) : 0
readonly property real iconsExtraWidth: {
if (!root.isVertical && SettingsData.showWorkspaceApps && loadedIcons.length > 0) {
@@ -816,8 +886,16 @@ Item {
return 0;
}
readonly property real visualWidth: baseWidth + iconsExtraWidth
readonly property real visualHeight: baseHeight + iconsExtraHeight
readonly property real visualWidth: {
if (contentImplicitWidth <= 0) return baseWidth + iconsExtraWidth;
const padding = root.isVertical ? Theme.spacingXS : Theme.spacingS;
return Math.max(baseWidth + iconsExtraWidth, contentImplicitWidth + padding);
}
readonly property real visualHeight: {
if (contentImplicitHeight <= 0) return baseHeight + iconsExtraHeight;
const padding = root.isVertical ? Theme.spacingS : Theme.spacingXS;
return Math.max(baseHeight + iconsExtraHeight, contentImplicitHeight + padding);
}
readonly property color unfocusedColor: {
switch (SettingsData.workspaceUnfocusedColorMode) {
@@ -915,8 +993,8 @@ Item {
} else if (CompositorService.isNiri) {
if (isRightClick) {
NiriService.toggleOverview();
} else {
NiriService.switchToWorkspace(modelData - 1);
} else if (modelData && modelData.idx !== undefined) {
NiriService.switchToWorkspace(modelData.idx);
}
} else if (CompositorService.isHyprland && modelData?.id) {
if (isRightClick && root.hyprlandOverviewLoader?.item) {
@@ -958,7 +1036,7 @@ Item {
if (root.useExtWorkspace) {
wsData = modelData;
} else if (CompositorService.isNiri) {
wsData = NiriService.allWorkspaces.find(ws => ws.idx + 1 === modelData && ws.output === root.effectiveScreenName) || null;
wsData = modelData || null;
} else if (CompositorService.isHyprland) {
wsData = modelData;
} else if (CompositorService.isDwl) {
@@ -984,6 +1062,8 @@ Item {
if (SettingsData.showWorkspaceApps) {
if (CompositorService.isDwl || CompositorService.isSway || CompositorService.isScroll) {
delegateRoot.loadedIcons = root.getWorkspaceIcons(modelData);
} else if (CompositorService.isNiri) {
delegateRoot.loadedIcons = root.getWorkspaceIcons(isPlaceholder ? null : modelData);
} else {
delegateRoot.loadedIcons = root.getWorkspaceIcons(CompositorService.isHyprland ? modelData : (modelData === -1 ? null : modelData));
}
@@ -1096,8 +1176,12 @@ Item {
Loader {
id: appIconsLoader
anchors.fill: parent
active: SettingsData.showWorkspaceApps
active: SettingsData.showWorkspaceApps || SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName || loadedHasIcon
sourceComponent: Item {
id: contentRoot
readonly property real contentWidth: contentRow.item?.implicitWidth ?? 0
readonly property real contentHeight: contentRow.item?.implicitHeight ?? 0
Loader {
id: contentRow
anchors.centerIn: parent

View File

@@ -49,7 +49,7 @@ Singleton {
function setWorkspaces(newMap) {
root.workspaces = newMap;
allWorkspaces = Object.values(newMap).sort((a, b) => a.idx - b.idx);
root.allWorkspaces = Object.values(newMap).sort((a, b) => a.idx - b.idx);
}
Component.onCompleted: fetchOutputs()
@@ -863,9 +863,13 @@ Singleton {
return currentOutputWorkspaces.map(w => w.idx + 1);
}
function getCurrentOutputWorkspaces() {
return currentOutputWorkspaces.slice();
}
function getCurrentWorkspaceNumber() {
if (focusedWorkspaceIndex >= 0 && focusedWorkspaceIndex < allWorkspaces.length) {
return allWorkspaces[focusedWorkspaceIndex].idx + 1;
return allWorkspaces[focusedWorkspaceIndex].idx;
}
return 1;
}