Godot: Android physical keyboard input getting stuck on left arrow key

Created on 16 Sep 2019  路  4Comments  路  Source: godotengine/godot

Godot version:
3.1.1 stable win64

OS/device including version:
Win10 x64 for export, Android 9 device, QWERTZ keyboard

Issue description:
Using a physical keyboard (in my case via https://github.com/Genymobile/scrcpy) and pressing the left arrow key gets all keyboard input stuck.
Touch/Mouse input still appears to be handled in my own project.

Steps to reproduce:

  • Set up a scene with a script that handles keyboard input in '_process(delta)' with 'is_action_pressed(...)'.
  • Export for android and play.
  • Press arrow keys up, right, down. Those work.
  • Press arrow key left, all currently pressed keys get stuck and no further keyboard input is accepted.

Minimal reproduction project:
https://github.com/The5-1/AndroidKeyboardBug

Possibly related:

6612 #6388 #8032

bug android core input porting

Most helpful comment

@lawnjelly, I stumble upon your gamedev.net post regarding Godot contributions and came to know about this issue. So I thought to take a look at it and fixed this issue. What I see is:

  1. This issue has nothing to do with KeyEvent.KEYCODE_BACK, this is special key code to tell activity to go back to previous activity or home screen if there is no previous activity, and this is being handled correctly.
  2. Issue is because of Android's weird behavior or you may say it an optimization. So when an Android app/game's activity return's false from onKeyDown api, Android system may optimize and does not send KeyUp event for that key down event. Also, strangely it does not happen in all cases and that why other key were working.
  3. I fixed it simply by returning true from onKeyDown and onKeyUp (for onKeyUp, it may not be needed but safer to return true) for every case where ever we dispatch runnable on queueEvent.

I am not sure about rules of submitting patches and I may take some time to figure them out, meanwhile please find patch generated on top of git tag 3.1.1-stable as follows:

diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index ccf78f26f..bd82bcdfb 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -307,6 +307,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, false);
                                }
                        });
+                       return true;
                };

                return super.onKeyUp(keyCode, event);
@@ -355,6 +356,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, true);
                                }
                        });
+                       return true;
                };

                return super.onKeyDown(keyCode, event);
 ```

Patch for master branch:
```diff
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index a443a0ad9..098ba2f7b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -106,6 +106,7 @@ public class GodotInputHandler implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, false);
                                }
                        });
+                       return true;
                };

                return false;
@@ -152,6 +153,7 @@ public class GodotInputHandler implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, true);
                                }
                        });
+                       return true;
                };

                return false;

All 4 comments

Just to add, I noticed this when fixing the bug that enabled android physical keyboards #29948. It wasn't 'introduced' by the fix as far as I could see, it already seemed to exist, but it is possible it wasn't occurring in the wild simply because most physical keyboards weren't working and were being treated as joysticks.

I didn't add an issue at the time but did mention it, and after small attempts to fix it decided it was more of a design decision and something for an android expert e.g. @m4gr3d ?

As far as I could see, the problem is caused because we return all keys as unhandled (see GodotInputHandler.java the return values of onKeyDown and onKeyUp are false:

https://github.com/godotengine/godot/blob/2861fd9552c242ef7a98f63312f253e6534c5b34/platform/android/java/src/org/godotengine/godot/input/GodotInputHandler.java#L68-L158

There seems to be some kind of in built android function that is called when pressing left arrow, it was crashing with something to do with audio on mine. I had a bit of a google but I couldn't work out what this was.

However regardless of that, the bigger question remains whether it is a good idea for us to be returning keys as unhandled, when some of them will be handled. Of course because of the godot design we don't know in advance which will be handled (it depends which have been assigned, maybe we could have the action keys return handled?).

I fixed this in my android build by simply returning true from both functions. But I'm not sure it is the 'correct' way of addressing the problem, it really requires discussion. Note that before my PR, these physical keyboards were (wrongly) being treated as joystick type devices, and that section of code _DOES_ return true.

If there aren't any android input experts, we could potentially try the quick fix (of returning true) and see if this causes any issues down the line by disabling default android 'quick keys', and fix those as required. I didn't do this in the original PR because it needed discussion and I wasn't sure if it was correct, PLUS it was the existing path for keyboards and I didn't want to break this (I was at the time under the impression that some physical keyboards were already using that path, whether this is correct or not, I do not know).

In summary there are 2 issues at play here:
1) Some default android key action seems to be causing a crash (probably in the audio)
2) Should godot be returning keyboard presses as handled or not?

_Wild hunch: Could it be that the left cursor is expected to perform the same as the back button by default?_

@lawnjelly, I stumble upon your gamedev.net post regarding Godot contributions and came to know about this issue. So I thought to take a look at it and fixed this issue. What I see is:

  1. This issue has nothing to do with KeyEvent.KEYCODE_BACK, this is special key code to tell activity to go back to previous activity or home screen if there is no previous activity, and this is being handled correctly.
  2. Issue is because of Android's weird behavior or you may say it an optimization. So when an Android app/game's activity return's false from onKeyDown api, Android system may optimize and does not send KeyUp event for that key down event. Also, strangely it does not happen in all cases and that why other key were working.
  3. I fixed it simply by returning true from onKeyDown and onKeyUp (for onKeyUp, it may not be needed but safer to return true) for every case where ever we dispatch runnable on queueEvent.

I am not sure about rules of submitting patches and I may take some time to figure them out, meanwhile please find patch generated on top of git tag 3.1.1-stable as follows:

diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index ccf78f26f..bd82bcdfb 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -307,6 +307,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, false);
                                }
                        });
+                       return true;
                };

                return super.onKeyUp(keyCode, event);
@@ -355,6 +356,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, true);
                                }
                        });
+                       return true;
                };

                return super.onKeyDown(keyCode, event);
 ```

Patch for master branch:
```diff
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index a443a0ad9..098ba2f7b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -106,6 +106,7 @@ public class GodotInputHandler implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, false);
                                }
                        });
+                       return true;
                };

                return false;
@@ -152,6 +153,7 @@ public class GodotInputHandler implements InputDeviceListener {
                                        GodotLib.key(keyCode, chr, true);
                                }
                        });
+                       return true;
                };

                return false;

Yes that's basically what I used to fix it in my android build (I returned true at the end of the function so as to catch the case of game devices too, just in case they also caused the same bug, your positioning may be better, I'll have to review it after the weekend).

I actually had more than just keyboard input stopping working (although I believe this may have happened too) I was actually getting a crash too in audio. This may have been happening to OP as well, but we would need adb logcat to see.

Without getting any further better info on this I'll probably just make a PR to change the return value to true, and hope it gets discussed in PR meeting. (I've only been delayed on this and another PR because of another Android build issue).

Indeed I too had the audio playback get stuck as well.
The sound currently output was repeated and overlapping at an extremely high rate.

Was this page helpful?
0 / 5 - 0 ratings