From e1a38cf02cfed4d6e8486e4d7d8b2edc6bf9867f Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Thu, 26 Dec 2024 11:57:15 -0500 Subject: [PATCH] panel.js: Only clip the panel size if necessary. Panel clipping occurs to prevent a hidden panel from being visible on an adjacent monitor edge. In some monitor configurations it can affect actor event picking, and the enter-events that trigger panel visibility are missed. Regardless of the pick problem, clipping should only be necessary if: - There's more than a single monitor. - There is at least a partial common edge shared by two monitors. - There is an auto- or intelligently-hidden panel enabled on that edge. --- js/ui/panel.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/js/ui/panel.js b/js/ui/panel.js index e9c171c20d..77158a71f4 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -2772,6 +2772,13 @@ Panel.prototype = { * current position in order to calculate the exposed size. */ _setClipRegion: function(hidden, offset) { + if (!this._shouldClipPanel()) { + // important during monitor layout changes. + this.actor.remove_clip(); // no-op if there wasn't any clipping to begin with. + Main.layoutManager.updateChrome() + return; + } + let animating = typeof offset === "number"; let isHorizontal = this.panelPosition == PanelLoc.top || this.panelPosition == PanelLoc.bottom; @@ -2839,6 +2846,56 @@ Panel.prototype = { Main.layoutManager.updateChrome() }, + _shouldClipPanel: function() { + const n_monitors = global.display.get_n_monitors(); + + if (n_monitors === 1) { + return false; + } + + for (let i = 0; i < n_monitors; i++) { + if (i === this.monitorIndex) { + continue; + } + + const m_rect = global.display.get_monitor_geometry(i); + const test_rect = new Meta.Rectangle(); + + switch (this.panelPosition) { + case PanelLoc.top: + case PanelLoc.bottom: + test_rect.x = this.actor.x; + test_rect.width = this.actor.width; + test_rect.height = this.height; + + if (this.panelPosition === PanelLoc.top) { + test_rect.y = this.monitor.y - this.height; + } else { + test_rect.y = this.monitor.y + this.monitor.height; + } + break; + case PanelLoc.left: + case PanelLoc.right: + test_rect.y = this.actor.y; + test_rect.height = this.actor.height; + test_rect.width = this.height; + + if (this.panelPosition === PanelLoc.left) { + test_rect.x = this.monitor.x - this.height; + } else { + test_rect.x = this.monitor.x + this.monitor.width; + } + break; + } + + if (m_rect.overlap(test_rect)) { + return true; + } + } + + return false; + }, + /** * _moveResizePanel: * @@ -2973,6 +3030,7 @@ Panel.prototype = { } // update position and clip region + global.log("POS", newX, newY); this.actor.set_position(newX, newY) this._setClipRegion(this._hidden);