diff --git a/modules/HoverPanel.qml b/modules/HoverPanel.qml index a71576c..e8aebd0 100644 --- a/modules/HoverPanel.qml +++ b/modules/HoverPanel.qml @@ -40,6 +40,17 @@ PanelWindow { color: "transparent" property bool _winVisible: false + property bool _pinned: false + + // When pinned, only the pin button area receives input — everything else passes through + mask: _pinned ? _pinMask : null + + property Region _pinMask: Region { + x: panelContainer.x + panelContainer.width - 28 + y: 0 + width: 28 + height: 28 + } WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.exclusiveZone: 0 @@ -75,7 +86,7 @@ PanelWindow { interval: 400 onTriggered: { root._grace = false; - if (!root.showPanel) + if (!root.showPanel && !root._pinned) root.dismiss(); } } @@ -90,6 +101,7 @@ PanelWindow { } function dismiss() { + _pinned = false; showAnim.stop(); hideAnim.start(); _grace = false; @@ -102,7 +114,7 @@ PanelWindow { Timer { id: _hideTimer interval: 150 - onTriggered: if (!root.showPanel && !root._grace) + onTriggered: if (!root.showPanel && !root._grace && !root._pinned) root.dismiss() } @@ -195,11 +207,55 @@ PanelWindow { width: root.contentWidth HoverHandler { - enabled: !root.popupMode - onHoveredChanged: if (!root.popupMode) + enabled: !root.popupMode && !root._pinned + onHoveredChanged: if (!root.popupMode && !root._pinned) root.panelHovered = hovered } } + + // Pin button — top-right corner, hover mode only + Item { + visible: !root.popupMode + x: parent.width - width - 4 + y: 4 + width: 20 + height: 20 + z: 2 + opacity: pinHover.hovered || root._pinned ? 1 : 0.35 + + Behavior on opacity { + NumberAnimation { + duration: 100 + } + } + + HoverHandler { + id: pinHover + } + + TapHandler { + cursorShape: Qt.PointingHandCursor + onTapped: { + root._pinned = !root._pinned; + if (!root._pinned && !root.showPanel) + root.dismiss(); + } + } + + Text { + anchors.centerIn: parent + text: "\uEB3F" + color: root._pinned ? root.accentColor : M.Theme.base04 + font.pixelSize: M.Theme.fontSize - 1 + font.family: M.Theme.iconFontFamily + + Behavior on color { + ColorAnimation { + duration: 100 + } + } + } + } } // Border overlay — on top of content so full-bleed items don't cover it