[gnome-shell] keyboard: Add KeyboardManager to manage the lifetime of the keyboard actor
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] keyboard: Add KeyboardManager to manage the lifetime of the keyboard actor
- Date: Wed, 16 Oct 2019 15:31:57 +0000 (UTC)
commit 7059dcced355d673022f145b0b050deef18832df
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date: Wed Aug 28 23:52:52 2019 +0200
keyboard: Add KeyboardManager to manage the lifetime of the keyboard actor
The Keyboard class used to be both a view and controller class, however in order
to make the keyboard a native Clutter.Actor, we need to separate the widget from
the controller class, so that we can manage the actor lifetime from the JS side.
Thus, initialize the keyboard actor on the Keyboard constructor and create a
KeyboardManager class to manage its state and lifetime.
Add proxy methods for the public functions that were used by other shell
components
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
js/ui/keyboard.js | 242 ++++++++++++++++++++++++++++++++----------------------
js/ui/main.js | 2 +-
2 files changed, 146 insertions(+), 98 deletions(-)
---
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index b6aa58fcb6..109c0a770e 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported Keyboard */
+/* exported KeyboardManager */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals;
@@ -1042,9 +1042,95 @@ var Keypad = class Keypad {
};
Signals.addSignalMethods(Keypad.prototype);
+var KeyboardManager = class KeyBoardManager {
+ constructor() {
+ this._keyboard = null;
+ this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
+ this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
+
+ this._lastDeviceId = null;
+ Meta.get_backend().connect('last-device-changed', (backend, deviceId) => {
+ let manager = Clutter.DeviceManager.get_default();
+ let device = manager.get_device(deviceId);
+
+ if (device.get_device_name().indexOf('XTEST') < 0) {
+ this._lastDeviceId = deviceId;
+ this._syncEnabled();
+ }
+ });
+ this._syncEnabled();
+ }
+
+ _lastDeviceIsTouchscreen() {
+ if (!this._lastDeviceId)
+ return false;
+
+ let manager = Clutter.DeviceManager.get_default();
+ let device = manager.get_device(this._lastDeviceId);
+
+ if (!device)
+ return false;
+
+ return device.get_device_type() == Clutter.InputDeviceType.TOUCHSCREEN_DEVICE;
+ }
+
+ _syncEnabled() {
+ let enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
+ let enabled = enableKeyboard || this._lastDeviceIsTouchscreen();
+ if (!enabled && !this._keyboard)
+ return;
+
+ if (enabled && !this._keyboard) {
+ this._keyboard = new Keyboard();
+ } else if (!enabled && this._keyboard) {
+ this._keyboard.setCursorLocation(null);
+ Main.layoutManager.hideKeyboard(true);
+ this._keyboard.destroy();
+ this._keyboard = null;
+ }
+ }
+
+ get keyboardActor() {
+ return this._keyboard.actor;
+ }
+
+ get visible() {
+ return this._keyboard && this._keyboard.actor.visible;
+ }
+
+ open(monitor) {
+ if (this._keyboard)
+ this._keyboard.open(monitor);
+ }
+
+ close() {
+ if (this._keyboard)
+ this._keyboard.close();
+ }
+
+ addSuggestion(text, callback) {
+ if (this._keyboard)
+ this._keyboard.addSuggestion(text, callback);
+ }
+
+ resetSuggestions() {
+ if (this._keyboard)
+ this._keyboard.resetSuggestions();
+ }
+
+ shouldTakeEvent(event) {
+ if (!this._keyboard)
+ return false;
+
+ let actor = event.get_source();
+ return Main.layoutManager.keyboardBox.contains(actor) ||
+ !!actor._extended_keys || !!actor.extended_key;
+ }
+};
+
var Keyboard = class Keyboard {
constructor() {
- this.actor = null;
+ this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true });
this._focusInExtendedKeys = false;
this._emojiActive = false;
@@ -1053,113 +1139,82 @@ var Keyboard = class Keyboard {
this._animFocusedWindow = null;
this._delayedAnimFocusWindow = null;
- this._enableKeyboard = false; // a11y settings value
- this._enabled = false; // enabled state (by setting or device type)
this._latched = false; // current level is latched
- this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
- this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
- this._lastDeviceId = null;
this._suggestions = null;
this._emojiKeyVisible = Meta.is_wayland_compositor();
this._focusTracker = new FocusTracker();
- this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
- this._focusTracker.connect('reset', () => {
+ this._connectSignal(this._focusTracker, 'position-changed',
+ this._onFocusPositionChanged.bind(this));
+ this._connectSignal(this._focusTracker, 'reset', () => {
this._delayedAnimFocusWindow = null;
this._animFocusedWindow = null;
this._oskFocusWindow = null;
});
- this._focusTracker.connect('focus-changed', (tracker, focused) => {
- // Valid only for X11
- if (Meta.is_wayland_compositor())
- return;
-
- if (focused)
- this.open(Main.layoutManager.focusIndex);
- else
- this.close();
- });
-
- Meta.get_backend().connect('last-device-changed',
- (backend, deviceId) => {
- let manager = Clutter.DeviceManager.get_default();
- let device = manager.get_device(deviceId);
-
- if (!device.get_device_name().includes('XTEST')) {
- this._lastDeviceId = deviceId;
- this._syncEnabled();
- }
+ // Valid only for X11
+ if (!Meta.is_wayland_compositor()) {
+ this._connectSignal(this._focusTracker, 'focus-changed', (_tracker, focused) => {
+ if (focused)
+ this.open(Main.layoutManager.focusIndex);
+ else
+ this.close();
});
- this._syncEnabled();
+ }
this._showIdleId = 0;
this._keyboardVisible = false;
- Main.layoutManager.connect('keyboard-visible-changed', (o, visible) => {
+ this._connectSignal(Main.layoutManager, 'keyboard-visible-changed', (_lm, visible) => {
this._keyboardVisible = visible;
});
this._keyboardRequested = false;
this._keyboardRestingId = 0;
- Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
- }
+ this._connectSignal(Main.layoutManager, 'monitors-changed', this._relayout.bind(this));
- get visible() {
- return this._keyboardVisible;
+ this._setupKeyboard();
+
+ this.actor.connect('destroy', this._onDestroy.bind(this));
}
- _onFocusPositionChanged(focusTracker) {
- let rect = focusTracker.getCurrentRect();
- this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
+ destroy() {
+ this.actor.destroy();
}
- _lastDeviceIsTouchscreen() {
- if (!this._lastDeviceId)
- return false;
+ _connectSignal(obj, signal, callback) {
+ if (!this._connectionsIDs)
+ this._connectionsIDs = [];
- let manager = Clutter.DeviceManager.get_default();
- let device = manager.get_device(this._lastDeviceId);
+ let id = obj.connect(signal, callback);
+ this._connectionsIDs.push([obj, id]);
+ return id;
+ }
- if (!device)
- return false;
+ get visible() {
+ return this._keyboardVisible && this.actor.visible;
+ }
- return device.get_device_type() == Clutter.InputDeviceType.TOUCHSCREEN_DEVICE;
+ _onFocusPositionChanged(focusTracker) {
+ let rect = focusTracker.getCurrentRect();
+ this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
}
- _syncEnabled() {
- let wasEnabled = this._enabled;
- this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
- this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen();
- if (!this._enabled && !this._keyboardController)
- return;
+ _onDestroy() {
+ for (let [obj, id] of this._connectionsIDs)
+ obj.disconnect(id);
+ delete this._connectionsIDs;
- if (this._enabled && !this._keyboardController)
- this._setupKeyboard();
- else if (!this._enabled)
- this.setCursorLocation(null);
+ this._clearShowIdle();
- if (!this._enabled && wasEnabled)
- Main.layoutManager.hideKeyboard(true);
- }
+ this._keyboardController = null;
+ this._suggestions = null;
+ this._aspectContainer = null;
+ this._emojiSelection = null;
+ this._keypad = null;
- _destroyKeyboard() {
- if (this._keyboardNotifyId)
- this._keyboardController.disconnect(this._keyboardNotifyId);
- if (this._keyboardGroupsChangedId)
- this._keyboardController.disconnect(this._keyboardGroupsChangedId);
- if (this._keyboardStateId)
- this._keyboardController.disconnect(this._keyboardStateId);
- if (this._emojiKeyVisibleId)
- this._keyboardController.disconnect(this._emojiKeyVisibleId);
- if (this._keypadVisibleId)
- this._keyboardController.disconnect(this._keypadVisibleId);
- if (this._focusNotifyId)
- global.stage.disconnect(this._focusNotifyId);
- this._clearShowIdle();
- this._keyboard = null;
- this.actor.destroy();
- this.actor = null;
+ Main.layoutManager.untrackChrome(this.actor);
+ Main.layoutManager.keyboardBox.remove_actor(this.actor);
if (this._languagePopup) {
this._languagePopup.destroy();
@@ -1168,7 +1223,6 @@ var Keyboard = class Keyboard {
}
_setupKeyboard() {
- this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
@@ -1196,7 +1250,7 @@ var Keyboard = class Keyboard {
this._emojiSelection.actor.hide();
this._keypad = new Keypad();
- this._keypad.connect('keyval', (keypad, keyval) => {
+ this._connectSignal(this._keypad, 'keyval', (_keypad, keyval) => {
this._keyboardController.keyvalPress(keyval);
this._keyboardController.keyvalRelease(keyval);
});
@@ -1212,14 +1266,20 @@ var Keyboard = class Keyboard {
// keyboard on RTL locales.
this.actor.text_direction = Clutter.TextDirection.LTR;
- this._keyboardNotifyId = this._keyboardController.connect('active-group',
this._onGroupChanged.bind(this));
- this._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed',
this._onKeyboardGroupsChanged.bind(this));
- this._keyboardStateId = this._keyboardController.connect('panel-state',
this._onKeyboardStateChanged.bind(this));
- this._keypadVisibleId = this._keyboardController.connect('keypad-visible',
this._onKeypadVisible.bind(this));
- this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this));
+ this._connectSignal(this._keyboardController, 'active-group',
+ this._onGroupChanged.bind(this));
+ this._connectSignal(this._keyboardController, 'groups-changed',
+ this._onKeyboardGroupsChanged.bind(this));
+ this._connectSignal(this._keyboardController, 'panel-state',
+ this._onKeyboardStateChanged.bind(this));
+ this._connectSignal(this._keyboardController, 'keypad-visible',
+ this._onKeypadVisible.bind(this));
+ this._connectSignal(global.stage, 'notify::key-focus',
+ this._onKeyFocusChanged.bind(this));
if (Meta.is_wayland_compositor())
- this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible',
this._onEmojiKeyVisible.bind(this));
+ this._connectSignal(this._keyboardController, 'emoji-visible',
+ this._onEmojiKeyVisible.bind(this));
this._relayout();
}
@@ -1245,7 +1305,7 @@ var Keyboard = class Keyboard {
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
- GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
+ GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.open');
}
}
@@ -1552,12 +1612,6 @@ var Keyboard = class Keyboard {
this._updateCurrentPageVisible();
}
- shouldTakeEvent(event) {
- let actor = event.get_source();
- return Main.layoutManager.keyboardBox.contains(actor) ||
- !!actor._extended_keys || !!actor.extended_key;
- }
-
_clearKeyboardRestTimer() {
if (!this._keyboardRestingId)
return;
@@ -1566,9 +1620,6 @@ var Keyboard = class Keyboard {
}
open(monitor) {
- if (!this._enabled)
- return;
-
this._clearShowIdle();
this._keyboardRequested = true;
@@ -1608,9 +1659,6 @@ var Keyboard = class Keyboard {
}
close() {
- if (!this._enabled)
- return;
-
this._clearShowIdle();
this._keyboardRequested = false;
diff --git a/js/ui/main.js b/js/ui/main.js
index ab5aff0dcb..93122890ec 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -189,7 +189,7 @@ function _initializeUI() {
messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel();
- keyboard = new Keyboard.Keyboard();
+ keyboard = new Keyboard.KeyboardManager();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]