1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 21:45:38 -05:00

native tray menu

This commit is contained in:
bbedward
2025-08-07 17:01:52 -04:00
parent 3dae0ec5e3
commit 9b7ca88e11
4 changed files with 22 additions and 214 deletions

View File

@@ -1,13 +1,15 @@
import QtQuick
import Quickshell
import Quickshell.Services.SystemTray
import qs.Common
Rectangle {
id: root
property var parentWindow: null
readonly property int calculatedWidth: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + (SystemTray.items.values.length - 1) * Theme.spacingXS + Theme.spacingS * 2 : 0
signal menuRequested(var menu, var item, real x, real y)
width: calculatedWidth
height: 30
@@ -84,16 +86,21 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
if (!trayItem)
return ;
return
if (mouse.button === Qt.LeftButton) {
if (!trayItem.onlyMenu)
trayItem.activate();
trayItem.activate()
} else if (mouse.button === Qt.RightButton) {
if (trayItem && trayItem.hasMenu)
root.menuRequested(null, trayItem, mouse.x, mouse.y);
if (trayItem.hasMenu) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
menuAnchor.menu = trayItem.menu
menuAnchor.anchor.window = parentWindow
menuAnchor.anchor.rect = Qt.rect(relativeX, Theme.barHeight + Theme.spacingS, parent.width, 1)
menuAnchor.open()
}
}
}
}
@@ -104,4 +111,8 @@ Rectangle {
}
QsMenuAnchor {
id: menuAnchor
}
}

View File

@@ -1,181 +0,0 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets
import qs.Common
import qs.Widgets
PanelWindow {
id: root
property bool showContextMenu: false
property real contextMenuX: 0
property real contextMenuY: 0
property var currentTrayMenu: null
property var currentTrayItem: null
visible: showContextMenu
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
anchors {
top: true
left: true
right: true
bottom: true
}
Rectangle {
id: menuContainer
x: contextMenuX
y: contextMenuY
width: Math.max(180, Math.min(300, menuList.maxTextWidth + Theme.spacingL * 2))
height: Math.max(60, menuList.contentHeight + Theme.spacingS * 2)
color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge
border.color: Theme.outlineMedium
border.width: 1
opacity: showContextMenu ? 1 : 0
scale: showContextMenu ? 1 : 0.85
Rectangle {
anchors.fill: parent
anchors.topMargin: 4
anchors.leftMargin: 2
anchors.rightMargin: -2
anchors.bottomMargin: -4
radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15)
z: parent.z - 1
}
Item {
anchors.fill: parent
anchors.margins: Theme.spacingS
QsMenuOpener {
id: menuOpener
menu: currentTrayItem && currentTrayItem.hasMenu ? currentTrayItem.menu : null
}
DankListView {
id: menuList
property real maxTextWidth: {
let maxWidth = 0;
if (model && model.values) {
for (let i = 0; i < model.values.length; i++) {
const item = model.values[i];
if (item && item.text) {
const textWidth = textMetrics.advanceWidth * item.text.length * 0.6;
maxWidth = Math.max(maxWidth, textWidth);
}
}
}
return Math.min(maxWidth, 280); // Cap at reasonable width
}
anchors.fill: parent
spacing: 1
model: menuOpener.children
TextMetrics {
id: textMetrics
font.pixelSize: Theme.fontSizeSmall
text: "M"
}
delegate: Rectangle {
width: ListView.view.width
height: modelData.isSeparator ? 5 : 28
radius: modelData.isSeparator ? 0 : Theme.cornerRadiusSmall
color: modelData.isSeparator ? "transparent" : (menuItemArea.containsMouse ? Theme.primaryHover : "transparent")
Rectangle {
visible: modelData.isSeparator
anchors.centerIn: parent
width: parent.width - Theme.spacingS * 2
height: 1
color: Theme.surfaceVariantAlpha
}
Row {
visible: !modelData.isSeparator
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
StyledText {
text: modelData.text || ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
maximumLineCount: 1
}
}
MouseArea {
id: menuItemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: modelData.isSeparator ? Qt.ArrowCursor : Qt.PointingHandCursor
enabled: !modelData.isSeparator
onClicked: {
if (modelData.triggered)
modelData.triggered();
showContextMenu = false;
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
MouseArea {
anchors.fill: parent
z: -1
onClicked: {
showContextMenu = false;
}
}
}

View File

@@ -542,16 +542,7 @@ PanelWindow {
id: systemTrayComponent
SystemTrayBar {
onMenuRequested: (menu, item, x, y) => {
systemTrayContextMenu.currentTrayMenu = menu;
systemTrayContextMenu.currentTrayItem = item;
systemTrayContextMenu.contextMenuX = rightSection.x + rightSection.width - 400 - Theme.spacingL;
systemTrayContextMenu.contextMenuY = Theme.barHeight - Theme.spacingXS;
systemTrayContextMenu.showContextMenu = true;
if (menu) {
menu.menuVisible = true;
}
}
parentWindow: root
}
}

View File

@@ -1,3 +1,4 @@
//@ pragma UseQApplication
import QtQuick
import Quickshell
@@ -21,8 +22,7 @@ import qs.Services
ShellRoot {
id: root
WallpaperBackground {
}
WallpaperBackground {}
Lock {
id: lock
@@ -36,7 +36,6 @@ ShellRoot {
delegate: TopBar {
modelData: item
}
}
Variants {
@@ -47,17 +46,12 @@ ShellRoot {
contextMenu: dockContextMenu
windowsMenu: dockWindowsMenu
}
}
CentcomPopout {
id: centcomPopout
}
SystemTrayContextMenu {
id: systemTrayContextMenu
}
DockContextMenu {
id: dockContextMenu
}
@@ -76,7 +70,6 @@ ShellRoot {
delegate: NotificationPopupManager {
modelData: item
}
}
ControlCenterPopout {
@@ -141,7 +134,6 @@ ShellRoot {
ProcessListModal {
id: processListModal
}
}
IpcHandler {
@@ -177,7 +169,6 @@ ShellRoot {
delegate: Toast {
modelData: item
}
}
Variants {
@@ -186,7 +177,6 @@ ShellRoot {
delegate: VolumePopup {
modelData: item
}
}
Variants {
@@ -195,7 +185,6 @@ ShellRoot {
delegate: MicMutePopup {
modelData: item
}
}
Variants {
@@ -204,7 +193,5 @@ ShellRoot {
delegate: BrightnessPopup {
modelData: item
}
}
}