From 477e87ac1a1a99cd4d7a9ee7bb789975e9fc1fbf Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 28 Sep 2020 22:28:08 -0400 Subject: [PATCH 10/13] userWidget: Disconnect signal connections on destroy At the moment an Avatar (and StIcon) are getting leaked every time the screen is locked. This is because the Avatar class sets up a global signal connection that prevents the object from getting garbage collected when its actor is destroyed. This commit adds a destroy handler to disconnect the signal connection. --- js/ui/userWidget.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/js/ui/userWidget.js b/js/ui/userWidget.js index 4e1ce25e9..0a80fa672 100644 --- a/js/ui/userWidget.js +++ b/js/ui/userWidget.js @@ -9,63 +9,73 @@ const Gio = imports.gi.Gio; const GObject = imports.gi.GObject; const Lang = imports.lang; const St = imports.gi.St; const Params = imports.misc.params; var AVATAR_ICON_SIZE = 64; // Adapted from gdm/gui/user-switch-applet/applet.c // // Copyright (C) 2004-2005 James M. Cape . // Copyright (C) 2008,2009 Red Hat, Inc. var Avatar = new Lang.Class({ Name: 'Avatar', _init(user, params) { this._user = user; params = Params.parse(params, { reactive: false, iconSize: AVATAR_ICON_SIZE, styleClass: 'framed-user-icon' }); this._iconSize = params.iconSize; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; this.actor = new St.Bin({ style_class: params.styleClass, track_hover: params.reactive, reactive: params.reactive, width: this._iconSize * scaleFactor, height: this._iconSize * scaleFactor }); + this.actor.connect('destroy', this._onDestroy.bind(this)); + // Monitor the scaling factor to make sure we recreate the avatar when needed. let themeContext = St.ThemeContext.get_for_stage(global.stage); - themeContext.connect('notify::scale-factor', this.update.bind(this)); + this._scaleFactorChangedId = themeContext.connect('notify::scale-factor', this.update.bind(this)); + }, + + _onDestroy() { + if (this._scaleFactorChangedId != 0) { + let themeContext = St.ThemeContext.get_for_stage(global.stage); + themeContext.disconnect(this._scaleFactorChangedId); + this._scaleFactorChangedId = 0; + } }, setSensitive(sensitive) { this.actor.can_focus = sensitive; this.actor.reactive = sensitive; }, update() { let iconFile = this._user.get_icon_file(); if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS)) iconFile = null; if (iconFile) { let file = Gio.File.new_for_path(iconFile); this.actor.child = null; this.actor.style = 'background-image: url("%s");'.format(iconFile); } else { this.actor.style = null; this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', icon_size: this._iconSize }); } let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; this.actor.set_size(this._iconSize * scaleFactor, this._iconSize * scaleFactor); } }); var UserWidgetLabel = new Lang.Class({ Name: 'UserWidgetLabel', Extends: St.Widget, -- 2.25.1