@@ -128,6 +128,7 @@ def __init__(
128128 self .height = 25
129129 self .__offset = 0
130130 self .event_queue : deque [Event ] = deque ()
131+ self .key_repeat_queue : dequeue [Event ] = deque ()
131132 try :
132133 self .out = io ._WindowsConsoleIO (self .output_fd , "w" ) # type: ignore[attr-defined]
133134 except ValueError :
@@ -390,6 +391,9 @@ def get_event(self, block: bool = True) -> Event | None:
390391 """Return an Event instance. Returns None if |block| is false
391392 and there is no event pending, otherwise waits for the
392393 completion of an event."""
394+ if self .key_repeat_queue :
395+ return self .key_repeat_queue .pop ()
396+
393397 if self .event_queue :
394398 return self .event_queue .pop ()
395399
@@ -407,31 +411,40 @@ def get_event(self, block: bool = True) -> Event | None:
407411 continue
408412 return None
409413
410- key = rec .Event .KeyEvent .uChar .UnicodeChar
411-
412- if rec .Event .KeyEvent .uChar .UnicodeChar == "\r " :
413- # Make enter make unix-like
414- return Event (evt = "key" , data = "\n " , raw = b"\n " )
415- elif rec .Event .KeyEvent .wVirtualKeyCode == 8 :
416- # Turn backspace directly into the command
414+ event = self ._event_from_keyevent (rec .Event .KeyEvent )
415+ if event is None and block :
416+ continue
417+
418+ # Queue this key event to be repeated if wRepeatCount > 1, such as when a 'dead key' is pressed twice
419+ for _ in range (rec .Event .KeyEvent .wRepeatCount - 1 ):
420+ self .key_repeat_queue .appendleft (event )
421+
422+ return event
423+
424+ def _event_from_keyevent (self , keyevent : KeyEvent ) -> Event | None :
425+ key = keyevent .uChar .UnicodeChar
426+
427+ if keyevent .uChar .UnicodeChar == "\r " :
428+ # Make enter make unix-like
429+ return Event (evt = "key" , data = "\n " , raw = b"\n " )
430+ elif keyevent .wVirtualKeyCode == 8 :
431+ # Turn backspace directly into the command
432+ return Event (
433+ evt = "key" ,
434+ data = "backspace" ,
435+ raw = keyevent .uChar .UnicodeChar ,
436+ )
437+ elif keyevent .uChar .UnicodeChar == "\x00 " :
438+ # Handle special keys like arrow keys and translate them into the appropriate command
439+ code = VK_MAP .get (keyevent .wVirtualKeyCode )
440+ if code :
417441 return Event (
418- evt = "key" ,
419- data = "backspace" ,
420- raw = rec .Event .KeyEvent .uChar .UnicodeChar ,
442+ evt = "key" , data = code , raw = keyevent .uChar .UnicodeChar
421443 )
422- elif rec .Event .KeyEvent .uChar .UnicodeChar == "\x00 " :
423- # Handle special keys like arrow keys and translate them into the appropriate command
424- code = VK_MAP .get (rec .Event .KeyEvent .wVirtualKeyCode )
425- if code :
426- return Event (
427- evt = "key" , data = code , raw = rec .Event .KeyEvent .uChar .UnicodeChar
428- )
429- if block :
430- continue
431444
432- return None
445+ return None
433446
434- return Event (evt = "key" , data = key , raw = rec . Event . KeyEvent .uChar .UnicodeChar )
447+ return Event (evt = "key" , data = key , raw = keyevent .uChar .UnicodeChar )
435448
436449 def push_char (self , char : int | bytes ) -> None :
437450 """
@@ -479,7 +492,7 @@ def wait(self, timeout: float | None) -> bool:
479492 # Poor man's Windows select loop
480493 start_time = time .time ()
481494 while True :
482- if msvcrt .kbhit (): # type: ignore[attr-defined]
495+ if msvcrt .kbhit () or self . key_repeat_queue : # type: ignore[attr-defined]
483496 return True
484497 if timeout and time .time () - start_time > timeout / 1000 :
485498 return False
0 commit comments