keyboard: Forward/handle content hints
Forward these from the IM, and handle the ones involving the OSK state: lowercase/uppercase/auto_capitalization/titlecase. The latter two involve peeking at the surrounding text, to figure out if it makes sense to toggle keyboard level. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3162>
This commit is contained in:
parent
64d300b525
commit
7db0e01b24
@ -1244,6 +1244,7 @@ export const Keyboard = GObject.registerClass({
|
|||||||
_onFocusPositionChanged(focusTracker) {
|
_onFocusPositionChanged(focusTracker) {
|
||||||
let rect = focusTracker.getCurrentRect();
|
let rect = focusTracker.getCurrentRect();
|
||||||
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
|
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
|
||||||
|
this._updateLevelFromHints();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDestroy() {
|
_onDestroy() {
|
||||||
@ -1305,6 +1306,7 @@ export const Keyboard = GObject.registerClass({
|
|||||||
'group-changed', this._onGroupChanged.bind(this),
|
'group-changed', this._onGroupChanged.bind(this),
|
||||||
'panel-state', this._onKeyboardStateChanged.bind(this),
|
'panel-state', this._onKeyboardStateChanged.bind(this),
|
||||||
'purpose-changed', this._onPurposeChanged.bind(this),
|
'purpose-changed', this._onPurposeChanged.bind(this),
|
||||||
|
'content-hints-changed', this._onContentHintsChanged.bind(this),
|
||||||
this);
|
this);
|
||||||
global.stage.connectObject('notify::key-focus',
|
global.stage.connectObject('notify::key-focus',
|
||||||
this._onKeyFocusChanged.bind(this), this);
|
this._onKeyFocusChanged.bind(this), this);
|
||||||
@ -1317,6 +1319,60 @@ export const Keyboard = GObject.registerClass({
|
|||||||
this._updateKeys();
|
this._updateKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onContentHintsChanged(controller, contentHint) {
|
||||||
|
this._contentHint = contentHint;
|
||||||
|
this._updateLevelFromHints();
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateLevelFromHints() {
|
||||||
|
// If the latch is enabled, avoid level changes
|
||||||
|
if (this._latched)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((this._contentHint & Clutter.InputContentHintFlags.LOWERCASE) !== 0) {
|
||||||
|
this._setActiveLevel('default');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._layers['shift'])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((this._contentHint & Clutter.InputContentHintFlags.UPPERCASE) !== 0) {
|
||||||
|
this._setActiveLevel('shift');
|
||||||
|
} else if (!this._surroundingTextId &&
|
||||||
|
(this._contentHint &
|
||||||
|
(Clutter.InputContentHintFlags.AUTO_CAPITALIZATION |
|
||||||
|
Clutter.InputContentHintFlags.TITLECASE)) !== 0) {
|
||||||
|
this._surroundingTextId =
|
||||||
|
Main.inputMethod.connect('surrounding-text-set', () => {
|
||||||
|
const [text, cursor] = Main.inputMethod.getSurroundingText();
|
||||||
|
if (!text || cursor === 0) {
|
||||||
|
// First character in the buffer
|
||||||
|
this._setActiveLevel('shift');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeCursor = GLib.utf8_substring(text, 0, cursor);
|
||||||
|
|
||||||
|
if ((this._contentHint & Clutter.InputContentHintFlags.TITLECASE) !== 0) {
|
||||||
|
if (beforeCursor.charAt(beforeCursor.length - 1) === ' ')
|
||||||
|
this._setActiveLevel('shift');
|
||||||
|
else
|
||||||
|
this._setActiveLevel('default');
|
||||||
|
} else if ((this._contentHint & Clutter.InputContentHintFlags.AUTO_CAPITALIZATION) !== 0) {
|
||||||
|
if (beforeCursor.charAt(beforeCursor.trimEnd().length - 1) === '.')
|
||||||
|
this._setActiveLevel('shift');
|
||||||
|
else
|
||||||
|
this._setActiveLevel('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
Main.inputMethod.disconnect(this._surroundingTextId);
|
||||||
|
this._surroundingTextId = 0;
|
||||||
|
});
|
||||||
|
Main.inputMethod.request_surrounding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onKeyFocusChanged() {
|
_onKeyFocusChanged() {
|
||||||
let focus = global.stage.key_focus;
|
let focus = global.stage.key_focus;
|
||||||
|
|
||||||
@ -1443,8 +1499,12 @@ export const Keyboard = GObject.registerClass({
|
|||||||
this._keyboardController.commit(str, this._modifiers).then(() => {
|
this._keyboardController.commit(str, this._modifiers).then(() => {
|
||||||
this._disableAllModifiers();
|
this._disableAllModifiers();
|
||||||
if (layout.mode === 'default' ||
|
if (layout.mode === 'default' ||
|
||||||
(layout.mode === 'latched' && !this._latched))
|
(layout.mode === 'latched' && !this._latched)) {
|
||||||
this._setActiveLevel('default');
|
if (this._contentHint !== 0)
|
||||||
|
this._updateLevelFromHints();
|
||||||
|
else
|
||||||
|
this._setActiveLevel('default');
|
||||||
|
}
|
||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1925,8 +1985,8 @@ class KeyboardController extends Signals.EventEmitter {
|
|||||||
this._currentSource = this._inputSourceManager.currentSource;
|
this._currentSource = this._inputSourceManager.currentSource;
|
||||||
|
|
||||||
Main.inputMethod.connectObject(
|
Main.inputMethod.connectObject(
|
||||||
'notify::content-purpose', this._onContentPurposeHintsChanged.bind(this),
|
'notify::content-purpose', this._onPurposeHintsChanged.bind(this),
|
||||||
'notify::content-hints', this._onContentPurposeHintsChanged.bind(this),
|
'notify::content-hints', this._onContentHintsChanged.bind(this),
|
||||||
'input-panel-state', (o, state) => this.emit('panel-state', state), this);
|
'input-panel-state', (o, state) => this.emit('panel-state', state), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1949,12 +2009,18 @@ class KeyboardController extends Signals.EventEmitter {
|
|||||||
this.emit('group-changed');
|
this.emit('group-changed');
|
||||||
}
|
}
|
||||||
|
|
||||||
_onContentPurposeHintsChanged(method) {
|
_onPurposeHintsChanged(method) {
|
||||||
const purpose = method.content_purpose;
|
const purpose = method.content_purpose;
|
||||||
this._purpose = purpose;
|
this._purpose = purpose;
|
||||||
this.emit('purpose-changed', purpose);
|
this.emit('purpose-changed', purpose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onContentHintsChanged(method) {
|
||||||
|
const contentHints = method.content_hints;
|
||||||
|
this._contentHints = contentHints;
|
||||||
|
this.emit('content-hints-changed', contentHints);
|
||||||
|
}
|
||||||
|
|
||||||
getCurrentGroup() {
|
getCurrentGroup() {
|
||||||
// Special case for Korean, if Hangul mode is disabled, use the 'us' keymap
|
// Special case for Korean, if Hangul mode is disabled, use the 'us' keymap
|
||||||
if (this._currentSource.id === 'hangul') {
|
if (this._currentSource.id === 'hangul') {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user