111 lines
3.6 KiB
QML
111 lines
3.6 KiB
QML
import Quickshell
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.components
|
|
import qs.services
|
|
|
|
// Left click focuses the window, or minimises it if it is already focused —
|
|
// except under attwm, which has no minimised state. Middle click closes it.
|
|
PanelButton {
|
|
id: root
|
|
|
|
// The window this button stands for: either an attwm window object from its
|
|
// IPC state, or a Toplevel handle from wlr-foreign-toplevel-management.
|
|
// Both carry the same facts under different names, so `attwm` says which is
|
|
// in hand rather than each read having to guess.
|
|
required property var win
|
|
required property bool attwm
|
|
|
|
readonly property string appId: (root.attwm ? root.win.app_id : root.win.appId) || ""
|
|
readonly property bool activated: root.attwm ? root.win.focused : root.win.activated
|
|
|
|
// Not on screen right now: minimised elsewhere, and under attwm parked on a
|
|
// tag nobody is viewing, which is that model's equivalent.
|
|
readonly property bool hidden: root.attwm ? !root.win.visible : root.win.minimized
|
|
|
|
// Desktop entries carry a proper themed icon; appId alone often works as an
|
|
// icon name too, which is the fallback AppIcon ends up using.
|
|
readonly property var entry: DesktopEntries.heuristicLookup(root.appId)
|
|
readonly property string title: root.win.title || root.appId || "Window"
|
|
|
|
active: root.activated
|
|
minContentWidth: Config.windowButtonMinWidth
|
|
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
|
|
|
opacity: root.hidden ? 0.55 : 1
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: Theme.animDuration
|
|
easing.type: Theme.animEasing
|
|
}
|
|
}
|
|
|
|
onClicked: event => {
|
|
if (event.button === Qt.MiddleButton) {
|
|
if (root.attwm)
|
|
Attwm.closeWindow(root.win.id);
|
|
else
|
|
root.win.close();
|
|
return;
|
|
}
|
|
|
|
if (root.attwm) {
|
|
// attwm has nothing to minimise into — a window is on a tag or it
|
|
// is not — so a click always means focus, and attwm brings the
|
|
// window's tags into view if they are not already.
|
|
Attwm.focusWindow(root.win.id);
|
|
return;
|
|
}
|
|
|
|
if (root.win.activated) {
|
|
root.win.minimized = true;
|
|
} else {
|
|
root.win.minimized = false;
|
|
root.win.activate();
|
|
}
|
|
}
|
|
|
|
// Both children are given the same height so the Row needs no anchors,
|
|
// which positioners disallow.
|
|
Row {
|
|
spacing: Theme.spacing + 2
|
|
|
|
AppIcon {
|
|
icon: (root.entry && root.entry.icon) || root.appId
|
|
fallbackLabel: root.appId || root.title
|
|
size: Theme.iconSize
|
|
}
|
|
|
|
Text {
|
|
id: label
|
|
|
|
// Clamp to the natural width so the button never depends on its own
|
|
// width, which would loop through PanelButton's implicit sizing.
|
|
width: Math.min(implicitWidth, Config.windowButtonMaxWidth)
|
|
height: Theme.iconSize
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
text: root.title
|
|
color: root.activated ? Theme.text : Theme.textDim
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSize
|
|
}
|
|
}
|
|
|
|
// Active-window underline, the usual taskbar affordance.
|
|
overlay: Rectangle {
|
|
anchors {
|
|
left: parent.left
|
|
right: parent.right
|
|
bottom: parent.bottom
|
|
leftMargin: Theme.radius
|
|
rightMargin: Theme.radius
|
|
}
|
|
height: 2
|
|
radius: 1
|
|
color: Theme.accent
|
|
visible: root.activated
|
|
}
|
|
}
|