From 45bc8ae292a176603ff2153d8fda8e641114d7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Tue, 18 Feb 2020 15:05:57 +0100 Subject: [PATCH] keyboard: Plug a leak of KeyboardControllers To make sure the GC really disposes the KeyboardController object we need to remove all references to the object, which means we have to disconnect signals the object connects to, too. This also fixes a bug where keys remain pressed forever and thus also break that key on real keyboards. It happens if the OSK gets destroyed during an OSK-key is being held so the StButton of the key is not released. That means the key remains pressed in the MetaVirtualInputDevice that we are now leaking because KeyboardController isn't garbage collected. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1015 --- js/ui/keyboard.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js index 868a4b3d3..15d92c592 100644 --- a/js/ui/keyboard.js +++ b/js/ui/keyboard.js @@ -1255,11 +1255,7 @@ class Keyboard extends St.BoxLayout { this._clearShowIdle(); - this._keyboardController = null; - this._suggestions = null; - this._aspectContainer = null; - this._emojiSelection = null; - this._keypad = null; + this._keyboardController.destroy(); Main.layoutManager.untrackChrome(this); Main.layoutManager.keyboardBox.remove_actor(this); @@ -1844,13 +1840,20 @@ var KeyboardController = class { this._onSourcesModified.bind(this)); this._currentSource = this._inputSourceManager.currentSource; - Main.inputMethod.connect('notify::content-purpose', - this._onContentPurposeHintsChanged.bind(this)); - Main.inputMethod.connect('notify::content-hints', - this._onContentPurposeHintsChanged.bind(this)); - Main.inputMethod.connect('input-panel-state', (o, state) => { - this.emit('panel-state', state); - }); + this._notifyContentPurposeId = Main.inputMethod.connect( + 'notify::content-purpose', this._onContentPurposeHintsChanged.bind(this)); + this._notifyContentHintsId = Main.inputMethod.connect( + 'notify::content-hints', this._onContentPurposeHintsChanged.bind(this)); + this._notifyInputPanelStateId = Main.inputMethod.connect( + 'input-panel-state', (o, state) => this.emit('panel-state', state)); + } + + destroy() { + this._inputSourceManager.disconnect(this._sourceChangedId); + this._inputSourceManager.disconnect(this._sourcesModifiedId); + Main.inputMethod.disconnect(this._notifyContentPurposeId); + Main.inputMethod.disconnect(this._notifyContentHintsId); + Main.inputMethod.disconnect(this._notifyInputPanelStateId); } _onSourcesModified() {