// System tray (StatusNotifierItem / AppIndicator). // // GNOME removed this and never replaced it; Nextcloud, RustDesk and Slack all // still expect it, so it is a first-class part of this bar. Left click // activates, right click opens the item's own menu — rendered in QML by // TrayMenu so it matches the rest of the shell instead of dropping a GTK menu // on top of it. import Quickshell import Quickshell.Services.SystemTray import Quickshell.Widgets import QtQuick import qs.config Row { id: root spacing: 2 Repeater { model: SystemTray.items delegate: Item { id: entry required property SystemTrayItem modelData implicitWidth: 26 implicitHeight: Theme.barHeight - 8 Rectangle { anchors.fill: parent radius: Theme.pillRadius border.width: 0 color: mouse.containsMouse ? Theme.alpha(Theme.fg, Theme.hoverAlpha) : "transparent" Behavior on color { ColorAnimation { duration: Theme.durFast } } } IconImage { anchors.centerIn: parent implicitSize: 16 asynchronous: true mipmap: true // `icon` is already a resolved URL — running it through // Quickshell.iconPath() would break it. source: entry.modelData.icon } MouseArea { id: mouse anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton cursorShape: Qt.PointingHandCursor onClicked: event => { // onlyMenu items have no activate action at all, so a left // click has to fall through to the menu or nothing happens. if (event.button === Qt.RightButton || entry.modelData.onlyMenu) { if (entry.modelData.hasMenu) menu.visible = !menu.visible; } else if (event.button === Qt.MiddleButton) { entry.modelData.secondaryActivate(); } else { entry.modelData.activate(); } } onWheel: event => entry.modelData.scroll(event.angleDelta.y, false) } TrayMenu { id: menu anchorItem: entry trayItem: entry.modelData } } } }