1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-31 08:52:49 -05:00

systemtray: new tray detail menu

This commit is contained in:
bbedward
2025-11-13 16:30:07 -05:00
parent 1858597fc9
commit d46b7528e7
4 changed files with 382 additions and 228 deletions

View File

@@ -1,10 +1,12 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Services
import qs.Widgets import qs.Widgets
Item { Item {
@@ -45,6 +47,7 @@ Item {
visible: allTrayItems.length > 0 visible: allTrayItems.length > 0
property bool menuOpen: false property bool menuOpen: false
property bool overflowWasOpenBeforeTrayMenu: false
Rectangle { Rectangle {
id: visualBackground id: visualBackground
@@ -157,17 +160,17 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => { onClicked: (mouse) => {
if (!delegateRoot.trayItem) { if (!delegateRoot.trayItem) return
return;
}
if (mouse.button === Qt.LeftButton && !delegateRoot.trayItem.onlyMenu) { if (mouse.button === Qt.LeftButton && !delegateRoot.trayItem.onlyMenu) {
delegateRoot.trayItem.activate(); delegateRoot.trayItem.activate()
return ; return
}
if (delegateRoot.trayItem.hasMenu) {
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVertical, root.axis);
} }
if (!delegateRoot.trayItem.hasMenu) return
root.overflowWasOpenBeforeTrayMenu = root.menuOpen
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVertical, root.axis)
} }
} }
} }
@@ -289,17 +292,17 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => { onClicked: (mouse) => {
if (!delegateRoot.trayItem) { if (!delegateRoot.trayItem) return
return;
}
if (mouse.button === Qt.LeftButton && !delegateRoot.trayItem.onlyMenu) { if (mouse.button === Qt.LeftButton && !delegateRoot.trayItem.onlyMenu) {
delegateRoot.trayItem.activate(); delegateRoot.trayItem.activate()
return ; return
}
if (delegateRoot.trayItem.hasMenu) {
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVertical, root.axis);
} }
if (!delegateRoot.trayItem.hasMenu) return
root.overflowWasOpenBeforeTrayMenu = root.menuOpen
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVertical, root.axis)
} }
} }
} }
@@ -349,7 +352,7 @@ Item {
screen: root.parentScreen screen: root.parentScreen
WlrLayershell.layer: WlrLayershell.Top WlrLayershell.layer: WlrLayershell.Top
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
WlrLayershell.namespace: "dms:tray-overflow-menu" WlrLayershell.namespace: "dms:tray-overflow-menu"
color: "transparent" color: "transparent"
@@ -360,10 +363,26 @@ Item {
bottom: true bottom: true
} }
readonly property real dpr: (typeof CompositorService !== "undefined" && CompositorService.getScreenScale)
? CompositorService.getScreenScale(overflowMenu.screen)
: (screen?.devicePixelRatio || 1)
property point anchorPos: Qt.point(screen.width / 2, screen.height / 2) property point anchorPos: Qt.point(screen.width / 2, screen.height / 2)
onVisibleChanged: { onVisibleChanged: {
if (visible) updatePosition() if (visible) {
updatePosition()
Qt.callLater(() => overflowFocusScope.forceActiveFocus())
}
}
FocusScope {
id: overflowFocusScope
anchors.fill: parent
focus: true
Keys.onEscapePressed: {
root.menuOpen = false
}
} }
function updatePosition() { function updatePosition() {
@@ -395,50 +414,71 @@ Item {
} }
} }
Rectangle { Item {
id: menuContainer id: menuContainer
width: 250
height: Math.min(screen.height - 100, menuColumn.implicitHeight + Theme.spacingS * 2)
x: { readonly property real rawWidth: {
const itemCount = root.allTrayItems.length
const cols = Math.min(5, itemCount)
const itemSize = 28
const spacing = 2
return cols * itemSize + (cols - 1) * spacing + Theme.spacingS * 2
}
readonly property real rawHeight: {
const itemCount = root.allTrayItems.length
const cols = Math.min(5, itemCount)
const rows = Math.ceil(itemCount / cols)
const itemSize = 28
const spacing = 2
return rows * itemSize + (rows - 1) * spacing + Theme.spacingS * 2
}
readonly property real alignedWidth: Theme.px(rawWidth, overflowMenu.dpr)
readonly property real alignedHeight: Theme.px(rawHeight, overflowMenu.dpr)
width: alignedWidth
height: alignedHeight
x: Theme.snap((() => {
if (root.isVertical) { if (root.isVertical) {
const edge = root.axis?.edge const edge = root.axis?.edge
if (edge === "left") { if (edge === "left") {
const targetX = overflowMenu.anchorPos.x const targetX = overflowMenu.anchorPos.x
return Math.min(overflowMenu.screen.width - width - 10, targetX) return Math.min(overflowMenu.screen.width - alignedWidth - 10, targetX)
} else { } else {
const targetX = overflowMenu.anchorPos.x - width const targetX = overflowMenu.anchorPos.x - alignedWidth
return Math.max(10, targetX) return Math.max(10, targetX)
} }
} else { } else {
const left = 10 const left = 10
const right = overflowMenu.width - width - 10 const right = overflowMenu.width - alignedWidth - 10
const want = overflowMenu.anchorPos.x - width / 2 const want = overflowMenu.anchorPos.x - alignedWidth / 2
return Math.max(left, Math.min(right, want)) return Math.max(left, Math.min(right, want))
} }
} })(), overflowMenu.dpr)
y: { y: Theme.snap((() => {
if (root.isVertical) { if (root.isVertical) {
const top = 10 const top = 10
const bottom = overflowMenu.height - height - 10 const bottom = overflowMenu.height - alignedHeight - 10
const want = overflowMenu.anchorPos.y - height / 2 const want = overflowMenu.anchorPos.y - alignedHeight / 2
return Math.max(top, Math.min(bottom, want)) return Math.max(top, Math.min(bottom, want))
} else { } else {
if (root.isAtBottom) { if (root.isAtBottom) {
const targetY = overflowMenu.anchorPos.y - height const targetY = overflowMenu.anchorPos.y - alignedHeight
return Math.max(10, targetY) return Math.max(10, targetY)
} else { } else {
const targetY = overflowMenu.anchorPos.y const targetY = overflowMenu.anchorPos.y
return Math.min(overflowMenu.screen.height - height - 10, targetY) return Math.min(overflowMenu.screen.height - alignedHeight - 10, targetY)
}
} }
} }
})(), overflowMenu.dpr)
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) property real shadowBlurPx: 10
radius: Theme.cornerRadius property real shadowSpreadPx: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) property real shadowBaseAlpha: 0.60
border.width: 1 readonly property real popupSurfaceAlpha: Theme.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
opacity: root.menuOpen ? 1 : 0 opacity: root.menuOpen ? 1 : 0
scale: root.menuOpen ? 1 : 0.85 scale: root.menuOpen ? 1 : 0.85
@@ -457,29 +497,44 @@ Item {
} }
} }
Rectangle { Item {
id: bgShadowLayer
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 4 layer.enabled: true
anchors.leftMargin: 2 layer.smooth: true
anchors.rightMargin: -2 layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
anchors.bottomMargin: -4 layer.textureMirroring: ShaderEffectSource.MirrorVertically
radius: parent.radius layer.samples: 4
color: Qt.rgba(0, 0, 0, 0.15)
z: parent.z - 1 layer.effect: MultiEffect {
autoPaddingEnabled: true
shadowEnabled: true
blurEnabled: false
maskEnabled: false
property int blurMax: 64
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / blurMax))
shadowScale: 1 + (2 * menuContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha)
}
} }
DankFlickable { Rectangle {
id: scrollView
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
contentWidth: width radius: Theme.cornerRadius
contentHeight: menuColumn.implicitHeight antialiasing: true
clip: true smooth: true
}
}
Column { Grid {
id: menuColumn id: menuGrid
width: parent.width anchors.centerIn: parent
columns: Math.min(5, root.allTrayItems.length)
spacing: 2 spacing: 2
rowSpacing: 2
Repeater { Repeater {
model: root.allTrayItems model: root.allTrayItems
@@ -509,23 +564,17 @@ Item {
return "" return ""
} }
width: menuColumn.width width: 28
height: 32 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: itemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: itemArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceContainer, 0)
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
IconImage { IconImage {
id: menuIconImg id: menuIconImg
width: 20 anchors.centerIn: parent
height: 20 width: Theme.barIconSize(root.barThickness)
anchors.verticalCenter: parent.verticalCenter height: Theme.barIconSize(root.barThickness)
source: parent.parent.iconSource source: parent.iconSource
asynchronous: true asynchronous: true
smooth: true smooth: true
mipmap: true mipmap: true
@@ -533,7 +582,7 @@ Item {
} }
Text { Text {
anchors.verticalCenter: parent.verticalCenter anchors.centerIn: parent
visible: !menuIconImg.visible visible: !menuIconImg.visible
text: { text: {
const itemId = trayItem?.id || "" const itemId = trayItem?.id || ""
@@ -544,53 +593,9 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
} }
StyledText {
text: trayItem?.tooltip?.title || trayItem?.id || "Unknown"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
width: Math.min(implicitWidth, menuColumn.width - 80)
}
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
width: 24
height: 24
radius: Theme.cornerRadius
color: visibilityArea.containsMouse ? Theme.primaryHover : "transparent"
DankIcon {
anchors.centerIn: parent
name: SessionData.isHiddenTrayId(trayItem?.id || "") ? "visibility_off" : "visibility"
size: 16
color: Theme.surfaceText
}
MouseArea {
id: visibilityArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const itemId = trayItem?.id || ""
if (!itemId) return
if (SessionData.isHiddenTrayId(itemId)) {
SessionData.showTrayId(itemId)
} else {
SessionData.hideTrayId(itemId)
}
}
}
}
MouseArea { MouseArea {
id: itemArea id: itemArea
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 32
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
@@ -602,7 +607,10 @@ Item {
root.menuOpen = false root.menuOpen = false
return return
} }
if (trayItem.hasMenu) {
if (!trayItem.hasMenu) return
root.overflowWasOpenBeforeTrayMenu = true
root.menuOpen = false root.menuOpen = false
root.showForTrayItem(trayItem, parent, parentScreen, root.isAtBottom, root.isVertical, root.axis) root.showForTrayItem(trayItem, parent, parentScreen, root.isAtBottom, root.isVertical, root.axis)
} }
@@ -611,8 +619,6 @@ Item {
} }
} }
} }
}
}
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -665,6 +671,20 @@ Item {
function close() { function close() {
showMenu = false showMenu = false
if (root.overflowWasOpenBeforeTrayMenu) {
root.menuOpen = true
Qt.callLater(() => {
if (overflowMenu.visible && overflowFocusScope) {
overflowFocusScope.forceActiveFocus()
}
})
}
root.overflowWasOpenBeforeTrayMenu = false
}
function closeWithAction() {
root.overflowWasOpenBeforeTrayMenu = false
close()
} }
function showSubMenu(entry) { function showSubMenu(entry) {
@@ -697,7 +717,7 @@ Item {
visible: menuRoot.showMenu && (menuRoot.trayItem?.hasMenu ?? false) visible: menuRoot.showMenu && (menuRoot.trayItem?.hasMenu ?? false)
WlrLayershell.layer: WlrLayershell.Top WlrLayershell.layer: WlrLayershell.Top
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
color: "transparent" color: "transparent"
anchors { anchors {
@@ -707,11 +727,29 @@ Item {
bottom: true bottom: true
} }
readonly property real dpr: (typeof CompositorService !== "undefined" && CompositorService.getScreenScale)
? CompositorService.getScreenScale(menuWindow.screen)
: (screen?.devicePixelRatio || 1)
property point anchorPos: Qt.point(screen.width / 2, screen.height / 2) property point anchorPos: Qt.point(screen.width / 2, screen.height / 2)
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
updatePosition() updatePosition()
Qt.callLater(() => menuFocusScope.forceActiveFocus())
}
}
FocusScope {
id: menuFocusScope
anchors.fill: parent
focus: true
Keys.onEscapePressed: {
if (entryStack.count > 0) {
menuRoot.goBack()
} else {
menuRoot.close()
}
} }
} }
@@ -744,64 +782,104 @@ Item {
} }
} }
Rectangle { Item {
id: menuContainer id: menuContainer
width: Math.min(500, Math.max(250, menuColumn.implicitWidth + Theme.spacingS * 2)) readonly property real rawWidth: Math.min(500, Math.max(250, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(40, menuColumn.implicitHeight + Theme.spacingS * 2) readonly property real rawHeight: Math.max(40, menuColumn.implicitHeight + Theme.spacingS * 2)
x: { readonly property real alignedWidth: Theme.px(rawWidth, menuWindow.dpr)
readonly property real alignedHeight: Theme.px(rawHeight, menuWindow.dpr)
width: alignedWidth
height: alignedHeight
x: Theme.snap((() => {
if (menuRoot.isVertical) { if (menuRoot.isVertical) {
const edge = menuRoot.axis?.edge const edge = menuRoot.axis?.edge
if (edge === "left") { if (edge === "left") {
const targetX = menuWindow.anchorPos.x const targetX = menuWindow.anchorPos.x
return Math.min(menuWindow.screen.width - width - 10, targetX) return Math.min(menuWindow.screen.width - alignedWidth - 10, targetX)
} else { } else {
const targetX = menuWindow.anchorPos.x - width const targetX = menuWindow.anchorPos.x - alignedWidth
return Math.max(10, targetX) return Math.max(10, targetX)
} }
} else { } else {
const left = 10 const left = 10
const right = menuWindow.width - width - 10 const right = menuWindow.width - alignedWidth - 10
const want = menuWindow.anchorPos.x - width / 2 const want = menuWindow.anchorPos.x - alignedWidth / 2
return Math.max(left, Math.min(right, want)) return Math.max(left, Math.min(right, want))
} }
} })(), menuWindow.dpr)
y: { y: Theme.snap((() => {
if (menuRoot.isVertical) { if (menuRoot.isVertical) {
const top = 10 const top = 10
const bottom = menuWindow.height - height - 10 const bottom = menuWindow.height - alignedHeight - 10
const want = menuWindow.anchorPos.y - height / 2 const want = menuWindow.anchorPos.y - alignedHeight / 2
return Math.max(top, Math.min(bottom, want)) return Math.max(top, Math.min(bottom, want))
} else { } else {
if (menuRoot.isAtBottom) { if (menuRoot.isAtBottom) {
const targetY = menuWindow.anchorPos.y - height const targetY = menuWindow.anchorPos.y - alignedHeight
return Math.max(10, targetY) return Math.max(10, targetY)
} else { } else {
const targetY = menuWindow.anchorPos.y const targetY = menuWindow.anchorPos.y
return Math.min(menuWindow.screen.height - height - 10, targetY) return Math.min(menuWindow.screen.height - alignedHeight - 10, targetY)
}
} }
} }
})(), menuWindow.dpr)
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) property real shadowBlurPx: 10
radius: Theme.cornerRadius property real shadowSpreadPx: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) property real shadowBaseAlpha: 0.60
border.width: 1 readonly property real popupSurfaceAlpha: Theme.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
opacity: menuRoot.showMenu ? 1 : 0 opacity: menuRoot.showMenu ? 1 : 0
scale: menuRoot.showMenu ? 1 : 0.85 scale: menuRoot.showMenu ? 1 : 0.85
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Item {
id: menuBgShadowLayer
anchors.fill: parent
layer.enabled: true
layer.smooth: true
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
layer.textureMirroring: ShaderEffectSource.MirrorVertically
layer.effect: MultiEffect {
autoPaddingEnabled: true
shadowEnabled: true
blurEnabled: false
maskEnabled: false
property int blurMax: 64
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / blurMax))
shadowScale: 1 + (2 * menuContainer.shadowSpreadPx) / Math.max(1, Math.min(menuBgShadowLayer.width, menuBgShadowLayer.height))
shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha)
}
}
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 4 color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
anchors.leftMargin: 2 radius: Theme.cornerRadius
anchors.rightMargin: -2 antialiasing: true
anchors.bottomMargin: -4 }
radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15)
z: parent.z - 1
} }
QsMenuAnchor { QsMenuAnchor {
@@ -832,12 +910,90 @@ Item {
anchors.topMargin: Theme.spacingS anchors.topMargin: Theme.spacingS
spacing: 1 spacing: 1
Rectangle {
visible: entryStack.count === 0
width: parent.width
height: 24
color: "transparent"
StyledText {
anchors.centerIn: parent
text: menuRoot.trayItem?.id || "Unknown"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
elide: Text.ElideMiddle
width: parent.width - Theme.spacingS * 2
horizontalAlignment: Text.AlignHCenter
}
}
Rectangle {
visible: entryStack.count === 0
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle {
visible: entryStack.count === 0
width: parent.width
height: 28
radius: 0
color: visibilityToggleArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceContainer, 0)
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
DankIcon {
name: SessionData.isHiddenTrayId(menuRoot.trayItem?.id || "") ? "visibility" : "visibility_off"
size: 16
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: SessionData.isHiddenTrayId(menuRoot.trayItem?.id || "") ? "Show in Tray" : "Hide from Tray"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: visibilityToggleArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const itemId = menuRoot.trayItem?.id || ""
if (!itemId) return
if (SessionData.isHiddenTrayId(itemId)) {
SessionData.showTrayId(itemId)
} else {
SessionData.hideTrayId(itemId)
}
menuRoot.closeWithAction()
}
}
}
Rectangle {
visible: entryStack.count === 0
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle { Rectangle {
visible: entryStack.count > 0 visible: entryStack.count > 0
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadius radius: 0
color: backArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: backArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceContainer, 0)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -863,6 +1019,7 @@ Item {
MouseArea { MouseArea {
id: backArea id: backArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: menuRoot.goBack() onClicked: menuRoot.goBack()
} }
@@ -886,33 +1043,35 @@ Item {
width: menuColumn.width width: menuColumn.width
height: menuEntry?.isSeparator ? 1 : 28 height: menuEntry?.isSeparator ? 1 : 28
radius: menuEntry?.isSeparator ? 0 : Theme.cornerRadius radius: 0
color: { color: {
if (menuEntry?.isSeparator) { if (menuEntry?.isSeparator) {
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
return itemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" return itemArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceContainer, 0)
} }
MouseArea { MouseArea {
id: itemArea id: itemArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
enabled: !menuEntry?.isSeparator && (menuEntry?.enabled !== false) enabled: !menuEntry?.isSeparator && (menuEntry?.enabled !== false)
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!menuEntry || menuEntry.isSeparator) return; if (!menuEntry || menuEntry.isSeparator) return
if (menuEntry.hasChildren) { if (menuEntry.hasChildren) {
menuRoot.showSubMenu(menuEntry); menuRoot.showSubMenu(menuEntry)
} else { return
}
if (typeof menuEntry.activate === "function") { if (typeof menuEntry.activate === "function") {
menuEntry.activate(); menuEntry.activate()
} else if (typeof menuEntry.triggered === "function") { } else if (typeof menuEntry.triggered === "function") {
menuEntry.triggered(); menuEntry.triggered()
}
Qt.createQmlObject('import QtQuick; Timer { interval: 80; running: true; repeat: false; onTriggered: menuRoot.close() }', menuRoot);
} }
Qt.createQmlObject('import QtQuick; Timer { interval: 80; running: true; repeat: false; onTriggered: menuRoot.closeWithAction() }', menuRoot)
} }
} }
@@ -996,20 +1155,6 @@ Item {
} }
} }
} }
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }
MouseArea { MouseArea {

View File

@@ -250,7 +250,10 @@ PanelWindow {
property int blurMax: 64 property int blurMax: 64
shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / blurMax)) shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / blurMax))
shadowScale: 1 + (2 * content.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height)) shadowScale: 1 + (2 * content.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
shadowColor: Qt.rgba(0, 0, 0, content.effectiveShadowAlpha) shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
return Theme.withAlpha(baseColor, content.effectiveShadowAlpha)
}
} }
Shape { Shape {

View File

@@ -143,7 +143,10 @@ PanelWindow {
property int blurMax: 64 property int blurMax: 64
shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / blurMax)) shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / blurMax))
shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height)) shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
shadowColor: Qt.rgba(0, 0, 0, osdContainer.effectiveShadowAlpha) shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
return Theme.withAlpha(baseColor, osdContainer.effectiveShadowAlpha)
}
} }
DankRectangle { DankRectangle {

View File

@@ -224,7 +224,10 @@ PanelWindow {
property int blurMax: 64 property int blurMax: 64
shadowBlur: Math.max(0, Math.min(1, contentWrapper.shadowBlurPx / blurMax)) shadowBlur: Math.max(0, Math.min(1, contentWrapper.shadowBlurPx / blurMax))
shadowScale: 1 + (2 * contentWrapper.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height)) shadowScale: 1 + (2 * contentWrapper.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
shadowColor: Qt.rgba(0, 0, 0, contentWrapper.effectiveShadowAlpha) shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest
return Theme.withAlpha(baseColor, contentWrapper.effectiveShadowAlpha)
}
} }
DankRectangle { DankRectangle {