-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
Fix #5784: Key bindings won't consume dead keys #7686
Fix #5784: Key bindings won't consume dead keys #7686
Conversation
Wow this is an incredibly creative way of tinkering with the tables inside user32. Props to the guy who discovered it. I did go read behind To be clear, both of these functions are updating a thread specific table about keyboard state. It's not strictly global. It's just that Why there isn't a more adequate way of doing this is likely lost to the sands of time. If this does the job, I'm perfectly OK with it. |
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html | ||
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned." | ||
std::array<wchar_t, 16> buffer; | ||
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0) |
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.
For clarity, the nullptr
in the final field here in the HKL
position is what is causing the internals behind ToUnicodeEx
to look up and modify the state in the thread.
Thanks for the detailed explanation! I've updated the PR message above. 👍 |
Oh. That link is to an archive of Michael S. Kaplan posts who I believe worked at Microsoft behind this stuff. So that really explains why it's the right answer then, huh? :) |
I'd like to have a look at this one before y'all merge it. I'll do that today. |
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 am deeply horrified that this is what's necessary, but I completely believe it.
Thank you so much for doing this. |
Let's assume the user has bound the dead key ^ to a sendInput command that sends "b". If the user presses the two keys ^a it'll produce "bâ", despite us marking the key event as handled. We can use `ToUnicodeEx` to clear such dead keys from the keyboard state and should make use of that for keybindings. Unfortunately `SetKeyboardState` cannot be used for this purpose as it doesn't clear the dead key state. Validation * Enabled a German keyboard layout * Added the following two keybindings: { "command": { "action": "sendInput", "input": "x" }, "keys": "q" }, { "command": { "action": "sendInput", "input": "b" }, "keys": "^" } * Pressed the following keys → ensured that the given text is printed: * q → x * ´ → nothing * a → á * ^ → b * a → a (previously this would print: â) * ´ → nothing * ^ → b * a → a (unfortunately we cannot specifically clear only ^) Closes #5784 (cherry picked from commit 4099aac)
🎉 Handy links: |
🎉 Handy links: |
Summary of the Pull Request
Let's assume the user has bound the dead key ^ to a sendInput command that sends "b".
If the user presses the two keys ^a it'll produce "bâ", despite us marking the key event as handled.
We can use
ToUnicodeEx
to clear such dead keys from the keyboard state and should make use of that for keybindings.Unfortunately
SetKeyboardState
cannot be used for this purpose as it doesn't clear the dead key state.PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed