textual icon indicating copy to clipboard operation
textual copied to clipboard

Apparent "bleed" of `Enter` into a newly-focused field when `Event` was the cause of eventual focus move

Open davep opened this issue 2 years ago • 2 comments

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)

davep avatar Nov 16 '22 21:11 davep

Needs an event.stop() inside Button._on_key to stop the key event propagating? This raises more questions though :)

darrenburns avatar Nov 16 '22 23:11 darrenburns

As discussed, switching to use BINDINGS instead of handling in _on_key would also probably fix (and is preferred approach).

darrenburns avatar Nov 17 '22 09:11 darrenburns

Closing as (finally) double-checked and fixed.

davep avatar Jan 10 '23 10:01 davep

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

github-actions[bot] avatar Jan 10 '23 10:01 github-actions[bot]