import QtQuick import Quickshell import Quickshell.Services.SystemTray import Quickshell.Io import "../../../config" Row { // Workspace Row id: trayRow spacing: Config.small_spacing_fun(height) Repeater { model: SystemTray.items Column{ Item { width: 1 height: Math.floor((bar.height - trayItem.height) / 2) } Rectangle { //trayItem id: trayItem width: iconImage.width + Config.spacing_fun(bar.height) height: iconImage.height + Config.spacing_fun(bar.height) radius: Config.radius_fun(trayRow.height) color: trayArea.containsMouse ? Colors.tertiaryContainer : modelData.active ? Colors.primaryContainer : Colors.secondaryContainer border.width: Config.border_width border.color: trayArea.containsMouse ? Colors.tertiaryContainer_fg : Colors.secondaryContainer_fg Process { id: steamRunner command: ["steam", "steam://open/main"] running: false } MouseArea { id: trayArea hoverEnabled: true cursorShape: Qt.PointingHandCursor anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton property int clickX: 0 property int clickY: 0 onClicked: (mouse) => { switch (mouse.button) { case Qt.LeftButton: console.log("[Tray] Activate: " + modelData.title) if (!modelData.onlyMenu) modelData.activate() if (modelData.title.trim() === "Steam") { console.log("[Tray] Starting Steam") steamRunner.startDetached() } break case Qt.RightButton: console.log("[Tray] Context menu: " + modelData.title) clickX = mouse.x clickY = mouse.y trayMenu.menu = modelData.menu trayMenu.open() break case Qt.MiddleButton: console.log("[Tray] Secondary activate: " + modelData.title) modelData.secondaryActivate() break } } } QsMenuAnchor { id: trayMenu anchor { item: trayArea edges: Edges.Top | Edges.Left gravity: Edges.Bottom | Edges.Right adjustment: PopupAdjustment.FlipX | PopupAdjustment.SlideY onAnchoring: { rect.x = trayArea.clickX rect.y = trayArea.clickY rect.w = 1 rect.h = 1 } } } Image { // Image id: iconImage anchors.centerIn: parent width: Config.halfBigIconSize(bar.height) height: Config.halfBigIconSize(bar.height) asynchronous: true cache: true } Timer { interval: Config.reload_interval running: true repeat: true triggeredOnStart: true onTriggered: { let src = modelData.icon; // console.log("########## icon: " + modelData.icon) // console.log("########## name: " + modelData.title) if (modelData.title.includes('GoXLR')) { // console.log("[Tray] Resolving GoXLR icon path") let pathMatch = src.match(/path=([^&]+)/); if (pathMatch && pathMatch[1]) { let folderPath = pathMatch[1]; let segments = folderPath.split('/'); let fileName = segments[segments.length - 1] + "-icon.png"; src = "file://" + pathMatch[1] + "/" + fileName; } } // if (modelData.title.includes('Nextcloud')) { // src = Quickshell.iconPath("Nextcloud") // } // console.log("########## icon: " + src) if (src.exists) { console.log("########## icon: " + src) } // Set the resolved source iconImage.source = src; } } } } } }