[gnome-shell/wip/carlosg/osk-updates: 165/180] ibusManager: Add OSK completion mode




commit 643f779583f48094aa36f0b220dbb63785cf63b3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Apr 22 13:28:02 2022 +0200

    ibusManager: Add OSK completion mode
    
    This mode changes the current IBus engine to ibus-typing-booster
    under the rug (i.e. no changes in keyboard status menu) for any
    XKB engine selected.
    
    In order to make it useful for the currently selected language,
    the typing-booster dictionary is changed to the current XKB
    layout language. And since the OSK has its own emoji panel,
    typing-boosters own emoji completion is disabled.
    
    These changes only apply as long as the OSK panel is shown,
    reverting to the original engine and typing-booster configuration
    after it is hidden. This in theory also caters for users that
    do have ibus-typing-booster enabled as an input source.
    
    The final effect is text prediction for the language that is
    being typed, according to the OSK layout, given that
    ibus-typing-booster and the relevant hunspell dictionaries are
    used.

 js/misc/ibusManager.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-
 js/misc/inputMethod.js |  7 ++++++
 js/ui/keyboard.js      | 11 +++++++++
 3 files changed, 79 insertions(+), 1 deletion(-)
---
diff --git a/js/misc/ibusManager.js b/js/misc/ibusManager.js
index ce43489aea..ebab179a2b 100644
--- a/js/misc/ibusManager.js
+++ b/js/misc/ibusManager.js
@@ -22,6 +22,13 @@ _checkIBusVersion(1, 5, 2);
 let _ibusManager = null;
 const IBUS_SYSTEMD_SERVICE = 'org.freedesktop.IBus.session.GNOME.service';
 
+const TYPING_BOOSTER_ENGINE = 'typing-booster';
+const IBUS_TYPING_BOOSTER_SCHEMA = 'org.freedesktop.ibus.engine.typing-booster';
+const KEY_EMOJIPREDICTIONS = 'emojipredictions';
+const KEY_DICTIONARY = 'dictionary';
+const KEY_INLINECOMPLETION = 'inlinecompletion';
+const KEY_INPUTMETHOD = 'inputmethod';
+
 function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
     if ((IBus.MAJOR_VERSION > requiredMajor) ||
         (IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
@@ -304,9 +311,12 @@ var IBusManager = class extends Signals.EventEmitter {
     }
 
     preloadEngines(ids) {
-        if (!this._ibus || ids.length == 0)
+        if (!this._ibus || !this._ready)
             return;
 
+        if (!ids.includes(TYPING_BOOSTER_ENGINE))
+            ids.push(TYPING_BOOSTER_ENGINE);
+
         if (this._preloadEnginesId != 0) {
             GLib.source_remove(this._preloadEnginesId);
             this._preloadEnginesId = 0;
@@ -326,4 +336,54 @@ var IBusManager = class extends Signals.EventEmitter {
                     return GLib.SOURCE_REMOVE;
                 });
     }
+
+    setCompletionEnabled(enabled) {
+        /* Needs typing-booster available */
+        if (!this._engines.has(TYPING_BOOSTER_ENGINE))
+            return false;
+        /* Can do only on xkb engines */
+        if (enabled && !this._currentEngineName.startsWith('xkb:'))
+            return false;
+
+        if (this._oskCompletion === enabled)
+            return true;
+
+        this._oskCompletion = enabled;
+        let settings =
+            new Gio.Settings({schema_id: IBUS_TYPING_BOOSTER_SCHEMA});
+
+        if (enabled) {
+            this._preOskState = {
+                'engine': this._currentEngineName,
+                'emoji': settings.get_value(KEY_EMOJIPREDICTIONS),
+                'langs': settings.get_value(KEY_DICTIONARY),
+                'completion': settings.get_value(KEY_INLINECOMPLETION),
+                'inputMethod': settings.get_value(KEY_INPUTMETHOD),
+            };
+            settings.reset(KEY_EMOJIPREDICTIONS);
+
+            const removeEncoding = l => l.replace(/\..*/, '');
+            const removeDups = (l, pos, arr) => {
+                return !pos || arr[pos - 1] !== l;
+            };
+            settings.set_string(
+                KEY_DICTIONARY,
+                GLib.get_language_names().map(removeEncoding)
+                    .sort().filter(removeDups).join(','));
+
+            settings.reset(KEY_INLINECOMPLETION);
+            settings.set_string(KEY_INPUTMETHOD, 'NoIME');
+            this.setEngine(TYPING_BOOSTER_ENGINE);
+        } else if (this._preOskState) {
+            const {engine, emoji, langs, completion, inputMethod} =
+                  this._preOskState;
+            this._preOskState = null;
+            this.setEngine(engine);
+            settings.set_value(KEY_EMOJIPREDICTIONS, emoji);
+            settings.set_value(KEY_DICTIONARY, langs);
+            settings.set_value(KEY_INLINECOMPLETION, completion);
+            settings.set_value(KEY_INPUTMETHOD, inputMethod);
+        }
+        return true;
+    }
 };
diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js
index ab4617e07b..76a7ed2cb2 100644
--- a/js/misc/inputMethod.js
+++ b/js/misc/inputMethod.js
@@ -315,4 +315,11 @@ var InputMethod = GObject.registerClass({
     hasPreedit() {
         return this._preeditVisible && this._preeditStr !== '' && this._preeditStr !== null;
     }
+
+    handleVirtualKey(keyval) {
+        this._context.process_key_event_async(
+            keyval, 0, 0, -1, null, null);
+        this._context.process_key_event_async(
+            keyval, 0, IBus.ModifierType.RELEASE_MASK, -1, null, null);
+    }
 });
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index 6fd24d24b8..39066057ac 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -1497,7 +1497,14 @@ var Keyboard = GObject.registerClass({
 
             if (key.action !== 'modifier') {
                 button.connect('commit', (actor, keyval, str) => {
+                    if (this._modifiers.length === 0 && str !== '' &&
+                        keyval && this._oskCompletionEnabled) {
+                        Main.inputMethod.handleVirtualKey(keyval);
+                        return;
+                    }
+
                     if (str === '' || !Main.inputMethod.currentFocus ||
+                        (keyval && this._oskCompletionEnabled) ||
                         this._modifiers.size > 0 ||
                         !this._keyboardController.commitString(str, true)) {
                         if (keyval !== 0) {
@@ -1865,6 +1872,8 @@ var Keyboard = GObject.registerClass({
             return;
         }
 
+        this._oskCompletionEnabled =
+            IBusManager.getIBusManager().setCompletionEnabled(true);
         this._clearKeyboardRestTimer();
 
         if (immediate) {
@@ -1899,6 +1908,8 @@ var Keyboard = GObject.registerClass({
         if (!this._keyboardVisible)
             return;
 
+        IBusManager.getIBusManager().setCompletionEnabled(false);
+        this._oskCompletionEnabled = false;
         this._clearKeyboardRestTimer();
 
         if (immediate) {


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