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 GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
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 PopupMenu = imports.ui.popupMenu;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
@ -19,6 +29,70 @@ const KEY_CURRENT_INPUT_SOURCE = 'current';
|
||||
const KEY_INPUT_SOURCES = 'sources';
|
||||
|
||||
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({
|
||||
Name: 'LayoutMenuItem',
|
||||
@ -58,6 +132,8 @@ const InputSourceIndicator = new Lang.Class({
|
||||
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
||||
this._xkbInfo = new GnomeDesktop.XkbInfo();
|
||||
|
||||
this._ibusManager = new IBusManager(Lang.bind(this, this._inputSourcesChanged));
|
||||
|
||||
this._inputSourcesChanged();
|
||||
|
||||
// re-using "allowSettings" for the keyboard layout is a bit shady,
|
||||
@ -120,13 +196,20 @@ const InputSourceIndicator = new Lang.Class({
|
||||
let infosByShortName = {};
|
||||
|
||||
for (let i = 0; i < nSources; i++) {
|
||||
let info = { exists: false };
|
||||
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, , ] =
|
||||
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)
|
||||
continue;
|
||||
@ -175,8 +258,19 @@ const InputSourceIndicator = new Lang.Class({
|
||||
|
||||
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
|
||||
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
|
||||
let id = sources.get_child_value(current).deep_unpack()[1];
|
||||
let [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
|
||||
let [type, id] = sources.get_child_value(current).deep_unpack();
|
||||
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)
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user