On Windows 11, pressing the 'escape' key in browser via textual-serve doesn't register until the mouse is moved or the 'escape' key is pressed again
On Windows 11 (and possibly other versions too), pressing the 'escape' key in browser via textual-serve doesn't register until the mouse is moved or until the 'escape' key is pressed again. Also, after pressing escape once, all further key strokes are "ignored" until the mouse is moved or the 'escape' key is pressed again, only then do all the keystrokes register. I'm not sure what is ultimately responsible for this: textual, the browser, or textual-serve.
Here's a tiny MRE to demonstrate this bug:
from textual.app import App
from textual import events
class TestApp(App):
def on_key(self, event: events.Key) -> None:
self.notify(str(event.key))
if __name__ == "__main__":
TestApp().run()
textual serve mre.py
The following sequence can be followed: Esc, a, b, c, <mouse move> OR Esc. The a, b, c notifications will not show till the end of the sequence. Note, pressing Esc a second time causes further weirdness that moving the mouse doesn't.
At the time of this report, I'm running: textual-dev 1.7.0, textual-serve 1.1.2 and textual 4.0.0
textual diagnose:
Versions
| Name | Value |
|---|---|
| Textual | 4.0.0 |
| Rich | 14.0.0 |
Python
| Name | Value |
|---|---|
| Version | 3.11.0 |
| Implementation | CPython |
| Compiler | MSC v.1933 64 bit (AMD64) |
| Executable | C:\Users\quantum\PycharmProjects\textual_mre\venv\Scripts\python.exe |
Operating System
| Name | Value |
|---|---|
| System | Windows |
| Release | 10 |
| Version | 10.0.22631 |
Terminal
| Name | Value |
|---|---|
| Terminal Application | Unknown |
| TERM | Not set |
| COLORTERM | Not set |
| FORCE_COLOR | Not set |
| NO_COLOR | Not set |
Rich Console options
| Name | Value |
|---|---|
| size | width=135, height=32 |
| legacy_windows | False |
| min_width | 1 |
| max_width | 135 |
| is_terminal | True |
| encoding | utf-8 |
| max_height | 32 |
| justify | None |
| overflow | None |
| no_wrap | False |
| highlight | None |
| markup | None |
| height | None |
We found the following entries in the FAQ which you may find helpful:
- How do I center a widget in a screen?
- Why do some key combinations never make it to my app?
- Why doesn't Textual support ANSI themes?
Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.
This project is developed and maintained by Will McGugan. Consider sponsoring Will's work on this project (and others).
This is an automated reply, generated by FAQtory
I'm able to reproduce this on Windows 11.
It appears to be an issue with ESC handling under Windows. The front-end (JavaScript) sends a data package with payload "\x1b" to textual_serve; textual_serve then sends the same payload to textual app. However, the latter would treat the ESC as the leading byte of a sequence, and wait until the full sequence is received. This is handled here.
Normally, the VT sequence parser contains logic to wait for no more than 100 milliseconds for the sequence after ESC to arrive before treating the ESC as an ESC. This mechanism appears to not work under Windows. It might be due to the InputReader implementation under Windows having no timeout support; the Linux counterpart has.
A possible workaround could be to have the front-end send the ESC as a meta packet (like focus, resize) instead of a data packet. Another possibility is to rely on the behavior that an escape sequence never crosses websocket packet boundary, and to treat a standalone ESC as a key press by itself without waiting for the subsequent characters. Yet another possibility is to fix the blocking read under Windows; this is done by the linked PR #6031.