[gnome-shell] signalTracker: Explicitly register destroyable types
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] signalTracker: Explicitly register destroyable types
- Date: Sun, 6 Mar 2022 00:16:08 +0000 (UTC)
commit fc4f9f61fa6ffc1bf284339bb387a0ab0fe98cea
Author: Florian Müllner <fmuellner gnome org>
Date: Sun Mar 6 00:30:16 2022 +0100
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>
js/misc/signalTracker.js | 22 ++++++++++++++++++++--
js/ui/environment.js | 2 ++
js/ui/messageTray.js | 3 +++
tests/unit/signalTracker.js | 3 ++-
4 files changed, 27 insertions(+), 3 deletions(-)
---
diff --git a/js/misc/signalTracker.js b/js/misc/signalTracker.js
index 3e83be7341..bcfa72de97 100644
--- a/js/misc/signalTracker.js
+++ b/js/misc/signalTracker.js
@@ -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);
+}
diff --git a/js/ui/environment.js b/js/ui/environment.js
index 2d3baf7225..7bd848f1ab 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -345,6 +345,8 @@ function init() {
SignalTracker.addObjectSignalMethods(prototype);
};
+ SignalTracker.registerDestroyableType(Clutter.Actor);
+
// Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout);
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 862ade6ef2..e001f2202b 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -10,6 +10,7 @@ const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Params = imports.misc.params;
+const SignalTracker = imports.misc.signalTracker;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@@ -493,6 +494,7 @@ var Notification = GObject.registerClass({
this.run_dispose();
}
});
+SignalTracker.registerDestroyableType(Notification);
var NotificationBanner = GObject.registerClass({
Signals: {
@@ -795,6 +797,7 @@ var Source = GObject.registerClass({
}
}
});
+SignalTracker.registerDestroyableType(Source);
var MessageTray = GObject.registerClass({
Signals: {
diff --git a/tests/unit/signalTracker.js b/tests/unit/signalTracker.js
index 40398c0b8a..a6f50e257b 100644
--- a/tests/unit/signalTracker.js
+++ b/tests/unit/signalTracker.js
@@ -8,13 +8,14 @@ const JsUnit = imports.jsUnit;
const Signals = imports.signals;
const Environment = imports.ui.environment;
-const { TransientSignalHolder } = imports.misc.signalTracker;
+const { TransientSignalHolder, registerDestroyableType } = imports.misc.signalTracker;
Environment.init();
const Destroyable = GObject.registerClass({
Signals: { 'destroy': {} },
}, class Destroyable extends GObject.Object {});
+registerDestroyableType(Destroyable);
class PlainEmitter {}
Signals.addSignalMethods(PlainEmitter.prototype);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]