Keyboard input event bugged with TextInput?

Basically I’ve been working on a Kivy application with multiple screens, and I’m trying to make it so that it will take you back to the main screen if the escape button is pressed. Things have been going well, as I followed this question’s answer, except the fact that when I focus on a TextInput widget and unfocus, the escape key shortcut, or more specifically the on_key_down event isn’t called anymore.

Anyone knows what’s wrong? Any helps would be appreciated!

Edit: Here’s my code, shortened and simplified:

test.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.config import Config


Config.set('kivy', 'exit_on_escape', 0)

class MainScreen(Screen):
    def __init__(self, **kwargs):
        super(Screen, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print(keycode[1])
        if keycode[1] == 'escape':
            if App.get_running_app().root.current == 'Main':
                App.get_running_app().stop()
                Window.close()
            else:
                App.get_running_app().root.current = 'Main'

class UhIDontHaveIdeaForANameBecauseItsAnExampleScreen(Screen):
    pass
     
class Test(App):    
    pass

Test().run()

test.kv

ScreenManager:
    MainScreen:
        id: Main
    UhIDontHaveIdeaForANameBecauseItsAnExampleScreen:
        id: Settings
    
<MainScreen>:
    name: 'Main'
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'idk just press it bruh'
        Button:
            id: butt
            text: 'no clue'
            on_release: app.root.current = 'NoClue'

<UhIDontHaveIdeaForANameBecauseItsAnExampleScreen>:
    name: 'NoClue'
    
    TextInput:
        size_hint: 0.4, 0.1
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}

Answer

You bind the main screen to listening to the keyboard when you create it but when you focus the Textinput kivy automatically bind the keyboard to the textinput so the _on_keyboard_down method in the MainScreen there are many solution to do this but we need to bind the main screen to the keyboard again so the _on_keyboard_down start to listening to the keyboard again and we can do this inside the textField with _on_textinput_focused method like bellow

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.textinput import TextInput

Config.set('kivy', 'exit_on_escape', 0)


class MainScreen(Screen):
    def __init__(self, **kwargs):
        super(Screen, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print(keycode[1])
        if keycode[1] == 'escape':
            if App.get_running_app().root.current == 'Main':
                App.get_running_app().stop()
                Window.close()
            else:
                App.get_running_app().root.current = 'Main'

class UhIDontHaveIdeaForANameBecauseItsAnExampleScreen(Screen):
    pass


class TextField(TextInput):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def _on_textinput_focused(self, instance, value, *largs):
        print(instance.focus)
        # test if the text input is focused 
        if not instance.focus:
            app=App.get_running_app()
            app.root.ids.Main._keyboard = Window.request_keyboard(app.root.ids.Main._keyboard_closed, self)
            app.root.ids.Main._keyboard.bind(on_key_down=app.root.ids.Main._on_keyboard_down)

class Test(App):
    pass


Test().run()


and use the TextField in the kv file like this

ScreenManager:
    MainScreen:
        id: Main
    UhIDontHaveIdeaForANameBecauseItsAnExampleScreen:
        id: Settings
    
<MainScreen>:
    name: 'Main'
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'idk just press it bruh'
        Button:
            id: butt
            text: 'no clue'
            on_release: app.root.current = 'NoClue'
<UhIDontHaveIdeaForANameBecauseItsAnExampleScreen>:
    name: 'NoClue'

    TextField:
        size_hint: 0.4, 0.1
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
<TextField>: