From 7b4a69f839fa5fc65821a1ca55bba80ac4356522 Mon Sep 17 00:00:00 2001 From: rakslice Date: Sat, 16 Jan 2021 19:22:01 -0800 Subject: [PATCH 1/3] when num lock is off, have numpad keys works as their numlock-off functions (arrows/home/end/pgup/pgdn/insert/delete) --- .../java/com/termux/terminal/KeyHandler.java | 77 ++++++++++++++++--- .../com/termux/terminal/KeyHandlerTest.java | 36 ++++++--- .../java/com/termux/view/TerminalView.java | 1 + 3 files changed, 92 insertions(+), 22 deletions(-) diff --git a/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java b/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java index a4d0f1ac..97e2637f 100644 --- a/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java +++ b/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java @@ -59,6 +59,7 @@ public final class KeyHandler { public static final int KEYMOD_ALT = 0x80000000; public static final int KEYMOD_CTRL = 0x40000000; public static final int KEYMOD_SHIFT = 0x20000000; + public static final int KEYMOD_NUM_LOCK = 0x10000000; private static final Map TERMCAP_TO_KEYCODE = new HashMap<>(); @@ -145,10 +146,16 @@ public final class KeyHandler { keyMod |= KEYMOD_ALT; keyCode &= ~KEYMOD_ALT; } + if ((keyCode & KEYMOD_NUM_LOCK) != 0) { + keyMod |= KEYMOD_NUM_LOCK; + keyCode &= ~KEYMOD_NUM_LOCK; + } return getCode(keyCode, keyMod, cursorKeysApplication, keypadApplication); } public static String getCode(int keyCode, int keyMode, boolean cursorApp, boolean keypadApplication) { + boolean numLockOn = (keyMode & KEYMOD_NUM_LOCK) != 0; + keyMode &= ~KEYMOD_NUM_LOCK; switch (keyCode) { case KEYCODE_DPAD_CENTER: return "\015"; @@ -249,31 +256,81 @@ public final class KeyHandler { case KEYCODE_NUMPAD_COMMA: return ","; case KEYCODE_NUMPAD_DOT: - return keypadApplication ? "\033On" : "."; + if (numLockOn) { + return keypadApplication ? "\033On" : "."; + } else { + // DELETE + return transformForModifiers("\033[3", keyMode, '~'); + } case KEYCODE_NUMPAD_SUBTRACT: return keypadApplication ? transformForModifiers("\033O", keyMode, 'm') : "-"; case KEYCODE_NUMPAD_DIVIDE: return keypadApplication ? transformForModifiers("\033O", keyMode, 'o') : "/"; case KEYCODE_NUMPAD_0: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'p') : "0"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'p') : "0"; + } else { + // INSERT + return transformForModifiers("\033[2", keyMode, '~'); + } case KEYCODE_NUMPAD_1: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'q') : "1"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'q') : "1"; + } else { + // END + return (keyMode == 0) ? (cursorApp ? "\033OF" : "\033[F") : transformForModifiers("\033[1", keyMode, 'F'); + } case KEYCODE_NUMPAD_2: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'r') : "2"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'r') : "2"; + } else { + // DOWN + return (keyMode == 0) ? (cursorApp ? "\033OB" : "\033[B") : transformForModifiers("\033[1", keyMode, 'B'); + } case KEYCODE_NUMPAD_3: - return keypadApplication ? transformForModifiers("\033O", keyMode, 's') : "3"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 's') : "3"; + } else { + // PGDN + return "\033[6~"; + } case KEYCODE_NUMPAD_4: - return keypadApplication ? transformForModifiers("\033O", keyMode, 't') : "4"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 't') : "4"; + } else { + // LEFT + return (keyMode == 0) ? (cursorApp ? "\033OD" : "\033[D") : transformForModifiers("\033[1", keyMode, 'D'); + } case KEYCODE_NUMPAD_5: return keypadApplication ? transformForModifiers("\033O", keyMode, 'u') : "5"; case KEYCODE_NUMPAD_6: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'v') : "6"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'v') : "6"; + } else { + // RIGHT + return (keyMode == 0) ? (cursorApp ? "\033OC" : "\033[C") : transformForModifiers("\033[1", keyMode, 'C'); + } case KEYCODE_NUMPAD_7: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'w') : "7"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'w') : "7"; + } else { + // HOME + return (keyMode == 0) ? (cursorApp ? "\033OH" : "\033[H") : transformForModifiers("\033[1", keyMode, 'H'); + } case KEYCODE_NUMPAD_8: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'x') : "8"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'x') : "8"; + } else { + // UP + return (keyMode == 0) ? (cursorApp ? "\033OA" : "\033[A") : transformForModifiers("\033[1", keyMode, 'A'); + } case KEYCODE_NUMPAD_9: - return keypadApplication ? transformForModifiers("\033O", keyMode, 'y') : "9"; + if (numLockOn) { + return keypadApplication ? transformForModifiers("\033O", keyMode, 'y') : "9"; + } else { + // PGUP + return "\033[5~"; + } case KEYCODE_NUMPAD_EQUALS: return keypadApplication ? transformForModifiers("\033O", keyMode, 'X') : "="; } diff --git a/terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java b/terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java index 0826c7fc..15b23761 100644 --- a/terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java +++ b/terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java @@ -174,18 +174,30 @@ public class KeyHandlerTest extends TestCase { assertKeysEquals("\033[23;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F11, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[24;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F12, KeyHandler.KEYMOD_SHIFT, false, false)); - assertKeysEquals("0", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_0, 0, false, false)); - assertKeysEquals("1", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_1, 0, false, false)); - assertKeysEquals("2", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_2, 0, false, false)); - assertKeysEquals("3", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_3, 0, false, false)); - assertKeysEquals("4", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_4, 0, false, false)); - assertKeysEquals("5", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_5, 0, false, false)); - assertKeysEquals("6", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_6, 0, false, false)); - assertKeysEquals("7", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_7, 0, false, false)); - assertKeysEquals("8", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_8, 0, false, false)); - assertKeysEquals("9", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_9, 0, false, false)); - assertKeysEquals(",", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_COMMA, 0, false, false)); - assertKeysEquals(".", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_DOT, 0, false, false)); + assertKeysEquals("0", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_0, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("1", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_1, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("2", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_2, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("3", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_3, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("4", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_4, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("5", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_5, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("6", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_6, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("7", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_7, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("8", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_8, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals("9", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_9, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals(",", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_COMMA, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + assertKeysEquals(".", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_DOT, KeyHandler.KEYMOD_NUM_LOCK, false, false)); + + assertKeysEquals("\033[2~", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_0, 0, false, false)); + assertKeysEquals("\033[F", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_1, 0, false, false)); + assertKeysEquals("\033[B", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_2, 0, false, false)); + assertKeysEquals("\033[6~", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_3, 0, false, false)); + assertKeysEquals("\033[D", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_4, 0, false, false)); + assertKeysEquals("5", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_5, 0, false, false)); + assertKeysEquals("\033[C", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_6, 0, false, false)); + assertKeysEquals("\033[H", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_7, 0, false, false)); + assertKeysEquals("\033[A", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_8, 0, false, false)); + assertKeysEquals("\033[5~", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_9, 0, false, false)); + assertKeysEquals("\033[3~", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_DOT, 0, false, false)); } } diff --git a/terminal-view/src/main/java/com/termux/view/TerminalView.java b/terminal-view/src/main/java/com/termux/view/TerminalView.java index 43392523..c8bc8207 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalView.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalView.java @@ -591,6 +591,7 @@ public final class TerminalView extends View { if (controlDown) keyMod |= KeyHandler.KEYMOD_CTRL; if (event.isAltPressed() || leftAltDown) keyMod |= KeyHandler.KEYMOD_ALT; if (event.isShiftPressed()) keyMod |= KeyHandler.KEYMOD_SHIFT; + if (event.isNumLockOn()) keyMod |= KeyHandler.KEYMOD_NUM_LOCK; if (!event.isFunctionPressed() && handleKeyCode(keyCode, keyMod)) { if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "handleKeyCode() took key event"); return true; From 78cdaef6d249833905868a2d64257691b6dbbdb4 Mon Sep 17 00:00:00 2001 From: rakslice Date: Sat, 16 Jan 2021 19:53:22 -0800 Subject: [PATCH 2/3] only send PF1 for num lock when in application mode --- .../src/main/java/com/termux/terminal/KeyHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java b/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java index 97e2637f..254f5e3a 100644 --- a/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java +++ b/terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java @@ -235,8 +235,11 @@ public final class KeyHandler { // Just do what xterm and gnome-terminal does: return prefix + (((keyMode & KEYMOD_CTRL) == 0) ? "\u007F" : "\u0008"); case KEYCODE_NUM_LOCK: - return "\033OP"; - + if (keypadApplication) { + return "\033OP"; + } else { + return null; + } case KEYCODE_SPACE: // If ctrl is not down, return null so that it goes through normal input processing (which may e.g. cause a // combining accent to be written): From fe584940e121a7ae500d9ea1f126aa13bf6d8527 Mon Sep 17 00:00:00 2001 From: rakslice Date: Sat, 16 Jan 2021 19:54:11 -0800 Subject: [PATCH 3/3] fix TerminalView possiblePropLocations IOBE --- terminal-view/src/main/java/com/termux/view/TerminalView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal-view/src/main/java/com/termux/view/TerminalView.java b/terminal-view/src/main/java/com/termux/view/TerminalView.java index c8bc8207..cd966323 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalView.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalView.java @@ -1549,7 +1549,7 @@ public final class TerminalView extends View { propsFile = new File(possiblePropLocations[0]); int i = 1; - while (!propsFile.exists() && i <= possiblePropLocations.length) { + while (!propsFile.exists() && i < possiblePropLocations.length) { propsFile = new File(possiblePropLocations[i]); i += 1; }