Tray: fix for hyprland (untested)

This commit is contained in:
ItsLemmy
2025-11-11 13:35:35 -05:00
parent 093b32803b
commit 8aa4254d57
6 changed files with 145 additions and 61 deletions
+23 -10
View File
@@ -15,18 +15,27 @@ Rectangle {
property ShellScreen screen
// Get shared tray menu window from MainScreen (via screen's parent MainScreen)
// Trigger re-evaluation when window is registered
property int trayMenuUpdateTrigger: 0
// Get shared tray menu window from PanelService (reactive to trigger changes)
readonly property var trayMenuWindow: {
// Access via PanelService to get the MainScreen that contains the trayMenuWindow
if (!screen)
return null
// Get any panel from this screen to access its parent MainScreen
const drawerPanel = PanelService.getPanel("trayDrawerPanel", screen)
return drawerPanel?.trayMenuWindow || null
// Reference trigger to force re-evaluation
var _ = trayMenuUpdateTrigger
return PanelService.getTrayMenuWindow(screen)
}
readonly property var trayMenu: trayMenuWindow ? trayMenuWindow.trayMenuLoader : null
Connections {
target: PanelService
function onTrayMenuWindowRegistered(registeredScreen) {
if (registeredScreen === screen) {
root.trayMenuUpdateTrigger++
}
}
}
// Widget properties passed from Bar.qml for per-instance settings
property string widgetId: ""
property string section: ""
@@ -310,7 +319,9 @@ Rectangle {
if (mouse.button === Qt.LeftButton) {
// Close any open menu first
trayMenuWindow.close()
if (trayMenuWindow) {
trayMenuWindow.close()
}
if (!modelData.onlyMenu) {
modelData.activate()
@@ -337,7 +348,7 @@ Rectangle {
drawerPanel.close()
}
if (modelData.hasMenu && modelData.menu && trayMenu.item) {
if (modelData.hasMenu && modelData.menu && trayMenuWindow && trayMenu && trayMenu.item) {
trayMenuWindow.open()
// Position menu based on bar position
@@ -365,7 +376,9 @@ Rectangle {
}
}
onEntered: {
trayMenuWindow.close()
if (trayMenuWindow) {
trayMenuWindow.close()
}
TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
}
onExited: TooltipService.hide()
+15
View File
@@ -83,5 +83,20 @@ Variants {
Logger.d("Shell", "BarExclusionZone created for", modelData?.name)
}
}
// TrayMenuWindow - separate window for tray context menus
// This must be a top-level PanelWindow.
Loader {
active: parent.windowLoaded && parent.shouldBeActive
asynchronous: false
sourceComponent: TrayMenuWindow {
screen: modelData
}
onLoaded: {
Logger.d("Shell", "TrayMenuWindow created for", modelData?.name)
}
}
}
}
-45
View File
@@ -44,7 +44,6 @@ PanelWindow {
readonly property alias trayDrawerPanel: trayDrawerPanel
readonly property alias wallpaperPanel: wallpaperPanel
readonly property alias wifiPanel: wifiPanel
readonly property alias trayMenuWindow: trayMenuWindow
Component.onCompleted: {
Logger.d("MainScreen", "Initialized for screen:", screen?.name, "- Dimensions:", screen?.width, "x", screen?.height, "- Position:", screen?.x, ",", screen?.y)
@@ -286,7 +285,6 @@ PanelWindow {
TrayDrawerPanel {
id: trayDrawerPanel
screen: root.screen
trayMenuWindow: root.trayMenuWindow
z: 50
Component.onCompleted: {
@@ -317,49 +315,6 @@ PanelWindow {
}
}
// ----------------------------------------------
// Shared TrayMenu window for context menus (used by both Tray widget and TrayDrawerPanel)
PanelWindow {
id: trayMenuWindow
anchors.top: true
anchors.left: true
anchors.right: true
anchors.bottom: true
visible: false
color: Color.transparent
screen: root.screen
// Expose the trayMenu Loader directly
readonly property alias trayMenuLoader: trayMenu
function open() {
visible = true
}
function close() {
visible = false
if (trayMenu.item) {
trayMenu.item.hideMenu()
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: trayMenuWindow.close()
}
Loader {
id: trayMenu
source: "../Bar/Extras/TrayMenu.qml"
onLoaded: {
if (item) {
item.screen = root.screen
}
}
}
}
// ----------------------------------------------
// Bar background placeholder - just for background positioning (actual bar content is in BarContentWindow)
Item {
+63
View File
@@ -0,0 +1,63 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Commons
import qs.Services.UI
import qs.Modules.Bar.Extras
// Separate window for TrayMenu context menus
// This is a top-level PanelWindow (sibling to MainScreen, not nested inside it)
PanelWindow {
id: root
required property ShellScreen screen
anchors.top: true
anchors.left: true
anchors.right: true
anchors.bottom: true
visible: false
color: Color.transparent
// Use Top layer (same as MainScreen) for proper event handling
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
WlrLayershell.namespace: "noctalia-traymenu-" + (screen?.name || "unknown")
WlrLayershell.exclusionMode: ExclusionMode.Ignore
// Expose the trayMenu Loader directly
readonly property alias trayMenuLoader: trayMenu
// Register with PanelService so panels can find this window
Component.onCompleted: {
objectName = "trayMenuWindow-" + (screen?.name || "unknown")
PanelService.registerTrayMenuWindow(screen, root)
}
function open() {
visible = true
}
function close() {
visible = false
if (trayMenu.item) {
trayMenu.item.hideMenu()
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: root.close()
}
Loader {
id: trayMenu
source: "../Bar/Extras/TrayMenu.qml"
onLoaded: {
if (item) {
item.screen = root.screen
}
}
}
}
+23 -6
View File
@@ -12,9 +12,6 @@ import qs.Modules.MainScreen
SmartPanel {
id: root
// Shared tray menu window (set by MainScreen)
property var trayMenuWindow: null
// Widget info for menu functionality
property string widgetSection: ""
property int widgetIndex: -1
@@ -99,9 +96,27 @@ SmartPanel {
}
}
// Get the trayMenu Loader from the shared window
// Trigger re-evaluation when window is registered
property int trayMenuUpdateTrigger: 0
// Get the trayMenu window and loader from PanelService (reactive to trigger changes)
readonly property var trayMenuWindow: {
// Reference trigger to force re-evaluation
var _ = trayMenuUpdateTrigger
return PanelService.getTrayMenuWindow(screen)
}
readonly property var trayMenu: trayMenuWindow ? trayMenuWindow.trayMenuLoader : null
Connections {
target: PanelService
function onTrayMenuWindowRegistered(registeredScreen) {
if (registeredScreen === screen) {
root.trayMenuUpdateTrigger++
}
}
}
panelContent: Item {
id: content
@@ -176,7 +191,7 @@ SmartPanel {
return
}
if (modelData.hasMenu && modelData.menu && trayMenu.item) {
if (modelData.hasMenu && modelData.menu && trayMenuWindow && trayMenu && trayMenu.item) {
trayMenuWindow.open()
// Position menu at the tray icon
@@ -211,7 +226,9 @@ SmartPanel {
}
onEntered: {
trayMenuWindow.close()
if (trayMenuWindow) {
trayMenuWindow.close()
}
TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
}
onExited: TooltipService.hide()
+21
View File
@@ -16,12 +16,33 @@ Singleton {
signal willOpen
signal didClose
// Tray menu windows (one per screen)
property var trayMenuWindows: ({})
signal trayMenuWindowRegistered(var screen)
// Register this panel (called after panel is loaded)
function registerPanel(panel) {
registeredPanels[panel.objectName] = panel
Logger.d("PanelService", "Registered panel:", panel.objectName)
}
// Register tray menu window for a screen
function registerTrayMenuWindow(screen, window) {
if (!screen || !window)
return
var key = screen.name
trayMenuWindows[key] = window
Logger.d("PanelService", "Registered tray menu window for screen:", key)
trayMenuWindowRegistered(screen)
}
// Get tray menu window for a screen
function getTrayMenuWindow(screen) {
if (!screen)
return null
return trayMenuWindows[screen.name] || null
}
// Returns a panel (loads it on-demand if not yet loaded)
function getPanel(name, screen) {
if (!screen) {