🪲 Fix occasional empty window
This commit is contained in:
+51
-52
@@ -75,10 +75,11 @@ class Extension {
|
||||
const extensionThis = this;
|
||||
|
||||
// We will monkey-patch these methods. Let's store the original ones.
|
||||
this._origAddWindowClone = Workspace.prototype._addWindowClone;
|
||||
this._origWindowRemoved = Workspace.prototype._windowRemoved;
|
||||
this._origDoRemoveWindow = Workspace.prototype._doRemoveWindow;
|
||||
this._origShouldAnimateActor = WindowManager.prototype._shouldAnimateActor;
|
||||
this._origAddWindowClone = Workspace.prototype._addWindowClone;
|
||||
this._origWindowRemoved = Workspace.prototype._windowRemoved;
|
||||
this._origDoRemoveWindow = Workspace.prototype._doRemoveWindow;
|
||||
this._origShouldAnimateActor = WindowManager.prototype._shouldAnimateActor;
|
||||
this._origWaitForOverviewToHide = WindowManager.prototype._waitForOverviewToHide;
|
||||
|
||||
// We will also override these animation times.
|
||||
this._origWindowTime = imports.ui.windowManager.DESTROY_WINDOW_ANIMATION_TIME;
|
||||
@@ -88,38 +89,28 @@ class Extension {
|
||||
// ------------------------------------------------ patching the window-open animation
|
||||
|
||||
// Here we add an effect to the window-open animation. This is done whenever a new
|
||||
// window is created.
|
||||
// window is created. Usually, there is no real window animation for opening windows
|
||||
// in the overview - only the window's clone is animated - but thanks to the hacks
|
||||
// below, we can show the real animations in the overview.
|
||||
|
||||
// If a window is created the transitions are set up in the async _mapWindow of the
|
||||
// WindowManager:
|
||||
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/windowManager.js#L1449
|
||||
// AFAIK, overriding this method is not possible as it's called by a signal to
|
||||
// which it is bound via the bind() method. To tweak the async transition
|
||||
// anyways, we override the actors ease() method once - the next time it will be
|
||||
// called by the _mapWindow(), we will intercept it!
|
||||
this._windowCreatedConnection =
|
||||
global.display.connect('window-created', (d, metaWin) => {
|
||||
let actor = metaWin.get_compositor_private();
|
||||
|
||||
// If we are currently in the overview, we add the effect to the original window
|
||||
// actor. The window preview in the overview is basically a Clutter.Clone which
|
||||
// shows the original window.
|
||||
if (Main.overview.visible && !Main.overview.closing) {
|
||||
const id = actor.connect('notify::mapped', () => {
|
||||
extensionThis._setupEffect(actor, true);
|
||||
actor.disconnect(id);
|
||||
});
|
||||
const orig = actor.ease;
|
||||
actor.ease = function(...params) {
|
||||
orig.apply(actor, params);
|
||||
actor.ease = orig;
|
||||
|
||||
}
|
||||
// If a window is created outside of the overview, the transitions are set up in
|
||||
// the async _mapWindow of the WindowManager which can defer the actual showing
|
||||
// of the window significantly, especially when currently leaving the overview:
|
||||
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/windowManager.js#L1449
|
||||
// AFAIK, overriding this method is not possible as it's called by a signal to
|
||||
// which it is bound via the bind() method. To tweak the async transition
|
||||
// anyways, we override the actors ease() method once - the next time it will be
|
||||
// called by the _mapWindow(), we will intercept it!
|
||||
else {
|
||||
const orig = actor.ease;
|
||||
actor.ease = function(...params) {
|
||||
orig.apply(actor, params);
|
||||
actor.ease = orig;
|
||||
|
||||
extensionThis._setupEffect(actor, true);
|
||||
};
|
||||
}
|
||||
extensionThis._setupEffect(actor, true);
|
||||
};
|
||||
});
|
||||
|
||||
// Some of the effects require that the window's actor is enlarged to provide a bigger
|
||||
@@ -147,13 +138,13 @@ class Extension {
|
||||
// Shell 3.38+. So effects cannot scale windows in the overview of GNOME 3.36...
|
||||
if (utils.shellVersionIsAtLeast(3, 38)) {
|
||||
const xID = realWindow.connect('notify::scale-x', () => {
|
||||
if (realWindow.scale_x > 0) {
|
||||
if (realWindow.scale_x > 0 && clone.allocation.get_size()[0] > 0) {
|
||||
clone.scale_x = realWindow.scale_x;
|
||||
}
|
||||
});
|
||||
|
||||
const yID = realWindow.connect('notify::scale-y', () => {
|
||||
if (realWindow.scale_y > 0) {
|
||||
if (realWindow.scale_y > 0 && clone.allocation.get_size()[1] > 0) {
|
||||
clone.scale_y = realWindow.scale_y;
|
||||
}
|
||||
});
|
||||
@@ -164,7 +155,7 @@ class Extension {
|
||||
});
|
||||
}
|
||||
|
||||
// This is actually need for the window-close animation on GNOME Shell 3.36.
|
||||
// This is actually needed for the window-close animation on GNOME Shell 3.36.
|
||||
// On GNOME 3.36, the window clone's 'destroy' handler only calls _removeWindowClone
|
||||
// but not _doRemoveWindow. The latter is required to trigger the repositioning of
|
||||
// the overview window layout. Therefore we call this method in addition.
|
||||
@@ -177,6 +168,27 @@ class Extension {
|
||||
return result;
|
||||
};
|
||||
|
||||
// Usually, windows are faded in after the overview is completely hidden. We enable
|
||||
// window-open animations by not waiting for this.
|
||||
WindowManager.prototype._waitForOverviewToHide = async function() {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
// Here comes the ULTRA-HACK: The method below is called (amongst others) by the
|
||||
// _destroyWindow and _mapWindow methods of the WindowManager. Usually, it returns
|
||||
// false when we are in the overview. This prevents the window animations. As we
|
||||
// cannot monkey-patch the _destroyWindow or _mapWindow methods themselves, we check
|
||||
// inside the method below whether it was called by either of those. If so, we return
|
||||
// true. Let's see if this breaks stuff left and right...
|
||||
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/windowManager.js#L1125
|
||||
WindowManager.prototype._shouldAnimateActor = function(...params) {
|
||||
const caller = (new Error()).stack.split('\n')[1];
|
||||
if (caller.includes('_destroyWindow@') || caller.includes('_mapWindow@')) {
|
||||
return true;
|
||||
}
|
||||
return extensionThis._origShouldAnimateActor.apply(this, params);
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------- patching the window-close animation
|
||||
|
||||
@@ -213,20 +225,6 @@ class Extension {
|
||||
}
|
||||
};
|
||||
|
||||
// Here comes the ULTRA-HACK: The method below is called (amongst others) by the
|
||||
// _destroyWindow method of the WindowManager. Usually, it returns false when we are
|
||||
// in the overview. This prevents the window-close animation. As we cannot
|
||||
// monkey-patch the _destroyWindow method itself, we check inside the method below
|
||||
// whether it was called by _destroyWindow. If so, we return true. Let's see if this
|
||||
// breaks stuff left and right...
|
||||
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/windowManager.js#L1125
|
||||
WindowManager.prototype._shouldAnimateActor = function(...params) {
|
||||
if ((new Error()).stack.split('\n')[1].includes('_destroyWindow@')) {
|
||||
return true;
|
||||
}
|
||||
return extensionThis._origShouldAnimateActor.apply(this, params);
|
||||
};
|
||||
|
||||
// With the code below, we hide the window-overlay (icon, label, close button) in the
|
||||
// overview once the close-animation is running. As the WindowPreview class is only
|
||||
// available on GNOME 3.38 and beyond, we cannot hide the overlay on GNOME 3.36.
|
||||
@@ -288,10 +286,11 @@ class Extension {
|
||||
global.window_manager.disconnect(this._destroyConnection);
|
||||
global.display.disconnect(this._windowCreatedConnection);
|
||||
|
||||
Workspace.prototype._addWindowClone = this._origAddWindowClone;
|
||||
Workspace.prototype._windowRemoved = this._origWindowRemoved;
|
||||
Workspace.prototype._doRemoveWindow = this._origDoRemoveWindow;
|
||||
WindowManager.prototype._shouldAnimateActor = this._origShouldAnimateActor;
|
||||
Workspace.prototype._addWindowClone = this._origAddWindowClone;
|
||||
Workspace.prototype._windowRemoved = this._origWindowRemoved;
|
||||
Workspace.prototype._doRemoveWindow = this._origDoRemoveWindow;
|
||||
WindowManager.prototype._shouldAnimateActor = this._origShouldAnimateActor;
|
||||
WindowManager.prototype._waitForOverviewToHide = this._origWaitForOverviewToHide;
|
||||
|
||||
imports.ui.windowManager.DESTROY_WINDOW_ANIMATION_TIME = this._origWindowTime;
|
||||
imports.ui.windowManager.DIALOG_DESTROY_WINDOW_ANIMATION_TIME = this._origDialogTime;
|
||||
|
||||
Reference in New Issue
Block a user