diff --git a/Modules/OSD/BrightnessOSD.qml b/Modules/OSD/BrightnessOSD.qml index 5118a2eb..05cfee03 100644 --- a/Modules/OSD/BrightnessOSD.qml +++ b/Modules/OSD/BrightnessOSD.qml @@ -24,10 +24,6 @@ DankOSD { } } - function resetHideTimer() { - if (root.shouldBeVisible) - root.hideTimer.restart() - } Connections { target: BrightnessService @@ -92,10 +88,14 @@ DankOSD { if (BrightnessService.brightnessAvailable) { root.brightnessDebounceTimer.pendingValue = newValue root.brightnessDebounceTimer.restart() - root.resetHideTimer() + resetHideTimer() } } + onContainsMouseChanged: { + setChildHovered(containsMouse) + } + onSliderDragFinished: function(finalValue) { if (BrightnessService.brightnessAvailable) { root.brightnessDebounceTimer.stop() diff --git a/Modules/OSD/VolumeOSD.qml b/Modules/OSD/VolumeOSD.qml index 80850f77..46c612d9 100644 --- a/Modules/OSD/VolumeOSD.qml +++ b/Modules/OSD/VolumeOSD.qml @@ -11,10 +11,6 @@ DankOSD { autoHideInterval: 3000 enableMouseInteraction: true - function resetHideTimer() { - if (root.shouldBeVisible) - root.hideTimer.restart() - } Connections { target: AudioService @@ -62,7 +58,10 @@ DankOSD { cursorShape: Qt.PointingHandCursor onClicked: { AudioService.toggleMute() - root.resetHideTimer() + resetHideTimer() + } + onContainsMouseChanged: { + setChildHovered(containsMouse || volumeSlider.containsMouse) } } } @@ -88,10 +87,14 @@ DankOSD { onSliderValueChanged: function(newValue) { if (AudioService.sink && AudioService.sink.audio) { AudioService.sink.audio.volume = newValue / 100 - root.resetHideTimer() + resetHideTimer() } } + onContainsMouseChanged: { + setChildHovered(containsMouse || muteButton.containsMouse) + } + Connections { target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null diff --git a/Modules/Toast.qml b/Modules/Toast.qml index 42d70b4a..a97a71f6 100644 --- a/Modules/Toast.qml +++ b/Modules/Toast.qml @@ -12,9 +12,36 @@ PanelWindow { id: root property var modelData + property bool shouldBeVisible: false + property real frozenWidth: 0 + + Connections { + target: ToastService + function onToastVisibleChanged() { + if (ToastService.toastVisible) { + shouldBeVisible = true + visible = true + } else { + // Freeze the width before starting exit animation + frozenWidth = toast.width + shouldBeVisible = false + closeTimer.restart() + } + } + } + + Timer { + id: closeTimer + interval: Theme.mediumDuration + 50 + onTriggered: { + if (!shouldBeVisible) { + visible = false + } + } + } screen: modelData - visible: ToastService.toastVisible + visible: shouldBeVisible WlrLayershell.layer: WlrLayershell.Overlay WlrLayershell.exclusiveZone: -1 WlrLayershell.keyboardFocus: WlrKeyboardFocus.None @@ -39,8 +66,9 @@ PanelWindow { } } - width: ToastService.hasDetails ? 380 : messageText.implicitWidth + Theme.iconSize - + Theme.spacingM * 3 + Theme.spacingL * 2 + width: shouldBeVisible ? + (ToastService.hasDetails ? 380 : messageText.implicitWidth + Theme.iconSize + Theme.spacingM * 3 + Theme.spacingL * 2) : + frozenWidth height: toastContent.height + Theme.spacingL * 2 anchors.horizontalCenter: parent.horizontalCenter y: Theme.barHeight - 4 + SettingsData.topBarSpacing + 2 @@ -58,7 +86,7 @@ PanelWindow { } radius: Theme.cornerRadius layer.enabled: true - opacity: ToastService.toastVisible ? 0.9 : 0 + opacity: shouldBeVisible ? 0.9 : 0 Column { id: toastContent @@ -228,9 +256,6 @@ PanelWindow { shadowOpacity: 0.3 } - transform: Translate { - y: ToastService.toastVisible ? 0 : -20 - } Behavior on opacity { NumberAnimation { @@ -247,11 +272,7 @@ PanelWindow { } Behavior on height { - enabled: ToastService.toastVisible - NumberAnimation { - duration: Anims.durShort - easing.type: Easing.Linear - } + enabled: false } Behavior on width { diff --git a/Widgets/DankOSD.qml b/Widgets/DankOSD.qml index 521828c0..c05799b9 100644 --- a/Widgets/DankOSD.qml +++ b/Widgets/DankOSD.qml @@ -35,8 +35,34 @@ PanelWindow { } function resetHideTimer() { - if (shouldBeVisible && enableMouseInteraction) - hideTimer.restart() + if (shouldBeVisible && enableMouseInteraction) { + // Only restart timer if we're not currently hovering + let isHovered = (enableMouseInteraction && mouseArea.containsMouse) || osdContainer.childHovered + if (!isHovered) { + hideTimer.restart() + } + } + } + + function stopHideTimer() { + if (enableMouseInteraction) + hideTimer.stop() + } + + function updateHoverState() { + let isHovered = (enableMouseInteraction && mouseArea.containsMouse) || osdContainer.childHovered + if (enableMouseInteraction) { + if (isHovered) { + stopHideTimer() + } else if (shouldBeVisible) { + resetHideTimer() + } + } + } + + function setChildHovered(hovered) { + osdContainer.childHovered = hovered + updateHoverState() } screen: modelData @@ -82,6 +108,7 @@ PanelWindow { id: osdContainer property bool containsMouse: enableMouseInteraction && mouseArea.containsMouse + property bool childHovered: false width: osdWidth height: osdHeight @@ -103,6 +130,14 @@ PanelWindow { acceptedButtons: Qt.NoButton propagateComposedEvents: true z: -1 + + onContainsMouseChanged: { + updateHoverState() + } + } + + onChildHoveredChanged: { + root.updateHoverState() } Loader { diff --git a/Widgets/DankSlider.qml b/Widgets/DankSlider.qml index ebe8897f..c8fb3b48 100644 --- a/Widgets/DankSlider.qml +++ b/Widgets/DankSlider.qml @@ -14,6 +14,7 @@ Item { property string unit: "%" property bool showValue: true property bool isDragging: false + readonly property bool containsMouse: sliderMouseArea.containsMouse signal sliderValueChanged(int newValue) signal sliderDragFinished(int finalValue)