From b264ae9888575df22e15d89a361845f84202106a Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Fri, 27 Jun 2025 21:37:15 +1000 Subject: internal: use hyprlandtoplevel --- modules/areapicker/Picker.qml | 2 +- modules/bar/Bar.qml | 2 +- modules/bar/components/ActiveWindow.qml | 4 +- modules/bar/components/workspaces/Workspace.qml | 6 +- modules/bar/popouts/ActiveWindow.qml | 10 +-- modules/windowinfo/Buttons.qml | 18 ++--- modules/windowinfo/Details.qml | 28 +++---- modules/windowinfo/Preview.qml | 10 +-- services/Hyprland.qml | 103 +++--------------------- 9 files changed, 53 insertions(+), 130 deletions(-) diff --git a/modules/areapicker/Picker.qml b/modules/areapicker/Picker.qml index 31aec02..f3a7eb0 100644 --- a/modules/areapicker/Picker.qml +++ b/modules/areapicker/Picker.qml @@ -36,7 +36,7 @@ MouseArea { property real sw: Math.abs(sx - ex) property real sh: Math.abs(sy - ey) - property list clients: Hyprland.clients.filter(c => c.workspace.id === Hyprland.activeWsId) + property list clients: Hyprland.toplevels.values.filter(c => c.workspace.id === Hyprland.activeWsId) function checkClientRects(x: real, y: real): void { for (const c of clients) { diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index 1d0db8d..9f5509b 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -101,7 +101,7 @@ Item { anchors.rightMargin: -Config.border.thickness onWheel: event => { - const activeWs = Hyprland.activeClient?.workspace?.name; + const activeWs = Hyprland.activeToplevel?.workspace?.name; if (activeWs?.startsWith("special:")) Hyprland.dispatch(`togglespecialworkspace ${activeWs.slice(8)}`); else if (event.angleDelta.y < 0 || Hyprland.activeWsId > 1) diff --git a/modules/bar/components/ActiveWindow.qml b/modules/bar/components/ActiveWindow.qml index f6204ae..fc0c303 100644 --- a/modules/bar/components/ActiveWindow.qml +++ b/modules/bar/components/ActiveWindow.qml @@ -60,7 +60,7 @@ Item { id: icon animate: true - text: Icons.getAppCategoryIcon(Hyprland.activeClient?.wmClass, "desktop_windows") + text: Icons.getAppCategoryIcon(Hyprland.activeToplevel?.lastIpcObject.class, "desktop_windows") color: root.colour anchors.horizontalCenter: parent.horizontalCenter @@ -77,7 +77,7 @@ Item { TextMetrics { id: metrics - text: Hyprland.activeClient?.title ?? qsTr("Desktop") + text: Hyprland.activeToplevel?.title ?? qsTr("Desktop") font.pointSize: Appearance.font.size.smaller font.family: Appearance.font.family.mono elide: Qt.ElideRight diff --git a/modules/bar/components/workspaces/Workspace.qml b/modules/bar/components/workspaces/Workspace.qml index dba0f86..0e0fcc9 100644 --- a/modules/bar/components/workspaces/Workspace.qml +++ b/modules/bar/components/workspaces/Workspace.qml @@ -76,14 +76,14 @@ Item { Repeater { model: ScriptModel { - values: Hyprland.clients.filter(c => c.workspace?.id === root.ws) + values: Hyprland.toplevels.values.filter(c => c.workspace?.id === root.ws) } MaterialIcon { - required property Hyprland.Client modelData + required property var modelData grade: 0 - text: Icons.getAppCategoryIcon(modelData.wmClass, "terminal") + text: Icons.getAppCategoryIcon(modelData.lastIpcObject.class, "terminal") color: Colours.palette.m3onSurfaceVariant } } diff --git a/modules/bar/popouts/ActiveWindow.qml b/modules/bar/popouts/ActiveWindow.qml index bbb2d7a..9575dde 100644 --- a/modules/bar/popouts/ActiveWindow.qml +++ b/modules/bar/popouts/ActiveWindow.qml @@ -12,7 +12,7 @@ Item { required property Item wrapper - implicitWidth: Hyprland.activeClient ? child.implicitWidth : -Appearance.padding.large * 2 + implicitWidth: Hyprland.activeToplevel ? child.implicitWidth : -Appearance.padding.large * 2 implicitHeight: child.implicitHeight Column { @@ -33,7 +33,7 @@ Item { Layout.alignment: Qt.AlignVCenter implicitSize: details.implicitHeight - source: Icons.getAppIcon(Hyprland.activeClient?.wmClass ?? "", "image-missing") + source: Icons.getAppIcon(Hyprland.activeToplevel?.lastIpcObject.class ?? "", "image-missing") } ColumnLayout { @@ -44,14 +44,14 @@ Item { StyledText { Layout.fillWidth: true - text: Hyprland.activeClient?.title ?? "" + text: Hyprland.activeToplevel?.title ?? "" font.pointSize: Appearance.font.size.normal elide: Text.ElideRight } StyledText { Layout.fillWidth: true - text: Hyprland.activeClient?.wmClass ?? "" + text: Hyprland.activeToplevel?.lastIpcObject.class ?? "" color: Colours.palette.m3onSurfaceVariant elide: Text.ElideRight } @@ -91,7 +91,7 @@ Item { ScreencopyView { id: preview - captureSource: Hyprland.activeClient ? ToplevelManager.activeToplevel : null + captureSource: Hyprland.activeToplevel?.wayland ?? null live: visible constraintSize.width: Config.bar.sizes.windowPreviewSize diff --git a/modules/windowinfo/Buttons.qml b/modules/windowinfo/Buttons.qml index f298073..c790a35 100644 --- a/modules/windowinfo/Buttons.qml +++ b/modules/windowinfo/Buttons.qml @@ -78,7 +78,7 @@ ColumnLayout { Button { required property int index readonly property int wsId: Math.floor((Hyprland.activeWsId - 1) / 10) * 10 + index + 1 - readonly property bool isCurrent: Hyprland.activeClient.workspace.id === wsId + readonly property bool isCurrent: Hyprland.activeToplevel?.workspace.id === wsId color: isCurrent ? Colours.palette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer onColor: isCurrent ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer @@ -86,7 +86,7 @@ ColumnLayout { disabled: isCurrent function onClicked(): void { - Hyprland.dispatch(`movetoworkspace ${wsId},address:${Hyprland.activeClient?.address}`); + Hyprland.dispatch(`movetoworkspace ${wsId},address:0x${Hyprland.activeToplevel?.address}`); } } } @@ -107,20 +107,20 @@ ColumnLayout { Layout.rightMargin: Appearance.padding.large Layout.bottomMargin: Appearance.padding.large - spacing: Hyprland.activeClient?.floating ? Appearance.spacing.normal : Appearance.spacing.small + spacing: Hyprland.activeToplevel?.lastIpcObject.floating ? Appearance.spacing.normal : Appearance.spacing.small Button { color: Colours.palette.m3secondaryContainer onColor: Colours.palette.m3onSecondaryContainer - text: Hyprland.activeClient?.floating ? qsTr("Tile") : qsTr("Float") + text: Hyprland.activeToplevel?.lastIpcObject.floating ? qsTr("Tile") : qsTr("Float") function onClicked(): void { - Hyprland.dispatch(`togglefloating address:${Hyprland.activeClient?.address}`); + Hyprland.dispatch(`togglefloating address:0x${Hyprland.activeToplevel?.address}`); } } Loader { - active: Hyprland.activeClient?.floating + active: Hyprland.activeToplevel?.lastIpcObject.floating asynchronous: true Layout.fillWidth: active Layout.leftMargin: active ? 0 : -parent.spacing @@ -129,10 +129,10 @@ ColumnLayout { sourceComponent: Button { color: Colours.palette.m3secondaryContainer onColor: Colours.palette.m3onSecondaryContainer - text: Hyprland.activeClient?.lastIpcObject.pinned ? qsTr("Unpin") : qsTr("Pin") + text: Hyprland.activeToplevel?.lastIpcObject.pinned ? qsTr("Unpin") : qsTr("Pin") function onClicked(): void { - Hyprland.dispatch(`pin address:${Hyprland.activeClient?.address}`); + Hyprland.dispatch(`pin address:0x${Hyprland.activeToplevel?.address}`); } } } @@ -143,7 +143,7 @@ ColumnLayout { text: qsTr("Kill") function onClicked(): void { - Hyprland.dispatch(`movetoworkspace ${wsId},address:${Hyprland.activeClient?.address}`); + Hyprland.dispatch(`movetoworkspace ${wsId},address:0x${Hyprland.activeToplevel?.address}`); } } } diff --git a/modules/windowinfo/Details.qml b/modules/windowinfo/Details.qml index da25f61..2d60352 100644 --- a/modules/windowinfo/Details.qml +++ b/modules/windowinfo/Details.qml @@ -14,7 +14,7 @@ ColumnLayout { Label { Layout.topMargin: Appearance.padding.large * 2 - text: Hyprland.activeClient?.title ?? qsTr("No active client") + text: Hyprland.activeToplevel?.title ?? qsTr("No active client") wrapMode: Text.WrapAtWordBoundaryOrAnywhere font.pointSize: Appearance.font.size.large @@ -22,7 +22,7 @@ ColumnLayout { } Label { - text: Hyprland.activeClient?.wmClass ?? qsTr("No active client") + text: Hyprland.activeToplevel?.lastIpcObject.class ?? qsTr("No active client") color: Colours.palette.m3tertiary font.pointSize: Appearance.font.size.larger @@ -41,31 +41,31 @@ ColumnLayout { Detail { icon: "location_on" - text: qsTr("Address: %1").arg(Hyprland.activeClient?.address ?? "unknown") + text: qsTr("Address: %1").arg(`0x${Hyprland.activeToplevel?.address}` ?? "unknown") color: Colours.palette.m3primary } Detail { icon: "location_searching" - text: qsTr("Position: %1, %2").arg(Hyprland.activeClient?.x ?? -1).arg(Hyprland.activeClient?.y ?? -1) + text: qsTr("Position: %1, %2").arg(Hyprland.activeToplevel?.lastIpcObject.at[0] ?? -1).arg(Hyprland.activeToplevel?.lastIpcObject.at[1] ?? -1) } Detail { icon: "resize" - text: qsTr("Size: %1 x %2").arg(Hyprland.activeClient?.width ?? -1).arg(Hyprland.activeClient?.height ?? -1) + text: qsTr("Size: %1 x %2").arg(Hyprland.activeToplevel?.lastIpcObject.size[0] ?? -1).arg(Hyprland.activeToplevel?.lastIpcObject.size[1] ?? -1) color: Colours.palette.m3tertiary } Detail { icon: "workspaces" - text: qsTr("Workspace: %1 (%2)").arg(Hyprland.activeClient?.workspace.name ?? -1).arg(Hyprland.activeClient?.workspace.id ?? -1) + text: qsTr("Workspace: %1 (%2)").arg(Hyprland.activeToplevel?.workspace.name ?? -1).arg(Hyprland.activeToplevel?.workspace.id ?? -1) color: Colours.palette.m3secondary } Detail { icon: "desktop_windows" text: { - const mon = Hyprland.activeClient?.monitor; + const mon = Hyprland.activeToplevel?.monitor; if (mon) return qsTr("Monitor: %1 (%2) at %3, %4").arg(mon.name).arg(mon.id).arg(mon.x).arg(mon.y); return qsTr("Monitor: unknown"); @@ -74,42 +74,42 @@ ColumnLayout { Detail { icon: "page_header" - text: qsTr("Initial title: %1").arg(Hyprland.activeClient?.initialTitle ?? "unknown") + text: qsTr("Initial title: %1").arg(Hyprland.activeToplevel?.lastIpcObject.initialTitle ?? "unknown") color: Colours.palette.m3tertiary } Detail { icon: "category" - text: qsTr("Initial class: %1").arg(Hyprland.activeClient?.initialClass ?? "unknown") + text: qsTr("Initial class: %1").arg(Hyprland.activeToplevel?.lastIpcObject.initialClass ?? "unknown") } Detail { icon: "account_tree" - text: qsTr("Process id: %1").arg(Hyprland.activeClient?.pid ?? -1) + text: qsTr("Process id: %1").arg(Hyprland.activeToplevel?.lastIpcObject.pid ?? -1) color: Colours.palette.m3primary } Detail { icon: "picture_in_picture_center" - text: qsTr("Floating: %1").arg(Hyprland.activeClient?.floating ? "yes" : "no") + text: qsTr("Floating: %1").arg(Hyprland.activeToplevel?.lastIpcObject.floating ? "yes" : "no") color: Colours.palette.m3secondary } Detail { icon: "gradient" - text: qsTr("Xwayland: %1").arg(Hyprland.activeClient?.lastIpcObject.xwayland ? "yes" : "no") + text: qsTr("Xwayland: %1").arg(Hyprland.activeToplevel?.lastIpcObject.xwayland ? "yes" : "no") } Detail { icon: "keep" - text: qsTr("Pinned: %1").arg(Hyprland.activeClient?.lastIpcObject.pinned ? "yes" : "no") + text: qsTr("Pinned: %1").arg(Hyprland.activeToplevel?.lastIpcObject.pinned ? "yes" : "no") color: Colours.palette.m3secondary } Detail { icon: "fullscreen" text: { - const fs = Hyprland.activeClient?.fullscreen; + const fs = Hyprland.activeToplevel?.lastIpcObject.fullscreen; if (fs) return qsTr("Fullscreen state: %1").arg(fs == 0 ? "off" : fs == 1 ? "maximised" : "on"); return qsTr("Fullscreen state: unknown"); diff --git a/modules/windowinfo/Preview.qml b/modules/windowinfo/Preview.qml index 96542c4..2619e8a 100644 --- a/modules/windowinfo/Preview.qml +++ b/modules/windowinfo/Preview.qml @@ -34,7 +34,7 @@ Item { Loader { anchors.centerIn: parent - active: !Hyprland.activeClient + active: !Hyprland.activeToplevel asynchronous: true sourceComponent: ColumnLayout { @@ -69,10 +69,10 @@ Item { anchors.centerIn: parent - captureSource: Hyprland.activeClient ? ToplevelManager.activeToplevel : null + captureSource: Hyprland.activeToplevel?.wayland ?? null live: true - constraintSize.width: parent.height * Math.min(screen.width / screen.height, Hyprland.activeClient.width / Hyprland.activeClient.height) + constraintSize.width: parent.height * Math.min(root.screen.width / root.screen.height, Hyprland.activeToplevel?.lastIpcObject.size[0] / Hyprland.activeToplevel?.lastIpcObject.size[1]) constraintSize.height: parent.height } } @@ -86,11 +86,11 @@ Item { animate: true text: { - const client = Hyprland.activeClient; + const client = Hyprland.activeToplevel; if (!client) return qsTr("No active client"); - const mon = Hyprland.monitors.values[Hyprland.activeClient.lastIpcObject.monitor]; + const mon = client.monitor; return qsTr("%1 on monitor %2 at %3, %4").arg(client.title).arg(mon.name).arg(client.x).arg(client.y); } } diff --git a/services/Hyprland.qml b/services/Hyprland.qml index 7626f53..bef1c34 100644 --- a/services/Hyprland.qml +++ b/services/Hyprland.qml @@ -1,114 +1,37 @@ pragma Singleton import Quickshell -import Quickshell.Io import Quickshell.Hyprland import QtQuick Singleton { id: root - readonly property list clients: [] + readonly property var toplevels: Hyprland.toplevels readonly property var workspaces: Hyprland.workspaces readonly property var monitors: Hyprland.monitors - property Client activeClient: null - readonly property HyprlandWorkspace activeWorkspace: focusedMonitor?.activeWorkspace ?? null + readonly property HyprlandToplevel activeToplevel: Hyprland.activeToplevel + readonly property HyprlandWorkspace focusedWorkspace: Hyprland.focusedWorkspace readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor - readonly property int activeWsId: activeWorkspace?.id ?? 1 - property point cursorPos - - function reload() { - Hyprland.refreshWorkspaces(); - Hyprland.refreshMonitors(); - getClients.running = true; - getActiveClient.running = true; - } + readonly property int activeWsId: focusedWorkspace?.id ?? 1 function dispatch(request: string): void { Hyprland.dispatch(request); } - Component.onCompleted: reload() - Connections { target: Hyprland function onRawEvent(event: HyprlandEvent): void { - if (!event.name.endsWith("v2")) - root.reload(); - } - } - - Process { - id: getClients - command: ["hyprctl", "-j", "clients"] - stdout: StdioCollector { - onStreamFinished: { - const clients = JSON.parse(text); - const rClients = root.clients; - - const destroyed = rClients.filter(rc => !clients.find(c => c.address === rc.address)); - for (const client of destroyed) - rClients.splice(rClients.indexOf(client), 1).forEach(c => c.destroy()); - - for (const client of clients) { - const match = rClients.find(c => c.address === client.address); - if (match) { - match.lastIpcObject = client; - } else { - rClients.push(clientComp.createObject(root, { - lastIpcObject: client - })); - } - } - } + if (event.name.endsWith("v2")) + return; + + if (event.name.includes("mon")) + Hyprland.refreshMonitors(); + else if (event.name.includes("workspace")) + Hyprland.refreshWorkspaces(); + else + Hyprland.refreshToplevels(); } } - - Process { - id: getActiveClient - command: ["hyprctl", "-j", "activewindow"] - stdout: StdioCollector { - onStreamFinished: { - const client = JSON.parse(text); - const rClient = root.activeClient; - if (client.address) { - if (rClient) - rClient.lastIpcObject = client; - else - root.activeClient = clientComp.createObject(root, { - lastIpcObject: client - }); - } else if (rClient) { - rClient.destroy(); - root.activeClient = null; - } - } - } - } - - component Client: QtObject { - required property var lastIpcObject - readonly property string address: lastIpcObject.address - readonly property string wmClass: lastIpcObject.class - readonly property string title: lastIpcObject.title - readonly property string initialClass: lastIpcObject.initialClass - readonly property string initialTitle: lastIpcObject.initialTitle - readonly property int x: lastIpcObject.at[0] - readonly property int y: lastIpcObject.at[1] - readonly property int width: lastIpcObject.size[0] - readonly property int height: lastIpcObject.size[1] - readonly property HyprlandWorkspace workspace: Hyprland.workspaces.values.find(w => w.id === lastIpcObject.workspace.id) ?? null - readonly property HyprlandMonitor monitor: Hyprland.monitors.values.find(m => m.id === lastIpcObject.monitor) ?? null - readonly property bool floating: lastIpcObject.floating - readonly property bool fullscreen: lastIpcObject.fullscreen - readonly property int pid: lastIpcObject.pid - readonly property int focusHistoryId: lastIpcObject.focusHistoryID - } - - Component { - id: clientComp - - Client {} - } } -- cgit v1.2.3-freya