textual
textual copied to clipboard
Apparent "bleed" of `Enter` into a newly-focused field when `Event` was the cause of eventual focus move
This stems from discussion #1197.
This one is likely easier to show with a demo than it is to explain. Simply put though, if some code, that can be initiated by the press of the Enter
key, results in focus being changed, it appears that the key press event bleeds into the newly-focused widget, causing unintended side-effects.
So, consider this code:
from textual.app import App, ComposeResult
from textual.widgets import Input, Button
class EnterLeak( App[ None ] ):
CSS = """Screen { align: center middle; }"""
def compose(self) -> ComposeResult:
yield Input( id="first", placeholder="Focus should go here" )
yield Input( id="second", placeholder="Focus actually goes here" )
yield Button( "Press me to try and focus the first field" )
def on_input_submitted( self, event: Input.Submitted ) -> None:
self.set_focus( self.query_one(
"#second" if event.input.id == "first" else "#first"
) )
def on_button_pressed( self, event: Button.Pressed ) -> None:
self.set_focus( self.query_one( "#first", Input ) )
if __name__ == "__main__":
EnterLeak().run()
Hitting enter when the Input
fields are focused will cause focus to bounce between the two Input
fields. On the other hand, the Button
in the example is coded to set focus to the first field. Pressing the button with the mouse makes that happen. On the other hand, pressing the button with the Enter
key causes the second Input
to gain focus.
With thanks to @apeaveysf for initially noticing this.
(Edit to add: initially there was a bug in the code that caused moving between the two fields using Enter to have a problem too; that's now corrected -- this is about how the button works)
Needs an event.stop()
inside Button._on_key
to stop the key event propagating? This raises more questions though :)
As discussed, switching to use BINDINGS
instead of handling in _on_key
would also probably fix (and is preferred approach).
Closing as (finally) double-checked and fixed.