package com.iiordanov.bVNC.input; import android.os.Handler; import android.os.SystemClock; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; import com.iiordanov.bVNC.MetaKeyBean; import com.iiordanov.bVNC.RdpCommunicator; import com.iiordanov.bVNC.RfbConnectable; import com.iiordanov.bVNC.RemoteCanvas; import com.iiordanov.tigervnc.rfb.UnicodeToKeysym; public class RemoteRdpKeyboard extends RemoteKeyboard { private final static String TAG = "RemoteRdpKeyboard"; protected RdpKeyboardMapper keyboardMapper; public RemoteRdpKeyboard (RfbConnectable r, RemoteCanvas v, Handler h) { super(r, v, h); context = v.getContext(); keyboardMapper = new RdpKeyboardMapper(); keyboardMapper.init(context); keyboardMapper.reset((RdpKeyboardMapper.KeyProcessingListener)r); } public boolean processLocalKeyEvent(int keyCode, KeyEvent evt, int additionalMetaState) { if (rfb != null && rfb.isInNormalProtocol()) { RemotePointer pointer = canvas.getPointer(); boolean down = (evt.getAction() == KeyEvent.ACTION_DOWN) || (evt.getAction() == KeyEvent.ACTION_MULTIPLE); 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; // Detect whether this event is coming from a default hardware keyboard. boolean defaultHardwareKbd = (evt.getDeviceId() == 0); if (!down) { switch (evt.getScanCode()) { case SCAN_LEFTCTRL: case SCAN_RIGHTCTRL: hardwareMetaState &= ~CTRL_MASK; break; } switch(keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: hardwareMetaState &= ~CTRL_MASK; break; } } else { // Look for standard scan-codes from hardware keyboards switch (evt.getScanCode()) { case SCAN_LEFTCTRL: case SCAN_RIGHTCTRL: hardwareMetaState |= CTRL_MASK; break; } switch(keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: hardwareMetaState |= CTRL_MASK; break; } } // Update the meta-state with writeKeyEvent. metaState = onScreenMetaState|hardwareMetaState|metaState; rfb.writeKeyEvent(keyCode, metaState, down); if (down) { lastDownMetaState = metaState; } else { lastDownMetaState = 0; } if (keyCode == 0 /*KEYCODE_UNKNOWN*/) { String s = evt.getCharacters(); if (s != null) { int numchars = s.length(); for (int i = 0; i < numchars; i++) { KeyEvent event = new KeyEvent(evt.getEventTime(), s.substring(i, i+1), KeyCharacterMap.FULL, 0); keyboardMapper.processAndroidKeyEvent(event); } } return true; } else { // Send the key to be processed through the KeyboardMapper. return keyboardMapper.processAndroidKeyEvent(evt); } } else { return false; } } public void sendMetaKey(MetaKeyBean meta) { RemotePointer pointer = canvas.getPointer(); int x = pointer.getX(); int y = pointer.getY(); if (meta.isMouseClick()) { //android.util.Log.e("RemoteRdpKeyboard", "is a mouse click"); int button = meta.getMouseButtons(); switch (button) { case RemoteVncPointer.MOUSE_BUTTON_LEFT: pointer.processPointerEvent(x, y, MotionEvent.ACTION_DOWN, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true, false, false, false, 0); break; case RemoteVncPointer.MOUSE_BUTTON_RIGHT: pointer.processPointerEvent(x, y, MotionEvent.ACTION_DOWN, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true, true, false, false, 0); break; case RemoteVncPointer.MOUSE_BUTTON_MIDDLE: pointer.processPointerEvent(x, y, MotionEvent.ACTION_DOWN, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true, false, true, false, 0); break; case RemoteVncPointer.MOUSE_BUTTON_SCROLL_UP: pointer.processPointerEvent(x, y, MotionEvent.ACTION_MOVE, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true, false, false, true, 0); break; case RemoteVncPointer.MOUSE_BUTTON_SCROLL_DOWN: pointer.processPointerEvent(x, y, MotionEvent.ACTION_MOVE, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, true, false, false, true, 1); break; } try { Thread.sleep(50); } catch (InterruptedException e) {} pointer.processPointerEvent(x, y, MotionEvent.ACTION_UP, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, false, false, false, false, 0); //rfb.writePointerEvent(x, y, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, button); //rfb.writePointerEvent(x, y, meta.getMetaFlags()|onScreenMetaState|hardwareMetaState, 0); } else if (meta.equals(MetaKeyBean.keyCtrlAltDel)) { // TODO: I should not need to treat this specially anymore. int savedMetaState = onScreenMetaState|hardwareMetaState; // Update the metastate rfb.writeKeyEvent(0, RemoteKeyboard.CTRL_MASK|RemoteKeyboard.ALT_MASK, false); keyboardMapper.processAndroidKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, 112)); keyboardMapper.processAndroidKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, 112)); rfb.writeKeyEvent(0, savedMetaState, false); } else { sendKeySym (meta.getKeySym(), meta.getMetaFlags()); } } }