pragma Singleton import QtQuick import Quickshell import Quickshell.Hyprland import Quickshell.Wayland import Quickshell.Io import qs.Common Singleton { id: root readonly property string hyprlandSignature: Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE") readonly property var focusedMon: Hyprland.focusedMonitor property var hasFullscreen: false property var isScreencasting: false property var sortedTopLevels: { if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values) { return []; } const topLevels = Array.from(Hyprland.toplevels.values); const sortedHyprland = topLevels.sort((a, b) => { if (a.monitor && b.monitor) { const monitorCompare = a.monitor.name.localeCompare(b.monitor.name); if (monitorCompare !== 0) { return monitorCompare; } } if (a.workspace && b.workspace) { const workspaceCompare = a.workspace.id - b.workspace.id; if (workspaceCompare !== 0) { return workspaceCompare; } } if (a.lastIpcObject && b.lastIpcObject && a.lastIpcObject.at && b.lastIpcObject.at) { const aX = a.lastIpcObject.at[0]; const bX = b.lastIpcObject.at[0]; const aY = a.lastIpcObject.at[1]; const bY = b.lastIpcObject.at[1]; const xCompare = aX - bX; if (Math.abs(xCompare) > 10) { return xCompare; } return aY - bY; } if (a.lastIpcObject && !b.lastIpcObject) { return -1; } if (!a.lastIpcObject && b.lastIpcObject) { return 1; } if (a.title && b.title) { return a.title.localeCompare(b.title); } return 0; }); return sortedHyprland.filter(tl => tl.wayland !== null); } property var topLevelWorkspaces: { return sortedTopLevels.map(topLevel => topLevel.workspace); } property ListModel sortedDesktopApplicationsModel: ListModel {} onSortedTopLevelsChanged: updateSortedDesktopApplications() function updateSortedDesktopApplications() { sortedDesktopApplicationsModel.clear(); for (const topLevel of sortedTopLevels) { const entry = DesktopEntries.heuristicLookup(topLevel.wayland.appId); sortedDesktopApplicationsModel.append({ topLevel: topLevel, desktopEntry: entry }); } } function workspaceApps(workspaceIndexAlign) { const list = [] const model = sortedDesktopApplicationsModel for (let i = 0; i < model.count; i++) { const item = model.get(i) if (item.topLevel.workspace.id === workspaceIndexAlign) list.push(item.desktopEntry) } return list } property var sortedDesktopApplications: { const sortedWayland = sortedTopLevels.map(topLevel => topLevel.wayland).filter(wayland => wayland !== null); const desktopEntries = sortedWayland.map(topLevel => { return DesktopEntries.heuristicLookup(topLevel.appId); }); const workspace = sortedTopLevels.map(topLevel => { return topLevel.workspace.id; }); const workspaceDesktopEntries = new Map(); for (let i = 0; i < workspace.length; i++) { const key = workspace[i]; const value = desktopEntries[i]; if (workspaceDesktopEntries.has(key)) { workspaceDesktopEntries.get(key).push(value); } else { workspaceDesktopEntries.set(key, [value]); } } return workspaceDesktopEntries; } Socket { path: `${Quickshell.env("XDG_RUNTIME_DIR")}/hypr/${Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")}/.socket2.sock` connected: true parser: SplitParser { property var fullscreenRegex: new RegExp("fullscreen>>.") property var screencastRegex: new RegExp("screencast>>.*") onRead: msg => { let match = fullscreenRegex.exec(msg); if (match != null) { if (msg.split(">>")[1] === "1") { root.hasFullscreen = true; } else { root.hasFullscreen = false; } } match = screencastRegex.exec(msg); if (match != null) { if (msg.split(">>")[1].split(',')[0] === "1") { root.isScreencasting = true; } else { root.isScreencasting = false; } } } } } }