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:
Rui Matos 2012-05-29 19:30:14 +02:00
parent e00c1cbd20
commit 14d3235f1a

View File

@ -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;