-
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
Fixed Ctrl+Alt shortcuts conflicting with AltGr #2235
Conversation
I've based this PR on a08666b btw, which is the common ancestor between master and release-0.3. |
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 think I’m comfortable with this. @lhecker again, thanks so much for being our AltGr expert. 😄
// provided with an appropriate unicode character. | ||
if (modifiers.IsAltGrPressed()) | ||
{ | ||
_SendKeyEvent(); |
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 not sure why we need to send an empty key event here.
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 key event handler must call _terminal->ClearSelection()
, because the char handler doesn't.
Additionally _terminal->SetCursorVisible(true);
must be called on a key press as the comment at line 683 states.
@@ -661,6 +664,31 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation | |||
e.Handled(handled); | |||
} | |||
|
|||
void TermControl::_SendKeyEvent() |
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.
Feel a bit weird about a void method wrapping a bool one and discarding the result
_SendKeyEvent(0, {}); | ||
} | ||
|
||
bool TermControl::_SendKeyEvent(WORD vkey, ControlKeyStates modifiers) |
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.
nit: add a doc comment!
@DHowett-MSFT No problem. 😅 I've amended this PR with comments for the two new functions. I've also tried to give them slightly more obvious names (although I failed at it I guess lol). E.g. my thoughts regarding character handling...You could for instance abstract AltGr, shortcut, etc. handling into one class each and concate them together to a stream of key/character event processors which implement the full, final keyboard handling.TermControl would also implement the common interface and be the final (self-referential) receiver in the chain.That way you do away with the current, loopy design, of TermControl handling a bit of the keys, pushing it down to Terminal , which implements a bit of the handling, which then pushes it down to VirtualTerminal which implements a bit of the handling and finally calls TermControl again through a std::function callback, which then stringifies the character/escape-sequence array and then calls TermControl again through a std::function callback which then sends it to the shell.It's very "loopy". 😄 |
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 have a pair of nits, but nothing worth blocking over. If someone else says this is fine and we should ship it, I'm not going to block this.
Overall great work with the fix here.
// the character handler counts on us though to: | ||
// - Clears the current selection. | ||
// - Makes the cursor briefly visible during typing. | ||
void TermControl::_HandleVoidKeyEvent() |
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.
nit: I think the name of this method could probably be better - the important meat of what this function is trying to accomplish isn't the sending of the void keypress, it's the dismissing of the selection and the cursor visibility.
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.
Do you have a suggestion for the function name? I can't come up with anything. 😕
(If we had something different to SendKeyEvent
- like e.g. GenerateKeyEvent
, which returns an optional input sequence - we could more comfortably abstract "reset selection and cursor" I suppose. That way you could move the "reset selection and cursor" handling to the more correct char handler, without the key event handler being responsible for this, right?)
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.
If we're just sending two constants over to _TrySendKeyEvent()
, why not get rid of the helper function overall and just add a comment where you use it?
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 fact that _TrySendKeyEvent()
supports a vkey == 0
seemed kinda hacky to me and I wanted to hide this hacky fact even from calls within the same class. So I created a hacky-wrapper function and prevent other methods from being "spoiled". 😄
Do you want me to inline this function?
This moves the detection of AltGr keypresses in front of the shortcut handling. This allows one to have Ctrl+Alt shortcuts, while simultaneously being able to use the AltGr key for special characters.
modifiers.IsCtrlPressed(), | ||
modifiers.IsAltPressed(), | ||
modifiers.IsShiftPressed(), | ||
vkey); | ||
handled = bindings.TryKeyChord(chord); | ||
vkey, |
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.
vkey, | |
vkey |
I don't think we need that extra ,
here
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 a list initialization expression, which is kinda akin to an array and I believe this project uses trailing commas for this. Right?
Do you want me to revert this change? It's technically not needed at all for this PR. 🙂
(It only snuck in, because I structured the code entirely differently in a previous attempt for this PR and I preferred block indents over visual indents. 🙈)
P.S.: In fact modern languages often allow (or even enforce) trailing commas on multiline expressions even, because it simplifies refactoring and diffs in the future.
If you want to add a trailing argument in the future and your vkey
doesn't have a trailing comma already, your diff will contain changes to two lines, even though one of them only adds a comma. This also makes git blame harder to use. Realistically it's unlikely someone is going to write a better VCS anytime soon either, that would understand this change contextually.
In Go for instance this will yield an missing ',' before newline in argument list
error.
Rust and Python (PEP8) follow the same reasoning after lengthy discussions each.
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.
// event and let the WM_CHAR handler kick in, which will be | ||
// provided with an appropriate unicode character. | ||
// | ||
// GH#2235: Make sure to handle AltGr before trying keybindings, |
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.
// GH#2235: Make sure to handle AltGr before trying keybindings, | |
// Make sure to handle AltGr before trying keybindings, |
It feels a bit weird to reference this PR. Let's just keep the comment.
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 usually like referencing the issue in the code near a bug fix like this. It can oftentimes provide a lot more context than just the comment in the code.
// the character handler counts on us though to: | ||
// - Clears the current selection. | ||
// - Makes the cursor briefly visible during typing. | ||
void TermControl::_HandleVoidKeyEvent() |
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.
If we're just sending two constants over to _TrySendKeyEvent()
, why not get rid of the helper function overall and just add a comment where you use it?
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 discussed this in a meeting today and we're all fine shipping this in the state it is. The naming thing was a nit anyways and this is real goodness we'd like to get out.
@DHowett-MSFT do the thing |
This moves the detection of AltGr keypresses in front of the shortcut handling. This allows one to have Ctrl+Alt shortcuts, while simultaneously being able to use the AltGr key for special characters. (cherry picked from commit 4529e46)
🎉 Handy links: |
Summary of the Pull Request
This moves the detection of AltGr keypresses in front of the shortcut handling.
This allows one to have Ctrl+Alt shortcuts, while simultaneously being able to use the AltGr key for special characters.
References
This fixes a regression in v0.3.2142.0, which automatically creates
Ctrl+Alt+[0-9]
shortcuts for switching between tabs. These conflicted with the detection of the AltGr key. inSendKeyEvent()
.Refixes #521.
PR Checklist
Detailed Description of the Pull Request / Additional comments
This PR has the flaw that it doesn't allow one to define AltGr shortcuts anymore.
Considering that it's probably more important to get a fix out of the door quickly I personally see this as a minor flaw though. VS Code has the same "flaw" for instance and doesn't allow AltGr combinations either.
We could fix it more correctly later on, by modifying the
IKeyBindings
interface andKeyChord
class.Validation Steps Performed
Ctrl+Alt+[0-9]
shortcuts simultaneously work.