Weird bug with keyboard bindings on Android

122 views
Skip to first unread message

Jimminer

unread,
Jul 21, 2022, 7:17:50 PM7/21/22
to Kivy users support
I stumbled upon a bug that from what I can tell, bugs out the keyboard binding.
Any suggestions on fixing this would be appreciated!

Setup:
I managed to reproduce this bug with 2 screens.
The first screen has a button (that takes you to the second screen) and a MDTextField
(I'm running Android 12 and built the apk with buildozer)

How to reproduce (see code below):
I could not reproduce on a Desktop machine! Only on Android
1. Open the app and just touch the text field (typing is not necessary)
2. Press the button (named "submit")
3. Try to press the Android's back button
If nothing happened, you reproduced the bug (normally a toast should come up)

Temporary solution:
While being in the bugged state (having at least touched the text field), either go to your
home screen or your recent apps screen (Without closing the app!) and reopen the app

Couldn't reproduce?
This is a video showing the following:
1. A run without touching the text field
2. A run with touching the text field (the bug) and doing the temporary solution

Code:
##############################################

from kivy.lang import Builder
from kivy.utils import platform
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.screenmanager import Screen
from kivymd.app import MDApp

if platform == "android":
     from kivymd.toast.androidtoast import toast
else:
     from kivymd.toast import toast


KV = """
MDScreen:

     MDNavigationLayout:

    ScreenManager:
        id: screenManager

        FirstScreen:
            name: "firstScreen"

        MainScreen:
            name: "mainScreen"

<FirstScreen>:

    MDBoxLayout:
        orientation: "vertical"

        MDFlatButton:
            text: "submit"
            on_release: app.submit()

        MDTextField:
            id: testfield

<MainScreen>:

    MDLabel:
        text: "main screen"

"""

class FirstScreen(Screen):
    def on_enter(self):
        pass

class MainScreen(Screen):
    def on_enter(self):
        pass

class MainApp(MDApp):
    def build(self):
        Window.bind(on_keyboard=self.keyboardBindings)
        return Builder.load_string(KV)
    def keyboardBindings(self, window, key, *largs):
        if key == 27:
            toast("ESC was pressed")
            return True

    def submit(self):
        testfield_text = self.root.ids.screenManager.get_screen("firstScreen").ids.testfield.text
        self.root.ids.screenManager.current = "mainScreen"


app = MainApp()
if __name__ == "__main__":
    app.run()

##############################################

The line where the variable testfield_text is set (inside submit function) is mandatory for the bug to happen!

Robert

unread,
Jul 21, 2022, 11:43:11 PM7/21/22
to Kivy users support
I think the expected behavior is:
1) if a text input has focus the first Esc/'Back button/gesture' de-focuses the text input.
2) When text input does not have focus Esc/Back stops the app.

But I notice in the code above the handler return True, so step 2) won't happen.

Jimminer

unread,
Jul 22, 2022, 1:07:44 PM7/22/22
to Kivy users support
Yes, that would be the expected behavior on an app without the keyboard bound to a function.
As you can also see from the video I posted, I do not press the back button while the text field is focused. To unfocus the text field I just tap anywhere on the screen (except the keyboard of course)

The expected behavior for this app should be a Toast displaying "ESC was pressed" whenever the back button is pressed. That is the case when running on desktop but not on Android!
After all, this is just reproducible code and it doesn't serve the same purpose as my main code. On my main code I use the back button as a "previous screen" trigger (where I also experience the same problem on Android)

Returning True lets the handler know that my function took care of the event and there's no need for kivy to do anything and ultimately should not be the cause of the problem.

Robert

unread,
Jul 22, 2022, 4:01:47 PM7/22/22
to Kivy users support
> Returning True lets the handler know that my function took care of the event and there's no need for kivy to do anything and ultimately should not be the cause of the problem.

This is not my understanding of the operation. We'll have to agree to differ.

Jimminer

unread,
Jul 22, 2022, 8:19:04 PM7/22/22
to Kivy users support
You are correct. I had a bad understanding.

The return just stopped further execution hence why the app was not closing.

The proper way to achieve this without using return is:
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')

Unfortunately, even after this change, the bug still persists.

Robert

unread,
Jul 22, 2022, 10:57:32 PM7/22/22
to Kivy users support
One down, one to go....


If you want submit or add to an issue, convert the example to Kivy first.

Jimminer

unread,
Jul 23, 2022, 7:29:41 PM7/23/22
to Kivy users support
I had seen that issue and some other similar issues and some people said that it's a fault of the sdl2 version that p4a is using.

I tried putting 2.0.10 as the required version of sdl2 (the version which supposedly fixed this bug) in the buildozer.spec but it would throw an error upon building the apk.
I also tried many combinations of android api/kivy versions which all ended up either having the same bug or just not working.

I guess the only solution is to wait for p4a to implement that sdl2 version or create a patch that fixes that specific bug.

Robert

unread,
Jul 23, 2022, 10:52:01 PM7/23/22
to Kivy users support
p4a a is a huge balancing act, you can change stuff from the current defaults but it almost always breaks something.

Jimminer

unread,
Jul 25, 2022, 6:43:55 PM7/25/22
to Kivy users support
Yeah, I tried many ways to implement that sdl2 change but as you said, it always broke something.

I will stick with using a button as a previous screen trigger until the bug is fixed.

Thanks for the help!

Robert

unread,
Jul 25, 2022, 8:15:57 PM7/25/22
to Kivy users support
If you are just using Back to navigate screens, this is a possible alternative:
Create a SwipeScreen that uses a gesture package called CommonGestures  not the Back button/gesture

Jimminer

unread,
Jul 26, 2022, 8:07:41 PM7/26/22
to Kivy users support
That's really nice! I will use this from now on. Thank you!
Reply all
Reply to author
Forward
0 new messages