Tray: reverted all the mitigation now that the real issue has been fixed in Quickshell.

This commit is contained in:
ItsLemmy
2025-11-15 21:01:48 -05:00
parent 3f1bcf1ae8
commit ead2b82680
2 changed files with 21 additions and 145 deletions

View File

@@ -19,136 +19,8 @@ PopupWindow {
property string widgetSection: ""
property int widgetIndex: -1
// Menu can be set directly (for submenus) or derived from trayItem
property var menu: null
property var stableMenu: null // Debounced menu for opener binding
property var menuItems: []
property int loadRetryCount: 0
property bool isLoadingMenu: false // Mutex to prevent concurrent access
// Debounce timer to prevent rapid menu rebinding
Timer {
id: menuDebounceTimer
interval: 50
repeat: false
onTriggered: {
// Update stable menu only after debounce period
if (root.visible && root.menu) {
root.stableMenu = root.menu
} else {
root.stableMenu = null
}
}
}
// Timer to defer menu loading to avoid freezing on opener.children access
// Uses retry mechanism with exponential backoff for reliability
Timer {
id: menuLoadTimer
interval: 50
repeat: false
onTriggered: {
// Early exit if not visible, no stable menu, or already loading
if (!root.visible || !root.stableMenu || root.isLoadingMenu) {
root.menuItems = []
root.loadRetryCount = 0
root.isLoadingMenu = false
return
}
// Set loading flag to prevent concurrent access
root.isLoadingMenu = true
try {
if (opener && opener.children && 'values' in opener.children) {
const values = opener.children.values
if (values && values.length > 0) {
root.menuItems = [...values]
root.loadRetryCount = 0 // Success, reset retry count
root.isLoadingMenu = false
} else {
// Empty menu - retry if we haven't exceeded max attempts
if (root.loadRetryCount < 3) {
root.loadRetryCount++
menuLoadTimer.interval = 150 * Math.pow(2, root.loadRetryCount - 1) // Exponential backoff: 150, 300, 600
root.isLoadingMenu = false // Release lock before retry
menuLoadTimer.running = true
} else {
// Max retries exceeded, give up gracefully
root.menuItems = []
root.loadRetryCount = 0
root.isLoadingMenu = false
}
}
} else {
// opener.children not ready - retry if we haven't exceeded max attempts
if (root.loadRetryCount < 3) {
root.loadRetryCount++
menuLoadTimer.interval = 150 * Math.pow(2, root.loadRetryCount - 1) // Exponential backoff
root.isLoadingMenu = false // Release lock before retry
menuLoadTimer.running = true
} else {
// Max retries exceeded, give up gracefully
root.menuItems = []
root.loadRetryCount = 0
root.isLoadingMenu = false
}
}
} catch (e) {
Logger.w("TrayMenu", "Error accessing menu items:", e)
root.menuItems = []
root.loadRetryCount = 0
root.isLoadingMenu = false
}
}
}
onVisibleChanged: {
if (visible && menu) {
// Cancel all pending operations
menuDebounceTimer.running = false
menuLoadTimer.running = false
root.isLoadingMenu = false
root.loadRetryCount = 0
// Start debounce for stable menu
menuDebounceTimer.running = true
} else if (!visible) {
// Clean up when hiding
menuDebounceTimer.running = false
menuLoadTimer.running = false
root.isLoadingMenu = false
root.loadRetryCount = 0
root.stableMenu = null
root.menuItems = []
}
}
onMenuChanged: {
// Cancel pending load whenever menu changes
menuLoadTimer.running = false
root.isLoadingMenu = false
root.loadRetryCount = 0
root.menuItems = []
if (visible && menu) {
// Restart debounce timer
menuDebounceTimer.running = false
menuDebounceTimer.running = true
} else {
menuDebounceTimer.running = false
root.stableMenu = null
}
}
onStableMenuChanged: {
if (visible && stableMenu) {
// Stable menu is ready, start loading
menuLoadTimer.interval = 150 // Reset to initial interval
menuLoadTimer.running = false
menuLoadTimer.running = true
}
}
// Derive menu from trayItem (only used for non-submenus)
readonly property QsMenuHandle menu: isSubMenu ? null : (trayItem ? trayItem.menu : null)
// Compute if current tray item is pinned
readonly property bool isPinned: {
@@ -193,8 +65,10 @@ PopupWindow {
return
}
if (!isSubMenu && trayItem && trayItem.menu) {
menu = trayItem.menu
if (!opener.children || opener.children.values.length === 0) {
//Logger.w("TrayMenu", "Menu not ready, delaying show")
Qt.callLater(() => showAt(item, x, y))
return
}
anchorItem = item
@@ -210,7 +84,7 @@ PopupWindow {
})
}
function hideMenu(closeWindow = true) {
function hideMenu() {
visible = false
// Clean up all submenus recursively
@@ -222,20 +96,23 @@ PopupWindow {
child.subMenu = null
}
}
}
// Close the parent TrayMenuWindow if this is not a submenu
// closeWindow parameter prevents infinite recursion
if (closeWindow && !isSubMenu && screen) {
const trayMenuWindow = PanelService.getTrayMenuWindow(screen)
if (trayMenuWindow) {
trayMenuWindow.close()
}
}
// Full-sized, transparent MouseArea to track the mouse.
MouseArea {
id: rootMouseArea
anchors.fill: parent
hoverEnabled: true
}
Item {
anchors.fill: parent
Keys.onEscapePressed: root.hideMenu()
}
QsMenuOpener {
id: opener
menu: root.stableMenu // Bind to debounced stable menu instead of raw menu
menu: root.menu
}
Rectangle {
@@ -280,7 +157,7 @@ PopupWindow {
spacing: 0
Repeater {
model: root.menuItems
model: opener.children ? [...opener.children.values] : []
delegate: Rectangle {
id: entry
@@ -399,7 +276,6 @@ PopupWindow {
entry.subMenu.anchorItem = entry
entry.subMenu.anchorX = openLeft ? -overlap : overlap
entry.subMenu.anchorY = 0
entry.subMenu.menuLoadTrigger++
entry.subMenu.visible = true
// Force anchor update with new position
Qt.callLater(() => {

View File

@@ -41,7 +41,7 @@ PanelWindow {
function close() {
visible = false
if (trayMenu.item) {
trayMenu.item.hideMenu(false) // Don't close window again (prevents recursion)
trayMenu.item.hideMenu()
}
}