-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Choose Summon keybinding #1489
Choose Summon keybinding #1489
Conversation
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.
had a couple issues with running on Ubuntu, though not sure if they're about the code, OS specific, or specific to what I'm running:
- some meta+ combinations such as Meta+B only hide but dont summon
- can't assign slash as the key code, which is the default shortcut
in general I think this could be a pretty big rabbit hole if we try to carve out edge cases for every single keyboard layout and locale. if there's no comprehensive way to simply map key codes to strings, maybe we can simplify the problem by only allowing the key code to be a fixed, smaller set of mostly universally-defined keys? possibly something like only letters, numbers, and a small set of punctuation like slashes
@@ -30,7 +32,37 @@ class Settings extends Component { | |||
} | |||
|
|||
render() { | |||
const { modifierKey, summonKey } = getSummonShortcut(this.store('platform')) | |||
const summonShortcut = this.store('main.shortcuts.summon') |
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.
can this logic be extracted into its own functional component?
platform, | ||
summonShortcut | ||
) | ||
hotkeys.unbind() |
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 kind of setup can be done in a useEffect
hook that runs when the value of configureShortcut
changes instead of every time it renders
const { modifierKey, summonKey } = getSummonShortcut(this.store('platform')) | ||
const summonShortcut = this.store('main.shortcuts.summon') | ||
const platform = this.store('platform') | ||
const { modifierKeys: summonModifierKeys, shortcutKey: summonShortcutKey } = getDisplayShortcut( |
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.
it seems like a bunch of extra work to store the shortcut as a deconstructed object and have to put it together in multiple places. can we just create the accelerator string once when its pressed and pass that around?
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.
The problem with this is that the accelerator string will never change according to the key layout of the user when it comes to displaying the shortcut. I thought it better to store the shortcut so that it can be mapped using the keyboard layoutMap API at runtime, rather than having to parse an accelerator each time
hotkeys.unbind() | ||
if (this.state.configureShortcut) { | ||
// disable existing shortcut whilst configuring a new one | ||
link.send('tray:action', 'setShortcut', 'summon', { |
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 don't think we should disable the shortcut as if the user cancels its now disabled if it was previously enabled
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.
Problem here is that if you try to set the same shortcut again it just hides Frame. Maybe this is less of an issue now we have a cancel button
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.
Setting the same shortcut again edge case definitely problematic so I made the cancel revert the state
const isModifierKey = modifierKeys.includes(event.key) | ||
|
||
// ignore modifier key solo keypresses and disabled keys | ||
if (!isModifierKey && !isDisabledKey(event, platform)) { |
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 logic can be moved into something like the getShorcutFromKeyEvent
function and that function can simply respond with the accelerator string or undefined if the shortcut is not valid
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 may also be able to leverage something like this: https://github.com/brrd/electron-is-accelerator
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 logic can be moved into something like the getShorcutFromKeyEvent function and that function can simply respond with the accelerator string or undefined if the shortcut is not valid
This works if we are storing the accelerator but I think it's better to keep the key code + modifiers as a single source of truth and create the accelerator from that
we may also be able to leverage something like this: brrd/electron-is-accelerator
Not been updated in a while, wouldn't want to rely on it
@goosewobbler also lets target canary as the base branch |
Co-authored-by: goosewobbler <goosewobbler@pm.me>
Co-authored-by: goosewobbler <goosewobbler@pm.me>
Co-authored-by: goosewobbler <goosewobbler@pm.me>
b8032e9
to
cc7c63b
Compare
Closed in favour of #1494 |
Allowing users to choose the summon keybinding. Key presses are detected and mapped to an accelerator which is registered using the globalShortcut API. We are still using the experimental keyboard API getLayoutMap to better represent shortcut keys to users with different keyboard layouts (though this does not work in all cases)
https://www.w3.org/TR/uievents-code/#code-value-tables
https://www.electronjs.org/docs/latest/api/accelerator
https://www.electronjs.org/docs/latest/api/global-shortcut
https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/getLayoutMap
Limitations
CTRL + SHIFT + D
works because multiple modifierKeys are allowed butCTRL + A + D
is not possible due to two shortcutKeys) - this is an Electron limitation, accelerators are defined as suchTesting
102 key UK keyboard (all platforms) & Macbook Pro UK keyboard (Mac)
Layouts - EN (US), EN (UK), ES (Spain), FR (France), DE (Germany)
Nonfunctional Bindings
Unless we disable these keys for every layout, there is currently no way to detect a layout (outside of specific cases where the event key property maps to a different code when it is likely to be nonfunctional).
Disabled Keys
Keys are disabled when a matching accelerator does not exist, or if the accelerator is partly or completely non-functional. In these cases a user would be able to successfully bind a key which wouldn't summon or hide Frame. Disabling the keys means that they won't register when the user presses them when trying to configure the shortcut.
It's not feasible to test all of the layouts so we will aim for a decent base level of coverage / disablement of problematic keys and rely on users to report nonfunctional bindings which would benefit their setup with a given keyboard & layout.
Global - disabled on all platforms
IntlBackslash
,IntlRo
,IntlYen
,Pause
,NumpadEnter
,AltRight
Mac
NumLock
Windows
F12
Disabled when the event key property doesn't match the expected one (most non EN layouts):
Backslash
,Backquote
,Minus
,Equal
,BracketLeft
,BracketRight
,Quote
,Comma
,Period
,Slash
,Semicolon
Linux
Backslash
,Backquote
,Minus
,Equal
,BracketLeft
,BracketRight
,Quote
,Comma
,Period
,Slash
Disabled when the event key property doesn't match the expected one (most non EN layouts):
Semicolon
TODO