From e58e37be2980f8c642580d5fa95cc1ddbf4c49f6 Mon Sep 17 00:00:00 2001 From: Attila Greguss Date: Wed, 27 Nov 2024 15:36:01 +0000 Subject: [PATCH] Always show panel if a menu is open on it (#11779) * fix: Resizing applet PopupMenus will go behind panel if panel is set to auto hide The problem is that the panel reports it's not visible even though it is, so the x,y calculation for PopupMenus are incorrect. Panels are not hidden until `global.menuStackLength` is bigger than one (meaning a PopupMenu is open for example) * Make sure only the panel that has open menus are shown * Use the new function instead of the stack directly * There is no need for the extra check in hide anymore * Add check back --- js/ui/main.js | 2 +- js/ui/panel.js | 24 ++++++++++++++++++++-- js/ui/popupMenu.js | 51 +++++++++++++++++++++++++++++----------------- js/ui/tooltips.js | 2 +- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/js/ui/main.js b/js/ui/main.js index 1d1a991bc0..023100579a 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -380,7 +380,7 @@ function start() { global.reparentActor(global.top_window_group, global.stage); - global.menuStackLength = 0; + global.menuStack = []; layoutManager = new Layout.LayoutManager(); diff --git a/js/ui/panel.js b/js/ui/panel.js index 3730449da8..e9c171c20d 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -3598,6 +3598,26 @@ Panel.prototype = { } }, + /** + * _panelHasOpenMenus: + * + * Checks if panel has open menus in the global.menuStack + * @returns + */ + _panelHasOpenMenus: function() { + if (global.menuStack == null || global.menuStack.length == 0) + return false; + + for (let i = 0; i < global.menuStack.length; i++) { + let menu = global.menuStack[i]; + if (menu.getPanel() === this.actor) { + return true; + } + } + + return false; + }, + /** * _updatePanelVisibility: * @@ -3608,7 +3628,7 @@ Panel.prototype = { * true = autohide, false = always show, intel = Intelligent */ _updatePanelVisibility: function() { - if (this._panelEditMode || this._peeking) + if (this._panelEditMode || this._peeking || this._panelHasOpenMenus()) this._shouldShow = true; else { switch (this._autohideSettings) { @@ -3838,7 +3858,7 @@ Panel.prototype = { if (this._destroyed) return; this._showHideTimer = 0; - if ((this._shouldShow && !force) || global.menuStackLength > 0) return; + if ((this._shouldShow && !force) || this._panelHasOpenMenus()) return; // setup panel tween - slide out the monitor edge leaving one pixel // if horizontal panel, animation on y. if vertical, animation on x. diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index 777aafb056..a12bcbbe3b 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -2292,6 +2292,29 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { */ setSourceAlignment(alignment) {} + /** + * getPanel: + * + * @returns panel (Clutter.Actor | null) actor of the panel this menu is on, or null if it is not on a panel + */ + getPanel() { + let parentPanel = null; + if (this.sourceActor.get_name() == "panel") { + parentPanel = this.sourceActor; + } else { + let parent = this.sourceActor.get_parent(); + while (parent) { + if (parent.get_name() == "panel") { + parentPanel = parent; + break; + } + parent = parent.get_parent(); + } + } + + return parentPanel; + } + /** * open: * @animate (boolean): whether to animate the open effect or not @@ -2308,28 +2331,18 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { this._updateAllSeparatorVisibility(); this.isOpen = true; - if (global.menuStackLength == undefined) - global.menuStackLength = 0; - global.menuStackLength += 1; + if (global.menuStack == undefined) + global.menuStack = []; + global.menuStack.push(this); + + Main.panelManager.updatePanelsVisibility(); this._signals.connect(this.actor, "paint", Lang.bind(this, this.on_paint)); /* If the sourceActor of our menu is located on a panel or from the panel itself, we want to position it just below the panel actors. This prevents some cases where the menu will otherwise partially overlap the panel and look strange visually */ - let parentPanel = null; - if (this.sourceActor.get_name() == "panel") { - parentPanel = this.sourceActor; - } else { - let parent = this.sourceActor.get_parent(); - while (parent) { - if (parent.get_name() == "panel") { - parentPanel = parent; - break; - } - parent = parent.get_parent(); - } - } + let parentPanel = this.getPanel(); if (parentPanel) { let monitor = Main.layoutManager.findMonitorForActor(this.sourceActor) @@ -2412,9 +2425,7 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { return; this.isOpen = false; - global.menuStackLength -= 1; - - Main.panelManager.updatePanelsVisibility(); + global.menuStack.splice(global.menuStack.indexOf(this), 1); if (this._activeMenuItem) this._activeMenuItem.setActive(false); @@ -2465,6 +2476,8 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { this.animating = false; this.actor.hide(); } + + Main.panelManager.updatePanelsVisibility(); this.emit('open-state-changed', false); // keep the order of open-state-changed -> menu-animated-closed in case it matters. diff --git a/js/ui/tooltips.js b/js/ui/tooltips.js index 1f260acb62..a09872340c 100644 --- a/js/ui/tooltips.js +++ b/js/ui/tooltips.js @@ -340,7 +340,7 @@ PanelItemTooltip.prototype = { }, show: function() { - if (this._tooltip.get_text() == "" || global.menuStackLength > 0 || !this.mousePosition) + if (this._tooltip.get_text() == "" || global.menuStack.length > 0 || !this.mousePosition) return; let op = this._tooltip.get_opacity();