178 lines
5.4 KiB
QML
178 lines
5.4 KiB
QML
// Compact, click-through system feedback. Repeated hardware-key presses update
|
|
// this one surface in place, avoiding a stack of notification cards.
|
|
|
|
import Quickshell
|
|
import Quickshell.Wayland
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.services
|
|
import qs.widgets
|
|
|
|
PanelWindow {
|
|
id: root
|
|
|
|
property var modelData: null
|
|
readonly property var presentation: OsdState.state
|
|
readonly property bool belongsHere: !OsdState.monitorName || !root.modelData
|
|
|| root.modelData.name === OsdState.monitorName
|
|
readonly property bool requestedVisible: OsdState.active && root.belongsHere
|
|
readonly property int horizontalPadding: 18
|
|
readonly property int contentGap: 14
|
|
readonly property int progressWidth: 156
|
|
readonly property int progressLabelWidth: 48
|
|
readonly property int messageWidth: Math.min(300, Math.max(52, Math.ceil(labelMetrics.advanceWidth)))
|
|
readonly property int desiredWidth: root.horizontalPadding * 2 + 24 + root.contentGap
|
|
+ (root.presentation.progress
|
|
? root.progressWidth + root.contentGap + root.progressLabelWidth
|
|
: root.messageWidth)
|
|
|
|
screen: root.modelData
|
|
anchors.bottom: true
|
|
margins.bottom: Theme.dockIconSize + Theme.dockPadding * 2 + Theme.barGap * 3
|
|
exclusiveZone: 0
|
|
exclusionMode: ExclusionMode.Ignore
|
|
implicitWidth: root.desiredWidth
|
|
implicitHeight: 64
|
|
color: "transparent"
|
|
mask: Region {}
|
|
|
|
WlrLayershell.namespace: "qs-popover-osd"
|
|
WlrLayershell.layer: WlrLayer.Overlay
|
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
|
|
|
property bool mapped: false
|
|
visible: root.mapped
|
|
|
|
onRequestedVisibleChanged: {
|
|
if (root.requestedVisible) {
|
|
unmapTimer.stop();
|
|
root.mapped = true;
|
|
entrance.restart();
|
|
} else if (root.mapped) {
|
|
unmapTimer.restart();
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
if (root.requestedVisible)
|
|
root.mapped = true;
|
|
}
|
|
|
|
Timer {
|
|
id: unmapTimer
|
|
interval: Theme.durNormal
|
|
onTriggered: root.mapped = false
|
|
}
|
|
|
|
Rectangle {
|
|
id: surface
|
|
anchors.fill: parent
|
|
radius: Theme.popoverRadius
|
|
color: Theme.alpha(Theme.bgPopover, 0.9)
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.fg, 0.1)
|
|
opacity: root.requestedVisible ? 1 : 0
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutCubic }
|
|
}
|
|
|
|
transform: Translate {
|
|
id: slide
|
|
y: root.requestedVisible ? 0 : 8
|
|
Behavior on y {
|
|
NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutCubic }
|
|
}
|
|
}
|
|
|
|
PrismEdge {
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 1
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
inset: parent.radius
|
|
}
|
|
|
|
Row {
|
|
anchors.centerIn: parent
|
|
spacing: root.contentGap
|
|
|
|
ThemedIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
size: 24
|
|
icon: root.presentation.icon
|
|
iconFallback: "dialog-information-symbolic"
|
|
tint: Theme.fg
|
|
}
|
|
|
|
Item {
|
|
visible: root.presentation.progress
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: visible ? root.progressWidth : 0
|
|
height: 8
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: height / 2
|
|
color: Theme.alpha(Theme.fg, 0.14)
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: parent.left
|
|
anchors.top: parent.top
|
|
anchors.bottom: parent.bottom
|
|
width: parent.width * root.presentation.ratio
|
|
radius: height / 2
|
|
color: Theme.accent
|
|
|
|
Behavior on width {
|
|
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.presentation.progress ? root.progressLabelWidth : root.messageWidth
|
|
text: root.presentation.label
|
|
color: Theme.fg
|
|
elide: Text.ElideRight
|
|
maximumLineCount: 1
|
|
horizontalAlignment: root.presentation.progress ? Text.AlignRight : Text.AlignLeft
|
|
font.family: Theme.fontFamily
|
|
font.features: Theme.tabularFigures
|
|
font.pixelSize: Theme.fontSize
|
|
font.weight: Font.DemiBold
|
|
}
|
|
}
|
|
}
|
|
|
|
TextMetrics {
|
|
id: labelMetrics
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSize
|
|
font.weight: Font.DemiBold
|
|
text: root.presentation.label
|
|
}
|
|
|
|
ParallelAnimation {
|
|
id: entrance
|
|
NumberAnimation {
|
|
target: surface
|
|
property: "opacity"
|
|
from: 0
|
|
to: 1
|
|
duration: Theme.durNormal
|
|
easing.type: Easing.OutCubic
|
|
}
|
|
NumberAnimation {
|
|
target: slide
|
|
property: "y"
|
|
from: 8
|
|
to: 0
|
|
duration: Theme.durNormal
|
|
easing.type: Easing.OutCubic
|
|
}
|
|
}
|
|
}
|