quickshell: apply dropdown pattern to tray context menu
Same morphing animation, concave corners, and dismiss behavior as the calendar popup. Menu drops down from bar at icon position. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3b7cc98fc9
commit
0aba95779a
1 changed files with 95 additions and 20 deletions
|
|
@ -714,7 +714,10 @@ in
|
|||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: (event) => {
|
||||
if (contextMenu.justDismissed) return;
|
||||
if (event.button === Qt.RightButton && modelData.hasMenu) {
|
||||
let pos = parent.mapToItem(bar.contentItem, parent.width / 2, 0);
|
||||
contextMenu.menuX = pos.x;
|
||||
contextMenu.trayItem = modelData;
|
||||
menuOpener.menu = modelData.menu;
|
||||
contextMenu.visible = true;
|
||||
|
|
@ -732,32 +735,112 @@ in
|
|||
PopupWindow {
|
||||
id: contextMenu
|
||||
property var trayItem: null
|
||||
anchor.item: trayArea
|
||||
anchor.edges: Edges.Bottom | Edges.Right
|
||||
anchor.gravity: Edges.Bottom | Edges.Left
|
||||
property bool open: false
|
||||
property bool justDismissed: false
|
||||
property real menuX: 0
|
||||
property real fullWidth: menuItems.width + 16
|
||||
property real fullHeight: menuItems.height + 12
|
||||
|
||||
anchor.window: bar
|
||||
anchor.rect.x: menuX - (fullWidth + 16) / 2
|
||||
anchor.rect.y: bar.height
|
||||
anchor.edges: Edges.Top | Edges.Left
|
||||
anchor.gravity: Edges.Bottom | Edges.Right
|
||||
anchor.adjustment: PopupAdjustment.Slide
|
||||
grabFocus: true
|
||||
visible: false
|
||||
color: "transparent"
|
||||
implicitWidth: menuColumn.width + 2
|
||||
implicitHeight: menuColumn.height + 2
|
||||
implicitWidth: fullWidth + 16
|
||||
implicitHeight: fullHeight + 4
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
open = true;
|
||||
} else {
|
||||
open = false;
|
||||
justDismissed = true;
|
||||
menuDismissGuard.start();
|
||||
menuOpener.menu = null;
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: menuDismissGuard
|
||||
interval: 100
|
||||
onTriggered: contextMenu.justDismissed = false
|
||||
}
|
||||
|
||||
QsMenuOpener {
|
||||
id: menuOpener
|
||||
}
|
||||
|
||||
// Concave corner — left
|
||||
Item {
|
||||
anchors.right: menuContent.left
|
||||
anchors.top: parent.top
|
||||
width: 8
|
||||
height: Math.min(8, menuContent.height)
|
||||
clip: true
|
||||
visible: menuContent.height > 0
|
||||
Canvas {
|
||||
anchors.top: parent.top
|
||||
width: 8; height: 8
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, 8, 8);
|
||||
ctx.fillStyle = "#D1${c.base00}";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0); ctx.lineTo(8, 0); ctx.lineTo(8, 8);
|
||||
ctx.arc(0, 8, 8, 0, -Math.PI / 2, true);
|
||||
ctx.closePath(); ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Concave corner — right
|
||||
Item {
|
||||
anchors.left: menuContent.right
|
||||
anchors.top: parent.top
|
||||
width: 8
|
||||
height: Math.min(8, menuContent.height)
|
||||
clip: true
|
||||
visible: menuContent.height > 0
|
||||
Canvas {
|
||||
anchors.top: parent.top
|
||||
width: 8; height: 8
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, 8, 8);
|
||||
ctx.fillStyle = "#D1${c.base00}";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0); ctx.lineTo(8, 0);
|
||||
ctx.arc(8, 8, 8, -Math.PI / 2, Math.PI, true);
|
||||
ctx.closePath(); ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: menuColumn
|
||||
width: menuItems.width + 16
|
||||
height: menuItems.height + 12
|
||||
color: "#${c.base00}"
|
||||
border.color: "#${c.base03}"
|
||||
border.width: 1
|
||||
id: menuContent
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
width: contextMenu.fullWidth
|
||||
height: contextMenu.open ? contextMenu.fullHeight : 0
|
||||
color: "#D1${c.base00}"
|
||||
radius: 8
|
||||
topLeftRadius: 0
|
||||
topRightRadius: 0
|
||||
clip: true
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: 220; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Column {
|
||||
id: menuItems
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 6
|
||||
width: 200
|
||||
|
||||
Repeater {
|
||||
|
|
@ -771,7 +854,6 @@ in
|
|||
? "#${c.base02}" : "transparent"
|
||||
radius: modelData.isSeparator ? 0 : 4
|
||||
|
||||
// Separator line
|
||||
Rectangle {
|
||||
visible: modelData.isSeparator
|
||||
anchors.centerIn: parent
|
||||
|
|
@ -780,7 +862,6 @@ in
|
|||
color: "#${c.base03}"
|
||||
}
|
||||
|
||||
// Menu item content
|
||||
RowLayout {
|
||||
visible: !modelData.isSeparator
|
||||
anchors.fill: parent
|
||||
|
|
@ -820,12 +901,6 @@ in
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
menuOpener.menu = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calendar popup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue