signalTracker: Add TransientSignalHolder class
There are cases where we want to connect to a number of signals for the lifetime of an object, but also other signals for a limited period (say: between show and hide). It is currently not possible to use disconnectObject() for the latter, because it will disconnect all signals. To address this use case, add a small class that can be used as a transient signal holder, while still benefiting from autocleanup by proxying the real owner. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2221>
This commit is contained in:
parent
7b0a94b246
commit
cf29ec2f22
@ -1,6 +1,34 @@
|
||||
/* exported addObjectSignalMethods */
|
||||
/* exported TransientSignalHolder, addObjectSignalMethods */
|
||||
const { GObject } = imports.gi;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
var TransientSignalHolder = GObject.registerClass(
|
||||
class TransientSignalHolder extends GObject.Object {
|
||||
static [GObject.signals] = {
|
||||
'destroy': {},
|
||||
};
|
||||
|
||||
constructor(owner) {
|
||||
super();
|
||||
|
||||
if (_hasDestroySignal(owner))
|
||||
owner.connectObject('destroy', () => this.destroy(), this);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.emit('destroy');
|
||||
}
|
||||
});
|
||||
|
||||
class SignalManager {
|
||||
/**
|
||||
* @returns {SignalManager} - the SignalManager singleton
|
||||
@ -31,23 +59,13 @@ class SignalTracker {
|
||||
* @param {Object=} owner - object that owns the tracker
|
||||
*/
|
||||
constructor(owner) {
|
||||
if (this._hasDestroySignal(owner))
|
||||
if (_hasDestroySignal(owner))
|
||||
this._ownerDestroyId = owner.connect_after('destroy', () => this.clear());
|
||||
|
||||
this._owner = owner;
|
||||
this._map = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} obj - an object
|
||||
* @returns {bool} - true if obj has a 'destroy' GObject signal
|
||||
*/
|
||||
_hasDestroySignal(obj) {
|
||||
return obj instanceof GObject.Object &&
|
||||
GObject.signal_lookup('destroy', obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef SignalData
|
||||
* @property {number[]} ownerSignals - a list of handler IDs
|
||||
@ -89,7 +107,7 @@ class SignalTracker {
|
||||
* @returns {void}
|
||||
*/
|
||||
track(obj, ...handlerIds) {
|
||||
if (this._hasDestroySignal(obj))
|
||||
if (_hasDestroySignal(obj))
|
||||
this._trackDestroy(obj);
|
||||
|
||||
this._getSignalData(obj).ownerSignals.push(...handlerIds);
|
||||
|
@ -8,6 +8,8 @@ const JsUnit = imports.jsUnit;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Environment = imports.ui.environment;
|
||||
const { TransientSignalHolder } = imports.misc.signalTracker;
|
||||
|
||||
Environment.init();
|
||||
|
||||
const Destroyable = GObject.registerClass({
|
||||
@ -77,3 +79,39 @@ emitter1.emit('signal');
|
||||
emitter2.emit('signal');
|
||||
|
||||
JsUnit.assertEquals(count, 10);
|
||||
|
||||
emitter1.connectObject('signal', handler, tracked1);
|
||||
emitter2.connectObject('signal', handler, tracked1);
|
||||
|
||||
transientHolder = new TransientSignalHolder(tracked1);
|
||||
|
||||
emitter1.connectObject('signal', handler, transientHolder);
|
||||
emitter2.connectObject('signal', handler, transientHolder);
|
||||
|
||||
emitter1.emit('signal');
|
||||
emitter2.emit('signal');
|
||||
|
||||
JsUnit.assertEquals(count, 14);
|
||||
|
||||
transientHolder.destroy();
|
||||
|
||||
emitter1.emit('signal');
|
||||
emitter2.emit('signal');
|
||||
|
||||
JsUnit.assertEquals(count, 16);
|
||||
|
||||
transientHolder = new TransientSignalHolder(tracked1);
|
||||
|
||||
emitter1.connectObject('signal', handler, transientHolder);
|
||||
emitter2.connectObject('signal', handler, transientHolder);
|
||||
|
||||
emitter1.emit('signal');
|
||||
emitter2.emit('signal');
|
||||
|
||||
JsUnit.assertEquals(count, 20);
|
||||
|
||||
tracked1.emit('destroy');
|
||||
emitter1.emit('signal');
|
||||
emitter2.emit('signal');
|
||||
|
||||
JsUnit.assertEquals(count, 20);
|
||||
|
Loading…
Reference in New Issue
Block a user