From 0a7507c617c08dbbccb4549665b87cf340f97e1c Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 11 May 2021 16:43:37 +0200 Subject: [PATCH] altTab: Avoid allocation cycle when showing CyclerHighlight CyclerHighlight was showing and resizing one of its child widgets when its own allocation was changed, queuing another relayout, resulting in allocation cycle warnings. Avoid this by updating the size of the highlight when the frame rect of window has changes rather than the size of the CyclerHighlight actor itself. Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4167 Part-of: --- js/ui/altTab.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/js/ui/altTab.js b/js/ui/altTab.js index bc8b17fac..6af9380ed 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -402,6 +402,7 @@ class CyclerHighlight extends St.Widget { _init() { super._init({ layout_manager: new Clutter.BinLayout() }); this._window = null; + this._sizeChangedId = 0; this._clone = new Clutter.Clone(); this.add_actor(this._clone); @@ -415,7 +416,6 @@ class CyclerHighlight extends St.Widget { this.add_constraint(constraint); - this.connect('notify::allocation', this._onAllocationChanged.bind(this)); this.connect('destroy', this._onDestroy.bind(this)); } @@ -423,6 +423,9 @@ class CyclerHighlight extends St.Widget { if (this._window == w) return; + if (this._sizeChangedId) + this._window.disconnect(this._sizeChangedId); + this._window = w; if (this._clone.source) @@ -434,21 +437,27 @@ class CyclerHighlight extends St.Widget { windowActor.hide(); this._clone.source = windowActor; - } - _onAllocationChanged() { - if (!this._window) { + if (this._window) { + this._onSizeChanged(); + this._sizeChangedId = this._window.connect('size-changed', + this._onSizeChanged.bind(this)); + } else { this._highlight.set_size(0, 0); this._highlight.hide(); - } else { - let [x, y] = this.allocation.get_origin(); - let rect = this._window.get_frame_rect(); - this._highlight.set_size(rect.width, rect.height); - this._highlight.set_position(rect.x - x, rect.y - y); - this._highlight.show(); } } + _onSizeChanged() { + const bufferRect = this._window.get_buffer_rect(); + const rect = this._window.get_frame_rect(); + this._highlight.set_size(rect.width, rect.height); + this._highlight.set_position( + rect.x - bufferRect.x, + rect.y - bufferRect.y); + this._highlight.show(); + } + _onDestroy() { this.window = null; }