[gnome-shell/wip/carlosg/osk-cldr: 27/45] misc: Add InputMethod class
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/carlosg/osk-cldr: 27/45] misc: Add InputMethod class
- Date: Thu, 25 Jan 2018 21:29:51 +0000 (UTC)
commit e5d3690960f1a56798c4ed3c898886ed94e5d6fd
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Dec 5 20:05:00 2017 +0100
misc: Add InputMethod class
This is a ClutterInputMethod implementation using IBus underneath. The
input method will interact with the currently focused ClutterInputFocus,
be it shell chrome or wayland clients through the text_input protocol.
js/js-resources.gresource.xml | 1 +
js/misc/inputMethod.js | 208 ++++++++++++++++++++++++++++++++++++++++++
js/ui/main.js | 5 +
3 files changed, 214 insertions(+)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index ba0d2f483..6834bf608 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -17,6 +17,7 @@
<file>misc/gnomeSession.js</file>
<file>misc/history.js</file>
<file>misc/ibusManager.js</file>
+ <file>misc/inputMethod.js</file>
<file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file>
diff --git a/js/misc/inputMethod.js b/js/misc/inputMethod.js
new file mode 100644
index 000000000..5f8e8c7a5
--- /dev/null
+++ b/js/misc/inputMethod.js
@@ -0,0 +1,208 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+const Clutter = imports.gi.Clutter;
+const IBus = imports.gi.IBus;
+const Keyboard = imports.ui.status.keyboard;
+const Lang = imports.lang;
+const Signals = imports.signals;
+
+var InputMethod = new Lang.Class({
+ Name: 'InputMethod',
+ Extends: Clutter.InputMethod,
+
+ _init: function() {
+ this.parent();
+ this._hints = 0;
+ this._purpose = 0;
+ this._enabled = true;
+ this._currentFocus = null;
+ this._ibus = IBus.Bus.new_async_client();
+ this._ibus.connect('connected', Lang.bind(this, this._onConnected));
+ this._ibus.connect('disconnected', Lang.bind(this, this._clear));
+ this.connect('notify::can-show-preedit', Lang.bind(this, this._updateCapabilities));
+
+ this._inputSourceManager = Keyboard.getInputSourceManager();
+ this._sourceChangedId = this._inputSourceManager.connect('current-source-changed',
+ Lang.bind(this, this._onSourceChanged));
+ this._currentSource = this._inputSourceManager.currentSource;
+
+ if (this._ibus.is_connected())
+ this._onConnected();
+ },
+
+ get currentFocus() {
+ return this._currentFocus;
+ },
+
+ _updateCapabilities: function() {
+ let caps = 0;
+
+ if (this.can_show_preedit)
+ caps |= IBus.Capabilite.PREEDIT_TEXT;
+
+ if (this._currentFocus)
+ caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
+ else
+ caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT |
IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY;
+
+ if (this._context)
+ this._context.set_capabilities(caps);
+ },
+
+ _onSourceChanged: function() {
+ this._currentSource = this._inputSourceManager.currentSource;
+ },
+
+ _onConnected: function() {
+ this._ibus.create_input_context_async ('gnome-shell', -1, null,
+ Lang.bind(this, this._setContext));
+ },
+
+ _setContext: function(bus, res) {
+ this._context = this._ibus.create_input_context_async_finish(res);
+ this._context.connect('enabled', Lang.bind(this, function () { this._enabled = true }));
+ this._context.connect('disabled', Lang.bind(this, function () { this._enabled = false }));
+ this._context.connect('commit-text', Lang.bind(this, this._onCommitText));
+ this._context.connect('delete-surrounding-text', Lang.bind(this, this._onDeleteSurroundingText));
+ this._context.connect('update-preedit-text', Lang.bind(this, this._onUpdatePreeditText));
+
+ this._updateCapabilities();
+ },
+
+ _clear: function() {
+ this._context = null;
+ this._hints = 0;
+ this._purpose = 0;
+ this._enabled = false;
+ },
+
+ _emitRequestSurrounding: function() {
+ if (this._context.needs_surrounding_text())
+ this.emit('request-surrounding');
+ },
+
+ _onCommitText: function(context, text) {
+ this.commit(text.get_text());
+ },
+
+ _onDeleteSurroundingText: function (context) {
+ this.delete_surrounding();
+ },
+
+ _onUpdatePreeditText: function (context, text, pos, visible) {
+ let str = null;
+ if (visible && text != null)
+ str = text.get_text();
+
+ this.set_preedit_text(str, pos);
+ },
+
+ vfunc_focus_in: function(focus) {
+ this._currentFocus = focus;
+ if (this._context) {
+ this._context.focus_in();
+ this._updateCapabilities();
+ this._emitRequestSurrounding();
+ }
+ },
+
+ vfunc_focus_out: function() {
+ this._currentFocus = null;
+ if (this._context) {
+ this._context.focus_out();
+ this._updateCapabilities();
+ }
+ },
+
+ vfunc_reset: function() {
+ if (this._context) {
+ this._context.reset();
+ this._emitRequestSurrounding();
+ }
+ },
+
+ vfunc_set_cursor_location: function(rect) {
+ if (this._context) {
+ this._context.set_cursor_location(rect.get_x(), rect.get_y(),
+ rect.get_width(), rect.get_height());
+ this._emitRequestSurrounding();
+ }
+ },
+
+ vfunc_set_surrounding: function(text, cursor, anchor) {
+ if (this._context)
+ this._context.set_surrounding_text(text, cursor, anchor);
+ },
+
+ vfunc_update_content_hints: function(hints) {
+ let ibusHints = 0;
+ if (hints & Clutter.InputContentHintFlags.COMPLETION)
+ ibusHints |= IBus.InputHints.WORD_COMPLETION;
+ if (hints & Clutter.InputContentHintFlags.SPELLCHECK)
+ ibusHints |= IBus.InputHints.SPELLCHECK;
+ if (hints & Clutter.InputContentHintFlags.AUTO_CAPITALIZATION)
+ ibusHints |= IBus.InputHints.UPPERCASE_SENTENCES;
+ if (hints & Clutter.InputContentHintFlags.LOWERCASE)
+ ibusHints |= IBus.InputHints.LOWERCASE;
+ if (hints & Clutter.InputContentHintFlags.UPPERCASE)
+ ibusHints |= IBus.InputHints.UPPERCASE_CHARS;
+ if (hints & Clutter.InputContentHintFlags.TITLECASE)
+ ibusHints |= IBus.InputHints.UPPERCASE_WORDS;
+
+ this._hints = ibusHints;
+ if (this._context)
+ this._context.set_content_type(this._purpose, this._hints);
+ },
+
+ vfunc_update_content_purpose: function(purpose) {
+ let ibusPurpose = 0;
+ if (purpose == Clutter.InputContentPurpose.NORMAL)
+ ibusPurpose = IBus.InputPurpose.FREE_FORM;
+ else if (purpose == Clutter.InputContentPurpose.ALPHA)
+ ibusPurpose = IBus.InputPurpose.ALPHA;
+ else if (purpose == Clutter.InputContentPurpose.DIGITS)
+ ibusPurpose = IBus.InputPurpose.DIGITS;
+ else if (purpose == Clutter.InputContentPurpose.NUMBER)
+ ibusPurpose = IBus.InputPurpose.NUMBER;
+ else if (purpose == Clutter.InputContentPurpose.PHONE)
+ ibusPurpose = IBus.InputPurpose.PHONE;
+ else if (purpose == Clutter.InputContentPurpose.URL)
+ ibusPurpose = IBus.InputPurpose.URL;
+ else if (purpose == Clutter.InputContentPurpose.EMAIL)
+ ibusPurpose = IBus.InputPurpose.EMAIL;
+ else if (purpose == Clutter.InputContentPurpose.NAME)
+ ibusPurpose = IBus.InputPurpose.NAME;
+ else if (purpose == Clutter.InputContentPurpose.PASSWORD)
+ ibusPurpose = IBus.InputPurpose.PASSWORD;
+
+ this._purpose = ibusPurpose;
+ if (this._context)
+ this._context.set_content_type(this._purpose, this._hints);
+ },
+
+ vfunc_filter_key_event: function(event) {
+ if (!this._context || !this._enabled)
+ return false;
+ if (!this._currentSource ||
+ this._currentSource.type == Keyboard.INPUT_SOURCE_TYPE_XKB)
+ return false;
+
+ let state = event.get_state();
+ if (state & IBus.ModifierType.IGNORED_MASK)
+ return false;
+
+ if (event.type() == Clutter.EventType.KEY_RELEASE)
+ state |= IBus.ModifierType.RELEASE_MASK;
+ this._context.process_key_event_async(event.get_key_symbol(),
+ event.get_key_code() - 8, // Convert XKB keycodes to evcodes
+ state, -1, null,
+ Lang.bind(this, (context, res) => {
+ try {
+ let retval =
context.process_key_event_async_finish(res);
+ this.notify_key_event(event, retval);
+ } catch (e) {
+ log('Error processing key on IM: ' + e.message);
+ }
+ }));
+ return true;
+ },
+});
diff --git a/js/ui/main.js b/js/ui/main.js
index 0f53edf48..7c1214e0a 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -19,6 +19,7 @@ const EndSessionDialog = imports.ui.endSessionDialog;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
+const InputMethod = imports.misc.inputMethod;
const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
@@ -80,6 +81,7 @@ var xdndHandler = null;
var keyboard = null;
var layoutManager = null;
var kbdA11yDialog = null;
+var inputMethod = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
@@ -173,6 +175,9 @@ function _initializeUI() {
if (LoginManager.canLock())
screenShield = new ScreenShield.ScreenShield();
+ inputMethod = new InputMethod.InputMethod();
+ Clutter.get_default_backend().set_input_method(inputMethod);
+
messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel();
keyboard = new Keyboard.Keyboard();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]