[Android] Idea for handle_input() in CNFGEGLDriver.c
Hello,
When you press shift on for instance the GBoard virtual keyboard, it inserts a semicolon.
Looking at CNFGEGLDriver.c, it's because:
- Semicolon has
code74 andunicode59. - Shift has
code59 andunicode0.
In both cases HandleKey receives 59.
Another conflict I found is with 'C' and backspace. Hacker Keyboard shows there's technically more, but they aren't used on Android (e.g. home/end, pgup/pgdn, alt + key, ctrl + key, num lock, scroll lock).
Defining ANDROID_USE_SCANCODES loses the information in event and gets too messy with having to maintain the state of the keyboard yourself. For instance Hacker Keyboard has Caps Lock if you press shift twice (so the graphics are all Caps), but GBoard does not.
I'd like to propose that handle_input() did
if (!AKeyEvent_getAction(event))
HandleKey(code, unicode);
Because it looks like bDown isn't useful at all with a virtual keyboard. It always sends a two events with a 0 and then a 1 for bDown.
Or that handle_input() added exceptions for these conflicts (at least for shift and backspace).
Hey! I'm sorry I haven't been able to get back to this. I'm not exactly sure of the right solution here, but I would love to have this solved. Do you see any downsides with adding this? I guess I'm not sure which situations it won't get input.
It's not like we could detect a down and up input both anyway, right?
Hi, yes there might be an issue with physical keyboards. I can try asking around if I can borrow a bluetooth keyboard somewhere. Or do you have one?
But I also now realize that in the current code the order in which the two bDown are sent determines whether the keycode was from a unicode conversion or not. When the key doesn't have a unicode equivalent the order of the bDown is 1 -> 0. If there is a unicode equivalent it is 0 -> 1.
But I do think it's a bit cumbersome to work with that.
With both up and down inputs do you mean with a modifier? I tried a lot of combinations, but it seems to be either
- Shift with bDown 1
- Key with bDown 0
- Key with bDown 1
- Shift with bDown 0
(Hacker Keyboard does this. Same for CTRL + key or pressing for instance tilde directly)
or
- Shift with bDown 1
- Shift with bDown 0
- Key with bDown 0
- Key with bDown 1
(GBoard does this)
BTW I'm currently making a todo / shopping list:

I do have a USB keyboard and otg adapter, hut not sure what I'd need to do
@dreua
Can you add this line to CNFGEGLDriver.c:
int unicode = AndroidGetUnicodeChar( code, AMotionEvent_getMetaState( event ) ); // Line 399
printf("PROKTEST: code:%d, unicode:%d, action:%d\n", code, unicode, AKeyEvent_getAction(event));
if( unicode ) // Line 400
I suppose you don't need AndroidDisplayKeyboard(1);
Then with adb logcat | grep PROKTEST, if you press Shift + a it might give the shift key and a capital A (like the virtual keyboard) in this case the bDown and modifier isn't actually needed because the unicode that gets sent already has all the information:
(example hacker keyboard)
PROKTEST: code:59, unicode:0, action:0
PROKTEST: code:29, unicode:65, action:0
PROKTEST: code:29, unicode:65, action:1
PROKTEST: code:59, unicode:0, action:1
(example GBoard)
PROKTEST: code:59, unicode:0, action:0
PROKTEST: code:59, unicode:0, action:1
PROKTEST: code:29, unicode:65, action:0
PROKTEST: code:29, unicode:65, action:1
or a lower case a (like Windows and Linux):
PROKTEST: code:59(?) unicode:0, action:1
PROKTEST: code:(??), unicode:97, action:1
PROKTEST: code:(??), unicode:97, action:0
PROKTEST: code:59(?), unicode:0, action:0
And either way, I'll try whether the current method is sufficient and works for what I can test. So it will use a buffer that says to ignore the next keycode/bDown pair.
Using a buffer which ignores duplicate keys on Android seems to work all right. But the solution is a bit quirky and I suppose it is what an app is required to do if it wants text entry.
Here is the code I used. NB it uses an ignore_buffer which can grow, but doesn't shrink. Because it's silly to make it go above what you normally use and even then I can't get it above size 5 in Hacker Keyboard (CTRL + SHIFT + ALT + "4 diamonds" + A) and not above size 1 in GBoard.
void HandleKey(int keycode, int bDown) {
# ifdef ANDROID
static int * ignore_buffer;
static int ignore_buffer_size;
int found = 0;
for (int i=0; i<ignore_buffer_size; i++) {
if (keycode == ignore_buffer[i]) {
ignore_buffer[i] = 0;
found = 1;
break;
}
}
if (! found) {
int assigned = 0;
for (int i=0; i<ignore_buffer_size; i++) {
if (ignore_buffer[i] == 0) {
ignore_buffer[i] = keycode;
assigned = 1;
break;
}
}
if (! assigned) {
ignore_buffer_size++;
ignore_buffer = realloc(ignore_buffer, ignore_buffer_size * sizeof(int));
ignore_buffer[ignore_buffer_size -1] = keycode;
}
} else {
return;
}
if (keycode == 59 && bDown) return; // Ignore shift key
if (keycode == 'C' && bDown) keycode = '\b'; // Backspace
key = keycode;
# else
/* Windows, Linux code */
# endif
}
This looks good to me - if you are interested in committing it. One question, though. How is ignore_buffer populated? It looks like it would corrupt the static area. @Procyon3