# HG changeset patch # User Carl Byington # Date 1402511311 25200 # Node ID 8887bff45deecbb6233afb1a87988ebb98fa2942 # Parent 1e931ef5f776969146f3910a3e64d8bd2878a84b start tn5250 integration diff -r 1e931ef5f776 -r 8887bff45dee src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java --- a/src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Wed Jun 11 10:11:29 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Wed Jun 11 11:28:31 2014 -0700 @@ -45,7 +45,6 @@ import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; import de.mud.terminal.VDUBuffer; import de.mud.terminal.vt320; @@ -91,20 +90,14 @@ private String customKeyboard = null; private int metaState = 0; - private int mDeadKey = 0; // TODO add support for the new API. private ClipboardManager clipboard = null; - private boolean selectingForCopy = false; private final SelectionArea selectionArea; - - private final SharedPreferences prefs; - private Toast debugToast = null; - private Toast metakeyToast = null; public TerminalKeyListener(TerminalManager manager, TerminalBridge bridge, @@ -149,13 +142,7 @@ if (prefs.getBoolean(PreferenceConstants.DEBUG_KEYCODES, false)) { String keyCodeString = String.format(": %d", keyCode); String toastText = v.getContext().getString(R.string.keycode_pressed) + keyCodeString; - - if (debugToast == null) - debugToast = Toast.makeText(v.getContext(), toastText, Toast.LENGTH_LONG); - else - debugToast.setText(toastText); - - debugToast.show(); + Log.d(TAG, toastText); } if (fullKeyboard()) { @@ -653,13 +640,7 @@ } private void showMetakeyToast(View v, String keyname) { - if (metakeyToast == null) - metakeyToast = Toast.makeText(v.getContext(), keyname, Toast.LENGTH_LONG); - else - metakeyToast.setText(keyname); - - metakeyToast.setGravity(Gravity.TOP | Gravity.RIGHT, 0, 0); - metakeyToast.show(); + Log.d(TAG, keyname); } public int keyAsControl(int key) { diff -r 1e931ef5f776 -r 8887bff45dee src/com/five_ten_sg/connectbot/transport/TN5250.java --- a/src/com/five_ten_sg/connectbot/transport/TN5250.java Wed Jun 11 10:11:29 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/transport/TN5250.java Wed Jun 11 11:28:31 2014 -0700 @@ -71,9 +71,11 @@ } @Override public void write(byte[] b) { + screen52.sendKeys(new String(b)); } @Override public void write(int b) { + screen52.sendKeys(new String(new byte[] {b})); } // bridge.monitor placement of new characters @Override @@ -96,8 +98,482 @@ String encoding) { super(manager, bridge, buffer, encoding); } + + /** + * Handle onKey() events coming down from a {@link com.five_ten_sg.connectbot.TerminalView} above us. + * Modify the keys to make more sense to a host then pass it to the 5250. + */ + public boolean onKey(View v, int keyCode, KeyEvent event) { + try { + // skip keys if we aren't connected yet or have been disconnected + if (bridge.isDisconnected() || bridge.transport == null) + return false; + + final boolean hardKeyboardHidden = manager.hardKeyboardHidden; + + // Ignore all key-up events except for the special keys + if (event.getAction() == KeyEvent.ACTION_UP) { + // There's nothing here for virtual keyboard users. + if (!hardKeyboard || (hardKeyboard && hardKeyboardHidden)) + return false; + + // if keycode debugging enabled, log and print the pressed key + if (prefs.getBoolean(PreferenceConstants.DEBUG_KEYCODES, false)) { + String keyCodeString = String.format(": %d", keyCode); + String toastText = v.getContext().getString(R.string.keycode_pressed) + keyCodeString; + Log.d(TAG, toastText); + } + + if (fullKeyboard()) { + switch (keyCode) { + case KeyEvent.KEYCODE_CTRL_LEFT: + case KeyEvent.KEYCODE_CTRL_RIGHT: + metaKeyUp(META_CTRL_ON); + return true; + + case KeyEvent.KEYCODE_ALT_LEFT: + case KeyEvent.KEYCODE_ALT_RIGHT: + metaKeyUp(META_ALT_ON); + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaKeyUp(META_SHIFT_ON); + return true; + + default: + } + } + else if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { + if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT + && (metaState & META_SLASH) != 0) { + metaState &= ~(META_SLASH | META_TRANSIENT); + buffer.write('/'); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT + && (metaState & META_TAB) != 0) { + metaState &= ~(META_TAB | META_TRANSIENT); + buffer.write("[tab]"); + return true; + } + } + else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { + if (keyCode == KeyEvent.KEYCODE_ALT_LEFT + && (metaState & META_SLASH) != 0) { + metaState &= ~(META_SLASH | META_TRANSIENT); + buffer.write('/'); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT + && (metaState & META_TAB) != 0) { + metaState &= ~(META_TAB | META_TRANSIENT); + buffer.write("[tab]"); + return true; + } + } + + return false; + } + + bridge.resetScrollPosition(); + + if (keyCode == KeyEvent.KEYCODE_UNKNOWN && + event.getAction() == KeyEvent.ACTION_MULTIPLE) { + byte[] input = event.getCharacters().getBytes(encoding); + buffer.write(input); + return true; + } + + int curMetaState = event.getMetaState(); + final int orgMetaState = curMetaState; + + if ((metaState & META_SHIFT_MASK) != 0) { + curMetaState |= KeyEvent.META_SHIFT_ON; + } + + if ((metaState & META_ALT_MASK) != 0) { + curMetaState |= KeyEvent.META_ALT_ON; + } + + int uchar = event.getUnicodeChar(curMetaState); + + // no hard keyboard? ALT-k should pass through to below + if ((orgMetaState & KeyEvent.META_ALT_ON) != 0 && + (!hardKeyboard || hardKeyboardHidden)) { + uchar = 0; + } + + if ((uchar & KeyCharacterMap.COMBINING_ACCENT) != 0) { + mDeadKey = uchar & KeyCharacterMap.COMBINING_ACCENT_MASK; + return true; + } + + if (mDeadKey != 0 && uchar != 0) { + uchar = KeyCharacterMap.getDeadChar(mDeadKey, uchar); + mDeadKey = 0; + } + + // handle customized keymaps + if (customKeymapAction(v, keyCode, event)) + return true; + + if (v != null) { + //Show up the CharacterPickerDialog when the SYM key is pressed + if ((isSymKey(keyCode) || uchar == KeyCharacterMap.PICKER_DIALOG_INPUT)) { + bridge.showCharPickerDialog(); + + if (metaState == 4) { // reset fn-key state + metaState = 0; + bridge.redraw(); + } + + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + //Show up the URL scan dialog when the search key is pressed + urlScan(v); + return true; + } + } + + // otherwise pass through to existing session + // print normal keys + if (uchar > 0x00 && keyCode != KeyEvent.KEYCODE_ENTER) { + metaState &= ~(META_SLASH | META_TAB); + // Remove shift and alt modifiers + final int lastMetaState = metaState; + metaState &= ~(META_SHIFT_ON | META_ALT_ON); + + if (metaState != lastMetaState) { + bridge.redraw(); + } + + if ((metaState & META_CTRL_MASK) != 0) { + metaState &= ~META_CTRL_ON; + bridge.redraw(); + + // If there is no hard keyboard or there is a hard keyboard currently hidden, + // CTRL-1 through CTRL-9 will send F1 through F9 + if ((!hardKeyboard || (hardKeyboard && hardKeyboardHidden)) + && sendFunctionKey(keyCode)) + return true; + + uchar = keyAsControl(uchar); + } + + // handle pressing f-keys + if ((hardKeyboard && !hardKeyboardHidden) + && (curMetaState & KeyEvent.META_ALT_ON) != 0 + && (curMetaState & KeyEvent.META_SHIFT_ON) != 0 + && sendFunctionKey(keyCode)) + return true; + + if (uchar < 0x80) + buffer.write(uchar); + else + buffer.write(new String(Character.toChars(uchar)).getBytes(encoding)); + + return true; + } + + // send ctrl and meta-keys as appropriate + if (!hardKeyboard || hardKeyboardHidden) { + int k = event.getUnicodeChar(0); + int k0 = k; + boolean sendCtrl = false; + boolean sendMeta = false; + + if (k != 0) { + if ((orgMetaState & HC_META_CTRL_ON) != 0) { + k = keyAsControl(k); + + if (k != k0) + sendCtrl = true; + + // send F1-F10 via CTRL-1 through CTRL-0 + if (!sendCtrl && sendFunctionKey(keyCode)) + return true; + } + else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { + sendMeta = true; + buffer.write(0x1b); + } + + if (sendMeta || sendCtrl) { + buffer.write(k); + return true; + } + } + } + + // handle meta and f-keys for full hardware keyboard + if (hardKeyboard && !hardKeyboardHidden && fullKeyboard()) { + int k = event.getUnicodeChar(orgMetaState & KeyEvent.META_SHIFT_ON); + int k0 = k; + + if (k != 0) { + if ((orgMetaState & HC_META_CTRL_ON) != 0) { + k = keyAsControl(k); + + if (k != k0) + buffer.write(k); + + return true; + } + else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { + buffer.write(0x1b); + buffer.write(k); + return true; + } + } + + if (sendFullSpecialKey(keyCode)) + return true; + } + + // try handling keymode shortcuts + if (hardKeyboard && !hardKeyboardHidden && + event.getRepeatCount() == 0) { + if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_RIGHT: + metaState |= META_SLASH; + return true; + + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaState |= META_TAB; + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + metaPress(META_SHIFT_ON); + return true; + + case KeyEvent.KEYCODE_ALT_LEFT: + metaPress(META_ALT_ON); + return true; + } + } + else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_LEFT: + metaState |= META_SLASH; + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + metaState |= META_TAB; + return true; + + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaPress(META_SHIFT_ON); + return true; + + case KeyEvent.KEYCODE_ALT_RIGHT: + metaPress(META_ALT_ON); + return true; + } + } + else { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_RIGHT: + case KeyEvent.KEYCODE_ALT_LEFT: + metaPress(META_ALT_ON); + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaPress(META_SHIFT_ON); + return true; + } + } + + // Handle hardware CTRL keys + if (keyCode == KeyEvent.KEYCODE_CTRL_LEFT || + keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) { + ctrlKeySpecial(); + return true; + } + } + + // look for special chars + switch (keyCode) { + case KEYCODE_ESCAPE: + buffer.write(0x1b); + return true; + + case KeyEvent.KEYCODE_TAB: + buffer.write("[tab]"); + return true; + + case KEYCODE_PAGE_DOWN: + buffer.write("[pgdown]"); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KEYCODE_PAGE_UP: + buffer.write("[pgup]"); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_MOVE_HOME: + buffer.write("[home]"); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_MOVE_END: + buffer.write("[end]"); // does not exist!! + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_CAMERA: + // check to see which shortcut the camera button triggers + String hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.CAMERA, + PreferenceConstants.HWBUTTON_SCREEN_CAPTURE); + return (handleShortcut(v, hwbuttonShortcut)); + + case KeyEvent.KEYCODE_VOLUME_UP: + // check to see which shortcut the volume button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.VOLUP, + PreferenceConstants.HWBUTTON_CTRL); + return (handleShortcut(v, hwbuttonShortcut)); + + case KeyEvent.KEYCODE_VOLUME_DOWN: + // check to see which shortcut the camera button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.VOLDN, + PreferenceConstants.HWBUTTON_TAB); + return (handleShortcut(v, hwbuttonShortcut)); + + case KeyEvent.KEYCODE_SEARCH: + // check to see which shortcut the search button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.SEARCH, + PreferenceConstants.HWBUTTON_ESC); + return (handleShortcut(v, hwbuttonShortcut)); + + case KeyEvent.KEYCODE_DEL: + if ((metaState & META_ALT_MASK) != 0) { + buffer.write("[insert]"); + } + else { + buffer.write("[backspace]"); + } + + metaState &= ~META_TRANSIENT; + return true; + + case KeyEvent.KEYCODE_ENTER: + buffer.write("[enter]"); + metaState &= ~META_TRANSIENT; + return true; + + case KeyEvent.KEYCODE_DPAD_LEFT: + if (selectingForCopy) { + selectionArea.decrementColumn(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.write("[home]"); + } + else { + buffer.write("[left]"); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_UP: + if (selectingForCopy) { + selectionArea.decrementRow(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.write("[pgup]"); + } + else { + buffer.write("[up]"); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_DOWN: + if (selectingForCopy) { + selectionArea.incrementRow(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.write("[pgdown]"); + } + else { + buffer.write("[down]"); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_RIGHT: + if (selectingForCopy) { + selectionArea.incrementColumn(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.write("[end]"); + } + else { + buffer.write("[right]"); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_CENTER: + ctrlKeySpecial(); + return true; + } + } + catch (IOException e) { + Log.e(TAG, "Problem while trying to handle an onKey() event", e); + + try { + bridge.transport.flush(); + } + catch (IOException ioe) { + Log.d(TAG, "Our transport was closed, dispatching disconnect event"); + bridge.dispatchDisconnect(false); + } + } + catch (NullPointerException npe) { + Log.d(TAG, "Input before connection established ignored."); + return true; + } + } + }; + public TN5250() { super(); }