This CL adds the ability to bind actions to a sequence of two
keypresses, rather than just one (e.g. Ctrl+K Ctrl+O). VS Code refers to
these as chords [1]. As we move forward with custom keyboard shortcuts,
it's necessary to implement chords in the DevTools so that users
can match their shortcuts to editor shortcuts that use chords or assign
custom chords. This CL also adds a Ctrl+K Ctrl+S shortcut to open the
shortcuts settings for testing purposes, but I plan to remove that
shortcut before landing this change. It will return later as part of the
VS Code editor preset.
My implementation of chords here is focused on two-keypress
shortcuts, e.g. Ctrl+K Ctrl+Shift+Q would be a valid chord but Ctrl+K
Ctrl+K Ctrl+O would not be because it has three parts. Limiting chords
to two parts simplifies the implementation and matches a similar
restriction in VS Code. Although other editors like vim and Atom allow
shortcuts of arbitrary length, that's not really a feature that users
have asked for and it would introduce extra complexity into
ShortcutRegistry for questionable gain. However, the new structure of
ShortcutRegistry leaves open the possibility of enabling
arbitrary-length shortcuts in the future.
ShortcutRegistry's approach to handling a key has been changed as
follows:
If a keypress comprises only modifiers (e.g Ctrl+Shift), then it's
ignored. The DevTools already disallow modifier-only shortcuts, so this
change just prevents modifiers from clearing the chord timeout.
If the first half of a chord has been pressed within the timeout
(currently 1000ms), then clear the timeout and try to execute the
current key as the second half of a chord. If that isn't a valid chord,
then try to execute both keys as separate shortcuts in sequence.
If there isn't an active timeout and the keypress is potentially the
first part of a chord, then set _activePrefixKey and
_activePrefixTimeout. If the timeout expires without a second key being
pressed, attempt to handle the keypress as an individual shortcut.
If the keypress isn't potentialy the first part of a chord and there
isn't an active timeout, then it will be handled as normal.
There were a few shortcuts handled outside of ShortcutRegistry (e.g.
sources.rename, debugger.toggle-breakpoint) that made the assumption
that checking the key of a single event was enough to determine whether
it matched a shortcut, so that flow has been reworked to centralize all
shortcut-matching in
ShortcutRegistry.handleKey().
Custom shortcuts design doc: https://docs.google.com/document/d/1oOPSWPxCHvMoBZ0Fw9jwFZt6gP4lrsrsl8DEAp-Hy7o/edit
[1] https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-rules
Bug: 174309
Change-Id: I1b3f384d7c65e41d0dbc5e32854fb331e052823f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2125620
Commit-Queue: Jack Lynch <jalyn@microsoft.com>
Reviewed-by: Robert Paveza <Rob.Paveza@microsoft.com>
Currently, ShortcutRegistry allows multiple shortcuts to be stored
within the same binding in a module.json, e.g. `"shortcut": "F8
Ctrl+\\"` creates two shortcuts, one on F8 and another on Ctrl+\. When
multi-keypress shortcuts/chords are added in the future, they'll use the
same format such that the above example would be interpreted as a single
shortcut bound to the F8 Ctrl+\ sequence. In order to allow that, it's
necessary to split up all of the existing shortcuts that are stored in
space-delimited strings so that they'll continue to function as
expected. This CL also updates the module.schema.json to disallow spaces
in shortcuts, a restriction that will be removed once multi-keypress
shortcuts are implemented.
Custom keyboard shortcuts design doc: https://docs.google.com/document/d/1oOPSWPxCHvMoBZ0Fw9jwFZt6gP4lrsrsl8DEAp-Hy7o/edit#heading=h.2xpjzz3fl1ju
Bug: 174309
Change-Id: I853f9918ad2892b2f4c4f3aec53013d7a6455f67
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2123807
Reviewed-by: Robert Paveza <Rob.Paveza@microsoft.com>
Reviewed-by: Vidal Diazleal <vidorteg@microsoft.com>
Commit-Queue: Jack Lynch <jalyn@microsoft.com>
Without this patch:
```
$ npm run check-json
> chrome-devtools-frontend@ check-json ~/projects/devtools/devtools-frontend
> node scripts/json_validator/validate_module_json.js
schema id ignored http://json-schema.org/draft-04/schema#
schema id ignored http://json-schema.org/draft-04/schema#
~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:92
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
^
Error: no schema with key or ref "http://json-schema.org/draft-04/schema#"
at Ajv.validate (~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:92:19)
at Ajv.validateSchema (~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:173:20)
at Ajv._addSchema (~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:306:10)
at Ajv.addSchema (~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:136:29)
at Ajv.addMetaSchema (~/projects/devtools/devtools-frontend/node_modules/ajv/lib/ajv.js:151:8)
at Object.<anonymous> (~/projects/devtools/devtools-frontend/scripts/json_validator/validate_module_json.js:20:5)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:643:32)
at Function.Module._load (internal/modules/cjs/loader.js:556:12)
```
After applying this patch:
```
$ npm run check-json
> chrome-devtools-frontend@ check-json ~/projects/devtools/devtools-frontend
> node scripts/json_validator/validate_module_json.js
schema $id ignored http://json-schema.org/draft-07/schema#
schema $id ignored http://json-schema.org/draft-07/schema#
schema $id ignored http://json-schema.org/draft-07/schema#
```
Fixed: chromium:1030215
Change-Id: Ie799ffbc9dfe50bdfedb18a0d9ac2ce63a9e4439
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1953774
Auto-Submit: Mathias Bynens <mathias@chromium.org>
Commit-Queue: Mathias Bynens <mathias@chromium.org>
Reviewed-by: Tim van der Lippe <tvanderlippe@chromium.org>