keyboard: Add/handle "modifier" action keys
These keys are handled so that the related modifier keyval (e.g. left control) is toggled on, and flushed on the next non-modifier key press submission. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2278>
This commit is contained in:
parent
3b81e0f8eb
commit
2920738d23
@ -24,6 +24,8 @@ const SHOW_KEYBOARD = 'screen-keyboard-enabled';
|
|||||||
/* KeyContainer puts keys in a grid where a 1:1 key takes this size */
|
/* KeyContainer puts keys in a grid where a 1:1 key takes this size */
|
||||||
const KEY_SIZE = 2;
|
const KEY_SIZE = 2;
|
||||||
|
|
||||||
|
const KEY_RELEASE_TIMEOUT = 50;
|
||||||
|
|
||||||
var AspectContainer = GObject.registerClass(
|
var AspectContainer = GObject.registerClass(
|
||||||
class AspectContainer extends St.Widget {
|
class AspectContainer extends St.Widget {
|
||||||
_init(params) {
|
_init(params) {
|
||||||
@ -274,6 +276,14 @@ var Key = GObject.registerClass({
|
|||||||
this._capturedPress = false;
|
this._capturedPress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get iconName() {
|
||||||
|
return this._icon.icon_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
set iconName(value) {
|
||||||
|
this._icon.icon_name = value;
|
||||||
|
}
|
||||||
|
|
||||||
_onDestroy() {
|
_onDestroy() {
|
||||||
if (this._boxPointer) {
|
if (this._boxPointer) {
|
||||||
this._boxPointer.destroy();
|
this._boxPointer.destroy();
|
||||||
@ -488,16 +498,10 @@ var Key = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLatched(latched) {
|
setLatched(latched) {
|
||||||
if (!this._icon)
|
if (latched)
|
||||||
return;
|
|
||||||
|
|
||||||
if (latched) {
|
|
||||||
this.keyButton.add_style_pseudo_class('latched');
|
this.keyButton.add_style_pseudo_class('latched');
|
||||||
this._icon.icon_name = 'keyboard-caps-lock-symbolic';
|
else
|
||||||
} else {
|
|
||||||
this.keyButton.remove_style_pseudo_class('latched');
|
this.keyButton.remove_style_pseudo_class('latched');
|
||||||
this._icon.icon_name = 'keyboard-shift-symbolic';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1280,6 +1284,8 @@ var Keyboard = GObject.registerClass({
|
|||||||
this._focusWindowStartY = null;
|
this._focusWindowStartY = null;
|
||||||
|
|
||||||
this._latched = false; // current level is latched
|
this._latched = false; // current level is latched
|
||||||
|
this._modifiers = new Set();
|
||||||
|
this._modifierKeys = new Map();
|
||||||
|
|
||||||
this._suggestions = null;
|
this._suggestions = null;
|
||||||
this._emojiKeyVisible = Meta.is_wayland_compositor();
|
this._emojiKeyVisible = Meta.is_wayland_compositor();
|
||||||
@ -1488,18 +1494,28 @@ var Keyboard = GObject.registerClass({
|
|||||||
if (key.width !== null)
|
if (key.width !== null)
|
||||||
button.setWidth(key.width);
|
button.setWidth(key.width);
|
||||||
|
|
||||||
button.connect('commit', (actor, keyval, str) => {
|
if (key.action !== 'modifier') {
|
||||||
if (str === '' || !Main.inputMethod.currentFocus ||
|
button.connect('commit', (actor, keyval, str) => {
|
||||||
!this._keyboardController.commitString(str, true)) {
|
if (str === '' || !Main.inputMethod.currentFocus ||
|
||||||
if (keyval != 0) {
|
this._modifiers.size > 0 ||
|
||||||
this._keyboardController.keyvalPress(keyval);
|
!this._keyboardController.commitString(str, true)) {
|
||||||
this._keyboardController.keyvalRelease(keyval);
|
if (keyval !== 0) {
|
||||||
|
this._forwardModifiers(this._modifiers, Clutter.EventType.KEY_PRESS);
|
||||||
|
this._keyboardController.keyvalPress(keyval);
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, KEY_RELEASE_TIMEOUT, () => {
|
||||||
|
this._keyboardController.keyvalRelease(keyval);
|
||||||
|
this._forwardModifiers(this._modifiers, Clutter.EventType.KEY_RELEASE);
|
||||||
|
this._disableAllModifiers();
|
||||||
|
return GLib.SOURCE_REMOVE;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._latched)
|
if (!this._latched)
|
||||||
this._setActiveLayer(0);
|
this._setActiveLayer(0);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (key.action !== null) {
|
if (key.action !== null) {
|
||||||
button.connect('released', () => {
|
button.connect('released', () => {
|
||||||
if (key.action === 'hide') {
|
if (key.action === 'hide') {
|
||||||
@ -1508,6 +1524,8 @@ var Keyboard = GObject.registerClass({
|
|||||||
this._popupLanguageMenu(button);
|
this._popupLanguageMenu(button);
|
||||||
} else if (key.action === 'emoji') {
|
} else if (key.action === 'emoji') {
|
||||||
this._toggleEmoji();
|
this._toggleEmoji();
|
||||||
|
} else if (key.action === 'modifier') {
|
||||||
|
this._toggleModifier(key.keyval);
|
||||||
} else if (!this._longPressed && key.action === 'levelSwitch') {
|
} else if (!this._longPressed && key.action === 'levelSwitch') {
|
||||||
this._setActiveLayer(key.level);
|
this._setActiveLayer(key.level);
|
||||||
this._setLatched(
|
this._setLatched(
|
||||||
@ -1531,6 +1549,12 @@ var Keyboard = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key.action === 'modifier') {
|
||||||
|
let modifierKeys = this._modifierKeys[key.keyval] || [];
|
||||||
|
modifierKeys.push(button);
|
||||||
|
this._modifierKeys[key.keyval] = modifierKeys;
|
||||||
|
}
|
||||||
|
|
||||||
if (key.action || key.keyval)
|
if (key.action || key.keyval)
|
||||||
button.keyButton.add_style_class_name('default-key');
|
button.keyButton.add_style_class_name('default-key');
|
||||||
|
|
||||||
@ -1543,6 +1567,35 @@ var Keyboard = GObject.registerClass({
|
|||||||
this._setCurrentLevelLatched(this._currentPage, this._latched);
|
this._setCurrentLevelLatched(this._currentPage, this._latched);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setModifierEnabled(keyval, enabled) {
|
||||||
|
if (enabled)
|
||||||
|
this._modifiers.add(keyval);
|
||||||
|
else
|
||||||
|
this._modifiers.delete(keyval);
|
||||||
|
|
||||||
|
for (const key of this._modifierKeys[keyval])
|
||||||
|
key.setLatched(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toggleModifier(keyval) {
|
||||||
|
const isActive = this._modifiers.has(keyval);
|
||||||
|
this._setModifierEnabled(keyval, !isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
_forwardModifiers(modifiers, type) {
|
||||||
|
for (const keyval of modifiers) {
|
||||||
|
if (type === Clutter.EventType.KEY_PRESS)
|
||||||
|
this._keyboardController.keyvalPress(keyval);
|
||||||
|
else if (type === Clutter.EventType.KEY_RELEASE)
|
||||||
|
this._keyboardController.keyvalRelease(keyval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableAllModifiers() {
|
||||||
|
for (const keyval of this._modifiers)
|
||||||
|
this._setModifierEnabled(keyval, false);
|
||||||
|
}
|
||||||
|
|
||||||
_popupLanguageMenu(keyActor) {
|
_popupLanguageMenu(keyActor) {
|
||||||
if (this._languagePopup)
|
if (this._languagePopup)
|
||||||
this._languagePopup.destroy();
|
this._languagePopup.destroy();
|
||||||
@ -1571,6 +1624,8 @@ var Keyboard = GObject.registerClass({
|
|||||||
for (let i = 0; i < layout.shiftKeys.length; i++) {
|
for (let i = 0; i < layout.shiftKeys.length; i++) {
|
||||||
let key = layout.shiftKeys[i];
|
let key = layout.shiftKeys[i];
|
||||||
key.setLatched(latched);
|
key.setLatched(latched);
|
||||||
|
key.iconName = latched
|
||||||
|
? 'keyboard-caps-lock-symbolic' : 'keyboard-shift-symbolic';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1688,6 +1743,7 @@ var Keyboard = GObject.registerClass({
|
|||||||
delete this._currentPage._destroyID;
|
delete this._currentPage._destroyID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._disableAllModifiers();
|
||||||
this._currentPage = currentPage;
|
this._currentPage = currentPage;
|
||||||
this._currentPage._destroyID = this._currentPage.connect('destroy', () => {
|
this._currentPage._destroyID = this._currentPage.connect('destroy', () => {
|
||||||
this._currentPage = null;
|
this._currentPage = null;
|
||||||
@ -1768,6 +1824,7 @@ var Keyboard = GObject.registerClass({
|
|||||||
|
|
||||||
this._animateHide();
|
this._animateHide();
|
||||||
this.setCursorLocation(null);
|
this.setCursorLocation(null);
|
||||||
|
this._disableAllModifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
_animateShow() {
|
_animateShow() {
|
||||||
|
Loading…
Reference in New Issue
Block a user