quickshell-toki-night/modules/bar/popouts/ActiveWindow.qml

425 lines
12 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}
}