import qs.config import qs.custom import qs.services import qs.util import Quickshell import Quickshell.Widgets import Quickshell.Hyprland import Quickshell.Wayland import QtQuick import QtQuick.Layouts Item { id: root required property PersistentProperties uiState required property Item wrapper required property HyprlandToplevel window property HyprlandToplevel toplevel: Hypr.activeToplevel property var screen: QsWindow.window.screen property bool pinned: false implicitWidth: childrenRect.width implicitHeight: childrenRect.height Component.onCompleted: { if (window) { state = "detail"; pinned = true; toplevel = window; } wrapper.window = null; } // States states: [ State { name: "detail" StateChangeScript { script: root.wrapper.persistent = true } ParentChange { target: header parent: infobox } PropertyChanges { infobox { visible: true } preview { visible: true } pin { visible: true } visit { visible: true } del { visible: true } expand { rotation: -90 } title { maximumLineCount: 1 } } } ] transitions: Transition { Anim { targets: [infobox, preview] property: "scale" from: 0; to: 1 } Anim { target: buttons property: "opacity" from: 0; to: 1 duration: Config.anim.durations.large * 2 } Anim { targets: header property: "scale" to: 1 } } // Reveal on window title change // (or close if window is invalid) Anim on opacity { id: reveal from: 0 to: 1 } onToplevelChanged: { root.opacity = 0; if (!toplevel) { root.wrapper.hasCurrent = false; } else if (!root.pinned) { reveal.restart(); } else { root.opacity = 1; } } RowLayout { id: layout spacing: 15 RowLayout { id: header spacing: 12 Binding { when: infobox.visible header { anchors.left: infobox.left anchors.right: infobox.right anchors.top: infobox.top anchors.margins: 12 } } IconImage { id: icon Layout.alignment: Qt.AlignVCenter implicitSize: 36 source: Icons.getAppIcon(toplevel?.lastIpcObject.class ?? "", "") } ColumnLayout { id: names spacing: 0 Layout.fillWidth: true Layout.maximumWidth: 400 CustomText { id: title Layout.fillWidth: true text: toplevel?.title ?? "" color: Config.colors.secondary elide: Text.ElideRight wrapMode: Text.WrapAtWordBoundaryOrAnywhere Behavior on text { Anim { target: names property: "opacity" from: 0 to: 1 } } } CustomText { Layout.fillWidth: true text: toplevel?.lastIpcObject.class ?? "" font.pointSize: Config.font.size.small color: Config.colors.tertiary elide: Text.ElideRight Behavior on text { Anim { target: names property: "opacity" from: 0 to: 1 } } } } } CustomRect { id: infobox visible: false transformOrigin: Item.TopRight implicitWidth: 300 implicitHeight: 240 color: Config.colors.container radius: 17 ColumnLayout { id: infolayout anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.topMargin: 48 anchors.margins: 12 spacing: 3 CustomRect { color: Config.colors.inactive Layout.fillWidth: true Layout.preferredHeight: 1 Layout.topMargin: 8 Layout.bottomMargin: 6 Layout.leftMargin: 5 Layout.rightMargin: 5 } Detail { icon: "workspaces" text: { for (let i = 0; i < root.uiState.workspaces.count; i++) { if (root.uiState.workspaces.get(i).workspace === root.toplevel?.workspace) return qsTr("Workspace: %1").arg(i + 1) } return qsTr("Workspace unknown") } } Detail { icon: "desktop_windows" text: { const mon = root.toplevel?.monitor; mon ? qsTr("Monitor: %1 (%2)").arg(mon.name).arg(mon.id) : qsTr("Monitor: unknown") } } Detail { icon: "location_on" text: qsTr("Address: %1").arg(`0x${root.toplevel?.address}` ?? "unknown") } Detail { icon: "location_searching" text: qsTr("Position: %1, %2").arg(root.toplevel?.lastIpcObject.at[0] ?? -1).arg(root.toplevel?.lastIpcObject.at[1] ?? -1) } Detail { icon: "resize" text: qsTr("Size: %1 тип %2").arg(root.toplevel?.lastIpcObject.size[0] ?? -1).arg(root.toplevel?.lastIpcObject.size[1] ?? -1) color: Config.colors.tertiary } Detail { icon: "account_tree" text: qsTr("Process id: %1").arg(Number(root.toplevel?.lastIpcObject.pid ?? -1).toLocaleString(undefined, "f")) color: Config.colors.primary } Detail { icon: "gradient" text: qsTr("Xwayland: %1").arg(root.toplevel?.lastIpcObject.xwayland ? "yes" : "no") } Detail { icon: "picture_in_picture_center" text: qsTr("Floating: %1").arg(root.toplevel?.lastIpcObject.floating ? "yes" : "no") color: Config.colors.secondary } } } ClippingWrapperRectangle { id: preview visible: false Layout.alignment: Qt.AlignVCenter transformOrigin: Item.TopLeft color: "transparent" radius: 12 ScreencopyView { captureSource: root.toplevel?.wayland ?? null live: true constraintSize.width: 375 constraintSize.height: 240 } } Item { id: buttons Layout.fillHeight: true width: buttonTopLayout.width property real buttonSize: 37 ColumnLayout { id: buttonTopLayout spacing: 2 anchors.top: parent.top StateLayer { id: expand implicitWidth: buttons.buttonSize implicitHeight: buttons.buttonSize function onClicked(): void { if (root.state === "") root.state = "detail"; else root.wrapper.hasCurrent = false; } MaterialIcon { anchors.centerIn: parent anchors.horizontalCenterOffset: font.pointSize * 0.05 text: "chevron_right" font.pointSize: Config.font.size.large } } StateLayer { id: pin visible: false implicitWidth: buttons.buttonSize implicitHeight: buttons.buttonSize function onClicked(): void { if (root.pinned) { root.pinned = false; root.toplevel = Qt.binding(() => Hypr.activeToplevel); } else { root.pinned = true; root.toplevel = root.toplevel; } } MaterialIcon { anchors.centerIn: parent text: "keep" fill: root.pinned font.pointSize: Config.font.size.large - 3 } } } ColumnLayout { id: buttonBottomLayout anchors.bottom: parent.bottom spacing: 2 StateLayer { id: visit visible: false implicitWidth: buttons.buttonSize implicitHeight: buttons.buttonSize disabled: Hypr.activeToplevel === root.toplevel function onClicked(): void { if (root.toplevel) Hypr.dispatch(`focuswindow address:0x${root.toplevel.address}`); } MaterialIcon { anchors.centerIn: parent text: "flip_to_front" color: parent.disabled ? Config.colors.inactive : Config.colors.primary font.pointSize: Config.font.size.large - 3 Behavior on color { CAnim {} } } } StateLayer { id: del visible: false Layout.bottomMargin: 8 color: Config.colors.error implicitWidth: buttons.buttonSize implicitHeight: buttons.buttonSize function onClicked(): void { if (root.toplevel) Hypr.dispatch(`killwindow address:0x${root.toplevel.address}`); root.wrapper.hasCurrent = false; } MaterialIcon { anchors.centerIn: parent text: "delete" color: Config.colors.error font.pointSize: Config.font.size.large - 3 } } } } } component Detail: RowLayout { id: detail required property string icon required property string text property alias color: icon.color Layout.fillWidth: true spacing: 7 MaterialIcon { id: icon Layout.alignment: Qt.AlignVCenter font.pointSize: Config.font.size.smaller text: detail.icon } CustomText { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter text: detail.text elide: Text.ElideRight font.family: Config.font.family.mono font.pointSize: Config.font.size.smaller } } }