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: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1842>
This commit is contained in:
Sebastian Keller 2021-05-11 16:43:37 +02:00
parent 5423179844
commit 0a7507c617

View File

@ -402,6 +402,7 @@ class CyclerHighlight extends St.Widget {
_init() { _init() {
super._init({ layout_manager: new Clutter.BinLayout() }); super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null; this._window = null;
this._sizeChangedId = 0;
this._clone = new Clutter.Clone(); this._clone = new Clutter.Clone();
this.add_actor(this._clone); this.add_actor(this._clone);
@ -415,7 +416,6 @@ class CyclerHighlight extends St.Widget {
this.add_constraint(constraint); this.add_constraint(constraint);
this.connect('notify::allocation', this._onAllocationChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} }
@ -423,6 +423,9 @@ class CyclerHighlight extends St.Widget {
if (this._window == w) if (this._window == w)
return; return;
if (this._sizeChangedId)
this._window.disconnect(this._sizeChangedId);
this._window = w; this._window = w;
if (this._clone.source) if (this._clone.source)
@ -434,21 +437,27 @@ class CyclerHighlight extends St.Widget {
windowActor.hide(); windowActor.hide();
this._clone.source = windowActor; 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.set_size(0, 0);
this._highlight.hide(); 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() { _onDestroy() {
this.window = null; this.window = null;
} }