liballeg/allegro5

Android-specific keys never trigger keyboard events

Opened this issue · 11 comments

Allegro defines a set of "Android game keys" in keycodes.h. Of the 18 defined keys, 10 never trigger keyboard events on Android after a successful call to al_install_joystick():

  • The following 10 never trigger a keyboard event: ALLEGRO_KEY_BUTTON_A, ALLEGRO_KEY_BUTTON_B, ALLEGRO_KEY_BUTTON_X, ALLEGRO_KEY_BUTTON_Y, ALLEGRO_KEY_BUTTON_L1, ALLEGRO_KEY_BUTTON_R1, ALLEGRO_KEY_DPAD_UP, ALLEGRO_KEY_DPAD_DOWN, ALLEGRO_KEY_DPAD_LEFT, ALLEGRO_KEY_DPAD_RIGHT.
  • The following 8 do trigger keyboard events: ALLEGRO_KEY_START, ALLEGRO_KEY_SELECT, ALLEGRO_KEY_BUTTON_L2, ALLEGRO_KEY_BUTTON_R2, ALLEGRO_KEY_THUMBL, ALLEGRO_KEY_THUMBR, ALLEGRO_KEY_DPAD_CENTER, ALLEGRO_KEY_SEARCH.
  • ALLEGRO_KEY_MENU, although not defined side-by-side with the Android game keys, also never triggers a keyboard event.

The keys that never trigger keyboard events are instead mapped to joystick input. Conversely, the keys that are not mapped to joystick input trigger keyboard events.

The present state of things leads to inconsistent behavior: in order to detect if the START button has been pressed, I have to listen to keyboard input. On the other hand, if I want to detect A, B, X, Y, I have to listen to joystick input. Other buttons behave in the same way: L1/R1 are detected as joystick input only, whereas L2/R2 are detected as keyboard input only.

Since Allegro defines 18 "Android game keys", could we have them all trigger keyboard events?

  • Keycodes have publicly defined names, whereas joystick button numbers do not. In my code, I remap the joystick button numbers defined in AllegroActivity to the XInput button numbers defined in src/win/wjoyxi.c for consistency.
  • If multiple gamepads are connected to a device, they all trigger keyboard events. This is not an issue, as Android game keys are already defined and gamepad differentiation can be done using the joystick API.
  • All 18 game keys are correctly recognized as long as you do not call al_install_joystick(). Once you do and it succeeds, Allegro blocks 10 keys (in addition to the menu key), leading to inconsistent behavior.

Correction: ALLEGRO_KEY_DPAD_* are never triggered anywhere because D-Pad KeyEvents are mapped to ALLEGRO_KEY_UP, ALLEGRO_KEY_DOWN, ALLEGRO_KEY_LEFT, ALLEGRO_KEY_RIGHT and ALLEGRO_KEY_ENTER instead of their ALLEGRO_KEY_DPAD_* equivalents.

Even though the ALLEGRO_KEY_DPAD_* keys are defined, they are never used anywhere inside Allegro. 🤷‍♂️

ALLEGRO_KEY_UP, // KeyEvent.KEYCODE_DPAD_UP
ALLEGRO_KEY_DOWN, // KeyEvent.KEYCODE_DPAD_DOWN
ALLEGRO_KEY_LEFT, // KeyEvent.KEYCODE_DPAD_LEFT
ALLEGRO_KEY_RIGHT, // KeyEvent.KEYCODE_DPAD_RIGHT
ALLEGRO_KEY_ENTER, // KeyEvent.KEYCODE_DPAD_CENTER

It seems weird to me to send duplicate events for a single key press. I would imagine the desired behavior is to either:

  • Never send the "Android game keys" events
  • Only send them if they joystick is not initialized

And, separately, they joystick API should surface all the relevant keys. I'll have to think about it some more.

On the other hand, keeping the present design
and extending the button set in the joystick API would maintain backwards
compatibility, but it would not address the inconsistent behavior.

This is probably the best option at this time (we can add an allegro5.cfg option to disable the old events). If I merge #1483 does this implement this or do we need more buttons?

