signalTracker: Explicitly register destroyable types
We currently assume that any '::destroy' signal on a GObject type has the semantics of the ClutterActor/GtkWidget signal, and should therefore result in all signals being disconnected. But we already have a case where the assumption doesn't hold: ShellWM uses '::destroy' for the closing animation of windows, and the ShellWM object itself remains very valid after the emission. So rather than making assumptions about '::destroy', check objects against a list of destroyable types that are explicitly registered as such. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2226>
This commit is contained in:

committed by
Marge Bot

parent
ba23279f1f
commit
fc4f9f61fa
@ -1,14 +1,15 @@
|
||||
/* exported TransientSignalHolder, addObjectSignalMethods */
|
||||
const { GObject } = imports.gi;
|
||||
|
||||
const destroyableTypes = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} obj - an object
|
||||
* @returns {bool} - true if obj has a 'destroy' GObject signal
|
||||
*/
|
||||
function _hasDestroySignal(obj) {
|
||||
return obj instanceof GObject.Object &&
|
||||
GObject.signal_lookup('destroy', obj);
|
||||
return destroyableTypes.some(type => obj instanceof type);
|
||||
}
|
||||
|
||||
var TransientSignalHolder = GObject.registerClass(
|
||||
@ -28,6 +29,7 @@ class TransientSignalHolder extends GObject.Object {
|
||||
this.emit('destroy');
|
||||
}
|
||||
});
|
||||
registerDestroyableType(TransientSignalHolder);
|
||||
|
||||
class SignalManager {
|
||||
/**
|
||||
@ -230,3 +232,19 @@ function addObjectSignalMethods(proto) {
|
||||
};
|
||||
proto['disconnect_object'] = proto['disconnectObject'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a GObject type as having a 'destroy' signal
|
||||
* that should disconnect all handlers
|
||||
*
|
||||
* @param {GObject.Type} gtype - a GObject type
|
||||
*/
|
||||
function registerDestroyableType(gtype) {
|
||||
if (!GObject.type_is_a(gtype, GObject.Object))
|
||||
throw new Error(`${gtype} is not a GObject subclass`);
|
||||
|
||||
if (!GObject.signal_lookup('destroy', gtype))
|
||||
throw new Error(`${gtype} does not have a destroy signal`);
|
||||
|
||||
destroyableTypes.push(gtype);
|
||||
}
|
||||
|
Reference in New Issue
Block a user