-
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
Delegate all character input to the character event handler #4192
Conversation
I'm almost done fixing all tests. Only |
OMG! All checks have passed?! I almost can't even believe it anymore. 😄 |
I've owed you a review for far too long on this particular PR. My schedule just became much more available, so I'm going to try and get to this today or Monday. Sorry for the delay! |
@zadjii-msft You don’t owe me anything. 🙂 |
I absolutely do - IMO, it's our responsibility as project maintainers to reply to good contributions like this in a reasonably prompt timeframe. If the community is going to be generous enough to contribute to us, then the least we owe is the time to review the contribution. That's at least my opinion on that matter. Besides, I wrote all this code originally like 3 years ago, so it's probably my specific responsibility to review you ripping and tearing this apart 😜 |
FYI I rebased this PR to resolve merge conflicts that have popped up. |
@zadjii-msft Do you happen to have time for some unicode love? 🙈🙈🙈 |
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.
Okay major apologies on still delaying this after I had just said that we owed you a review 😅. There was some discussion on whether or not this would make the 1.0 cut or not - initially we were worried that such a major change to our core input handling wouldn't be safe enough, and we wouldn't have the time to properly vet it. Looking over this, it seems to me like this isn't actually all that major a change. The heaviest change is really just in TerminalInput::HandleKey
, but that is mostly just making it more readable. I'm also hoping that this solves #391, though I can't really be sure.
I did find one little bug while playing with this:
- Ctrl+Alt+Space seems to send
Instead of
^[^R 27 0033 0x1b 18 0022 0x12
(output from^[^@ 27 0033 0x1b 0 0000 0x00
showkey -a
)
Otherwise, I think this looks good for selfhosting for 1.0. @DHowett-MSFT let's pull this one in for the next build too.
// - keyEvent - Key event to translate | ||
// Return Value: | ||
// - True if the event was handled. | ||
bool TerminalInput::HandleKey(const IInputEvent* const pInEvent) |
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.
@ other reviewers: this change isn't so bad if you open the two versions of this function up in not github. Github makes this diff hard to follow, but it's actually a lot easier to read now.
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'm sorry. 🙈
Most changes to this function where necessary to ensure everything still works when you funnel character events into HandleKey()
instead of HandleChar()
(which doesn't exist anymore).
At some point I got so confused by the code that I just decided to rewrite this function from scratch.
This also means though that it actually might be best if you review changes to this function by pulling up the current code and comparing it side-by-side with the one in my PR, without viewing the diff.
While the structure is entirely different, you should quickly notice that the logic flow itself is the same as before.
I added comments to each section explaining how I understood the code and why it's necessary.
@zadjii-msft Honestly I wouldn't be mad at all if you didn't merge this before 1.0. |
@zadjii-msft I feel like I'm loosing my mind. 😐 In the meantime I'll change the if condition to reflect the current master branch, because that fixes the issue for whatever reason. |
@zadjii-msft I've force-pushed a new version that reduces the amount of changes in this PR by about a quarter. 🙂 |
F*** Now I remember why I rebuilt the entire |
Since the last time you reviewed, @zadjii-msft, this has happened. If you dislike the size of this PR I could find a way to integrate the changes necessary for #3516 without modifying |
Don't worry about it, happens all the time! Providing that delta link is much appreciated :)
lol no, it's perfectly fine. It's just one of those types of changes that github has a particularly hard time with. I couldn't care less about the actual size, looking through the code I'm not terribly scared of it. You're version of |
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.
Okay so Ctrl+Alt+Space was fixed for conhost, but it looks like it's still broken in the Terminal 😢 Now it's just generating a ^@
, a single NUL.
I think the Terminal is synthesizing the right sequence, but maybe conpty is generating the wrong input for it now, or maybe the input that's generated by conpty doesn't get re-translated back to ^[^@
correctly. I can try to keep investigating to figure out where the miscommunication is, if you need help.
Other than this, I think everything looks great
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'm investigating more - turns out that ctrl+alt+space thing isn't a regression from this change, conpty just doesn't know how to deal with that right now. So you're off the hook on that one
@zadjii-msft Yeah I was just about to say that as well. As I wrote above the most puzzling thing for me though is if you change this if condition (line 510) to a simple |
Okay I maybe saw what happened here.
I'm not sure what's exactly the right behavior here. I'd think we probably should send a different key, but I'll need to investigate more. It's possible that the |
…e's a problem in Win32 quite yet. (#5208) ## Summary of the Pull Request When conpty is in VT input mode, we pass through all the input we receive. This includes all the other `Action*Dispatch` methods, but missed this one. ## References * Missed during #4856 * Discovered during the course of the #4192 review * #5205 Also investigated part of the issue, but found a different bug. ## PR Checklist * [x] Doesn't close anything, just related to above things. * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments This will fix the <kbd>ctrl+alt+space</kbd> in the Terminal thing mentioned in #4192, but doesn't actually resolve the root cause of that bug (which is tracked in #5205).
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 only found one complaint. This is, for all intents and purposes, almost perfect.
auto vkey = _TakeVirtualKeyFromLastKeyEvent(scanCode); | ||
if (vkey == 0 && scanCode != 0) | ||
{ | ||
vkey = _ScanCodeFromVirtualKey(scanCode); |
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 name worries me. Below, we have VirtualKeyFromCharacter
, but here we're assigning vkey
but the function name implies it returns a ScanCode
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.
You‘re right: This should be _VirtualKeyFromScanCode
. 👍
// For perf optimization, filter out any typically printable Virtual Keys (e.g. A-Z) | ||
// This is in lieu of an O(1) sparse table or other such less-maintainable methods. | ||
// VK_CANCEL is an exception and we want to send the associated uChar as is. |
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.
Is this a worthwhile optimization to keep? I'd be interested in seeing the real-world performance impact.
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.
_translateDefaultMapping
is an extremely simple and fast method (<1us I‘m sure) and I suppose it‘s not necessary to retain such an optimization.
On the other hand the intention of the previous code is easy to understand and doesn’t add much complexity.
I‘ll gladly add it back in. 👍
(Our of curiosity I‘ll make sure to post the performance impact of that function tomorrow. 🙂)
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 believe you that it's incredibly minor, so I am okay leaving out the optimization. It used to be a std::map, but then it was replaced with an std::array and not revisited. No need to share performance traces as a requirement for landing this 😄
(You'll probably need to merge master to get the spell checking bot going again, but I bet it's going to complain about |
Hello @DHowett-MSFT! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
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 love this. Thank you.
🎉 Handy links: |
} | ||
// For Alt+Ctrl+Key messages GetCharData() returns 0. | ||
// -> Get the char from the virtual key. | ||
ch = LOWORD(MapVirtualKeyW(keyEvent.GetVirtualKeyCode(), MAPVK_VK_TO_CHAR)); |
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.
@lhecker this may be broken for non-US layouts.
See https://stackoverflow.com/q/72464583/1795050
My basic idea was that
WM_CHAR
is just the betterWM_KEYDOWN
.The latter fails to properly support common dead key sequences like in
#3516.
As such I added some logic to
Terminal::SendKeyEvent
to make it returnfalse if the pressed key represents a printable character.
This causes us to receive a character event with a (hopefully) correctly
composed code unit, which then gets sent to
Terminal::SendCharEvent
.Terminal::SendCharEvent
in turn had to be modified to supportpotentially pressed modifier keys, since
Terminal::SendKeyEvent
isn'tdoing that for us anymore.
Lastly
TerminalInput
had to be modified heavily to support characterevents with modifier key states. In order to do so I merged its
HandleKey
andHandleChar
methods into a single one, that now handlesboth cases.
Since key events will now contain character data and character events
key codes the decision logic in
TerminalInput::HandleKey
had to berewritten.
PR Checklist
Validation Steps Performed
this I modified
TermControl::_SendPastedTextToConnection
to send thedata to
_terminal->SendCharEvent()
instead. I then pasted the teststring ""𐐌𐐜𐐬" and ensured that the new
TerminalInput::_SendChar
method still correctly assembles surrogate pairs.
Closes #3516
Closes #3554 (obsoleted by this PR)
Potentially impacts #391, which sounds like a duplicate of #3516