import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Wayland import Quickshell.Services.SystemTray import Quickshell.Widgets import "../../config" as Cfg Item { id: root property real panelRadius: Cfg.Config.radius / 2 property int borderWidth: Cfg.Config.panelBorderWidth property bool isTop: true property var targetScreen: null property string barSide: "right" readonly property var t: Cfg.Config.theme property bool expanded: false property bool manuallyExpanded: false property var menuWindow: null implicitWidth: bgRect.width implicitHeight: bgRect.height Rectangle { id: bgRect anchors.verticalCenter: parent.verticalCenter height: Cfg.Config.trayHeight width: mainRow.width radius: root.panelRadius color: bgHover.hovered ? root.t.trayBgHover : root.t.trayBg border.color: bgHover.hovered ? root.t.trayBorderHover : root.t.trayBorder border.width: root.borderWidth Behavior on color { ColorAnimation { duration: 150 } } Behavior on border.color { ColorAnimation { duration: 150 } } HoverHandler { id: bgHover onHoveredChanged: { if (!root.manuallyExpanded) { root.expanded = hovered; } } } Row { id: mainRow anchors.verticalCenter: parent.verticalCenter leftPadding: root.expanded && root.barSide === "right" ? 8 : 0 rightPadding: root.expanded && root.barSide === "left" ? 8 : 0 Behavior on leftPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } Behavior on rightPadding { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } layoutDirection: root.barSide === "left" ? Qt.LeftToRight : Qt.RightToLeft spacing: root.expanded ? 4 : 0 Behavior on spacing { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } Item { id: toggleArea width: Cfg.Config.trayHeight height: Cfg.Config.trayHeight z: 10 TapHandler { onTapped: { root.manuallyExpanded = !root.manuallyExpanded; root.expanded = root.manuallyExpanded; } } Text { anchors.centerIn: parent text: root.expanded ? (root.barSide === "left" ? "󰅁" : "󰅂") : (root.barSide === "left" ? "󰅂" : "󰅁") color: root.t.trayIcon font.pixelSize: Cfg.Config.trayHeight * 0.55 } } Row { id: iconsRow spacing: 6 clip: true anchors.verticalCenter: parent.verticalCenter width: root.expanded ? implicitWidth : 0 opacity: root.expanded ? 1 : 0 Behavior on width { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } Behavior on opacity { NumberAnimation { duration: 150 } } Repeater { model: SystemTray.items delegate: MouseArea { id: iconDelegate required property SystemTrayItem modelData property alias item: iconDelegate.modelData implicitWidth: Cfg.Config.trayIconSize implicitHeight: Cfg.Config.trayIconSize width: Cfg.Config.trayIconSize height: Cfg.Config.trayIconSize acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton hoverEnabled: true onClicked: function(mouse) { if (mouse.button === Qt.LeftButton) { item.activate() } else if (mouse.button === Qt.MiddleButton) { item.secondaryActivate() } else if (mouse.button === Qt.RightButton) { menuAnchor.open() } } onWheel: function(wheel) { wheel.accepted = true item.scroll(wheel.angleDelta.y / 120, false) } IconImage { anchors.fill: parent source: item.icon } QsMenuAnchor { id: menuAnchor menu: item.menu anchor.window: root.menuWindow anchor.adjustment: PopupAdjustment.Flip anchor.onAnchoring: { if (!root.menuWindow) return const global = iconDelegate.mapToGlobal(0, iconDelegate.height) const local = root.menuWindow.contentItem.mapFromGlobal( global.x, global.y ) menuAnchor.anchor.rect = Qt.rect( local.x, local.y, iconDelegate.width, 0 ) } } } } } } } }