By the way, how do you test the gamepads? Does your Android device come with builtin buttons? Are you somehow attaching the gamepad to the device? I've tried it a bit with my phone and a F310 and didn't have any luck.

This is probably the best option at this time (we can add an allegro5.cfg option to disable the old events). If I merge #1483 does this implement this or do we need more buttons?

There are two more game buttons defined on Android (KeyEvent): BUTTON_Z and BUTTON_C. Should I add them as well? These have not been defined in allegro5/keycodes.h.

#1483 neither changes existing behavior nor adds an allegro5.cfg option. It only adds more joystick buttons.

What would be the best course of action at this time? May I be of help?

By the way, how do you test the gamepads? Does your Android device come with builtin buttons? Are you somehow attaching the gamepad to the device? I've tried it a bit with my phone and a F310 and didn't have any luck.

I test with a bluetooth controller, using ex_joystick_events (I modify it and set the joystick ID to 1). I also do cross-testing with an external app I downloaded from the Play Store.

I think the goal should be to get the Android joystick to be as good as possible, with all the keys mapped. The keyboard events should be left as is, and I'll add a config option to disable them.

I think the goal should be to get the Android joystick to be as good as possible, with all the keys mapped. The keyboard events should be left as is, and I'll add a config option to disable them.

Okay. I can get BUTTON_Z and BUTTON_C mapped too for completeness. Getting the Android joystick to be as good as possible is a different issue with some design choices. May I give feedback on the matter?

In order to make the Android joysticks better, I would change their button numbers so that they match the button numbers defined in Allegro's Windows XInput driver. I would do this to unify things using the Xbox 360 controller as a reference, because it's a very good reference with a known layout.

Android game buttons have a known layout too, which is similar to and a superset of the layout of the Xbox 360 controller. It would be handy if the buttons defined in src/win/wjoyxi.c were defined the same way on Android.

Out of the first 10 joystick buttons currently defined on Allegro for Android, 4 are defined in the same way as on wjoyxi.c (A, B, X, Y) and 6 are defined differently (L1, R1, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, DPAD_DOWN). In order to get consistent input on XInput and on Android, an Allegro user has to remap these 6 buttons, when in principle there would be no need. Also, newly defined buttons will need remapping as well because of this mismatch.

The Android joystick would certainly be better if we had a consistent mapping. Conceptually, it is already similar to the Xbox 360 controller. Would this be a worthwhile change?

Whoops, forgot to respond. There's two things. First, is consistent cross-platform mapping, which should be fixed, but out of scope here. I just meant that the Android joystick has all the buttons/axes mapped.

I test with a bluetooth controller, using ex_joystick_events (I modify it and set the joystick ID to 1).

I tried that with a USB controller, but it doesn't seem to see it, perhaps I need to edit the requested permissions.

First, is consistent cross-platform mapping, which should be fixed, but out of scope here.

Would you like it fixed at this time? A consistent mapping already exists for controllers designed to be used with Android.

I tried that with a USB controller, but it doesn't seem to see it, perhaps I need to edit the requested permissions.

Have you tried it with a third-party app or with a different controller? Is your controller switch in XID mode?

I just meant that the Android joystick has all the buttons/axes mapped.

Okay. I'm going to add BUTTON_Z and BUTTON_C as joystick buttons. Should I add them as keyboard buttons as well? They are not defined in keycodes.h.

Here is another design issue of the Android joystick of Allegro: the menu button, recognized as a joystick button by Allegro, is not strictly a gamepad button on Android. It used to be present on older phones, next to the back and to the home buttons. It's long gone from the phones, but you can still see it in remotes of Smart TVs.

START, SELECT and MODE are gamepad buttons. Menu is not, but some manufacturers do implement it in their gamepads. Those who do often implement the Back button as well. In spite of this, the Back button is not recognized as a joystick button by Allegro. Back is also not strictly a gamepad button. I find it more common to see start & select instead of menu & back.

In order to make the Android joystick better, we could design it in a more principled way, based on the Android documentation. Was the present design based on a specific controller?

Now #1483 adds all gamepad buttons and improves the design of the Android joystick.