diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml | 1981 |
1 files changed, 0 insertions, 1981 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml deleted file mode 100644 index 3721e35..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/WorkspaceSwitcher.qml +++ /dev/null @@ -1,1981 +0,0 @@ -import QtQuick -import QtQuick.Effects -import Quickshell -import Quickshell.Widgets -import Quickshell.Hyprland -import Quickshell.I3 -import qs.Common -import qs.Services -import qs.Widgets - -Item { - id: root - - property bool isVertical: axis?.isVertical ?? false - property var axis: null - property string screenName: "" - property real widgetHeight: 30 - property real barThickness: 48 - property var barConfig: null - property var blurBarWindow: null - property var hyprlandOverviewLoader: null - property var parentScreen: null - - readonly property real _leftMargin: { - if (isVertical) - return 0; - root.x; - if (!root.parent) - return 0; - const gap = root.mapToItem(null, 0, 0).x; - return (gap > 0 && gap < 30) ? gap + 5 : 0; - } - readonly property real _rightMargin: { - if (isVertical) - return 0; - root.x; - root.width; - if (!root.parent || !blurBarWindow) - return 0; - const gap = blurBarWindow.width - root.mapToItem(null, root.width, 0).x; - return (gap > 0 && gap < 30) ? gap + 5 : 0; - } - readonly property real _topMargin: { - if (!isVertical) - return 0; - root.y; - if (!root.parent) - return 0; - const gap = root.mapToItem(null, 0, 0).y; - return (gap > 0 && gap < 30) ? gap + 5 : 0; - } - readonly property real _bottomMargin: { - if (!isVertical) - return 0; - root.y; - root.height; - if (!root.parent || !blurBarWindow) - return 0; - const gap = blurBarWindow.height - root.mapToItem(null, 0, root.height).y; - return (gap > 0 && gap < 30) ? gap + 5 : 0; - } - - property int _desktopEntriesUpdateTrigger: 0 - readonly property var sortedToplevels: { - return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName); - } - - readonly property string effectiveScreenName: { - if (!SettingsData.workspaceFollowFocus) - return root.screenName; - - switch (CompositorService.compositor) { - case "niri": - return NiriService.currentOutput || root.screenName; - case "hyprland": - return Hyprland.focusedWorkspace?.monitor?.name || root.screenName; - case "dwl": - return DwlService.activeOutput || root.screenName; - case "sway": - case "scroll": - case "miracle": - const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); - return focusedWs?.monitor?.name || root.screenName; - default: - return root.screenName; - } - } - - readonly property bool useExtWorkspace: DMSService.forceExtWorkspace || (!CompositorService.isNiri && !CompositorService.isHyprland && !CompositorService.isDwl && !CompositorService.isSway && !CompositorService.isScroll && !CompositorService.isMiracle && ExtWorkspaceService.extWorkspaceAvailable) - - Connections { - target: DesktopEntries - function onApplicationsChanged() { - _desktopEntriesUpdateTrigger++; - } - } - - property var currentWorkspace: { - if (useExtWorkspace) - return getExtWorkspaceActiveWorkspace(); - - switch (CompositorService.compositor) { - case "niri": - return getNiriActiveWorkspace(); - case "hyprland": - return getHyprlandActiveWorkspace(); - case "dwl": - const activeTags = getDwlActiveTags(); - return activeTags.length > 0 ? activeTags[0] : -1; - case "sway": - case "scroll": - case "miracle": - return getSwayActiveWorkspace(); - default: - return 1; - } - } - property var dwlActiveTags: { - if (CompositorService.isDwl) { - return getDwlActiveTags(); - } - return []; - } - property var workspaceList: { - if (useExtWorkspace) { - const baseList = getExtWorkspaceWorkspaces(); - return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList; - } - - let baseList; - switch (CompositorService.compositor) { - case "niri": - baseList = getNiriWorkspaces(); - break; - case "hyprland": - baseList = getHyprlandWorkspaces(); - break; - case "dwl": - baseList = getDwlTags(); - break; - case "sway": - case "scroll": - case "miracle": - baseList = getSwayWorkspaces(); - break; - default: - return [1]; - } - return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList; - } - - function getSwayWorkspaces() { - const workspaces = I3.workspaces?.values || []; - if (workspaces.length === 0) - return [ - { - "num": 1 - } - ]; - - function mapWorkspace(ws) { - return { - "num": ws.number, - "name": ws.name, - "focused": ws.focused, - "active": ws.active, - "urgent": ws.urgent, - "monitor": ws.monitor - }; - } - - if (!root.screenName || SettingsData.workspaceFollowFocus) { - return workspaces.slice().sort((a, b) => a.num - b.num).map(mapWorkspace); - } - - const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === root.screenName); - return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num).map(mapWorkspace) : [ - { - "num": 1 - } - ]; - } - - function getSwayActiveWorkspace() { - if (!root.screenName || SettingsData.workspaceFollowFocus) { - const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); - return focusedWs ? focusedWs.num : 1; - } - - const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === root.screenName && ws.focused === true); - return focusedWs ? focusedWs.num : 1; - } - - function getHyprlandWorkspaces() { - const workspaces = Hyprland.workspaces?.values || []; - if (workspaces.length === 0) { - return [ - { - id: 1, - name: "1" - } - ]; - } - - let filtered = workspaces.filter(ws => ws.id > -1); - if (filtered.length === 0) { - return [ - { - id: 1, - name: "1" - } - ]; - } - - if (!root.screenName || SettingsData.workspaceFollowFocus) { - filtered = filtered.slice().sort((a, b) => a.id - b.id); - } else { - const monitorWorkspaces = filtered.filter(ws => ws.monitor?.name === root.screenName); - filtered = monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.id - b.id) : [ - { - id: 1, - name: "1" - } - ]; - } - - if (!SettingsData.showOccupiedWorkspacesOnly) { - return filtered; - } - - const hyprlandToplevels = Array.from(Hyprland.toplevels?.values || []); - const activeWsId = root.currentWorkspace; - return filtered.filter(ws => { - if (ws.id === activeWsId) - return true; - return hyprlandToplevels.some(tl => tl.workspace?.id === ws.id); - }); - } - - function getHyprlandActiveWorkspace() { - if (!root.screenName || SettingsData.workspaceFollowFocus) { - return Hyprland.focusedWorkspace?.id || 1; - } - - const monitor = Hyprland.monitors?.values?.find(m => m.name === root.screenName); - return monitor?.activeWorkspace?.id || 1; - } - - function getWorkspaceIcons(ws) { - _desktopEntriesUpdateTrigger; - if (!SettingsData.showWorkspaceApps || !ws) { - return []; - } - - let targetWorkspaceId; - if (CompositorService.isNiri) { - if (!ws || typeof ws !== "object") { - const wsNumber = typeof ws === "number" ? ws : -1; - if (wsNumber <= 0) { - return []; - } - const workspace = NiriService.allWorkspaces.find(w => w.idx + 1 === wsNumber && w.output === root.effectiveScreenName); - if (!workspace) { - 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) { - if (typeof ws !== "object" || ws.tag === undefined) { - return []; - } - targetWorkspaceId = ws.tag; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - targetWorkspaceId = ws.num !== undefined ? ws.num : ws; - } else { - return []; - } - - const wins = CompositorService.isNiri ? (NiriService.windows || []) : CompositorService.sortedToplevels; - - const byApp = {}; - let isActiveWs = false; - if (CompositorService.isNiri) { - isActiveWs = NiriService.allWorkspaces.some(ws => ws.id === targetWorkspaceId && ws.is_active); - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true); - isActiveWs = focusedWs ? (focusedWs.num === targetWorkspaceId) : false; - } else if (CompositorService.isDwl) { - const output = DwlService.getOutputState(root.effectiveScreenName); - if (output && output.tags) { - const tag = output.tags.find(t => t.tag === targetWorkspaceId); - isActiveWs = tag ? (tag.state === 1) : false; - } - } else { - isActiveWs = targetWorkspaceId === root.currentWorkspace; - } - - wins.forEach((w, i) => { - if (!w) { - return; - } - - let winWs = null; - if (CompositorService.isNiri) { - winWs = w.workspace_id; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - winWs = w.workspace?.num; - } else { - const hyprlandToplevels = Array.from(Hyprland.toplevels?.values || []); - const hyprToplevel = hyprlandToplevels.find(ht => ht.wayland === w); - winWs = hyprToplevel?.workspace?.id; - } - - if (winWs === undefined || winWs === null || winWs !== targetWorkspaceId) { - return; - } - - const keyBase = (w.app_id || w.appId || w.class || w.windowClass || "unknown"); - const moddedId = Paths.moddedAppId(keyBase); - const key = isActiveWs || !SettingsData.groupWorkspaceApps ? `${moddedId}_${i}` : moddedId; - - if (!byApp[key]) { - const isQuickshell = keyBase === "org.quickshell" || keyBase === "com.danklinux.dms"; - const isSteamApp = Paths.isSteamApp(moddedId); - const desktopEntry = DesktopEntries.heuristicLookup(moddedId); - const icon = Paths.getAppIcon(moddedId, desktopEntry); - const appName = Paths.getAppName(moddedId, desktopEntry); - byApp[key] = { - "type": "icon", - "icon": icon, - "isQuickshell": isQuickshell, - "isSteamApp": isSteamApp, - "active": !!((w.activated || w.is_focused) || (CompositorService.isNiri && w.is_focused)), - "count": 1, - "windowId": w.address || w.id, - "fallbackText": appName || "" - }; - } else { - byApp[key].count++; - if ((w.activated || w.is_focused) || (CompositorService.isNiri && w.is_focused)) { - byApp[key].active = true; - } - } - }); - - return Object.values(byApp); - } - - function padWorkspaces(list) { - const padded = list.slice(); - let placeholder; - if (useExtWorkspace) { - placeholder = { - "id": "", - "name": "", - "active": false, - "hidden": true - }; - } else if (CompositorService.isNiri) { - placeholder = { - "id": -1, - "idx": -1, - "name": "" - }; - } else if (CompositorService.isHyprland) { - placeholder = { - "id": -1, - "name": "" - }; - } else if (CompositorService.isDwl) { - placeholder = { - "tag": -1 - }; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - placeholder = { - "num": -1 - }; - } else { - placeholder = -1; - } - while (padded.length < 3) { - padded.push(placeholder); - } - return padded; - } - - function getNiriWorkspaces() { - if (NiriService.allWorkspaces.length === 0) { - 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) { - const currentWorkspaces = NiriService.getCurrentOutputWorkspaces(); - workspaces = currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces; - } else { - 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(ws => { - if (ws.is_active) - return true; - return NiriService.windows?.some(win => win.workspace_id === ws.id) ?? false; - }); - } - - function getNiriActiveWorkspace() { - if (NiriService.allWorkspaces.length === 0) { - return 1; - } - - if (!root.screenName || SettingsData.workspaceFollowFocus) { - return NiriService.getCurrentWorkspaceNumber(); - } - - const activeWs = NiriService.allWorkspaces.find(ws => ws.output === root.screenName && ws.is_active); - return activeWs ? activeWs.idx : 1; - } - - function getDwlTags() { - if (!DwlService.dwlAvailable) - return []; - - const targetScreen = root.effectiveScreenName; - const output = DwlService.getOutputState(targetScreen); - if (!output || !output.tags || output.tags.length === 0) - return []; - - if (SettingsData.dwlShowAllTags) { - return output.tags.map(tag => ({ - "tag": tag.tag, - "state": tag.state, - "clients": tag.clients, - "focused": tag.focused - })); - } - - const visibleTagIndices = DwlService.getVisibleTags(targetScreen); - return visibleTagIndices.map(tagIndex => { - const tagData = output.tags.find(t => t.tag === tagIndex); - return { - "tag": tagIndex, - "state": tagData?.state ?? 0, - "clients": tagData?.clients ?? 0, - "focused": tagData?.focused ?? false - }; - }); - } - - function getDwlActiveTags() { - if (!DwlService.dwlAvailable) - return []; - - return DwlService.getActiveTags(root.effectiveScreenName); - } - - function getExtWorkspaceWorkspaces() { - const groups = ExtWorkspaceService.groups; - if (!ExtWorkspaceService.extWorkspaceAvailable || groups.length === 0) { - return [ - { - "id": "1", - "name": "1", - "active": false - } - ]; - } - - const group = groups.find(g => g.outputs && g.outputs.includes(root.screenName)); - if (!group || !group.workspaces) { - return [ - { - "id": "1", - "name": "1", - "active": false - } - ]; - } - - let visible = group.workspaces.filter(ws => !ws.hidden); - - const hasValidCoordinates = visible.some(ws => ws.coordinates && ws.coordinates.length > 0); - if (hasValidCoordinates) { - visible = visible.sort((a, b) => { - const coordsA = a.coordinates || [0, 0]; - const coordsB = b.coordinates || [0, 0]; - if (coordsA[0] !== coordsB[0]) - return coordsA[0] - coordsB[0]; - return coordsA[1] - coordsB[1]; - }); - } - - visible = visible.map(ws => ({ - id: ws.id, - name: ws.name, - coordinates: ws.coordinates, - state: ws.state, - active: ws.active, - urgent: ws.urgent, - hidden: ws.hidden, - groupID: group.id - })); - - return visible.length > 0 ? visible : [ - { - "id": "1", - "name": "1", - "active": false - } - ]; - } - - function getExtWorkspaceActiveWorkspace() { - if (!ExtWorkspaceService.extWorkspaceAvailable) { - return 1; - } - - const activeWs = ExtWorkspaceService.getActiveWorkspaceForOutput(root.screenName); - return activeWs ? (activeWs.id || activeWs.name || "1") : "1"; - } - - readonly property real dpr: parentScreen ? CompositorService.getScreenScale(parentScreen) : 1 - readonly property real padding: (root.barConfig?.removeWidgetPadding ?? false) ? 0 : Theme.snap((root.barConfig?.widgetPadding ?? 12) * (widgetHeight / 30), dpr) - readonly property real visualWidth: isVertical ? widgetHeight : (workspaceRow.implicitWidth + padding * 2) - readonly property real visualHeight: isVertical ? (workspaceRow.implicitHeight + padding * 2) : widgetHeight - readonly property real appIconSize: Theme.barIconSize(barThickness, -6 + SettingsData.workspaceAppIconSizeOffset, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale) - - function getRealWorkspaces() { - 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) - return ws && ws.tag !== -1; - if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - return ws && ws.num !== -1; - return ws !== -1; - }); - } - - function switchToWorkspaceByModelData(data) { - if (!data) - return; - - if (root.useExtWorkspace && (data.id || data.name)) { - ExtWorkspaceService.activateWorkspace(data.id || data.name, data.groupID || ""); - return; - } - - switch (CompositorService.compositor) { - case "niri": - if (data.idx !== undefined) - NiriService.switchToWorkspace(data.idx); - break; - case "hyprland": - if (data.id) - Hyprland.dispatch(`workspace ${data.id}`); - break; - case "dwl": - if (data.tag !== undefined) - DwlService.switchToTag(root.screenName, data.tag); - break; - case "sway": - case "scroll": - case "miracle": - if (data.num) - try { - I3.dispatch(`workspace number ${data.num}`); - } catch (_) {} - break; - } - } - - function findClosestWorkspaceIndex(localX, localY) { - if (workspaceRepeater.count === 0) - return -1; - - let closestIdx = -1; - let closestDist = Infinity; - - for (let i = 0; i < workspaceRepeater.count; i++) { - const item = workspaceRepeater.itemAt(i); - if (!item) - continue; - const center = item.mapToItem(root, item.width / 2, item.height / 2); - const dist = isVertical ? Math.abs(localY - center.y) : Math.abs(localX - center.x); - if (dist < closestDist) { - closestDist = dist; - closestIdx = i; - } - } - return closestIdx; - } - - function switchWorkspace(direction) { - if (useExtWorkspace) { - const realWorkspaces = getRealWorkspaces(); - if (realWorkspaces.length < 2) { - return; - } - - const currentIndex = realWorkspaces.findIndex(ws => (ws.id || ws.name) === root.currentWorkspace); - 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) { - return; - } - - const nextWorkspace = realWorkspaces[nextIndex]; - ExtWorkspaceService.activateWorkspace(nextWorkspace.id || nextWorkspace.name, nextWorkspace.groupID || ""); - } else if (CompositorService.isNiri) { - const realWorkspaces = getRealWorkspaces(); - if (realWorkspaces.length < 2) { - return; - } - - 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); - - if (nextIndex === validIndex) { - return; - } - - 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) { - return; - } - - const currentIndex = realWorkspaces.findIndex(ws => ws.id === root.currentWorkspace); - 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) { - return; - } - - Hyprland.dispatch(`workspace ${realWorkspaces[nextIndex].id}`); - } else if (CompositorService.isDwl) { - const realWorkspaces = getRealWorkspaces(); - if (realWorkspaces.length < 2) { - return; - } - - const currentIndex = realWorkspaces.findIndex(ws => ws.tag === root.currentWorkspace); - 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) { - return; - } - - DwlService.switchToTag(root.screenName, realWorkspaces[nextIndex].tag); - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - const realWorkspaces = getRealWorkspaces(); - if (realWorkspaces.length < 2) { - return; - } - - const currentIndex = realWorkspaces.findIndex(ws => ws.num === root.currentWorkspace); - 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) { - return; - } - - try { - I3.dispatch(`workspace number ${realWorkspaces[nextIndex].num}`); - } catch (_) {} - } - } - - 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 || CompositorService.isMiracle) - 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) { - isPlaceholder = modelData?.tag === -1; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - isPlaceholder = modelData?.num === -1; - } else { - isPlaceholder = modelData === -1; - } - - if (isPlaceholder) - return index + 1; - - let workspaceName = ""; - if (SettingsData.showWorkspaceName) { - workspaceName = modelData?.name ?? ""; - - if (workspaceName && workspaceName !== "") { - if (root.isVertical) { - workspaceName = workspaceName.charAt(0); - } - } else { - workspaceName = ""; - } - } - - 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 || CompositorService.isMiracle - readonly property bool hasWorkspaces: getRealWorkspaces().length > 0 - readonly property bool shouldShow: hasNativeWorkspaceSupport || (useExtWorkspace && hasWorkspaces) - - width: shouldShow ? (isVertical ? barThickness : visualWidth) : 0 - height: shouldShow ? (isVertical ? visualHeight : barThickness) : 0 - visible: shouldShow - - Item { - id: visualBackground - width: root.visualWidth - height: root.visualHeight - anchors.centerIn: parent - - Rectangle { - id: outline - anchors.centerIn: parent - width: { - const borderWidth = (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0; - return parent.width + borderWidth * 2; - } - height: { - const borderWidth = (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0; - return parent.height + borderWidth * 2; - } - radius: (barConfig?.noBackground ?? false) ? 0 : Theme.cornerRadius - color: "transparent" - border.width: { - if (barConfig?.widgetOutlineEnabled ?? false) { - return barConfig?.widgetOutlineThickness ?? 1; - } - return 0; - } - border.color: { - if (!(barConfig?.widgetOutlineEnabled ?? false)) { - return "transparent"; - } - const colorOption = barConfig?.widgetOutlineColor || "primary"; - const opacity = barConfig?.widgetOutlineOpacity ?? 1.0; - switch (colorOption) { - case "surfaceText": - return Theme.withAlpha(Theme.surfaceText, opacity); - case "secondary": - return Theme.withAlpha(Theme.secondary, opacity); - case "primary": - return Theme.withAlpha(Theme.primary, opacity); - default: - return Theme.withAlpha(Theme.primary, opacity); - } - } - } - - Rectangle { - id: background - anchors.fill: parent - radius: (barConfig?.noBackground ?? false) ? 0 : Theme.cornerRadius - color: { - if ((barConfig?.noBackground ?? false)) - return "transparent"; - const baseColor = Theme.widgetBaseBackgroundColor; - const transparency = (root.barConfig && root.barConfig.widgetTransparency !== undefined) ? root.barConfig.widgetTransparency : 1.0; - if (Theme.widgetBackgroundHasAlpha) { - return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * transparency); - } - return Theme.withAlpha(baseColor, transparency); - } - } - } - - MouseArea { - id: edgeMouseArea - z: -1 - x: -root._leftMargin - y: -root._topMargin - width: root.width + root._leftMargin + root._rightMargin - height: root.height + root._topMargin + root._bottomMargin - acceptedButtons: Qt.LeftButton | Qt.RightButton - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - - property real touchpadAccumulator: 0 - property real mouseAccumulator: 0 - property bool scrollInProgress: false - - Timer { - id: scrollCooldown - interval: 100 - onTriggered: parent.scrollInProgress = false - } - - onClicked: mouse => { - const rootPos = edgeMouseArea.mapToItem(root, mouse.x, mouse.y); - switch (mouse.button) { - case Qt.RightButton: - if (CompositorService.isNiri) { - NiriService.toggleOverview(); - } else if (CompositorService.isHyprland && root.hyprlandOverviewLoader?.item) { - root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen; - } - break; - case Qt.LeftButton: - const idx = root.findClosestWorkspaceIndex(rootPos.x, rootPos.y); - if (idx >= 0) - root.switchToWorkspaceByModelData(root.workspaceList[idx]); - break; - } - } - - onWheel: wheel => { - if (Math.abs(wheel.angleDelta.x) > Math.abs(wheel.angleDelta.y)) { - wheel.accepted = false; - return; - } - - if (scrollInProgress) - return; - - const delta = wheel.angleDelta.y; - const isTouchpad = wheel.pixelDelta && wheel.pixelDelta.y !== 0; - const reverse = SettingsData.reverseScrolling ? -1 : 1; - - if (isTouchpad) { - touchpadAccumulator += delta; - if (Math.abs(touchpadAccumulator) < 500) - return; - const direction = touchpadAccumulator * reverse < 0 ? 1 : -1; - root.switchWorkspace(direction); - scrollInProgress = true; - scrollCooldown.restart(); - touchpadAccumulator = 0; - return; - } - - mouseAccumulator += delta; - if (Math.abs(mouseAccumulator) < 120) - return; - const direction = mouseAccumulator * reverse < 0 ? 1 : -1; - root.switchWorkspace(direction); - scrollInProgress = true; - scrollCooldown.restart(); - mouseAccumulator = 0; - } - } - - property int dragSourceIndex: -1 - property int dragTargetIndex: -1 - property bool suppressShiftAnimation: false - - onWorkspaceListChanged: { - if (dragSourceIndex >= 0) { - dragSourceIndex = -1; - dragTargetIndex = -1; - suppressShiftAnimation = false; - } - } - - Flow { - id: workspaceRow - - x: isVertical ? visualBackground.x : (parent.width - implicitWidth) / 2 - y: isVertical ? (parent.height - implicitHeight) / 2 : visualBackground.y - spacing: Theme.spacingS - flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight - - Repeater { - id: workspaceRepeater - model: ScriptModel { - values: root.workspaceList - } - - Item { - id: delegateRoot - - property bool isDropTarget: root.dragTargetIndex === index - - z: dragHandler.dragging ? 1000 : 1 - - property real shiftOffset: { - if (root.dragSourceIndex < 0 || index === root.dragSourceIndex) - return 0; - const dragIdx = root.dragSourceIndex; - const dropIdx = root.dragTargetIndex; - if (dropIdx < 0) - return 0; - const shiftAmount = delegateRoot.width + Theme.spacingS; - if (dragIdx < dropIdx && index > dragIdx && index <= dropIdx) - return -shiftAmount; - if (dragIdx > dropIdx && index >= dropIdx && index < dragIdx) - return shiftAmount; - return 0; - } - - transform: Translate { - x: root.isVertical ? 0 : delegateRoot.shiftOffset - y: root.isVertical ? delegateRoot.shiftOffset : 0 - Behavior on x { - enabled: !root.suppressShiftAnimation - NumberAnimation { - duration: 150 - easing.type: Easing.OutCubic - } - } - Behavior on y { - enabled: !root.suppressShiftAnimation - NumberAnimation { - duration: 150 - easing.type: Easing.OutCubic - } - } - } - - 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) - return !!(modelData && root.dwlActiveTags.includes(modelData.tag)); - if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - return !!(modelData && modelData.num === root.currentWorkspace); - return modelData === root.currentWorkspace; - } - property bool isOccupied: { - if (CompositorService.isHyprland) - return Array.from(Hyprland.toplevels?.values || []).some(tl => tl.workspace?.id === modelData?.id); - if (CompositorService.isDwl) - return modelData.clients > 0; - if (CompositorService.isNiri) { - const workspace = NiriService.allWorkspaces.find(ws => ws.idx + 1 === modelData && ws.output === root.effectiveScreenName); - return workspace ? (NiriService.windows?.some(win => win.workspace_id === workspace.id) ?? false) : false; - } - return false; - } - 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) - return !!(modelData && modelData.tag === -1); - if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - return !!(modelData && modelData.num === -1); - return modelData === -1; - } - property bool isHovered: mouseArea.containsMouse - - property var loadedWorkspaceData: null - property bool loadedIsUrgent: false - property bool isUrgent: { - if (root.useExtWorkspace) - return modelData?.urgent ?? false; - if (CompositorService.isHyprland) - return modelData?.urgent ?? false; - if (CompositorService.isNiri) - return loadedIsUrgent; - if (CompositorService.isDwl) - return modelData?.state === 2; - if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - return loadedIsUrgent; - return false; - } - readonly property var loadedIconData: { - if (isPlaceholder) - return null; - const name = modelData?.name; - if (!name) - return null; - return SettingsData.getWorkspaceNameIcon(name); - } - readonly property bool loadedHasIcon: loadedIconData !== null - property var loadedIcons: [] - - readonly property int stableIconCount: { - if (!SettingsData.showWorkspaceApps || isPlaceholder) - return 0; - - let targetWorkspaceId; - if (root.useExtWorkspace) { - targetWorkspaceId = modelData?.id || modelData?.name; - } else if (CompositorService.isNiri) { - targetWorkspaceId = modelData?.id; - } else if (CompositorService.isHyprland) { - targetWorkspaceId = modelData?.id; - } else if (CompositorService.isDwl) { - targetWorkspaceId = modelData?.tag; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - targetWorkspaceId = modelData?.num; - } - if (targetWorkspaceId === undefined || targetWorkspaceId === null) - return 0; - - const wins = CompositorService.isNiri ? (NiriService.windows || []) : CompositorService.sortedToplevels; - const seen = {}; - let groupedCount = 0; - let totalCount = 0; - - for (let i = 0; i < wins.length; i++) { - const w = wins[i]; - if (!w) - continue; - - let winWs = null; - if (CompositorService.isNiri) { - winWs = w.workspace_id; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - winWs = w.workspace?.num; - } else if (CompositorService.isHyprland) { - const hyprlandToplevels = Array.from(Hyprland.toplevels?.values || []); - const hyprToplevel = hyprlandToplevels.find(ht => ht.wayland === w); - winWs = hyprToplevel?.workspace?.id; - } - - if (winWs !== targetWorkspaceId) - continue; - totalCount++; - - const appKey = w.app_id || w.appId || w.class || w.windowClass || "unknown"; - if (!seen[appKey]) { - seen[appKey] = true; - groupedCount++; - } - } - - return (SettingsData.groupWorkspaceApps && !isActive) ? groupedCount : totalCount; - } - - readonly property real baseWidth: root.isVertical ? (SettingsData.showWorkspaceApps ? Math.max(widgetHeight * 0.7, root.appIconSize + Theme.spacingXS * 2) : widgetHeight * 0.5) : (isActive ? Math.max(root.widgetHeight * 1.05, root.appIconSize * 1.6) : Math.max(root.widgetHeight * 0.7, root.appIconSize * 1.2)) - readonly property real baseHeight: root.isVertical ? (isActive ? Math.max(root.widgetHeight * 1.05, root.appIconSize * 1.6) : Math.max(root.widgetHeight * 0.7, root.appIconSize * 1.2)) : (SettingsData.showWorkspaceApps ? Math.max(widgetHeight * 0.7, root.appIconSize + Theme.spacingXS * 2) : widgetHeight * 0.5) - readonly property bool hasWorkspaceName: SettingsData.showWorkspaceName && modelData?.name && modelData.name !== "" - readonly property bool workspaceNamesEnabled: SettingsData.showWorkspaceName && (CompositorService.isNiri || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - readonly property real contentImplicitWidth: appIconsLoader.item?.contentWidth ?? 0 - readonly property real contentImplicitHeight: appIconsLoader.item?.contentHeight ?? 0 - - readonly property real iconsExtraWidth: { - if (!root.isVertical && SettingsData.showWorkspaceApps && stableIconCount > 0) { - const numIcons = Math.min(stableIconCount, SettingsData.maxWorkspaceIcons); - return numIcons * root.appIconSize + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0); - } - return 0; - } - readonly property real iconsExtraHeight: { - if (root.isVertical && SettingsData.showWorkspaceApps && stableIconCount > 0) { - const numIcons = Math.min(stableIconCount, SettingsData.maxWorkspaceIcons); - return numIcons * root.appIconSize + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0); - } - return 0; - } - - 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) { - case "s": - return Theme.surface; - case "sc": - return Theme.surfaceContainer; - case "sch": - return Theme.surfaceContainerHigh; - default: - return Theme.surfaceTextAlpha; - } - } - - readonly property color activeColor: { - switch (SettingsData.workspaceColorMode) { - case "s": - return Theme.surface; - case "sc": - return Theme.surfaceContainer; - case "sch": - return Theme.surfaceContainerHigh; - case "none": - return unfocusedColor; - default: - return Theme.primary; - } - } - - readonly property color occupiedColor: { - switch (SettingsData.workspaceOccupiedColorMode) { - case "sec": - return Theme.secondary; - case "s": - return Theme.surface; - case "sc": - return Theme.surfaceContainer; - case "sch": - return Theme.surfaceContainerHigh; - case "schh": - return Theme.surfaceContainerHighest; - default: - return unfocusedColor; - } - } - - readonly property color urgentColor: { - switch (SettingsData.workspaceUrgentColorMode) { - case "primary": - return Theme.primary; - case "secondary": - return Theme.secondary; - case "s": - return Theme.surface; - case "sc": - return Theme.surfaceContainer; - default: - return Theme.error; - } - } - - readonly property color focusedBorderColor: { - switch (SettingsData.workspaceFocusedBorderColor) { - case "surfaceText": - return Theme.surfaceText; - case "secondary": - return Theme.secondary; - default: - return Theme.primary; - } - } - - function getContrastingIconColor(bgColor) { - const luminance = 0.299 * bgColor.r + 0.587 * bgColor.g + 0.114 * bgColor.b; - return luminance > 0.4 ? Qt.rgba(0.15, 0.15, 0.15, 1) : Qt.rgba(0.8, 0.8, 0.8, 1); - } - - readonly property color quickshellIconActiveColor: getContrastingIconColor(activeColor) - readonly property color quickshellIconInactiveColor: getContrastingIconColor(unfocusedColor) - - Item { - id: dragHandler - anchors.fill: parent - property bool dragging: false - property point dragStartPos: Qt.point(0, 0) - property real dragAxisOffset: 0 - - Connections { - target: root - function onWorkspaceListChanged() { - if (dragHandler.dragging) { - dragHandler.dragging = false; - dragHandler.dragAxisOffset = 0; - mouseArea.mousePressed = false; - } - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: !isPlaceholder - cursorShape: isPlaceholder ? Qt.ArrowCursor : (dragHandler.dragging ? Qt.ClosedHandCursor : Qt.PointingHandCursor) - enabled: !isPlaceholder - acceptedButtons: Qt.LeftButton | Qt.RightButton - - property bool mousePressed: false - - onPressed: mouse => { - if (mouse.button === Qt.LeftButton && CompositorService.isNiri && SettingsData.workspaceDragReorder && !isPlaceholder) { - mousePressed = true; - dragHandler.dragStartPos = Qt.point(mouse.x, mouse.y); - } - } - - onPositionChanged: mouse => { - if (!mousePressed || !CompositorService.isNiri || !SettingsData.workspaceDragReorder || isPlaceholder) - return; - - if (!dragHandler.dragging) { - const distance = root.isVertical ? Math.abs(mouse.y - dragHandler.dragStartPos.y) : Math.abs(mouse.x - dragHandler.dragStartPos.x); - if (distance > 5) { - dragHandler.dragging = true; - root.dragSourceIndex = index; - root.dragTargetIndex = index; - } - } - - if (!dragHandler.dragging) - return; - - const rawAxisOffset = root.isVertical ? (mouse.y - dragHandler.dragStartPos.y) : (mouse.x - dragHandler.dragStartPos.x); - - const itemSize = (root.isVertical ? delegateRoot.height : delegateRoot.width) + Theme.spacingS; - const maxOffsetPositive = (root.workspaceList.length - 1 - index) * itemSize; - const maxOffsetNegative = -index * itemSize; - const axisOffset = Math.max(maxOffsetNegative, Math.min(maxOffsetPositive, rawAxisOffset)); - dragHandler.dragAxisOffset = axisOffset; - - const slotOffset = Math.round(axisOffset / itemSize); - const newTargetIndex = Math.max(0, Math.min(root.workspaceList.length - 1, index + slotOffset)); - - if (newTargetIndex !== root.dragTargetIndex) { - root.dragTargetIndex = newTargetIndex; - } - } - - onReleased: mouse => { - const wasDragging = dragHandler.dragging; - const didReorder = wasDragging && root.dragTargetIndex >= 0 && root.dragTargetIndex !== root.dragSourceIndex; - - if (didReorder) { - const sourceWs = root.workspaceList[root.dragSourceIndex]; - const targetWs = root.workspaceList[root.dragTargetIndex]; - - if (sourceWs && targetWs && sourceWs.idx !== undefined && targetWs.idx !== undefined) { - root.suppressShiftAnimation = true; - NiriService.moveWorkspaceToIndex(sourceWs.idx, targetWs.idx); - Qt.callLater(() => root.suppressShiftAnimation = false); - } - } - - mousePressed = false; - dragHandler.dragging = false; - dragHandler.dragAxisOffset = 0; - root.dragSourceIndex = -1; - root.dragTargetIndex = -1; - - if (wasDragging || isPlaceholder) - return; - - if (mouse.button === Qt.LeftButton) { - if (root.useExtWorkspace && (modelData?.id || modelData?.name)) { - ExtWorkspaceService.activateWorkspace(modelData.id || modelData.name, modelData.groupID || ""); - } else if (CompositorService.isNiri) { - if (modelData && modelData.idx !== undefined) { - NiriService.switchToWorkspace(modelData.idx); - } - } else if (CompositorService.isHyprland && modelData?.id) { - Hyprland.dispatch(`workspace ${modelData.id}`); - } else if (CompositorService.isDwl && modelData?.tag !== undefined) { - DwlService.switchToTag(root.screenName, modelData.tag); - } else if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && modelData?.num) { - try { - I3.dispatch(`workspace number ${modelData.num}`); - } catch (_) {} - } - } else if (mouse.button === Qt.RightButton) { - if (CompositorService.isNiri) { - NiriService.toggleOverview(); - } else if (CompositorService.isHyprland && root.hyprlandOverviewLoader?.item) { - root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen; - } else if (CompositorService.isDwl && modelData?.tag !== undefined) { - DwlService.toggleTag(root.screenName, modelData.tag); - } - } - } - } - - Timer { - id: dataUpdateTimer - interval: 50 - onTriggered: { - if (isPlaceholder) { - delegateRoot.loadedWorkspaceData = null; - delegateRoot.loadedIcons = []; - delegateRoot.loadedIsUrgent = false; - return; - } - - var wsData = null; - if (root.useExtWorkspace) { - wsData = modelData; - } else if (CompositorService.isNiri) { - wsData = modelData || null; - } else if (CompositorService.isHyprland) { - wsData = modelData; - } else if (CompositorService.isDwl) { - wsData = modelData; - } else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - wsData = modelData; - } - delegateRoot.loadedWorkspaceData = wsData; - if (CompositorService.isNiri) { - const workspaceId = wsData?.id; - delegateRoot.loadedIsUrgent = workspaceId ? NiriService.windows.some(w => w.workspace_id === workspaceId && w.is_urgent) : false; - } else { - delegateRoot.loadedIsUrgent = wsData?.urgent ?? false; - } - - if (SettingsData.showWorkspaceApps) { - if (CompositorService.isDwl || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) { - 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)); - } - } else { - delegateRoot.loadedIcons = []; - } - } - } - - function updateAllData() { - dataUpdateTimer.restart(); - } - - width: root.isVertical ? root.widgetHeight : visualWidth - height: root.isVertical ? visualHeight : root.widgetHeight - - Behavior on width { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on height { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Rectangle { - id: focusedBorderRing - x: root.isVertical ? (root.widgetHeight - width) / 2 : (parent.width - width) / 2 - y: root.isVertical ? (parent.height - height) / 2 : (root.widgetHeight - height) / 2 - width: { - const borderWidth = (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? SettingsData.workspaceFocusedBorderThickness : 0; - return delegateRoot.visualWidth + borderWidth * 2; - } - height: { - const borderWidth = (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? SettingsData.workspaceFocusedBorderThickness : 0; - return delegateRoot.visualHeight + borderWidth * 2; - } - radius: Theme.cornerRadius - color: "transparent" - border.width: (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? SettingsData.workspaceFocusedBorderThickness : 0 - border.color: (SettingsData.workspaceFocusedBorderEnabled && isActive && !isPlaceholder) ? focusedBorderColor : "transparent" - - Behavior on width { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on height { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on border.width { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on border.color { - ColorAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - } - - Rectangle { - id: visualContent - width: delegateRoot.visualWidth - height: delegateRoot.visualHeight - x: root.isVertical ? (root.widgetHeight - width) / 2 : (parent.width - width) / 2 - y: root.isVertical ? (parent.height - height) / 2 : (root.widgetHeight - height) / 2 - radius: Theme.cornerRadius - color: isActive ? activeColor : isUrgent ? urgentColor : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.withAlpha(unfocusedColor, 0.7) : isOccupied ? occupiedColor : unfocusedColor - opacity: dragHandler.dragging ? 0.8 : 1.0 - - border.width: dragHandler.dragging ? 2 : (isUrgent ? 2 : (isDropTarget ? 2 : 0)) - border.color: dragHandler.dragging ? Theme.primary : (isUrgent ? urgentColor : (isDropTarget ? Theme.primary : "transparent")) - - transform: Translate { - x: root.isVertical ? 0 : (dragHandler.dragging ? dragHandler.dragAxisOffset : 0) - y: root.isVertical ? (dragHandler.dragging ? dragHandler.dragAxisOffset : 0) : 0 - } - - Behavior on opacity { - NumberAnimation { - duration: Theme.shortDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on width { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on height { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on color { - ColorAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on border.width { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on border.color { - ColorAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Loader { - id: appIconsLoader - anchors.fill: parent - 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 - sourceComponent: root.isVertical ? columnLayout : rowLayout - } - - Component { - id: rowLayout - Row { - spacing: 4 - visible: loadedIcons.length > 0 || SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName || loadedHasIcon - - Item { - visible: loadedHasIcon && loadedIconData?.type === "icon" - width: wsIcon.width - height: root.appIconSize - - DankIcon { - id: wsIcon - anchors.verticalCenter: parent.verticalCenter - name: loadedIconData?.value ?? "" - size: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - weight: (isActive && !isPlaceholder) ? 500 : 400 - } - } - - Item { - visible: loadedHasIcon && loadedIconData?.type === "text" - width: wsText.implicitWidth - height: root.appIconSize - - StyledText { - id: wsText - anchors.verticalCenter: parent.verticalCenter - text: loadedIconData?.value ?? "" - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal - } - } - - Item { - visible: ((SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon) || (loadedHasIcon && SettingsData.showWorkspaceName && hasWorkspaceName) - width: wsIndexText.implicitWidth - height: root.appIconSize - - StyledText { - id: wsIndexText - anchors.verticalCenter: parent.verticalCenter - text: loadedHasIcon ? (modelData?.name ?? "") : root.getWorkspaceIndex(modelData, index) - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal - } - } - - Repeater { - model: ScriptModel { - values: loadedIcons.slice(0, SettingsData.maxWorkspaceIcons) - } - delegate: Item { - width: root.appIconSize - height: root.appIconSize - readonly property bool appHighlightActive: SettingsData.workspaceActiveAppHighlightEnabled && modelData.active - readonly property color appBorderColor: appHighlightActive ? focusedBorderColor : Theme.primarySelected - readonly property color appGlyphColor: appHighlightActive ? focusedBorderColor : Theme.primary - readonly property real appOpacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6 - - IconImage { - id: rowAppIcon - anchors.fill: parent - source: modelData.icon || "" - opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: !modelData.isQuickshell && !modelData.isSteamApp && status === Image.Ready - } - - Rectangle { - anchors.fill: parent - visible: !modelData.isQuickshell && !modelData.isSteamApp && rowAppIcon.status !== Image.Ready - color: Theme.surfaceContainer - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: appBorderColor - opacity: appOpacity - - StyledText { - anchors.centerIn: parent - text: (modelData.fallbackText || "?").charAt(0).toUpperCase() - font.pixelSize: parent.width * 0.45 - color: appGlyphColor - font.weight: Font.Bold - } - } - - Rectangle { - anchors.fill: parent - visible: !modelData.isQuickshell && modelData.isSteamApp && rowSteamIcon.status !== Image.Ready - color: Theme.surfaceContainer - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: appBorderColor - opacity: appOpacity - - DankIcon { - anchors.centerIn: parent - size: parent.width * 0.7 - name: "sports_esports" - color: appGlyphColor - } - } - - IconImage { - anchors.fill: parent - source: modelData.icon - opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isQuickshell - layer.enabled: true - layer.effect: MultiEffect { - saturation: 0 - colorization: 1 - colorizationColor: appHighlightActive ? focusedBorderColor : (isActive ? quickshellIconActiveColor : quickshellIconInactiveColor) - } - } - - IconImage { - id: rowSteamIcon - anchors.fill: parent - source: modelData.icon - opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isSteamApp && modelData.icon - } - - DankIcon { - anchors.centerIn: parent - size: root.appIconSize - name: "sports_esports" - color: appHighlightActive ? focusedBorderColor : Theme.widgetTextColor - opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isSteamApp && !modelData.icon - } - - Rectangle { - anchors.fill: parent - visible: (rowAppIcon.visible || rowSteamIcon.visible || modelData.isQuickshell) && appHighlightActive - color: "transparent" - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: focusedBorderColor - z: 1 - } - - MouseArea { - id: rowAppMouseArea - anchors.fill: parent - enabled: isActive - cursorShape: Qt.PointingHandCursor - onClicked: { - const winId = modelData.windowId; - if (!winId) - return; - if (CompositorService.isHyprland) { - Hyprland.dispatch(`focuswindow address:${winId}`); - } else if (CompositorService.isNiri) { - NiriService.focusWindow(winId); - } - } - } - - Rectangle { - visible: modelData.count > 1 && !isActive - width: root.appIconSize * 0.67 - height: root.appIconSize * 0.67 - radius: root.appIconSize * 0.33 - color: "black" - border.color: "white" - border.width: 1 - anchors.right: parent.right - anchors.bottom: parent.bottom - z: 2 - - Text { - anchors.centerIn: parent - text: modelData.count - font.pixelSize: root.appIconSize * 0.44 - color: "white" - } - } - } - } - } - } - - Component { - id: columnLayout - Column { - spacing: 4 - visible: loadedIcons.length > 0 || SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName || loadedHasIcon - - DankIcon { - visible: loadedHasIcon && loadedIconData?.type === "icon" - anchors.horizontalCenter: parent.horizontalCenter - name: loadedIconData?.value ?? "" - size: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - weight: (isActive && !isPlaceholder) ? 500 : 400 - } - - StyledText { - visible: loadedHasIcon && loadedIconData?.type === "text" - anchors.horizontalCenter: parent.horizontalCenter - text: loadedIconData?.value ?? "" - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal - } - - StyledText { - visible: ((SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon) || (loadedHasIcon && SettingsData.showWorkspaceName && hasWorkspaceName) - anchors.horizontalCenter: parent.horizontalCenter - text: loadedHasIcon ? (root.isVertical ? (modelData?.name ?? "").charAt(0) : (modelData?.name ?? "")) : root.getWorkspaceIndex(modelData, index) - color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium - font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale, barConfig?.maximizeWidgetText) - font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal - } - - Repeater { - model: ScriptModel { - values: loadedIcons.slice(0, SettingsData.maxWorkspaceIcons) - } - delegate: Item { - width: root.appIconSize - height: root.appIconSize - readonly property bool appHighlightActive: SettingsData.workspaceActiveAppHighlightEnabled && modelData.active - readonly property color appBorderColor: appHighlightActive ? focusedBorderColor : Theme.primarySelected - readonly property color appGlyphColor: appHighlightActive ? focusedBorderColor : Theme.primary - readonly property real appOpacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6 - - IconImage { - id: colAppIcon - anchors.fill: parent - source: modelData.icon || "" - opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: !modelData.isQuickshell && !modelData.isSteamApp && status === Image.Ready - } - - Rectangle { - anchors.fill: parent - visible: !modelData.isQuickshell && !modelData.isSteamApp && colAppIcon.status !== Image.Ready - color: Theme.surfaceContainer - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: appBorderColor - opacity: appOpacity - - StyledText { - anchors.centerIn: parent - text: (modelData.fallbackText || "?").charAt(0).toUpperCase() - font.pixelSize: parent.width * 0.45 - color: appGlyphColor - font.weight: Font.Bold - } - } - - Rectangle { - anchors.fill: parent - visible: !modelData.isQuickshell && modelData.isSteamApp && colSteamIcon.status !== Image.Ready - color: Theme.surfaceContainer - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: appBorderColor - opacity: appOpacity - - DankIcon { - anchors.centerIn: parent - size: parent.width * 0.7 - name: "sports_esports" - color: appGlyphColor - } - } - - IconImage { - anchors.fill: parent - source: modelData.icon - opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isQuickshell - layer.enabled: true - layer.effect: MultiEffect { - saturation: 0 - colorization: 1 - colorizationColor: appHighlightActive ? focusedBorderColor : (isActive ? quickshellIconActiveColor : quickshellIconInactiveColor) - } - } - - IconImage { - id: colSteamIcon - anchors.fill: parent - source: modelData.icon - opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isSteamApp && modelData.icon - } - - DankIcon { - anchors.centerIn: parent - size: root.appIconSize - name: "sports_esports" - color: appHighlightActive ? focusedBorderColor : Theme.widgetTextColor - opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6 - visible: modelData.isSteamApp && !modelData.icon - } - - Rectangle { - anchors.fill: parent - visible: (colAppIcon.visible || colSteamIcon.visible || modelData.isQuickshell) && appHighlightActive - color: "transparent" - radius: Theme.cornerRadius * (root.appIconSize / 40) - border.width: 1 - border.color: focusedBorderColor - z: 1 - } - - MouseArea { - id: colAppMouseArea - anchors.fill: parent - enabled: isActive - cursorShape: Qt.PointingHandCursor - onClicked: { - const winId = modelData.windowId; - if (!winId) - return; - if (CompositorService.isHyprland) { - Hyprland.dispatch(`focuswindow address:${winId}`); - } else if (CompositorService.isNiri) { - NiriService.focusWindow(winId); - } - } - } - - Rectangle { - visible: modelData.count > 1 && !isActive - width: root.appIconSize * 0.67 - height: root.appIconSize * 0.67 - radius: root.appIconSize * 0.33 - color: "black" - border.color: "white" - border.width: 1 - anchors.right: parent.right - anchors.bottom: parent.bottom - z: 2 - - Text { - anchors.centerIn: parent - text: modelData.count - font.pixelSize: root.appIconSize * 0.44 - color: "white" - } - } - } - } - } - } - } - } - } - - Component.onCompleted: updateAllData() - - Connections { - target: CompositorService - function onSortedToplevelsChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: NiriService - enabled: CompositorService.isNiri - function onAllWorkspacesChanged() { - delegateRoot.updateAllData(); - } - function onWindowUrgentChanged() { - delegateRoot.updateAllData(); - } - function onWindowsChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: SettingsData - function onShowWorkspaceAppsChanged() { - delegateRoot.updateAllData(); - } - function onWorkspaceNameIconsChanged() { - delegateRoot.updateAllData(); - } - function onAppIdSubstitutionsChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: DwlService - enabled: CompositorService.isDwl - function onStateChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: Hyprland.workspaces - enabled: CompositorService.isHyprland - function onValuesChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: I3.workspaces - enabled: (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) - function onValuesChanged() { - delegateRoot.updateAllData(); - } - } - Connections { - target: ExtWorkspaceService - enabled: root.useExtWorkspace - function onStateChanged() { - delegateRoot.updateAllData(); - } - } - } - } - } - - Component.onCompleted: { - if (useExtWorkspace && !DMSService.activeSubscriptions.includes("extworkspace")) { - DMSService.addSubscription("extworkspace"); - } - _updateBlurRegistration(); - } - - property bool _blurRegistered: false - readonly property bool _shouldBlur: BlurService.enabled && blurBarWindow && blurBarWindow.registerBlurWidget && !(barConfig?.noBackground ?? false) && root.visible && root.width > 0 - - on_ShouldBlurChanged: _updateBlurRegistration() - - function _updateBlurRegistration() { - if (_shouldBlur && !_blurRegistered) { - blurBarWindow.registerBlurWidget(visualBackground); - _blurRegistered = true; - } else if (!_shouldBlur && _blurRegistered) { - if (blurBarWindow && blurBarWindow.unregisterBlurWidget) - blurBarWindow.unregisterBlurWidget(visualBackground); - _blurRegistered = false; - } - } - - Component.onDestruction: { - if (_blurRegistered && blurBarWindow && blurBarWindow.unregisterBlurWidget) - blurBarWindow.unregisterBlurWidget(visualBackground); - } -} |