import Quickshell import Quickshell.Widgets import QtQuick import "../.." PopupWindow { id: root color: "transparent" implicitWidth: bar.width implicitHeight: Math.max(popupContainer.height, 800) + 20 mask: Region { item: popupContainer } anchor { window: bar rect: Qt.rect(0, 0, bar.width, bar.height) edges: Edges.Bottom | Edges.Left gravity: Edges.Bottom | Edges.Right adjustment: PopupAdjustment.None } required property var bar property var isOpen: false property var padding: 5 property var item property var content function set(item, content) { isOpen = false; root.item = item; root.content = content; popupContent.data = content; let itemPos = item.mapToItem(root.bar.contentItem, 0, root.bar.height, item.width, 0).x; position(itemPos); popupContainer.opacity = 0; popupContent.opacity = 0; } function position(itemPos) { if (itemPos === undefined) return; let rightEdge = itemPos + popupContainer.implicitWidth; let maxRightEdge = root.width - padding; let isTouchingRightEdge = rightEdge > maxRightEdge; if (isTouchingRightEdge) { // touching right edge, reposition // console.log("touching right edge"); popupContainer.x = maxRightEdge - popupContainer.implicitWidth; popupContainer.y = padding; } else { // not touching right edge popupContainer.x = itemPos; popupContainer.y = padding; } } function show() { isOpen = true; root.visible = true; // set and leave open root.content.visible = true; popupContainer.opacity = 1; popupContent.opacity = 1; } function hide() { isOpen = false; popupContainer.opacity = 0; popupContent.opacity = 0; root.item = undefined; root.content = undefined; popupContent.data = []; } function toggle() { if (isOpen) { hide(); } else { show(); } } WrapperRectangle { id: popupContainer color: ShellSettings.settings.colors["surface"] radius: 12 margin: 8 clip: true opacity: 0 visible: opacity > 0 // spooky, likely to cause problems lol width: implicitWidth height: implicitHeight // needed to handle occurences where items are resized while open onImplicitWidthChanged: { if (root.isOpen) { let itemPos = root.item.mapToItem(root.bar.contentItem, 0, root.bar.height, root.item.width, 0).x; root.position(itemPos); } } Item { id: popupContent implicitWidth: Math.max(childrenRect.width, 120) implicitHeight: Math.max(childrenRect.height, 60) Behavior on opacity { NumberAnimation { duration: 200 easing.type: Easing.Linear from: 0 to: 1 } } } HoverHandler { id: hover enabled: true acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad onHoveredChanged: { if (hovered == false) root.hide(); } } Behavior on opacity { NumberAnimation { duration: 200 easing.type: Easing.Linear } } Behavior on width { SmoothedAnimation { duration: 200 easing.type: Easing.Linear } } Behavior on height { SmoothedAnimation { duration: 200 easing.type: Easing.Linear } } Behavior on x { enabled: root.visible SmoothedAnimation { duration: 200 easing.type: Easing.OutQuad } } } }