mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Tray: fix for hyprland (untested)
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user