status/keyboard: Add support for IBus input sources
We connect to the IBus daemon asyncronously and use it to query info about input sources of the type 'ibus'. In case the daemon is or becomes unreachable we just skip showing input sources of this type. https://bugzilla.gnome.org/show_bug.cgi?id=641531
This commit is contained in:
parent
e00c1cbd20
commit
14d3235f1a
@ -6,9 +6,19 @@ const Gio = imports.gi.Gio;
|
|||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var IBus = imports.gi.IBus;
|
||||||
|
if (!('new_async' in IBus.Bus))
|
||||||
|
throw "IBus version is too old";
|
||||||
|
} catch (e) {
|
||||||
|
var IBus = null;
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
const PanelMenu = imports.ui.panelMenu;
|
||||||
@ -19,6 +29,70 @@ const KEY_CURRENT_INPUT_SOURCE = 'current';
|
|||||||
const KEY_INPUT_SOURCES = 'sources';
|
const KEY_INPUT_SOURCES = 'sources';
|
||||||
|
|
||||||
const INPUT_SOURCE_TYPE_XKB = 'xkb';
|
const INPUT_SOURCE_TYPE_XKB = 'xkb';
|
||||||
|
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
|
||||||
|
|
||||||
|
const IBusManager = new Lang.Class({
|
||||||
|
Name: 'IBusManager',
|
||||||
|
|
||||||
|
_init: function(readyCallback) {
|
||||||
|
if (!IBus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IBus.init();
|
||||||
|
|
||||||
|
this._readyCallback = readyCallback;
|
||||||
|
|
||||||
|
this._ibus = null;
|
||||||
|
this._engines = {};
|
||||||
|
this._ready = false;
|
||||||
|
|
||||||
|
this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS,
|
||||||
|
Gio.BusNameWatcherFlags.NONE,
|
||||||
|
Lang.bind(this, this._onNameAppeared),
|
||||||
|
Lang.bind(this, this._clear));
|
||||||
|
},
|
||||||
|
|
||||||
|
_clear: function() {
|
||||||
|
if (this._ibus)
|
||||||
|
this._ibus.destroy();
|
||||||
|
|
||||||
|
this._ibus = null;
|
||||||
|
this._engines = {};
|
||||||
|
this._ready = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onNameAppeared: function() {
|
||||||
|
this._ibus = IBus.Bus.new_async();
|
||||||
|
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onConnected: function() {
|
||||||
|
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
|
||||||
|
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
|
||||||
|
},
|
||||||
|
|
||||||
|
_initEngines: function(ibus, result) {
|
||||||
|
let enginesList = this._ibus.list_engines_async_finish(result);
|
||||||
|
if (enginesList) {
|
||||||
|
for (let i = 0; i < enginesList.length; ++i) {
|
||||||
|
let name = enginesList[i].get_name();
|
||||||
|
this._engines[name] = enginesList[i];
|
||||||
|
}
|
||||||
|
this._ready = true;
|
||||||
|
if (this._readyCallback)
|
||||||
|
this._readyCallback();
|
||||||
|
} else {
|
||||||
|
this._clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getEngineDesc: function(id) {
|
||||||
|
if (!IBus || !this._ready)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this._engines[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const LayoutMenuItem = new Lang.Class({
|
const LayoutMenuItem = new Lang.Class({
|
||||||
Name: 'LayoutMenuItem',
|
Name: 'LayoutMenuItem',
|
||||||
@ -58,6 +132,8 @@ const InputSourceIndicator = new Lang.Class({
|
|||||||
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
||||||
this._xkbInfo = new GnomeDesktop.XkbInfo();
|
this._xkbInfo = new GnomeDesktop.XkbInfo();
|
||||||
|
|
||||||
|
this._ibusManager = new IBusManager(Lang.bind(this, this._inputSourcesChanged));
|
||||||
|
|
||||||
this._inputSourcesChanged();
|
this._inputSourcesChanged();
|
||||||
|
|
||||||
// re-using "allowSettings" for the keyboard layout is a bit shady,
|
// re-using "allowSettings" for the keyboard layout is a bit shady,
|
||||||
@ -120,13 +196,20 @@ const InputSourceIndicator = new Lang.Class({
|
|||||||
let infosByShortName = {};
|
let infosByShortName = {};
|
||||||
|
|
||||||
for (let i = 0; i < nSources; i++) {
|
for (let i = 0; i < nSources; i++) {
|
||||||
|
let info = { exists: false };
|
||||||
let [type, id] = sources.get_child_value(i).deep_unpack();
|
let [type, id] = sources.get_child_value(i).deep_unpack();
|
||||||
if (type != INPUT_SOURCE_TYPE_XKB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let info = {};
|
if (type == INPUT_SOURCE_TYPE_XKB) {
|
||||||
[info.exists, info.displayName, info.shortName, , ] =
|
[info.exists, info.displayName, info.shortName, , ] =
|
||||||
this._xkbInfo.get_layout_info(id);
|
this._xkbInfo.get_layout_info(id);
|
||||||
|
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
|
||||||
|
let engineDesc = this._ibusManager.getEngineDesc(id);
|
||||||
|
if (engineDesc) {
|
||||||
|
info.exists = true;
|
||||||
|
info.displayName = engineDesc.get_longname();
|
||||||
|
info.shortName = engineDesc.get_symbol();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!info.exists)
|
if (!info.exists)
|
||||||
continue;
|
continue;
|
||||||
@ -175,8 +258,19 @@ const InputSourceIndicator = new Lang.Class({
|
|||||||
|
|
||||||
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
|
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
|
||||||
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
||||||
let id = sources.get_child_value(current).deep_unpack()[1];
|
let [type, id] = sources.get_child_value(current).deep_unpack();
|
||||||
let [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
|
let xkbLayout = '';
|
||||||
|
let xkbVariant = '';
|
||||||
|
|
||||||
|
if (type == INPUT_SOURCE_TYPE_XKB) {
|
||||||
|
[, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
|
||||||
|
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
|
||||||
|
let engineDesc = this._ibusManager.getEngineDesc(id);
|
||||||
|
if (engineDesc) {
|
||||||
|
xkbLayout = engineDesc.get_layout();
|
||||||
|
xkbVariant = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!xkbLayout || xkbLayout.length == 0)
|
if (!xkbLayout || xkbLayout.length == 0)
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user