-
Notifications
You must be signed in to change notification settings - Fork 58
Improve reliability of catching modifier key-up events #156
Conversation
still very WIP, lots of pieces still on the floor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good.
Overall the approach of maintaining a separate collection of pending matches that you don't clear on the timeout seems sound. It's always hard for me to look at something this complex and say "yep, no regressions", but the approach makes sense.
Biggest style nitpick is you gotta convert all the snake_case
to camelCase
because that's how things are in JS/CoffeeScript land.
I made one suggestion that may or may not work out when explored, which is to store the pending keydown-keyup style bindings in a separate array always rather than puling them out of the partial matches. They really are a different class of match, and I think expressing that in the way the essential state is maintained might lead to more clarity. I could be wrong about this though and you'd have to dig in to find out.
assert(isModifierKeyup('^cmd')) | ||
assert(isModifierKeyup('^ctrl-shift')) | ||
assert(isModifierKeyup('^alt-cmd')) | ||
it "returns false for modifier keydowns", -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Should insert an empty line above this second it
.
KeyBinding = require '../src/key-binding' | ||
|
||
describe "KeyBinding", -> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: 🔥 this newline.
|
||
describe "KeyBinding", -> | ||
|
||
describe "is_matched_modifer_keydown_keyup", -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snake_case
camelCase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method name is also quite a mouthful. I'm not sure I can come up with anything better though.
|
||
describe "is_matched_modifer_keydown_keyup", -> | ||
|
||
describe "returns false when the binding...", -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this ...
approach. Cute!
@@ -0,0 +1,54 @@ | |||
KeyBinding = require '../src/key-binding' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea unit testing this class.
exports.keydownEvent = (key, options) -> | ||
return buildKeyboardEvent(key, 'keydown', options) | ||
|
||
exports.keyupEvent = (key, options) -> | ||
return buildKeyboardEvent(key, 'keyup', options) | ||
|
||
exports.getModKeys = (keystroke) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally spell stuff out fully for maximal clarity throughout the Atom codebase. getModifierKeys
or getModifiers
would be better.
@@ -95,6 +95,10 @@ class KeymapManager | |||
pendingStateTimeoutHandle: null | |||
dvorakQwertyWorkaroundEnabled: false | |||
|
|||
# Pending matches to bindings that begin with a modifier keydown and and with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and and
➡️ and end
?
keystroke = @keystrokeForKeyboardEvent(event) | ||
console.log(keystroke) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
@@ -513,6 +519,15 @@ class KeymapManager | |||
dispatchedExactMatch = null | |||
partialMatches = @findPartialMatches(partialMatchCandidates, target) | |||
|
|||
if @pendingPartialMatchedModifierKeystrokes? and isModifierKeyup(keystroke) | |||
for binding in @pendingPartialMatchedModifierKeystrokes | |||
binding_mod_keyups = getModKeys(binding.keystrokeArray[binding.keystrokeArray.length-1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be encapsulated in a method in the binding that takes the keystroke string?
@pendingPartialMatches = pendingPartialMatches | ||
if enableTimeout | ||
@pendingStateTimeoutHandle = setTimeout(@terminatePendingState.bind(this, true), @partialMatchTimeout) | ||
|
||
cancelPendingState: -> | ||
buildPendingPartialMatchedModiferKeystrokes: -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it would make more sense to store the matched-keydown-keyup style bindings in a separate array all the time rather than filtering them out of the partial matches array later. You could potentially do this in the findMatchCandidates
method.
This will get merged after the next release, meaning it should land in 1.14. |
🎉 |
For MRU tab switching, these key bindings were added:
The
^ctrl
is a key-up event on the ctrl key. Catching it is necessary to correctly push the current item to the top of the MRU stack. But we fail to catch the ctrl key-up in any of these cases:^ctrl-shift
,^shift ^ctrl
, or^ctrl ^shift
and only the last will successfully match the binding.This PR addresses this bug as follows:
Should fix atom/tabs#314 and is a prerequisite for adding the MRU list UI (atom/tabs#388) that fixes atom/atom#11035.