inputMethod: Use forward_key() method to forward key events

ClutterVirtualInputDevice has the limitation that event flags won't be
made to contain CLUTTER_EVENT_FLAG_INPUT_METHOD, possibly causing feedback
loops.

As the event gets injected up the platform dependent bits, we can avoid
care on not pressing the same key twice, we still expect coherence between
key presses and releases from the IM though.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/531
This commit is contained in:
Carlos Garnacho 2018-09-27 21:09:02 +02:00 committed by Carlos Garnacho
parent 501a1aff68
commit d44ffc1158

View File

@ -15,8 +15,6 @@ var InputMethod = new Lang.Class({
this._purpose = 0; this._purpose = 0;
this._enabled = true; this._enabled = true;
this._currentFocus = null; this._currentFocus = null;
this._currentEvent = null;
this._doForwardEvent = false;
this._preeditStr = ''; this._preeditStr = '';
this._preeditPos = 0; this._preeditPos = 0;
this._ibus = IBus.Bus.new_async(); this._ibus = IBus.Bus.new_async();
@ -29,9 +27,6 @@ var InputMethod = new Lang.Class({
this._onSourceChanged.bind(this)); this._onSourceChanged.bind(this));
this._currentSource = this._inputSourceManager.currentSource; this._currentSource = this._inputSourceManager.currentSource;
let deviceManager = Clutter.DeviceManager.get_default();
this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
if (this._ibus.is_connected()) if (this._ibus.is_connected())
this._onConnected(); this._onConnected();
}, },
@ -121,20 +116,16 @@ var InputMethod = new Lang.Class({
_onForwardKeyEvent(context, keyval, keycode, state) { _onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0; let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~(IBus.ModifierType.RELEASE_MASK);
if (this._currentEvent) { let curEvent = Clutter.get_current_event();
// If we are handling this same event in filter_key_press(), let time;
// just let it go through, sending the same event again will if (curEvent)
// be silenced away because the key counts as pressed. time = curEvent.get_time();
if (this._currentEvent.get_key_symbol() == keyval && else
(this._currentEvent.type() == Clutter.EventType.KEY_PRESS) == press) { time = global.display.get_current_time_roundtrip();
this._doForwardEvent = true;
return;
}
}
this._virtualDevice.notify_key(Clutter.get_current_event_time(), keycode, this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press);
press ? Clutter.KeyState.PRESSED : Clutter.KeyState.RELEASED);
}, },
vfunc_focus_in(focus) { vfunc_focus_in(focus) {
@ -242,22 +233,13 @@ var InputMethod = new Lang.Class({
if (event.type() == Clutter.EventType.KEY_RELEASE) if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK; state |= IBus.ModifierType.RELEASE_MASK;
this._currentEvent = event;
this._doForwardEvent = false;
this._context.process_key_event_async(event.get_key_symbol(), this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, null, state, -1, null,
(context, res) => { (context, res) => {
try { try {
let retval = context.process_key_event_async_finish(res); let retval = context.process_key_event_async_finish(res);
if (this._doForwardEvent)
retval = false;
this.notify_key_event(event, retval); this.notify_key_event(event, retval);
this._doForwardEvent = false;
this._currentEvent = null;
} catch (e) { } catch (e) {
log('Error processing key on IM: ' + e.message); log('Error processing key on IM: ' + e.message);
} }