2014-02-14 07:35:05 -05:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2019-01-31 09:07:06 -05:00
|
|
|
/* exported getIBusManager */
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2020-03-04 11:52:27 -05:00
|
|
|
const { Gio, GLib, IBus, Meta } = imports.gi;
|
2014-02-14 07:35:05 -05:00
|
|
|
const Signals = imports.signals;
|
|
|
|
|
2018-01-17 11:01:24 -05:00
|
|
|
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
|
|
|
|
|
|
|
// Ensure runtime version matches
|
|
|
|
_checkIBusVersion(1, 5, 2);
|
2014-02-14 07:35:05 -05:00
|
|
|
|
|
|
|
let _ibusManager = null;
|
|
|
|
|
2014-11-27 03:23:01 -05:00
|
|
|
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
|
2014-11-10 05:09:08 -05:00
|
|
|
if ((IBus.MAJOR_VERSION > requiredMajor) ||
|
|
|
|
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
|
|
|
|
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
|
|
|
|
IBus.MICRO_VERSION >= requiredMicro))
|
|
|
|
return;
|
|
|
|
|
2019-08-19 15:12:13 -04:00
|
|
|
throw "Found IBus version %d.%d.%d but required is %d.%d.%d"
|
|
|
|
.format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
|
|
|
|
requiredMajor, requiredMinor, requiredMicro);
|
2014-11-10 05:09:08 -05:00
|
|
|
}
|
|
|
|
|
2014-02-14 07:35:05 -05:00
|
|
|
function getIBusManager() {
|
|
|
|
if (_ibusManager == null)
|
|
|
|
_ibusManager = new IBusManager();
|
|
|
|
return _ibusManager;
|
|
|
|
}
|
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var IBusManager = class {
|
|
|
|
constructor() {
|
|
|
|
IBus.init();
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
// This is the longest we'll keep the keyboard frozen until an input
|
|
|
|
// source is active.
|
|
|
|
this._MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
|
|
|
|
this._PRELOAD_ENGINES_DELAY_TIME = 30; // sec
|
2014-06-05 12:47:48 -04:00
|
|
|
|
2014-02-14 07:35:05 -05:00
|
|
|
|
|
|
|
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
|
|
|
|
|
|
|
|
this._panelService = null;
|
2019-06-29 19:02:34 -04:00
|
|
|
this._engines = new Map();
|
2014-02-14 07:35:05 -05:00
|
|
|
this._ready = false;
|
|
|
|
this._registerPropertiesId = 0;
|
|
|
|
this._currentEngineName = null;
|
2014-11-10 05:09:08 -05:00
|
|
|
this._preloadEnginesId = 0;
|
2014-02-14 07:35:05 -05:00
|
|
|
|
|
|
|
this._ibus = IBus.Bus.new_async();
|
2017-12-01 19:27:35 -05:00
|
|
|
this._ibus.connect('connected', this._onConnected.bind(this));
|
|
|
|
this._ibus.connect('disconnected', this._clear.bind(this));
|
2014-02-14 07:35:05 -05:00
|
|
|
// Need to set this to get 'global-engine-changed' emitions
|
|
|
|
this._ibus.set_watch_ibus_signal(true);
|
2017-12-01 19:27:35 -05:00
|
|
|
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
|
2014-05-29 09:27:42 -04:00
|
|
|
|
2020-03-04 11:52:27 -05:00
|
|
|
this._spawn(Meta.is_wayland_compositor() ? [] : ['--xim']);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-05-29 09:27:42 -04:00
|
|
|
|
2019-08-15 07:28:59 -04:00
|
|
|
_spawn(extraArgs = []) {
|
2014-05-29 09:27:42 -04:00
|
|
|
try {
|
2019-08-15 07:29:53 -04:00
|
|
|
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs];
|
2020-02-29 12:43:28 -05:00
|
|
|
let launcher = Gio.SubprocessLauncher.new(Gio.SubprocessFlags.NONE);
|
|
|
|
// Forward the right X11 Display for ibus-x11
|
|
|
|
let display = GLib.getenv('GNOME_SETUP_DISPLAY');
|
|
|
|
if (display)
|
|
|
|
launcher.setenv('DISPLAY', display, true);
|
2020-03-08 22:09:47 -04:00
|
|
|
launcher.spawnv(cmdLine);
|
2019-01-28 20:26:39 -05:00
|
|
|
} catch (e) {
|
2019-01-29 19:18:24 -05:00
|
|
|
log(`Failed to launch ibus-daemon: ${e.message}`);
|
2014-05-29 09:27:42 -04:00
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2019-08-15 07:28:59 -04:00
|
|
|
restartDaemon(extraArgs = []) {
|
|
|
|
this._spawn(['-r', ...extraArgs]);
|
|
|
|
}
|
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_clear() {
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
if (this._cancellable) {
|
|
|
|
this._cancellable.cancel();
|
|
|
|
this._cancellable = null;
|
|
|
|
}
|
|
|
|
|
2019-09-25 16:15:38 -04:00
|
|
|
if (this._preloadEnginesId) {
|
|
|
|
GLib.source_remove(this._preloadEnginesId);
|
|
|
|
this._preloadEnginesId = 0;
|
|
|
|
}
|
|
|
|
|
2014-02-14 07:35:05 -05:00
|
|
|
if (this._panelService)
|
|
|
|
this._panelService.destroy();
|
|
|
|
|
|
|
|
this._panelService = null;
|
|
|
|
this._candidatePopup.setPanelService(null);
|
2019-06-29 19:02:34 -04:00
|
|
|
this._engines.clear();
|
2014-02-14 07:35:05 -05:00
|
|
|
this._ready = false;
|
|
|
|
this._registerPropertiesId = 0;
|
|
|
|
this._currentEngineName = null;
|
|
|
|
|
|
|
|
this.emit('ready', false);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_onConnected() {
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
this._cancellable = new Gio.Cancellable();
|
|
|
|
this._ibus.list_engines_async(-1, this._cancellable,
|
|
|
|
this._initEngines.bind(this));
|
2014-02-14 07:35:05 -05:00
|
|
|
this._ibus.request_name_async(IBus.SERVICE_PANEL,
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
|
|
|
|
this._initPanelService.bind(this));
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_initEngines(ibus, result) {
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
try {
|
|
|
|
let enginesList = this._ibus.list_engines_async_finish(result);
|
2014-02-14 07:35:05 -05:00
|
|
|
for (let i = 0; i < enginesList.length; ++i) {
|
|
|
|
let name = enginesList[i].get_name();
|
2019-06-29 19:02:34 -04:00
|
|
|
this._engines.set(name, enginesList[i]);
|
2014-02-14 07:35:05 -05:00
|
|
|
}
|
|
|
|
this._updateReadiness();
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
} catch (e) {
|
|
|
|
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
|
|
|
return;
|
|
|
|
|
|
|
|
logError(e);
|
2014-02-14 07:35:05 -05:00
|
|
|
this._clear();
|
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_initPanelService(ibus, result) {
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
let success = false;
|
|
|
|
try {
|
|
|
|
success = !!this._ibus.request_name_async_finish(result);
|
|
|
|
} catch (e) {
|
|
|
|
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
|
|
|
return;
|
|
|
|
logError(e);
|
|
|
|
}
|
|
|
|
|
2014-02-14 07:35:05 -05:00
|
|
|
if (success) {
|
|
|
|
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
|
|
|
|
object_path: IBus.PATH_PANEL });
|
|
|
|
this._candidatePopup.setPanelService(this._panelService);
|
2017-12-01 19:27:35 -05:00
|
|
|
this._panelService.connect('update-property', this._updateProperty.bind(this));
|
2018-05-25 05:35:49 -04:00
|
|
|
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
|
|
|
|
let cursorLocation = { x, y, width: w, height: h };
|
|
|
|
this.emit('set-cursor-location', cursorLocation);
|
|
|
|
});
|
2018-09-18 06:54:29 -04:00
|
|
|
this._panelService.connect('focus-in', (panel, path) => {
|
|
|
|
if (!GLib.str_has_suffix(path, '/InputContext_1'))
|
2019-08-19 13:55:49 -04:00
|
|
|
this.emit('focus-in');
|
2018-09-18 06:54:29 -04:00
|
|
|
});
|
2019-01-27 19:42:00 -05:00
|
|
|
this._panelService.connect('focus-out', () => this.emit('focus-out'));
|
2018-05-25 05:35:49 -04:00
|
|
|
|
2014-11-27 03:23:01 -05:00
|
|
|
try {
|
|
|
|
// IBus versions older than 1.5.10 have a bug which
|
|
|
|
// causes spurious set-content-type emissions when
|
|
|
|
// switching input focus that temporarily lose purpose
|
|
|
|
// and hints defeating its intended semantics and
|
|
|
|
// confusing users. We thus don't use it in that case.
|
|
|
|
_checkIBusVersion(1, 5, 10);
|
2017-12-01 19:27:35 -05:00
|
|
|
this._panelService.connect('set-content-type', this._setContentType.bind(this));
|
2014-11-27 03:23:01 -05:00
|
|
|
} catch (e) {
|
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
// If an engine is already active we need to get its properties
|
2019-08-19 20:20:08 -04:00
|
|
|
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
|
2014-02-14 07:35:05 -05:00
|
|
|
let engine;
|
|
|
|
try {
|
2019-08-19 20:20:08 -04:00
|
|
|
engine = this._ibus.get_global_engine_async_finish(res);
|
2014-02-14 07:35:05 -05:00
|
|
|
if (!engine)
|
|
|
|
return;
|
2019-01-28 20:26:39 -05:00
|
|
|
} catch (e) {
|
2014-02-14 07:35:05 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._engineChanged(this._ibus, engine.get_name());
|
2017-10-30 20:38:18 -04:00
|
|
|
});
|
2014-02-14 07:35:05 -05:00
|
|
|
this._updateReadiness();
|
|
|
|
} else {
|
|
|
|
this._clear();
|
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateReadiness() {
|
2019-06-29 19:02:34 -04:00
|
|
|
this._ready = this._engines.size > 0 && this._panelService != null;
|
2014-02-14 07:35:05 -05:00
|
|
|
this.emit('ready', this._ready);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_engineChanged(bus, engineName) {
|
2014-02-14 07:35:05 -05:00
|
|
|
if (!this._ready)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._currentEngineName = engineName;
|
|
|
|
|
|
|
|
if (this._registerPropertiesId != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._registerPropertiesId =
|
2017-10-30 20:38:18 -04:00
|
|
|
this._panelService.connect('register-properties', (p, props) => {
|
2014-02-14 07:35:05 -05:00
|
|
|
if (!props.get(0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._panelService.disconnect(this._registerPropertiesId);
|
|
|
|
this._registerPropertiesId = 0;
|
|
|
|
|
|
|
|
this.emit('properties-registered', this._currentEngineName, props);
|
2017-10-30 20:38:18 -04:00
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateProperty(panel, prop) {
|
2014-02-14 07:35:05 -05:00
|
|
|
this.emit('property-updated', this._currentEngineName, prop);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_setContentType(panel, purpose, hints) {
|
2014-11-27 03:23:01 -05:00
|
|
|
this.emit('set-content-type', purpose, hints);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-11-27 03:23:01 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
activateProperty(key, state) {
|
2014-02-14 07:35:05 -05:00
|
|
|
this._panelService.property_activate(key, state);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-02-14 07:35:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
getEngineDesc(id) {
|
2019-06-29 19:02:34 -04:00
|
|
|
if (!this._ready || !this._engines.has(id))
|
2014-02-14 07:35:05 -05:00
|
|
|
return null;
|
|
|
|
|
2019-06-29 19:02:34 -04:00
|
|
|
return this._engines.get(id);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-06-05 12:47:48 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
setEngine(id, callback) {
|
2014-11-27 03:23:01 -05:00
|
|
|
// Send id even if id == this._currentEngineName
|
|
|
|
// because 'properties-registered' signal can be emitted
|
|
|
|
// while this._ibusSources == null on a lock screen.
|
2018-01-17 11:01:24 -05:00
|
|
|
if (!this._ready) {
|
2014-06-05 12:47:48 -04:00
|
|
|
if (callback)
|
|
|
|
callback();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
this._ibus.set_global_engine_async(id,
|
|
|
|
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
|
|
|
|
this._cancellable, (_bus, res) => {
|
|
|
|
try {
|
|
|
|
this._ibus.set_global_engine_async_finish(res);
|
|
|
|
} catch (e) {
|
|
|
|
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
|
|
|
logError(e);
|
|
|
|
}
|
|
|
|
if (callback)
|
|
|
|
callback();
|
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-11-10 05:09:08 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
preloadEngines(ids) {
|
2018-01-17 11:01:24 -05:00
|
|
|
if (!this._ibus || ids.length == 0)
|
2014-11-10 05:09:08 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (this._preloadEnginesId != 0) {
|
2019-08-19 14:50:33 -04:00
|
|
|
GLib.source_remove(this._preloadEnginesId);
|
2014-11-10 05:09:08 -05:00
|
|
|
this._preloadEnginesId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._preloadEnginesId =
|
2019-08-19 14:50:33 -04:00
|
|
|
GLib.timeout_add_seconds(
|
|
|
|
GLib.PRIORITY_DEFAULT,
|
|
|
|
this._PRELOAD_ENGINES_DELAY_TIME,
|
|
|
|
() => {
|
|
|
|
this._ibus.preload_engines_async(
|
|
|
|
ids,
|
|
|
|
-1,
|
ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.
In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-09-25 14:56:46 -04:00
|
|
|
this._cancellable,
|
2019-08-19 14:50:33 -04:00
|
|
|
null);
|
|
|
|
this._preloadEnginesId = 0;
|
|
|
|
return GLib.SOURCE_REMOVE;
|
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
|
|
|
};
|
2014-02-14 07:35:05 -05:00
|
|
|
Signals.addSignalMethods(IBusManager.prototype);
|