ibusManager: Disable IBus input sources on password entries
Input method preedit text needs to be disabled on password entries for security and usability reasons. IBus 1.5.7 provides the signal set-content-type so that panel UIs can handle these special purpose input entries: https://github.com/ibus/ibus/commit/6ca5ddb302c9 Unfortunately 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. https://bugzilla.gnome.org/show_bug.cgi?id=730628
This commit is contained in:
parent
19c7da7b08
commit
d8ca374a06
@ -8,7 +8,7 @@ const Signals = imports.signals;
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
var IBus = imports.gi.IBus;
|
var IBus = imports.gi.IBus;
|
||||||
_checkIBusVersion();
|
_checkIBusVersion(1, 5, 2);
|
||||||
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var IBus = null;
|
var IBus = null;
|
||||||
@ -17,11 +17,7 @@ try {
|
|||||||
|
|
||||||
let _ibusManager = null;
|
let _ibusManager = null;
|
||||||
|
|
||||||
function _checkIBusVersion() {
|
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
|
||||||
var requiredMajor = 1;
|
|
||||||
var requiredMinor = 5;
|
|
||||||
var requiredMicro = 2;
|
|
||||||
|
|
||||||
if ((IBus.MAJOR_VERSION > requiredMajor) ||
|
if ((IBus.MAJOR_VERSION > requiredMajor) ||
|
||||||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
|
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
|
||||||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
|
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
|
||||||
@ -125,6 +121,16 @@ const IBusManager = new Lang.Class({
|
|||||||
object_path: IBus.PATH_PANEL });
|
object_path: IBus.PATH_PANEL });
|
||||||
this._candidatePopup.setPanelService(this._panelService);
|
this._candidatePopup.setPanelService(this._panelService);
|
||||||
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
|
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
|
||||||
|
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);
|
||||||
|
this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
// If an engine is already active we need to get its properties
|
// If an engine is already active we need to get its properties
|
||||||
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
|
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
|
||||||
let engine;
|
let engine;
|
||||||
@ -174,6 +180,10 @@ const IBusManager = new Lang.Class({
|
|||||||
this.emit('property-updated', this._currentEngineName, prop);
|
this.emit('property-updated', this._currentEngineName, prop);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_setContentType: function(panel, purpose, hints) {
|
||||||
|
this.emit('set-content-type', purpose, hints);
|
||||||
|
},
|
||||||
|
|
||||||
activateProperty: function(key, state) {
|
activateProperty: function(key, state) {
|
||||||
this._panelService.property_activate(key, state);
|
this._panelService.property_activate(key, state);
|
||||||
},
|
},
|
||||||
@ -186,7 +196,10 @@ const IBusManager = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
setEngine: function(id, callback) {
|
setEngine: function(id, callback) {
|
||||||
if (!IBus || !this._ready || id == this._currentEngineName) {
|
// Send id even if id == this._currentEngineName
|
||||||
|
// because 'properties-registered' signal can be emitted
|
||||||
|
// while this._ibusSources == null on a lock screen.
|
||||||
|
if (!IBus || !this._ready) {
|
||||||
if (callback)
|
if (callback)
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
|
@ -155,6 +155,7 @@ const InputSourceManager = new Lang.Class({
|
|||||||
this._ibusSources = {};
|
this._ibusSources = {};
|
||||||
|
|
||||||
this._currentSource = null;
|
this._currentSource = null;
|
||||||
|
this._backupSource = null;
|
||||||
|
|
||||||
// All valid input sources currently in the gsettings
|
// All valid input sources currently in the gsettings
|
||||||
// KEY_INPUT_SOURCES list ordered by most recently used
|
// KEY_INPUT_SOURCES list ordered by most recently used
|
||||||
@ -183,6 +184,7 @@ const InputSourceManager = new Lang.Class({
|
|||||||
this._ibusManager.connect('ready', Lang.bind(this, this._ibusReadyCallback));
|
this._ibusManager.connect('ready', Lang.bind(this, this._ibusReadyCallback));
|
||||||
this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
|
this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
|
||||||
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
|
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
|
||||||
|
this._ibusManager.connect('set-content-type', Lang.bind(this, this._ibusSetContentType));
|
||||||
|
|
||||||
global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
|
global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
|
||||||
|
|
||||||
@ -192,6 +194,7 @@ const InputSourceManager = new Lang.Class({
|
|||||||
this._overviewHiddenId = 0;
|
this._overviewHiddenId = 0;
|
||||||
this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
|
this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
|
||||||
this._sourcesPerWindowChanged();
|
this._sourcesPerWindowChanged();
|
||||||
|
this._disableIBus = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
reload: function() {
|
reload: function() {
|
||||||
@ -309,6 +312,8 @@ const InputSourceManager = new Lang.Class({
|
|||||||
[exists, displayName, shortName, , ] =
|
[exists, displayName, shortName, , ] =
|
||||||
this._xkbInfo.get_layout_info(id);
|
this._xkbInfo.get_layout_info(id);
|
||||||
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
|
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
|
||||||
|
if (this._disableIBus)
|
||||||
|
continue;
|
||||||
let engineDesc = this._ibusManager.getEngineDesc(id);
|
let engineDesc = this._ibusManager.getEngineDesc(id);
|
||||||
if (engineDesc) {
|
if (engineDesc) {
|
||||||
let language = IBus.get_language_name(engineDesc.get_language());
|
let language = IBus.get_language_name(engineDesc.get_language());
|
||||||
@ -379,8 +384,20 @@ const InputSourceManager = new Lang.Class({
|
|||||||
}
|
}
|
||||||
this._mruSources = mruSources.concat(sourcesList);
|
this._mruSources = mruSources.concat(sourcesList);
|
||||||
|
|
||||||
if (this._mruSources.length > 0)
|
if (this._mruSources.length > 0) {
|
||||||
|
if (!this._disableIBus && this._backupSource) {
|
||||||
|
for (let i = 0; i < this._mruSources.length; i++) {
|
||||||
|
if (this._mruSources[i].type == this._backupSource.type &&
|
||||||
|
this._mruSources[i].id == this._backupSource.id) {
|
||||||
|
let currentSource = this._mruSources.splice(i, 1);
|
||||||
|
this._mruSources = currentSource.concat(this._mruSources);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._backupSource = null;
|
||||||
|
}
|
||||||
this._mruSources[0].activate();
|
this._mruSources[0].activate();
|
||||||
|
}
|
||||||
|
|
||||||
// All ibus engines are preloaded here to reduce the launching time
|
// All ibus engines are preloaded here to reduce the launching time
|
||||||
// when users switch the input sources.
|
// when users switch the input sources.
|
||||||
@ -437,6 +454,27 @@ const InputSourceManager = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_ibusSetContentType: function(im, purpose, hints) {
|
||||||
|
if (purpose == IBus.InputPurpose.PASSWORD) {
|
||||||
|
if (Object.keys(this._inputSources).length == Object.keys(this._ibusSources).length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._disableIBus)
|
||||||
|
return;
|
||||||
|
this._disableIBus = true;
|
||||||
|
this._backupSource = this._currentSource;
|
||||||
|
} else {
|
||||||
|
if (!this._disableIBus)
|
||||||
|
return;
|
||||||
|
this._disableIBus = false;
|
||||||
|
}
|
||||||
|
// If this._mruSources is not cleared before this.reload() is called,
|
||||||
|
// the order is different from the original one as IM sources will
|
||||||
|
// be appended to XKB sources.
|
||||||
|
this._mruSources = [];
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
|
||||||
_getNewInputSource: function(current) {
|
_getNewInputSource: function(current) {
|
||||||
for (let i in this._inputSources) {
|
for (let i in this._inputSources) {
|
||||||
let is = this._inputSources[i];
|
let is = this._inputSources[i];
|
||||||
|
Loading…
Reference in New Issue
Block a user