package com.iiordanov.bVNC.input; import android.os.Handler; import android.view.InputDevice; import android.view.KeyEvent; import com.iiordanov.bVNC.MetaKeyBean; import com.iiordanov.bVNC.RfbConnectable; import com.iiordanov.bVNC.RemoteCanvas; import com.iiordanov.tigervnc.rfb.UnicodeToKeysym; public class RemoteVncKeyboard extends RemoteKeyboard { private final static String TAG = "RemoteKeyboard"; public static boolean rAltAsIsoL3Shift = false; public RemoteVncKeyboard (RfbConnectable r, RemoteCanvas v, Handler h, boolean rAltAsIsoL3Shift) { super(r, v, h); // Indicate we want Right Alt to be ISO L3 SHIFT if preferred. if (rAltAsIsoL3Shift) RemoteVncKeyboard.rAltAsIsoL3Shift = rAltAsIsoL3Shift; } public boolean processLocalKeyEvent(int keyCode, KeyEvent evt, int additionalMetaState) { android.util.Log.e(TAG, evt.toString() + " " + keyCode); if (rfb != null && rfb.isInNormalProtocol()) { RemotePointer pointer = canvas.getPointer(); boolean down = (evt.getAction() == KeyEvent.ACTION_DOWN) || (evt.getAction() == KeyEvent.ACTION_MULTIPLE); boolean unicode = false; int numchars = 1; int metaState = additionalMetaState | convertEventMetaState (evt); if (keyCode == KeyEvent.KEYCODE_MENU) return true; // Ignore menu key if (pointer.handleHardwareButtons(keyCode, evt, metaState|onScreenMetaState|hardwareMetaState)) return true; int key = 0, keysym = 0; // Detect whether this event is coming from a default hardware keyboard. boolean defaultHardwareKbd = (evt.getDeviceId() == 0); if (!down) { switch (evt.getScanCode()) { case SCAN_ESC: key = 0xff1b; break; case SCAN_LEFTCTRL: hardwareMetaState &= ~CTRL_MASK; break; case SCAN_RIGHTCTRL: hardwareMetaState &= ~RCTRL_MASK; break; case SCAN_F1: keysym = 0xffbe; break; case SCAN_F2: keysym = 0xffbf; break; case SCAN_F3: keysym = 0xffc0; break; case SCAN_F4: keysym = 0xffc1; break; case SCAN_F5: keysym = 0xffc2; break; case SCAN_F6: keysym = 0xffc3; break; case SCAN_F7: keysym = 0xffc4; break; case SCAN_F8: keysym = 0xffc5; break; case SCAN_F9: keysym = 0xffc6; break; case SCAN_F10: keysym = 0xffc7; break; } switch(keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: hardwareMetaState &= ~CTRL_MASK; break; case KeyEvent.KEYCODE_ALT_LEFT: // Leaving KeyEvent.KEYCODE_ALT_LEFT for symbol input on hardware keyboards. if (!defaultHardwareKbd) hardwareMetaState &= ~ALT_MASK; break; case KeyEvent.KEYCODE_ALT_RIGHT: hardwareMetaState &= ~RALT_MASK; break; } } switch(keyCode) { case KeyEvent.KEYCODE_BACK: keysym = 0xff1b; break; case KeyEvent.KEYCODE_DPAD_LEFT: keysym = 0xff51; break; case KeyEvent.KEYCODE_DPAD_UP: keysym = 0xff52; break; case KeyEvent.KEYCODE_DPAD_RIGHT: keysym = 0xff53; break; case KeyEvent.KEYCODE_DPAD_DOWN: keysym = 0xff54; break; case KeyEvent.KEYCODE_DEL: keysym = 0xff08; break; case KeyEvent.KEYCODE_ENTER: keysym = 0xff0d; break; case KeyEvent.KEYCODE_TAB: keysym = 0xff09; break; case 92 /* KEYCODE_PAGE_UP */: keysym = 0xff55; break; case 93 /* KEYCODE_PAGE_DOWN */: keysym = 0xff56; break; case 111 /* KEYCODE_ESCAPE */: keysym = 0xff1b; break; case 112 /* KEYCODE_FORWARD_DEL */: keysym = 0xffff; break; case 113 /* KEYCODE_CTRL_LEFT */: keysym = 0xffe3; break; case 114 /* KEYCODE_CTRL_RIGHT */: keysym = 0xffe4; break; case 115 /* KEYCODE_CAPS_LOCK */: keysym = 0xffe5; break; case 116 /* KEYCODE_SCROLL_LOCK */: keysym = 0xff14; break; case 117 /* KEYCODE_META_LEFT */: keysym = 0xffeb; break; case 118 /* KEYCODE_META_RIGHT */: keysym = 0xffec; break; case 120 /* KEYCODE_SYSRQ */: keysym = 0xff61; break; case 121 /* KEYCODE_BREAK */: keysym = 0xff6b; break; case 122 /* KEYCODE_MOVE_HOME */: keysym = 0xff50; break; case 123 /* KEYCODE_MOVE_END */: keysym = 0xff57; break; case 124 /* KEYCODE_INSERT */: keysym = 0xff63; break; case 131 /* KEYCODE_F1 */: keysym = 0xffbe; break; case 132 /* KEYCODE_F2 */: keysym = 0xffbf; break; case 133 /* KEYCODE_F3 */: keysym = 0xffc0; break; case 134 /* KEYCODE_F4 */: keysym = 0xffc1; break; case 135 /* KEYCODE_F5 */: keysym = 0xffc2; break; case 136 /* KEYCODE_F6 */: keysym = 0xffc3; break; case 137 /* KEYCODE_F7 */: keysym = 0xffc4; break; case 138 /* KEYCODE_F8 */: keysym = 0xffc5; break; case 139 /* KEYCODE_F9 */: keysym = 0xffc6; break; case 140 /* KEYCODE_F10 */: keysym = 0xffc7; break; case 141 /* KEYCODE_F11 */: keysym = 0xffc8; break; case 142 /* KEYCODE_F12 */: keysym = 0xffc9; break; case 143 /* KEYCODE_NUM_LOCK */: keysym = 0xff7f; break; case 0 /* KEYCODE_UNKNOWN */: if (evt.getCharacters() != null) { key = evt.getCharacters().charAt(0); keysym = UnicodeToKeysym.translate(key); numchars = evt.getCharacters().length(); unicode = true; } break; default: // Modifier handling is a bit tricky. Alt, Ctrl, and Super should be passed // through to the VNC server so that they get handled there, but strip // them from the character before retrieving the Unicode char from it. // Don't clear Shift, we still want uppercase characters. int metaMask = (0x00007000 | 0x00070000); // KeyEvent.META_CTRL_MASK | KeyEvent.META_META_MASK // When events come from a default hardware keyboard, we still want alt-key combinations to // give us symbols, so we only strip out KeyEvent.META_ALT_MASK only if we've decided to send // over ALT as a separate key modifier in convertEventMetaState(). if ((metaState & ALT_MASK) != 0 || (metaState & RALT_MASK) != 0) { metaMask |= 0x00000032; /* KeyEvent.META_ALT_MASK */ } KeyEvent copy = new KeyEvent(evt.getDownTime(), evt.getEventTime(), evt.getAction(), evt.getKeyCode(), evt.getRepeatCount(), evt.getMetaState() & ~metaMask, evt.getDeviceId(), evt.getScanCode()); key = copy.getUnicodeChar(); keysym = UnicodeToKeysym.translate(key); break; } if (down) { // Look for standard scan-codes from hardware keyboards switch (evt.getScanCode()) { case SCAN_ESC: keysym = 0xff1b; break; case SCAN_LEFTCTRL: hardwareMetaState |= CTRL_MASK; break; case SCAN_RIGHTCTRL: hardwareMetaState |= RCTRL_MASK; break; case SCAN_F1: keysym = 0xffbe; break; case SCAN_F2: keysym = 0xffbf; break; case SCAN_F3: keysym = 0xffc0; break; case SCAN_F4: keysym = 0xffc1; break; case SCAN_F5: keysym = 0xffc2; break; case SCAN_F6: keysym = 0xffc3; break; case SCAN_F7: keysym = 0xffc4; break; case SCAN_F8: keysym = 0xffc5; break; case SCAN_F9: keysym = 0xffc6; break; case SCAN_F10: keysym = 0xffc7; break; } switch(keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: hardwareMetaState |= CTRL_MASK; break; case KeyEvent.KEYCODE_ALT_LEFT: // Leaving KeyEvent.KEYCODE_ALT_LEFT for symbol input on hardware keyboards. if (!defaultHardwareKbd) hardwareMetaState |= ALT_MASK; break; case KeyEvent.KEYCODE_ALT_RIGHT: hardwareMetaState |= RALT_MASK; break; } } try { if (afterMenu) { afterMenu = false; if (!down && keysym != lastKeyDown) return true; } if (down) lastKeyDown = keysym; metaState = metaState|onScreenMetaState|hardwareMetaState; if (down) { lastDownMetaState = metaState; } else { lastDownMetaState = 0; } if (numchars == 1) { //android.util.Log.e(TAG, "Sending key. Down: " + down + ", key: " + key + ". keysym:" + keysym + ", metaState: " + metaState); rfb.writeKeyEvent(keysym, metaState, down); // If this is a unicode key, the up event will never come, so we artificially insert it. if (unicode) rfb.writeKeyEvent(keysym, metaState, false); } else if (numchars > 1) { for (int i = 0; i < numchars; i++) { key = evt.getCharacters().charAt(i); keysym = UnicodeToKeysym.translate(key); //android.util.Log.e(TAG, "Sending multiple keys. Key: " + key + " keysym: " + keysym + ", metaState: " + metaState); rfb.writeKeyEvent(keysym, metaState, true); rfb.writeKeyEvent(keysym, metaState, false); lastDownMetaState = 0; } } } catch (Exception e) { e.printStackTrace(); } return true; } return false; } public void sendMetaKey(MetaKeyBean meta) { RemotePointer pointer = canvas.getPointer(); int x = pointer.getX(); int y = pointer.getY(); if (meta.isMouseClick()) { rfb.writePointerEvent(x, y, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, meta.getMouseButtons()); rfb.writePointerEvent(x, y, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, 0); } else { rfb.writeKeyEvent(meta.getKeySym(), meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true); rfb.writeKeyEvent(meta.getKeySym(), meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, false); } } }