Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Idea for handle_input() in CNFGEGLDriver.c #67

Open
Procyon3 opened this issue May 24, 2021 · 6 comments
Open

[Android] Idea for handle_input() in CNFGEGLDriver.c #67

Procyon3 opened this issue May 24, 2021 · 6 comments

Comments

@Procyon3
Copy link

Procyon3 commented May 24, 2021

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 code 74 and unicode 59.
  • Shift has code 59 and unicode 0.

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).

@cnlohr
Copy link
Member

cnlohr commented Jun 1, 2021

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?

@Procyon3
Copy link
Author

Procyon3 commented Jun 1, 2021

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

  1. Shift with bDown 1
  2. Key with bDown 0
  3. Key with bDown 1
  4. Shift with bDown 0

(Hacker Keyboard does this. Same for CTRL + key or pressing for instance tilde directly)

or

  1. Shift with bDown 1
  2. Shift with bDown 0
  3. Key with bDown 0
  4. Key with bDown 1

(GBoard does this)

BTW I'm currently making a todo / shopping list:

shopping_small

@dreua
Copy link
Member

dreua commented Jun 2, 2021

I do have a USB keyboard and otg adapter, hut not sure what I'd need to do

@Procyon3
Copy link
Author

Procyon3 commented Jun 2, 2021

@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.

@Procyon3
Copy link
Author

Procyon3 commented Jun 5, 2021

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
}

@cnlohr
Copy link
Member

cnlohr commented Jul 26, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants