@@ -8,6 +8,7 @@ import (
88 "errors"
99 "fmt"
1010 "strings"
11+ "time"
1112 "unicode"
1213 "unicode/utf16"
1314 "unicode/utf8"
@@ -22,7 +23,7 @@ import (
2223// given event channel.
2324func (d *TerminalReader) ReceiveEvents(ctx context.Context, events chan<- Event) error {
2425 for {
25− evs, err := d.handleConInput(readConsoleInput)
26+ evs, err := d.handleConInput()
2627 if errors.Is(err, errNotConInputReader) {
2728 return d.receiveEvents(ctx, events)
2829 }
@@ -41,31 +42,45 @@ func (d *TerminalReader) ReceiveEvents(ctx context.Context, events chan<- Event)
4142
4243var errNotConInputReader = fmt.Errorf("handleConInput: not a conInputReader")
4344
44−func (d *TerminalReader) handleConInput(
45− finput func(windows.Handle, []xwindows.InputRecord) (uint32, error),
46−) ([]Event, error) {
45+func (d *TerminalReader) handleConInput() ([]Event, error) {
4746 cc, ok := d.rd.(*conInputReader)
4847 if !ok {
4948 return nil, errNotConInputReader
5049 }
5150
52− // read up to 256 events, this is to allow for sequences events reported as
53− // key events.
54− var events [256]xwindows.InputRecord
55− _, err := finput(cc.conin, events[:])
56− if err != nil {
51+ var (
52+ events []xwindows.InputRecord
53+ err error
54+ )
55+ for {
56+ // Peek up to 256 events, this is to allow for sequences events reported as
57+ // key events.
58+ events, err = peekNConsoleInputs(cc.conin, 256)
5759 if cc.isCanceled() {
5860 return nil, cancelreader.ErrCanceled
5961 }
62+ if err != nil {
63+ return nil, fmt.Errorf("peek coninput events: %w", err)
64+ }
65+ if len(events) > 0 {
66+ break
67+ }
68+
69+ // Sleep for a bit to avoid busy waiting.
70+ time.Sleep(10 * time.Millisecond)
71+ }
72+
73+ events, err = readNConsoleInputs(cc.conin, uint32(len(events)))
74+ if cc.isCanceled() {
75+ return nil, cancelreader.ErrCanceled
76+ }
77+ if err != nil {
6078 return nil, fmt.Errorf("read coninput events: %w", err)
6179 }
6280
6381 var evs []Event
6482 for _, event := range events {
6583 if e := d.SequenceParser.parseConInputEvent(event, &d.keyState, d.MouseMode, d.logger); e != nil {
66− if e == nil {
67− continue
68− }
6984 if multi, ok := e.(MultiEvent); ok {
7085 if d.logger != nil {
7186 for _, ev := range multi {
@@ -223,6 +238,16 @@ func highWord(data uint32) uint16 {
223238 return uint16((data & 0xFFFF0000) >> 16) //nolint:gosec
224239}
225240
241+func readNConsoleInputs(console windows.Handle, maxEvents uint32) ([]xwindows.InputRecord, error) {
242+ if maxEvents == 0 {
243+ return nil, fmt.Errorf("maxEvents cannot be zero")
244+ }
245+
246+ records := make([]xwindows.InputRecord, maxEvents)
247+ n, err := readConsoleInput(console, records)
248+ return records[:n], err
249+}
250+
226251func readConsoleInput(console windows.Handle, inputRecords []xwindows.InputRecord) (uint32, error) {
227252 if len(inputRecords) == 0 {
228253 return 0, fmt.Errorf("size of input record buffer cannot be zero")
@@ -235,7 +260,6 @@ func readConsoleInput(console windows.Handle, inputRecords []xwindows.InputRecor
235260 return read, err //nolint:wrapcheck
236261}
237262
238−//nolint:unused
239263func peekConsoleInput(console windows.Handle, inputRecords []xwindows.InputRecord) (uint32, error) {
240264 if len(inputRecords) == 0 {
241265 return 0, fmt.Errorf("size of input record buffer cannot be zero")
@@ -248,6 +272,16 @@ func peekConsoleInput(console windows.Handle, inputRecords []xwindows.InputRecor
248272 return read, err //nolint:wrapcheck
249273}
250274
275+func peekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]xwindows.InputRecord, error) {
276+ if maxEvents == 0 {
277+ return nil, fmt.Errorf("maxEvents cannot be zero")
278+ }
279+
280+ records := make([]xwindows.InputRecord, maxEvents)
281+ n, err := peekConsoleInput(console, records)
282+ return records[:n], err
283+}
284+
251285// parseWin32InputKeyEvent parses a single key event from either the Windows
252286// Console API or win32-input-mode events. When state is nil, it means this is
253287// an event from win32-input-mode. Otherwise, it's a key event from the Windows
@@ -506,7 +540,9 @@ func (p *SequenceParser) parseWin32InputKeyEvent(state *win32InputState, vkc uin
506540
507541 var text string
508542 keyCode := baseCode
509− if !unicode.IsControl(r) {
543+ if unicode.IsControl(r) {
544+ return p.parseControl(byte(r))
545+ } else {
510546 rw := utf8.EncodeRune(utf8Buf[:], r)
511547 keyCode, _ = utf8.DecodeRune(utf8Buf[:rw])
512548 if unicode.IsPrint(keyCode) && (cks == 0 ||
@@ -517,18 +553,18 @@ func (p *SequenceParser) parseWin32InputKeyEvent(state *win32InputState, vkc uin
517553 // then the key event is a printable event i.e. [text] is not empty.
518554 text = string(keyCode)
519555 }
520− }
521556
522− key.Code = keyCode
523− key.Text = text
524− key.Mod = translateControlKeyState(cks)
525− key.BaseCode = baseCode
526− key = ensureKeyCase(key, cks)
527− if keyDown {
528− return KeyPressEvent(key)
529− }
557+ key.Code = keyCode
558+ key.Text = text
559+ key.Mod = translateControlKeyState(cks)
560+ key.BaseCode = baseCode
561+ key = ensureKeyCase(key, cks)
562+ if keyDown {
563+ return KeyPressEvent(key)
564+ }
530565
531− return KeyReleaseEvent(key)
566+ return KeyReleaseEvent(key)
567+ }
532568}
533569
534570// ensureKeyCase ensures that the key's text is in the correct case based on the