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
Clean up InputBuffer coalescing and preprocessing #15671
Clean up InputBuffer coalescing and preprocessing #15671
Conversation
@@ -611,6 +611,7 @@ class InputBufferTests | |||
auto inputEvent2 = IInputEvent::Create(record2); | |||
// write another event to a non-empty buffer | |||
waitEvent = false; | |||
storage.clear(); |
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.
Starting with this PR, _WriteBuffer
moves its items out of the argument, without emptying the argument. This results in this test failing. In a follow-up PR this will not be a problem anymore, because I'll remove IInputEvent
.
UnblockWriteConsole(CONSOLE_OUTPUT_SUSPENDED); | ||
continue; | ||
} | ||
// intercept control-s |
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.
hey uh, does this fix #809?
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.
Does Ctrl+Q un-suspend 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.
wait, ^S is not VK_PAUSe...
this is the problem with the old comments you found...
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.
Ah, you're right. The old code looked like this:
// intercept control-s
if ((g_ciConsoleInformation.pInputBuffer->InputMode & ENABLE_LINE_INPUT) &&
(InputEvent->Event.KeyEvent.wVirtualKeyCode == VK_PAUSE || IsPauseKey(&InputEvent->Event.KeyEvent)))
{
I'll add that back. It fits into the PR.
@@ -779,40 +796,12 @@ void InputBuffer::_WriteBuffer(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& | |||
// record at a time because this is the original behavior of | |||
// the input buffer. Changing this behavior may break stuff | |||
// that was depending on it. | |||
if (initialInEventsSize == 1 && !_storage.empty()) | |||
if (initialInEventsSize == 1 && !_storage.empty() && _CoalesceEvent(inEvents[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.
I find it strange that we're doing a size check and a [0]
inside a range-for-loop. Is that the clearest way to represent this concept?
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.
Not at all! 😄
The old code did this check once, at the start of the function and outside of the loop. But I felt like this is a good tradeoff between making the code simpler while not changing too much.
@@ -905,76 +826,44 @@ bool InputBuffer::_CanCoalesce(const KeyEvent& a, const KeyEvent& b) const noexc | |||
// the buffer with updated values from an incoming event, instead of | |||
// storing the incoming event (which would make the original one | |||
// redundant/out of date with the most current state). | |||
bool InputBuffer::_CoalesceRepeatedKeyPressEvents(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& inEvents) | |||
bool InputBuffer::_CoalesceEvent(const std::unique_ptr<IInputEvent>& inEvent) const noexcept |
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.
How can this be const? It modifies lastEvent
which is in _storage
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.
Because std::unique_ptr
is a pointer and const
in C++ has about as much meaning as me saying that I won't eat that second pudding today: https://godbolt.org/z/38334rzjc
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 const
will go away once I use INPUT_RECORD
, because then there's no std::unique_ptr
anymore.)
(lastKey.GetVirtualScanCode() == inKey.GetVirtualScanCode() || WI_IsFlagSet(inKey.GetActiveModifierKeys(), NLS_IME_CONVERSION)) && | ||
lastKey.GetCharData() == inKey.GetCharData() && | ||
lastKey.GetActiveModifierKeys() == inKey.GetActiveModifierKeys() && | ||
// TODO: This behavior is an import from old conhost v1 and has been broken for decades. |
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.
track with issue#?
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 you don't mind, I don't want to track that separately in my backlog. After all, this is a bug that is directly standing in my path of removing IsGlyphFullWidth
everywhere that is outside of TextBuffer
(and ROW
) and thus would get addressed by me anyways in the near term.
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.
Hell I mean, you could just say TODO:GH#8000 since that's the megathread tracking your crusade, but idgaf
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.
Oh, right I could've done that... 😮
But... Eh, I don't want to wait 30min for the CI. I'll just cross my fingers to not die within the next few months. 😄
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.
Wow it's kinda horrifying looking at that old code nowadays
(lastKey.GetVirtualScanCode() == inKey.GetVirtualScanCode() || WI_IsFlagSet(inKey.GetActiveModifierKeys(), NLS_IME_CONVERSION)) && | ||
lastKey.GetCharData() == inKey.GetCharData() && | ||
lastKey.GetActiveModifierKeys() == inKey.GetActiveModifierKeys() && | ||
// TODO: This behavior is an import from old conhost v1 and has been broken for decades. |
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.
Hell I mean, you could just say TODO:GH#8000 since that's the megathread tracking your crusade, but idgaf
Ok, it's March 2024. Can I have Ctrl-s actually pause my running program now? Like I could do for many years, on various Windows platforms? I have a newish Windows-11 HP laptop, it updates itself regularly, and when I am running a program that outputs diagnostics to Cmd session window, I still cannot ctrl-s pause the running prgm (like I can on all my Linux and MacOS machines...) Do I need to edit the registry or something? It's in my left-hand's muscle-memory - rest left thumb on CTRL key, press "s" key, have a look, press "q" to continue. Works on Linux and MacOS. How do I re-enable this on my Window-11 machine? |
@DHowett-MSFT you guys need to re-open #809 -- the bot closed it. |
This reverts a number of changes to input handling to how it used to be
in conhost v1. It merges the input event coalescing logic into a single
function and inlines the console suspension event handling, because
soon these functions will receive
std::span
arguments which cannotbe preprocessed anymore, unlike a
std::deque
.It also adds back support for Ctrl-S being an alias for VK_PAUSE
which was lost in commit fccc741 in 2018.
Closes #809
Validation Steps Performed