diff --git a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js index d19e5f88c7..5c25f5c3fc 100644 --- a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js @@ -1937,6 +1937,14 @@ class CinnamonMenuApplet extends Applet.TextIconApplet { return Clutter.EVENT_STOP; } break; + case Clutter.KEY_A: + case Clutter.KEY_a: + if (ctrlKey) { + let textLen = this.searchEntryText.get_text().length; + this.searchEntryText.set_selection(0, textLen); + return Clutter.EVENT_STOP; + } + break; case Clutter.KEY_Menu: if (this._activeContainer === this.applicationsBox) { this.toggleContextMenu(active._delegate); diff --git a/js/ui/main.js b/js/ui/main.js index 1ba0868689..8c7962b810 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -1306,6 +1306,7 @@ function _shouldFilterKeybinding(entry) { * to give the multi-key binding a chance to activate on key-press. */ let _modifierOnlyAction = 0; +let _lastModifierKeyCode = 0; function _isModifierKeyval(symbol) { return symbol === Clutter.KEY_Super_L || symbol === Clutter.KEY_Super_R || @@ -1314,6 +1315,25 @@ function _isModifierKeyval(symbol) { symbol === Clutter.KEY_Shift_L || symbol === Clutter.KEY_Shift_R; } +function _modifierMaskForKeySymbol(symbol) { + switch (symbol) { + case Clutter.KEY_Control_L: + case Clutter.KEY_Control_R: + return Clutter.ModifierType.CONTROL_MASK; + case Clutter.KEY_Shift_L: + case Clutter.KEY_Shift_R: + return Clutter.ModifierType.SHIFT_MASK; + case Clutter.KEY_Alt_L: + case Clutter.KEY_Alt_R: + return Clutter.ModifierType.MOD1_MASK; + case Clutter.KEY_Super_L: + case Clutter.KEY_Super_R: + return Clutter.ModifierType.MOD4_MASK; + default: + return 0; + } +} + function _stageEventHandler(actor, event) { if (modalCount == 0) return false; @@ -1345,10 +1365,34 @@ function _stageEventHandler(actor, event) { return true; } } + + // Try reverse order for multi-modifier keybindings (e.g., Shift+Ctrl + // when the binding is stored as Ctrl+Shift). If a previous modifier + // key was pressed without matching, try its keycode with this key's + // modifier mask. + if (action <= 0 && _lastModifierKeyCode > 0) { + let currentMask = _modifierMaskForKeySymbol(event.get_key_symbol()); + action = global.display.get_keybinding_action(_lastModifierKeyCode, currentMask); + if (action > 0) { + let entry = keybindingManager.getBindingById(action); + if (!_shouldFilterKeybinding(entry)) { + _modifierOnlyAction = action; + _lastModifierKeyCode = 0; + return true; + } + } + } + + // Any modifier key press that doesn't match cancels a pending + // single-modifier action from a previous modifier press. + _modifierOnlyAction = 0; + _lastModifierKeyCode = keyCode; return false; } + // Non-modifier key press clears pending modifier-only action. _modifierOnlyAction = 0; + _lastModifierKeyCode = 0; // During modal, muffin's process_iso_next_group doesn't run, handle xkb 'grp' // here. @@ -1370,11 +1414,14 @@ function _stageEventHandler(actor, event) { } // Release event - activate the single-key modifier keybinding if one was stored. - if (_isModifierKeyval(event.get_key_symbol()) && _modifierOnlyAction > 0) { - let action = _modifierOnlyAction; - _modifierOnlyAction = 0; - keybindingManager.invoke_keybinding_action_by_id(action); - return true; + if (_isModifierKeyval(event.get_key_symbol())) { + _lastModifierKeyCode = 0; + if (_modifierOnlyAction > 0) { + let action = _modifierOnlyAction; + _modifierOnlyAction = 0; + keybindingManager.invoke_keybinding_action_by_id(action); + return true; + } } return false; @@ -1390,6 +1437,7 @@ function _findModal(actor) { function _completeModalSetup(actor, mode, onDismiss) { _modifierOnlyAction = 0; + _lastModifierKeyCode = 0; if (modalCount == 0) Meta.disable_unredirect_for_display(global.display); diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index 34f2cc130f..6ee9d08066 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -1858,6 +1858,8 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { opacity: 255, onComplete: () => { this.animating = false; + let [xPos, yPos] = this._calculatePosition(); + this.actor.set_position(xPos, yPos); } } @@ -1891,8 +1893,7 @@ var PopupMenu = class PopupMenu extends PopupMenuBase { this.animating = false; let [xPos, yPos] = this._calculatePosition(); // should this be conditional on this._slidePosition being -1? - this.actor.x = xPos; - this.actor.y = yPos; + this.actor.set_position(xPos, yPos); this.actor.show(); }