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

Home and End on a hardware keyboard do not seem to work, likewise SHIFT+PAGEUP/DOWN #731

Closed
felagund opened this issue Jun 23, 2018 · 4 comments · Fixed by #794
Closed

Comments

@felagund
Copy link

I have a hardware keyboard on my phone (Gemini PDA) that has Home, End and PgUp and PgDn keys that are entered by pressing fn+left/right/up/down arrows respectively. While ctrl+left jumps to previous word correctly, these keys behave as if I was not pressing the fn key at all (so while I am issueing "home", Termux thinks I am pressing the left key ignoring me also pressing "Fn" at the same time).

I will be happy to provide additional debugging, tried running xev but that is missing due to Android not running X.

zevv added a commit to zevv/termux-app that referenced this issue Jul 24, 2018
zevv added a commit to zevv/termux-app that referenced this issue Jul 25, 2018
…ard, Fixes termux#731.

```
Fn+Left -> Home
Fn+Right -> End
Fn+Up -> Page Up
Fn+Down -> Page Down
```
zevv added a commit to zevv/termux-app that referenced this issue Jul 25, 2018
…ard, Fixes termux#731.

  Fn+Left  -> Home
  Fn+Right -> End
  Fn+Up    -> Page Up
  Fn+Down  -> Page Down
zevv added a commit to zevv/termux-app that referenced this issue Jul 25, 2018
…ard, Fixes termux#731.

  Fn+Left  -> Home
  Fn+Right -> End
  Fn+Up    -> Page Up
  Fn+Down  -> Page Down
@Konehaltia
Copy link

I think I've found the root cause of this problem. I'm not an Android expert, so
take it with a grain of salt.

The Gemini keyboard's KCM file is located at /system/usr/keychars/Generic.kcm.
I've included the relevant part below. See
https://source.android.com/devices/input/key-character-map-files for the file
format documentation.

key DPAD_LEFT {
  base:                        fallback DPAD_LEFT
  fn:                          fallback MOVE_HOME
}

key DPAD_DOWN {
  base:                        fallback DPAD_DOWN
  fn:                          fallback PAGE_DOWN
}

key DPAD_RIGHT {
  base:                        fallback DPAD_RIGHT
  fn:                          fallback MOVE_END
}

key DPAD_UP {
  base:                        fallback DPAD_UP
  fn:                          fallback PAGE_UP
}

Note the fallback declarations. When they are used, the app receives two key
events - the original and the fallback. If the app handles the original, the
fallback is canceled.

I'll use the Page Up combination (Fn+Up) as an example. The same applies to all four.

Here's a description of what happens when the user presses Fn+Up on the Gemini
in Termux. The events are handled by onKeyDown at
terminal-view/src/main/java/com/termux/view/TerminalView.java.

First, the method is called with a KeyEvent where the code is DPAD_UP and the
Function modifier is set.

Termux looks at the key code and the Ctrl/Alt/Shift modifiers. It doesn't check
the Function modifier's status at all (!), and thus believes it's seeing a pure
DPAD_UP. Termux handles it as such, and tells Android the event has been
handled (returns true from onKeyDown).

Since the initial event was handled, the fallback event is canceled.

Here's the relevant code:

int keyMod = 0;
if (controlDownFromEvent) keyMod |= KeyHandler.KEYMOD_CTRL;
if (event.isAltPressed()) keyMod |= KeyHandler.KEYMOD_ALT;
if (event.isShiftPressed()) keyMod |= KeyHandler.KEYMOD_SHIFT;
if (handleKeyCode(keyCode, keyMod)) {
    if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "handleKeyCode() took key event");
    return true;
}

Here's one way to stop Termux from mistaking Fn+X for X:

if (!event.isFunctionPressed() && handleKeyCode(keyCode, keyMod)) {

After that change, Fn+Up is no longer interpreted as just Up. However, we now
have a second problem: it doesn't get interpreted as Page Up either! Pressing
the combination simply does nothing.

The second problem is caused by some code further down that handles key events
that map to Unicode characters - for example, pressing the A key. Termux checks
if the event maps to a character. If it doesn't, the event is ignored but
reported as handled. Thus, the fallback event is still canceled.

Here's the relevant code:

int result = event.getUnicodeChar(effectiveMetaState);
if (LOG_KEY_EVENTS)
    Log.i(EmulatorDebug.LOG_TAG, "KeyEvent#getUnicodeChar(" + effectiveMetaState + ") returned: " + result);
if (result == 0) {
    return true;
}

I'm not sure why Termux claims to have handled the event (returns true) here.
I'm not very familiar with Android's key events or Android development in
general, and as such I don't know what the implications are.

That said, I tried changing the code to report that Termux didn't handle the
event - that is, to return false.

Since the original event is now reported as unhandled, Android goes ahead with
the fallback event - in this case, PAGE_UP without the Fn modifier. That event
is successfully handled by existing Termux code.

Thus, with this second change, Page Up and the other Fn+arrow combinations
started working.

if (result == 0) {
    return false;
}

I didn't notice any obvious problems after the change. I can still type all the
characters I've tried. However, if it does cause any problems, the effect can be
limited to situations where the Fn key is pressed.

if (result == 0) {
    return !event.isFunctionPressed();
}

Note that this way of solving the problem doesn't just fix the Fn+arrow
combinations. It also allows Gemini users (and others with a Function key) to
map other Fn-combinations to various other non-printable keys by using
fallback declarations in the KCM file.

Also, there seems to be a second modifier key - SYM - that Termux doesn't
check. It might be a good idea to have more general checks for any unhandled
modifier keys, since any users with those keys will presumably have the same
problem. The logic could probably be flipped to call handleKeyCode only when
the modifier mask consists entirely of currently handled modifiers (Ctrl, Alt,
Shift).

zevv added a commit to zevv/termux-app that referenced this issue Jul 31, 2018
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes termux#731.

Original diagnosis and fix by Konehaltia.
zevv added a commit to zevv/termux-app that referenced this issue Jul 31, 2018
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes termux#731.

Original diagnosis and fix by Konehaltia.
@zevv
Copy link
Contributor

zevv commented Jul 31, 2018

Thanks for figuring that out!

Would this do?

zevv@e71ed7b

fornwall pushed a commit that referenced this issue Aug 1, 2018
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes #731.

Original diagnosis and fix by Konehaltia.
@fornwall
Copy link
Member

fornwall commented Aug 1, 2018

The fix by @zevv in #794 has been released in version 0.65 of the app and should be available as an update shortly.

Thanks for all the work here, let us know if anything can be improved!

@zevv
Copy link
Contributor

zevv commented Aug 2, 2018 via email

@ghost ghost locked and limited conversation to collaborators Oct 17, 2021
AdamMickiewich pushed a commit to VolyaTeam/dzida-app that referenced this issue Aug 8, 2022
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes termux#731.

Original diagnosis and fix by Konehaltia.
shrihankp pushed a commit to reisxd/termux-app that referenced this issue Oct 20, 2022
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes termux#731.

Original diagnosis and fix by Konehaltia.
frikke pushed a commit to frikke/termux-app that referenced this issue Aug 20, 2023
- in onKeyDown() return false when the key is not handled.

The above two changes fix the handling of Fn-key combo's on devices with
a physical keyboard, allowing the android system defined fallbacks from
`/system/usr/keychars/Generic.kcm` to be properly handled.

Fixes termux#731.

Original diagnosis and fix by Konehaltia.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants