import QtQuick import QtQuick.Effects import QtQuick.Layouts import Quickshell import Quickshell.Services.SystemTray import "." as M RowLayout { id: root spacing: M.Theme.moduleSpacing + 2 required property var bar property var _activeMenu: null Repeater { model: SystemTray.items delegate: Item { id: iconItem required property SystemTrayItem modelData readonly property bool _needsAttention: modelData.status === 2 property bool _hovered: false property real _pulseOpacity: 1 implicitWidth: 18 implicitHeight: 18 SequentialAnimation { running: iconItem._needsAttention loops: Animation.Infinite NumberAnimation { target: iconItem property: "_pulseOpacity" to: 0.3 duration: 400 easing.type: Easing.InOutQuad } NumberAnimation { target: iconItem property: "_pulseOpacity" to: 1 duration: 400 easing.type: Easing.InOutQuad } onRunningChanged: if (!running) iconItem._pulseOpacity = 1 } Item { anchors.fill: parent opacity: iconItem._pulseOpacity layer.enabled: iconItem._needsAttention || iconItem._hovered layer.effect: MultiEffect { shadowEnabled: true shadowColor: iconItem._needsAttention ? M.Theme.base08 : M.Theme.base05 shadowBlur: iconItem._needsAttention ? 0.8 : 0.5 shadowVerticalOffset: 0 shadowHorizontalOffset: 0 } M.ThemedIcon { anchors.fill: parent source: iconItem.modelData.icon tint: iconItem._needsAttention ? M.Theme.base08 : M.Theme.base0D } } HoverHandler { onHoveredChanged: { iconItem._hovered = hovered; const tip = [iconItem.modelData.tooltipTitle, iconItem.modelData.tooltipDescription].filter(s => s).join("\n") || iconItem.modelData.title; if (hovered && tip) { M.FlyoutState.text = tip; M.FlyoutState.itemX = iconItem.mapToGlobal(iconItem.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0); M.FlyoutState.screen = QsWindow.window?.screen ?? null; M.FlyoutState.visible = true; } else if (!hovered) { M.FlyoutState.visible = false; } } } MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: mouse => { if (mouse.button === Qt.LeftButton) { iconItem.modelData.activate(); } else if (mouse.button === Qt.RightButton) { if (iconItem.modelData.menu) { if (root._activeMenu && root._activeMenu !== menuLoader) root._activeMenu.active = false; menuLoader.active = true; M.FlyoutState.visible = false; root._activeMenu = menuLoader; } else { iconItem.modelData.secondaryActivate(); } } } } // Per-icon context menu window, created on demand Loader { id: menuLoader active: false sourceComponent: M.TrayMenu { handle: iconItem.modelData.menu screen: root.bar.screen anchorX: iconItem.mapToGlobal(iconItem.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) onDismissed: { menuLoader.active = false; root._activeMenu = null; } } } } } }