@@ -492,8 +492,7 @@ size_t InputBuffer::Prepend(const std::span<const INPUT_RECORD>& inEvents)
492
492
return STATUS_SUCCESS;
493
493
}
494
494
495
- _vtInputShouldSuppress = true ;
496
- auto resetVtInputSuppress = wil::scope_exit ([&]() { _vtInputShouldSuppress = false ; });
495
+ const auto wakeup = _wakeupReadersOnExit ();
497
496
498
497
// read all of the records out of the buffer, then write the
499
498
// prepend ones, then write the original set. We need to do it
@@ -503,35 +502,15 @@ size_t InputBuffer::Prepend(const std::span<const INPUT_RECORD>& inEvents)
503
502
std::deque<INPUT_RECORD> existingStorage;
504
503
existingStorage.swap (_storage);
505
504
506
- // We will need this variable to pass to _WriteBuffer so it can attempt to determine wait status.
507
- // However, because we swapped the storage out from under it with an empty deque, it will always
508
- // return true after the first one (as it is filling the newly emptied backing deque.)
509
- // Then after the second one, because we've inserted some input, it will always say false.
510
- auto unusedWaitStatus = false ;
511
-
512
505
// write the prepend records
513
506
size_t prependEventsWritten;
514
- _WriteBuffer (inEvents, prependEventsWritten, unusedWaitStatus);
515
- FAIL_FAST_IF (!(unusedWaitStatus));
507
+ _WriteBuffer (inEvents, prependEventsWritten);
516
508
517
509
for (const auto & event : existingStorage)
518
510
{
519
511
_storage.push_back (event);
520
512
}
521
513
522
- // We need to set the wait event if there were 0 events in the
523
- // input queue when we started.
524
- // Because we did interesting manipulation of the wait queue
525
- // in order to prepend, we can't trust what _WriteBuffer said
526
- // and instead need to set the event if the original backing
527
- // buffer (the one we swapped out at the top) was empty
528
- // when this whole thing started.
529
- if (existingStorage.empty ())
530
- {
531
- ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
532
- }
533
- WakeUpReadersWaitingForData ();
534
-
535
514
return prependEventsWritten;
536
515
}
537
516
catch (...)
@@ -575,21 +554,9 @@ size_t InputBuffer::Write(const std::span<const INPUT_RECORD>& inEvents)
575
554
return 0 ;
576
555
}
577
556
578
- _vtInputShouldSuppress = true ;
579
- auto resetVtInputSuppress = wil::scope_exit ([&]() { _vtInputShouldSuppress = false ; });
580
-
581
- // Write to buffer.
557
+ const auto wakeup = _wakeupReadersOnExit ();
582
558
size_t EventsWritten;
583
- bool SetWaitEvent;
584
- _WriteBuffer (inEvents, EventsWritten, SetWaitEvent);
585
-
586
- if (SetWaitEvent)
587
- {
588
- ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
589
- }
590
-
591
- // Alert any writers waiting for space.
592
- WakeUpReadersWaitingForData ();
559
+ _WriteBuffer (inEvents, EventsWritten);
593
560
return EventsWritten;
594
561
}
595
562
catch (...)
607
574
return ;
608
575
}
609
576
610
- const auto initiallyEmptyQueue = _storage.empty ();
611
-
577
+ const auto wakeup = _wakeupReadersOnExit ();
612
578
_writeString (text);
613
-
614
- if (initiallyEmptyQueue && !_storage.empty ())
615
- {
616
- ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
617
- }
618
-
619
- WakeUpReadersWaitingForData ();
620
579
}
621
580
CATCH_LOG ()
622
581
@@ -625,29 +584,26 @@ CATCH_LOG()
625
584
// input buffer and the next application will suddenly get a "\x1b[I" sequence in their input. See GH#13238.
626
585
void InputBuffer::WriteFocusEvent(bool focused) noexcept
627
586
{
587
+ const auto wakeup = _wakeupReadersOnExit ();
588
+
628
589
if (IsInVirtualTerminalInputMode ())
629
590
{
630
591
if (const auto out = _termInput.HandleFocus (focused))
631
592
{
632
- _HandleTerminalInputCallback (*out);
593
+ _writeString (*out);
633
594
}
634
595
}
635
596
else
636
597
{
637
- // This is a mini-version of Write().
638
- const auto wasEmpty = _storage.empty ();
639
598
_storage.push_back (SynthesizeFocusEvent (focused));
640
- if (wasEmpty)
641
- {
642
- ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
643
- }
644
- WakeUpReadersWaitingForData ();
645
599
}
646
600
}
647
601
648
602
// Returns true when mouse input started. You should then capture the mouse and produce further events.
649
603
bool InputBuffer::WriteMouseEvent (til::point position, const unsigned int button, const short keyState, const short wheelDelta)
650
604
{
605
+ const auto wakeup = _wakeupReadersOnExit ();
606
+
651
607
if (IsInVirtualTerminalInputMode ())
652
608
{
653
609
// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx
@@ -669,7 +625,7 @@ bool InputBuffer::WriteMouseEvent(til::point position, const unsigned int button
669
625
670
626
if (const auto out = _termInput.HandleMouse (position, button, keyState, wheelDelta, state))
671
627
{
672
- _HandleTerminalInputCallback (*out);
628
+ _writeString (*out);
673
629
return true ;
674
630
}
675
631
}
@@ -690,25 +646,38 @@ static bool IsPauseKey(const KEY_EVENT_RECORD& event)
690
646
return ctrlButNotAlt && event.wVirtualKeyCode == L' S' ;
691
647
}
692
648
649
+ void InputBuffer::_wakeupReadersImpl (bool initiallyEmpty)
650
+ {
651
+ if (!_storage.empty ())
652
+ {
653
+ // It would be fine to call SetEvent() unconditionally,
654
+ // but technically we only need to ResetEvent() if the buffer is empty,
655
+ // and SetEvent() once it stopped being so, which is what this code does.
656
+ if (initiallyEmpty)
657
+ {
658
+ ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
659
+ }
660
+
661
+ WakeUpReadersWaitingForData ();
662
+ }
663
+ }
664
+
693
665
// Routine Description:
694
666
// - Coalesces input events and transfers them to storage queue.
695
667
// Arguments:
696
668
// - inRecords - The events to store.
697
669
// - eventsWritten - The number of events written since this function
698
670
// was called.
699
- // - setWaitEvent - on exit, true if buffer became non-empty.
700
671
// Return Value:
701
672
// - None
702
673
// Note:
703
674
// - The console lock must be held when calling this routine.
704
675
// - will throw on failure
705
- void InputBuffer::_WriteBuffer (const std::span<const INPUT_RECORD>& inEvents, _Out_ size_t & eventsWritten, _Out_ bool & setWaitEvent )
676
+ void InputBuffer::_WriteBuffer (const std::span<const INPUT_RECORD>& inEvents, _Out_ size_t & eventsWritten)
706
677
{
707
678
auto & gci = ServiceLocator::LocateGlobals ().getConsoleInformation ();
708
679
709
680
eventsWritten = 0 ;
710
- setWaitEvent = false ;
711
- const auto initiallyEmptyQueue = _storage.empty ();
712
681
const auto initialInEventsSize = inEvents.size ();
713
682
const auto vtInputMode = IsInVirtualTerminalInputMode ();
714
683
@@ -739,7 +708,7 @@ void InputBuffer::_WriteBuffer(const std::span<const INPUT_RECORD>& inEvents, _O
739
708
// GH#11682: TerminalInput::HandleKey can handle both KeyEvents and Focus events seamlessly
740
709
if (const auto out = _termInput.HandleKey (inEvent))
741
710
{
742
- _HandleTerminalInputCallback (*out);
711
+ _writeString (*out);
743
712
eventsWritten++;
744
713
continue ;
745
714
}
@@ -759,10 +728,6 @@ void InputBuffer::_WriteBuffer(const std::span<const INPUT_RECORD>& inEvents, _O
759
728
_storage.push_back (inEvent);
760
729
++eventsWritten;
761
730
}
762
- if (initiallyEmptyQueue && !_storage.empty ())
763
- {
764
- setWaitEvent = true ;
765
- }
766
731
}
767
732
768
733
// Routine Description::
@@ -826,36 +791,6 @@ bool InputBuffer::IsInVirtualTerminalInputMode() const
826
791
return WI_IsFlagSet (InputMode, ENABLE_VIRTUAL_TERMINAL_INPUT);
827
792
}
828
793
829
- // Routine Description:
830
- // - Handler for inserting key sequences into the buffer when the terminal emulation layer
831
- // has determined a key can be converted appropriately into a sequence of inputs
832
- // Arguments:
833
- // - inEvents - Series of input records to insert into the buffer
834
- // Return Value:
835
- // - <none>
836
- void InputBuffer::_HandleTerminalInputCallback (const TerminalInput::StringType& text)
837
- {
838
- try
839
- {
840
- if (text.empty ())
841
- {
842
- return ;
843
- }
844
-
845
- _writeString (text);
846
-
847
- if (!_vtInputShouldSuppress)
848
- {
849
- ServiceLocator::LocateGlobals ().hInputEvent .SetEvent ();
850
- WakeUpReadersWaitingForData ();
851
- }
852
- }
853
- catch (...)
854
- {
855
- LOG_HR (wil::ResultFromCaughtException ());
856
- }
857
- }
858
-
859
794
void InputBuffer::_writeString (const std::wstring_view& text)
860
795
{
861
796
for (const auto & wch : text)
0 commit comments