[gnome-shell/wip/carlosg/osk-cldr: 44/45] keyboard: Add languages selection popup



commit bc42d910e87af7f9c04ceaf32dae2fa556270901
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Jan 23 16:45:46 2018 +0100

    keyboard: Add languages selection popup
    
    Currently the language options displayed pretty much mirror those of the
    top bar keyboard layout selection popup. It may make sense in the future
    to only list languages, and automatically switch to the enabled IMs that
    the OSK can benefit from (eg. by filling in suggestions).

 js/ui/keyboard.js        | 97 +++++++++++++++++++++++++++++++++++++++++++++---
 js/ui/status/keyboard.js |  4 +-
 2 files changed, 94 insertions(+), 7 deletions(-)
---
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index cc36cbd70..0a3b0f9c1 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -16,7 +16,9 @@ const InputSourceManager = imports.ui.status.keyboard;
 const BoxPointer = imports.ui.boxpointer;
 const Layout = imports.ui.layout;
 const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
 const Tweener = imports.ui.tweener;
+const Util = imports.misc.util;
 
 var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
 var KEY_LONG_PRESS_TIME = 250;
@@ -38,19 +40,19 @@ const defaultKeysPost = [
     [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
       [{ label: '⏎', width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
       [{ label: '⇧', width: 3, level: 1, right: true }],
-      [{ label: '🌐', width: 1.5 }, { label: '⌨', width: 1.5, action: 'hide' }] ],
+      [{ label: '🌐', width: 1.5, action: 'languageMenu' }, { label: '⌨', width: 1.5, action: 'hide' }] ],
     [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
       [{ label: '⏎', width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
       [{ label: '⇪', width: 3, level: 0, right: true }],
-      [{ label: '🌐', width: 1.5 }, { label: '⌨', width: 1.5, action: 'hide' }] ],
+      [{ label: '🌐', width: 1.5, action: 'languageMenu' }, { label: '⌨', width: 1.5, action: 'hide' }] ],
     [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
       [{ label: '⏎', width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
       [{ label: '=/<', width: 3, level: 3, right: true }],
-      [{ label: '🌐', width: 1.5 }, { label: '⌨', width: 1.5, action: 'hide' }] ],
+      [{ label: '🌐', width: 1.5, action: 'languageMenu' }, { label: '⌨', width: 1.5, action: 'hide' }] ],
     [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
       [{ label: '⏎', width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
       [{ label: '?123', width: 3, level: 2, right: true }],
-      [{ label: '🌐', width: 1.5 }, { label: '⌨', width: 1.5, action: 'hide' }] ],
+      [{ label: '🌐', width: 1.5, action: 'languageMenu' }, { label: '⌨', width: 1.5, action: 'hide' }] ],
 ];
 
 var KeyContainer = new Lang.Class({
@@ -175,6 +177,66 @@ var Suggestions = new Lang.Class({
 });
 Signals.addSignalMethods(Suggestions.prototype);
 
+var LanguageSelectionPopup = new Lang.Class({
+    Name: 'LanguageSelectionPopup',
+    Extends: PopupMenu.PopupMenu,
+
+    _init: function(actor) {
+        this.parent(actor, 0.5, St.Side.BOTTOM);
+
+        let inputSourceManager = InputSourceManager.getInputSourceManager();
+        let inputSources = inputSourceManager.inputSources;
+
+        for (let i in inputSources) {
+            let is = inputSources[i];
+
+            this.addAction(is.displayName, Lang.bind(this, () => {
+                inputSourceManager.activateInputSource(is, true);
+            }));
+        }
+
+        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+        this.addAction(_("Region & Language Settings"), Lang.bind(this, this._launchSettings));
+        this._capturedEventId = 0;
+    },
+
+    _launchSettings: function() {
+        Util.spawn(['gnome-control-center', 'region']);
+        this.close(true);
+    },
+
+    _onCapturedEvent: function(actor, event) {
+        if (event.get_source() == this.actor ||
+            this.actor.contains(event.get_source()))
+            return Clutter.EVENT_PROPAGATE;
+
+        if (event.type() == Clutter.EventType.BUTTON_PRESS || event.type() == Clutter.EventType.TOUCH_BEGIN)
+            this.close(true);
+
+        return Clutter.EVENT_STOP;
+    },
+
+    open: function(animate) {
+        this.parent(animate);
+        this._capturedEventId = global.stage.connect('captured-event',
+                                                     Lang.bind(this, this._onCapturedEvent));
+    },
+
+    close: function(animate) {
+        this.parent(animate);
+        if (this._capturedEventId != 0) {
+            global.stage.disconnect(this._capturedEventId);
+            this._capturedEventId = 0;
+        }
+    },
+
+    destroy: function() {
+        if (this._capturedEventId != 0)
+            global.stage.disconnect(this._capturedEventId);
+        this.parent();
+    },
+});
+
 var Key = new Lang.Class({
     Name: 'Key',
 
@@ -415,6 +477,7 @@ var Keyboard = new Lang.Class({
         this._focusCaretTracker = new FocusCaretTracker.FocusCaretTracker();
         this._focusCaretTracker.connect('focus-changed', Lang.bind(this, this._onFocusChanged));
         this._focusCaretTracker.connect('caret-moved', Lang.bind(this, this._onCaretMoved));
+        this._languagePopup = null;
         this._currentAccessible = null;
         this._caretTrackingEnabled = false;
         this._updateCaretPositionId = 0;
@@ -576,8 +639,11 @@ var Keyboard = new Lang.Class({
         else if (!this._enabled)
             this.setCursorLocation(null);
 
-        if (!this._enabled && wasEnabled)
+        if (!this._enabled && wasEnabled) {
+            if (this._languagePopup)
+                this._languagePopup.close(true);
             Main.layoutManager.hideKeyboard(true);
+        }
     },
 
     _destroyKeyboard: function() {
@@ -592,6 +658,11 @@ var Keyboard = new Lang.Class({
         this._keyboard = null;
         this.actor.destroy();
         this.actor = null;
+
+        if (this._languagePopup) {
+            this._languagePopup.destroy();
+            this._languagePopup = null;
+        }
     },
 
     _setupKeyboard: function() {
@@ -712,6 +783,15 @@ var Keyboard = new Lang.Class({
         }
     },
 
+    _popupLanguageMenu: function(keyActor) {
+        if (this._languagePopup)
+            this._languagePopup.destroy();
+
+        this._languagePopup = new LanguageSelectionPopup(keyActor);
+        Main.layoutManager.addChrome(this._languagePopup.actor);
+        this._languagePopup.open(true);
+    },
+
     _loadDefaultKeys: function(keys, layout, numLevels, numKeys) {
         let extraButton;
         for (let i = 0; i < keys.length; i++) {
@@ -728,6 +808,8 @@ var Keyboard = new Lang.Class({
             if (key.width != null)
                 extraButton.setWidth(key.width);
 
+            let actor = extraButton.actor;
+
             extraButton.connect('released', Lang.bind(this, function() {
                 if (switchToLevel != null)
                     this._onLevelChanged(switchToLevel);
@@ -739,6 +821,8 @@ var Keyboard = new Lang.Class({
                     this._keyboardController.keyvalRelease(keyval);
                 else if (action == 'hide')
                     this.hide();
+                else if (action == 'languageMenu')
+                    this._popupLanguageMenu(actor);
             }));
 
             /* Fixup default keys based on the number of levels/keys */
@@ -940,6 +1024,9 @@ var Keyboard = new Lang.Class({
 
         Main.layoutManager.hideKeyboard();
         this.setCursorLocation(null);
+
+        if (this._languagePopup)
+            this._languagePopup.close(true);
     },
 
     resetSuggestions: function(suggestions) {
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index b2f10322d..c27442984 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -457,7 +457,7 @@ var InputSourceManager = new Lang.Class({
         this._changePerWindowSource();
     },
 
-    _activateInputSource: function(is, interactive) {
+    activateInputSource: function(is, interactive) {
         KeyboardManager.holdKeyboard();
         this._keyboardManager.apply(is.xkbId);
 
@@ -578,7 +578,7 @@ var InputSourceManager = new Lang.Class({
                                      infosList[i].displayName,
                                      infosList[i].shortName,
                                      i);
-            is.connect('activate', Lang.bind(this, this._activateInputSource));
+            is.connect('activate', Lang.bind(this, this.activateInputSource));
 
             if (!(is.shortName in inputSourcesByShortName))
                 inputSourcesByShortName[is.shortName] = [];


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]