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

[FR]: bluetooth keyboard support #338

Open
pazos opened this issue Nov 4, 2021 · 7 comments
Open

[FR]: bluetooth keyboard support #338

pazos opened this issue Nov 4, 2021 · 7 comments

Comments

@pazos
Copy link
Member

pazos commented Nov 4, 2021

@pazos Could you elaborate on this point? I'd like support for a bluetooth keyboard on android. Let me know if I should open a new issue for bluetooth keyboard support to talk about this.

  1. You need key translation functions. Each time the user presses a key we receive a bunch of key sequence events (onNativeKeyDown/Up) that we need to translate to the chars displayed on the screen.

The 3rd point is doable and somehow required to get bluetooth/physical keyboards support.

Originally posted by @beelzebielsk in koreader/koreader#7423 (comment)

@pazos
Copy link
Member Author

pazos commented Nov 4, 2021

Some context first.

NativeActivities are meant mostly for games. There's a native api to deal with input which covers most of the KeyEvent framework used on the JVM counterpart. One thing missing is KeyEvent.getUnicodeChar, which is used to retrieve a single character based on a given key event.

getUnicodeChar returns an integer that needs to be casted to a char. It represents a single unicode character if it's > 0. Some non-translatable keys, such as back, will report 0.

The problem here is: if we try to call that method from our keyevent handler using JNI our main thread will be blocked until that function returns. 99% of that time will be caused by the JNI overhead.

IIRC there's a way to ignore keyevents on native code just by not consuming them. They will be forwarded to other parts of the activity and, if not consumed yet, to the system.

We already use that to forward media keys to the system: https://github.com/koreader/koreader-base/blob/master/ffi/input_android.lua#L123-L129

In theory, for these events, you should be able to catch them with a standard KeyEvent Listener from managed code. If we're able to do that the rest should be easy:

  1. add a new function android.setInputState(true/false) to signal if the user is or not inserting text by any means.
  2. that function sets a variable android.isInputState
  3. the keyevent handler check if android.isInputState is true. If that happens it will ignore most keyevents, so they can be catched from MainActivity. If android.isInputState is false the current keyevent handler will be used.
  4. Add a keyevent listener to MainActivity that catches all keyevents, gets unicode chars and, if they're > 0, sends them to lua.

For a proof of concept you can try to catch the keyevents we actually ignore and just print their keycodes when they arrive.

@ryanwwest
Copy link

ryanwwest commented Nov 13, 2023

Here's something interesting. I've been using https://www.8bitdo.com/micro/ as remote controller for KOReader mainly just to turn pages forward and backward (you can map its keys to most normal physical keyboard keycodes) with left arrow/right arrow, which work fine (up/down arrow too). I was trying to find a way to map the Android 'back button' to a keycode to back out of menus / go back in location history, but eventually realized that the Escape key mapping probably doesn't work because Android bluetooth keyboards aren't supported yet.

However, other keybindings are working: j,k,h,enter. h invokes the black crosshair cursor (which I don't know how to disable thereafter), j and k both do something to toggle hiding and showing the rendered page (but the status bar remains visible), and Enter shows the lower menu. So somehow this is already partially working?

@NiLuJe
Copy link
Member

NiLuJe commented Nov 13, 2023

h invokes the black crosshair cursor (which I don't know how to disable thereafter)

That's not us

j and k both do something to toggle hiding and showing the rendered page (but the status bar remains visible)

That also doesn't feel like us, unless something is going very screwy somewhere.

and Enter shows the lower menu.

That, at least, is probably us, as Enter is bound to toggle menus on keyboards IIRC.

@Frenzie
Copy link
Member

Frenzie commented Nov 13, 2023

That, at least, is probably us, as Enter is bound to toggle menus on keyboards IIRC.

True, but does that mean controllers map regular back and enter on Android?

@ryanwwest
Copy link

ryanwwest commented Nov 13, 2023

I specifically mapped different keys to the 'enter' button in 8BitDo's Ultimate software. So I don't think it's being interpreted as a specific 'gamepad' keycode but a generic keyboard 'enter' keycode.

I haven't found a way to map the Android 'back' button to a generic keyboard keycode yet (not KOReader specific).

h invokes the black crosshair cursor (which I don't know how to disable thereafter)
That's not us

I think this is KOReader but might be an archaic feature added before some of the current maintainers were active (somewhere else, someone else didn't know about this either). Here's a screenshot of the feature on macos, invokable with h and then you can use the arrow keys and enter to select text to highlight (and for the record escape cancels it, but escape doesn't work on Android):
Screen Shot 2023-11-13 at 11 54 41

Main point though was that it seems like some keyboard bindings work already on Android, but not all.

@pazos
Copy link
Member Author

pazos commented Nov 13, 2023

Yup, bluetooth remote controllers are very well supported on android. You can remap any key even from within KOReader, following https://github.com/koreader/koreader/wiki/Android-tips-and-tricks#customize-keys

What's left unimplemented is the translation of key events (with optional key modifiers) to text, like it happens on SDL targets.

@Frenzie
Copy link
Member

Frenzie commented Nov 13, 2023

I think this is KOReader but might be an archaic feature added before some of the current maintainers were active

On the contrary, it's brand spanking new. ;-)

koreader/koreader#8877

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

No branches or pull requests

4 participants