/* Input.java
* Component: ProperJavaRDP
*
* Revision: $Revision: 1.7 $
* Author: $Author: telliott $
* Date: $Date: 2005/09/27 14:15:39 $
*
* Copyright (c) 2005 Propero Limited
*
* Purpose: Handles input events and sends relevant input data
* to server
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* (See gpl.txt for details of the GNU General Public License.)
*
*/
package org.jopenray.rdp;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.Collections;
import java.util.Vector;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jopenray.rdp.keymapping.KeyCode;
import org.jopenray.rdp.keymapping.KeyCodeFileBased;
import org.jopenray.rdp.keymapping.KeyMapException;
public class Input {
protected static Logger logger = Logger.getLogger(Input.class);
public KeyCodeFileBased newKeyMapper = null;
public Vector<Integer> pressedKeys;
protected static boolean capsLockOn = false;
protected static boolean numLockOn = false;
protected static boolean scrollLockOn = false;
protected static boolean serverAltDown = false;
protected static boolean altDown = false;
protected static boolean ctrlDown = false;
protected static long last_mousemove = 0;
// Using this flag value (0x0001) seems to do nothing, and after running
// through other possible values, the RIGHT flag does not appear to be
// implemented
protected static final int KBD_FLAG_RIGHT = 0x0001;
protected static final int KBD_FLAG_EXT = 0x0100;
// QUIET flag is actually as below (not 0x1000 as in rdesktop)
protected static final int KBD_FLAG_QUIET = 0x200;
protected static final int KBD_FLAG_DOWN = 0x4000;
protected static final int KBD_FLAG_UP = 0x8000;
protected static final int RDP_KEYPRESS = 0;
protected static final int RDP_KEYRELEASE = KBD_FLAG_DOWN | KBD_FLAG_UP;
protected static final int MOUSE_FLAG_MOVE = 0x0800;
protected static final int MOUSE_FLAG_BUTTON1 = 0x1000;
protected static final int MOUSE_FLAG_BUTTON2 = 0x2000;
protected static final int MOUSE_FLAG_BUTTON3 = 0x4000;
protected static final int MOUSE_FLAG_BUTTON4 = 0x0280; // wheel up -
// rdesktop 1.2.0
protected static final int MOUSE_FLAG_BUTTON5 = 0x0380; // wheel down -
// rdesktop 1.2.0
protected static final int MOUSE_FLAG_DOWN = 0x8000;
protected static final int RDP_INPUT_SYNCHRONIZE = 0;
protected static final int RDP_INPUT_CODEPOINT = 1;
protected static final int RDP_INPUT_VIRTKEY = 2;
protected static final int RDP_INPUT_SCANCODE = 4;
protected static final int RDP_INPUT_MOUSE = 0x8001;
protected static int time = 0;
public KeyEvent lastKeyEvent = null;
public boolean modifiersValid = false;
public boolean keyDownWindows = false;
protected RDPCanvas canvas = null;
protected Rdp rdp = null;
KeyCode keys = null;
/**
* Create a new Input object with a given keymap object
*
* @param c
* Canvas on which to listen for input events
* @param r
* Rdp layer on which to send input messages
* @param k
* Key map to use in handling keyboard events
*/
public Input(RDPCanvas c, Rdp r, KeyCodeFileBased k) {
newKeyMapper = k;
canvas = c;
rdp = r;
if (Options.debug_keyboard)
logger.setLevel(Level.DEBUG);
addInputListeners();
pressedKeys = new Vector();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.setDefaultFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.setDefaultFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET);
}
/**
* Create a new Input object, using a keymap generated from a specified file
*
* @param c
* Canvas on which to listen for input events
* @param r
* Rdp layer on which to send input messages
* @param keymapFile
* Path to file containing keymap data
*/
public Input(RDPCanvas c, Rdp r, String keymapFile) {
try {
newKeyMapper = new KeyCodeFileBased(keymapFile);
} catch (KeyMapException kmEx) {
kmEx.printStackTrace();
}
canvas = c;
rdp = r;
if (Options.debug_keyboard)
logger.setLevel(Level.DEBUG);
addInputListeners();
pressedKeys = new Vector();
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.setDefaultFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.setDefaultFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET);
}
/**
* Add all relevant input listeners to the canvas
*/
public void addInputListeners() {
// System.out.println("Input.addInputListeners() on " + canvas);
canvas.addMouseListener(new RdesktopMouseAdapter());
canvas.addMouseMotionListener(new RdesktopMouseMotionAdapter());
canvas.addKeyListener(new RdesktopKeyAdapter());
canvas.addMouseWheelListener(new RdesktopMouseWheelAdapter());
}
/**
* Send a sequence of key actions to the server
*
* @param pressSequence
* String representing a sequence of key actions. Actions are
* represented as a pair of consecutive characters, the first
* character's value (cast to integer) being the scancode to
* send, the second (cast to integer) of the pair representing
* the action (0 == UP, 1 == DOWN, 2 == QUIET UP, 3 == QUIET
* DOWN).
*/
public void sendKeyPresses(String pressSequence) {
try {
String debugString = "Sending keypresses: ";
for (int i = 0; i < pressSequence.length(); i += 2) {
int scancode = pressSequence.charAt(i);
int action = pressSequence.charAt(i + 1);
int flags = 0;
if (action == KeyCodeFileBased.UP)
flags = RDP_KEYRELEASE;
else if (action == KeyCodeFileBased.DOWN)
flags = RDP_KEYPRESS;
else if (action == KeyCodeFileBased.QUIETUP)
flags = RDP_KEYRELEASE | KBD_FLAG_QUIET;
else if (action == KeyCodeFileBased.QUIETDOWN)
flags = RDP_KEYPRESS | KBD_FLAG_QUIET;
long t = getTime();
debugString += "(0x"
+ Integer.toHexString(scancode)
+ ", "
+ ((action == KeyCodeFileBased.UP || action == KeyCodeFileBased.QUIETUP) ? "up"
: "down")
+ ((flags & KBD_FLAG_QUIET) != 0 ? " quiet" : "")
+ " at " + t + ")";
sendScancode(t, flags, scancode);
}
if (pressSequence.length() > 0)
logger.debug(debugString);
} catch (Exception ex) {
return;
}
}
/**
* Retrieve the next "timestamp", by incrementing previous stamp (up to the
* maximum value of an integer, at which the timestamp is reverted to 1)
*
* @return New timestamp value
*/
public static int getTime() {
time++;
if (time == Integer.MAX_VALUE)
time = 1;
return time;
}
/**
* Handle loss of focus to the main canvas. Clears all depressed keys
* (sending release messages to the server.
*/
public void lostFocus() {
clearKeys();
modifiersValid = false;
}
/**
* Handle the main canvas gaining focus. Check locking key states.
*/
public void gainedFocus() {
doLockKeys(); // ensure lock key states are correct
}
/**
* Send a keyboard event to the server
*
* @param time
* Time stamp to identify this event
* @param flags
* Flags defining the nature of the event (eg:
* press/release/quiet/extended)
* @param scancode
* Scancode value identifying the key in question
*/
public void sendScancode(long time, int flags, int scancode) {
if (scancode == 0x38) { // be careful with alt
if ((flags & RDP_KEYRELEASE) != 0) {
// logger.info("Alt release, serverAltDown = " + serverAltDown);
serverAltDown = false;
}
if ((flags == RDP_KEYPRESS)) {
// logger.info("Alt press, serverAltDown = " + serverAltDown);
serverAltDown = true;
}
}
if ((scancode & KeyCode.SCANCODE_EXTENDED) != 0) {
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
scancode & ~KeyCode.SCANCODE_EXTENDED, 0);
} else
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, flags, scancode, 0);
}
/**
* Release any modifier keys that may be depressed.
*/
public void clearKeys() {
if (!modifiersValid)
return;
altDown = false;
ctrlDown = false;
if (lastKeyEvent == null)
return;
if (lastKeyEvent.isShiftDown())
sendScancode(getTime(), RDP_KEYRELEASE, 0x2a); // shift
if (lastKeyEvent.isAltDown() || serverAltDown) {
sendScancode(getTime(), RDP_KEYRELEASE, 0x38); // ALT
sendScancode(getTime(), RDP_KEYPRESS | KBD_FLAG_QUIET, 0x38); // ALT
sendScancode(getTime(), RDP_KEYRELEASE | KBD_FLAG_QUIET, 0x38); // l.alt
}
if (lastKeyEvent.isControlDown()) {
sendScancode(getTime(), RDP_KEYRELEASE, 0x1d); // l.ctrl
// sendScancode(getTime(), RDP_KEYPRESS | KBD_FLAG_QUIET, 0x1d); //
// Ctrl
// sendScancode(getTime(), RDP_KEYRELEASE | KBD_FLAG_QUIET, 0x1d);
// // ctrl
}
if (lastKeyEvent.isAltGraphDown())
sendScancode(getTime(), RDP_KEYRELEASE,
0x38 | KeyCode.SCANCODE_EXTENDED); // r.alt
}
/**
* Send keypress events for any modifier keys that are currently down
*/
public void setKeys() {
if (!modifiersValid)
return;
if (lastKeyEvent == null)
return;
if (lastKeyEvent.isShiftDown())
sendScancode(getTime(), RDP_KEYPRESS, 0x2a); // shift
if (lastKeyEvent.isAltDown())
sendScancode(getTime(), RDP_KEYPRESS, 0x38); // l.alt
if (lastKeyEvent.isControlDown())
sendScancode(getTime(), RDP_KEYPRESS, 0x1d); // l.ctrl
if (lastKeyEvent.isAltGraphDown())
sendScancode(getTime(), RDP_KEYPRESS,
0x38 | KeyCode.SCANCODE_EXTENDED); // r.alt
}
class RdesktopKeyAdapter extends KeyAdapter {
/**
* Construct an RdesktopKeyAdapter based on the parent KeyAdapter class
*/
public RdesktopKeyAdapter() {
super();
}
/**
* Handle a keyPressed event, sending any relevant keypresses to the
* server
*/
@Override
public void keyPressed(KeyEvent e) {
lastKeyEvent = e;
modifiersValid = true;
long time = getTime();
// Some java versions have keys that don't generate keyPresses -
// here we add the key so we can later check if it happened
pressedKeys.addElement(new Integer(e.getKeyCode()));
logger.debug("PRESSED keychar='" + e.getKeyChar() + "' keycode=0x"
+ Integer.toHexString(e.getKeyCode()) + " char='"
+ ((char) e.getKeyCode()) + "'");
if (rdp != null) {
if (!handleSpecialKeys(time, e, true)) {
sendKeyPresses(newKeyMapper.getKeyStrokes(e));
}
// sendScancode(time, RDP_KEYPRESS, keys.getScancode(e));
}
}
/**
* Handle a keyTyped event, sending any relevant keypresses to the
* server
*/
@Override
public void keyTyped(KeyEvent e) {
lastKeyEvent = e;
modifiersValid = true;
long time = getTime();
// Some java versions have keys that don't generate keyPresses -
// here we add the key so we can later check if it happened
pressedKeys.addElement(new Integer(e.getKeyCode()));
logger.debug("TYPED keychar='" + e.getKeyChar() + "' keycode=0x"
+ Integer.toHexString(e.getKeyCode()) + " char='"
+ ((char) e.getKeyCode()) + "'");
if (rdp != null) {
if (!handleSpecialKeys(time, e, true))
sendKeyPresses(newKeyMapper.getKeyStrokes(e));
// sendScancode(time, RDP_KEYPRESS, keys.getScancode(e));
}
}
/**
* Handle a keyReleased event, sending any relevent key events to the
* server
*/
@Override
public void keyReleased(KeyEvent e) {
// Some java versions have keys that don't generate keyPresses -
// we added the key to the vector in keyPressed so here we check for
// it
Integer keycode = new Integer(e.getKeyCode());
if (!pressedKeys.contains(keycode)) {
this.keyPressed(e);
}
pressedKeys.removeElement(keycode);
lastKeyEvent = e;
modifiersValid = true;
long time = getTime();
logger.debug("RELEASED keychar='" + e.getKeyChar() + "' keycode=0x"
+ Integer.toHexString(e.getKeyCode()) + " char='"
+ ((char) e.getKeyCode()) + "'");
if (rdp != null) {
if (!handleSpecialKeys(time, e, false))
sendKeyPresses(newKeyMapper.getKeyStrokes(e));
// sendScancode(time, RDP_KEYRELEASE, keys.getScancode(e));
}
}
}
/**
* Act on any keyboard shortcuts that a specified KeyEvent may describe
*
* @param time
* Time stamp for event to send to server
* @param e
* Keyboard event to be checked for shortcut keys
* @param pressed
* True if key was pressed, false if released
* @return True if a shortcut key combination was detected and acted upon,
* false otherwise
*/
public boolean handleShortcutKeys(long time, KeyEvent e, boolean pressed) {
if (!e.isAltDown())
return false;
if (!altDown)
return false; // all of the below have ALT on
switch (e.getKeyCode()) {
/*
* case KeyEvent.VK_M: if(pressed) ((RdesktopFrame_Localised)
* canvas.getParent()).toggleMenu(); break;
*/
case KeyEvent.VK_ENTER:
sendScancode(time, RDP_KEYRELEASE, 0x38);
altDown = false;
break;
/*
* The below case block handles "real" ALT+TAB events. Once the TAB in
* an ALT+TAB combination has been pressed, the TAB is sent to the
* server with the quiet flag on, as is the subsequent ALT-up.
*
* This ensures that the initial ALT press is "undone" by the server.
*
* --- Tom Elliott, 7/04/05
*/
case KeyEvent.VK_TAB: // Alt+Tab received, quiet combination
sendScancode(time, (pressed ? RDP_KEYPRESS : RDP_KEYRELEASE)
| KBD_FLAG_QUIET, 0x0f);
if (!pressed) {
sendScancode(time, RDP_KEYRELEASE | KBD_FLAG_QUIET, 0x38); // Release
// Alt
}
if (pressed)
logger.debug("Alt + Tab pressed, ignoring, releasing tab");
break;
case KeyEvent.VK_PAGE_UP: // Alt + PgUp = Alt-Tab
sendScancode(time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE, 0x0f); // TAB
if (pressed)
logger.debug("shortcut pressed: sent ALT+TAB");
break;
case KeyEvent.VK_PAGE_DOWN: // Alt + PgDown = Alt-Shift-Tab
if (pressed) {
sendScancode(time, RDP_KEYPRESS, 0x2a); // Shift
sendScancode(time, RDP_KEYPRESS, 0x0f); // TAB
logger.debug("shortcut pressed: sent ALT+SHIFT+TAB");
} else {
sendScancode(time, RDP_KEYRELEASE, 0x0f); // TAB
sendScancode(time, RDP_KEYRELEASE, 0x2a); // Shift
}
break;
case KeyEvent.VK_INSERT: // Alt + Insert = Alt + Esc
sendScancode(time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE, 0x01); // ESC
if (pressed)
logger.debug("shortcut pressed: sent ALT+ESC");
break;
case KeyEvent.VK_HOME: // Alt + Home = Ctrl + Esc (Start)
if (pressed) {
sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
sendScancode(time, RDP_KEYPRESS, 0x1d); // left Ctrl
sendScancode(time, RDP_KEYPRESS, 0x01); // Esc
logger.debug("shortcut pressed: sent CTRL+ESC (Start)");
} else {
sendScancode(time, RDP_KEYRELEASE, 0x01); // escape
sendScancode(time, RDP_KEYRELEASE, 0x1d); // left ctrl
// sendScancode(time,RDP_KEYPRESS,0x38); // ALT
}
break;
case KeyEvent.VK_END: // Ctrl+Alt+End = Ctrl+Alt+Del
if (ctrlDown) {
sendScancode(time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE,
0x53 | KeyCode.SCANCODE_EXTENDED); // DEL
if (pressed)
logger.debug("shortcut pressed: sent CTRL+ALT+DEL");
}
break;
case KeyEvent.VK_DELETE: // Alt + Delete = Menu
if (pressed) {
sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
// need to do another press and release to shift focus from
// to/from menu bar
sendScancode(time, RDP_KEYPRESS, 0x38); // ALT
sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
sendScancode(time, RDP_KEYPRESS,
0x5d | KeyCode.SCANCODE_EXTENDED); // Menu
logger.debug("shortcut pressed: sent MENU");
} else {
sendScancode(time, RDP_KEYRELEASE,
0x5d | KeyCode.SCANCODE_EXTENDED); // Menu
// sendScancode(time,RDP_KEYPRESS,0x38); // ALT
}
break;
case KeyEvent.VK_SUBTRACT: // Ctrl + Alt + Minus (on NUM KEYPAD) =
// Alt+PrtSc
if (ctrlDown) {
if (pressed) {
sendScancode(time, RDP_KEYRELEASE, 0x1d); // Ctrl
sendScancode(time, RDP_KEYPRESS,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
logger.debug("shortcut pressed: sent ALT+PRTSC");
} else {
sendScancode(time, RDP_KEYRELEASE,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
sendScancode(time, RDP_KEYPRESS, 0x1d); // Ctrl
}
}
break;
case KeyEvent.VK_ADD: // Ctrl + ALt + Plus (on NUM KEYPAD) = PrtSc
case KeyEvent.VK_EQUALS: // for laptops that can't do Ctrl-Alt+Plus
if (ctrlDown) {
if (pressed) {
sendScancode(time, RDP_KEYRELEASE, 0x38); // Alt
sendScancode(time, RDP_KEYRELEASE, 0x1d); // Ctrl
sendScancode(time, RDP_KEYPRESS,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
logger.debug("shortcut pressed: sent PRTSC");
} else {
sendScancode(time, RDP_KEYRELEASE,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
sendScancode(time, RDP_KEYPRESS, 0x1d); // Ctrl
sendScancode(time, RDP_KEYPRESS, 0x38); // Alt
}
}
break;
case KeyEvent.VK_MINUS: // for laptops that can't do Ctrl+Alt+Minus
if (ctrlDown) {
if (pressed) {
sendScancode(time, RDP_KEYRELEASE, 0x1d); // Ctrl
sendScancode(time, RDP_KEYPRESS,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
logger.debug("shortcut pressed: sent ALT+PRTSC");
} else {
sendScancode(time, RDP_KEYRELEASE,
0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
sendScancode(time, RDP_KEYPRESS, 0x1d); // Ctrl
}
}
break;
default:
return false;
}
return true;
}
/**
* Deal with modifier keys as control, alt or caps lock
*
* @param time
* Time stamp for key event
* @param e
* Key event to check for special keys
* @param pressed
* True if key was pressed, false if released
* @return
*/
public boolean handleSpecialKeys(long time, KeyEvent e, boolean pressed) {
if (handleShortcutKeys(time, e, pressed))
return true;
switch (e.getKeyCode()) {
case KeyEvent.VK_CONTROL:
ctrlDown = pressed;
return false;
case KeyEvent.VK_ALT:
altDown = pressed;
return false;
case KeyEvent.VK_CAPS_LOCK:
if (pressed && Options.caps_sends_up_and_down)
capsLockOn = !capsLockOn;
if (!Options.caps_sends_up_and_down) {
if (pressed)
capsLockOn = true;
else
capsLockOn = false;
}
return false;
case KeyEvent.VK_NUM_LOCK:
if (pressed)
numLockOn = !numLockOn;
return false;
case KeyEvent.VK_SCROLL_LOCK:
if (pressed)
scrollLockOn = !scrollLockOn;
return false;
case KeyEvent.VK_PAUSE: // untested
if (pressed) { // E1 1D 45 E1 9D C5
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0xe1, 0);
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0x1d, 0);
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0x45, 0);
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0xe1, 0);
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0x9d, 0);
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYPRESS,
0xc5, 0);
} else { // release left ctrl
rdp.sendInput((int) time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
0x1d, 0);
}
break;
// Removed, as java on MacOS send the option key as VK_META
/*
* case KeyEvent.VK_META: // Windows key logger.debug("Windows key
* received"); if(pressed){ sendScancode(time, RDP_KEYPRESS, 0x1d); //
* left ctrl sendScancode(time, RDP_KEYPRESS, 0x01); // escape } else{
* sendScancode(time, RDP_KEYRELEASE, 0x01); // escape
* sendScancode(time, RDP_KEYRELEASE, 0x1d); // left ctrl } break;
*/
// haven't found a way to detect BREAK key in java - VK_BREAK doesn't
// exist
/*
* case KeyEvent.VK_BREAK: if(pressed){
* sendScancode(time,RDP_KEYPRESS,(KeyCode.SCANCODE_EXTENDED | 0x46));
* sendScancode(time,RDP_KEYPRESS,(KeyCode.SCANCODE_EXTENDED | 0xc6)); }
* // do nothing on release break;
*/
default:
return false; // not handled - use sendScancode instead
}
return true; // handled - no need to use sendScancode
}
/**
* Turn off any locking key, check states if available
*/
public void triggerReadyToSend() {
capsLockOn = false;
numLockOn = false;
scrollLockOn = false;
doLockKeys(); // ensure lock key states are correct
}
protected void doLockKeys() {
if (!Options.useLockingKeyState)
return;
if (Constants.OS == Constants.LINUX)
return; // broken for linux
if (Constants.OS == Constants.MAC)
return; // unsupported operation for mac
logger.debug("doLockKeys");
try {
Toolkit tk = Toolkit.getDefaultToolkit();
if (tk.getLockingKeyState(KeyEvent.VK_CAPS_LOCK) != capsLockOn) {
capsLockOn = !capsLockOn;
logger.debug("CAPS LOCK toggle");
sendScancode(getTime(), RDP_KEYPRESS, 0x3a);
sendScancode(getTime(), RDP_KEYRELEASE, 0x3a);
}
if (tk.getLockingKeyState(KeyEvent.VK_NUM_LOCK) != numLockOn) {
numLockOn = !numLockOn;
logger.debug("NUM LOCK toggle");
sendScancode(getTime(), RDP_KEYPRESS, 0x45);
sendScancode(getTime(), RDP_KEYRELEASE, 0x45);
}
if (tk.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK) != scrollLockOn) {
scrollLockOn = !scrollLockOn;
logger.debug("SCROLL LOCK toggle");
sendScancode(getTime(), RDP_KEYPRESS, 0x46);
sendScancode(getTime(), RDP_KEYRELEASE, 0x46);
}
} catch (Exception e) {
Options.useLockingKeyState = false;
}
}
/**
* Handle pressing of the middle mouse button, sending relevent event data
* to the server
*
* @param e
* MouseEvent detailing circumstances under which middle button
* was pressed
*/
protected void middleButtonPressed(MouseEvent e) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3
| MOUSE_FLAG_DOWN, e.getX(), e.getY());
}
/**
* Handle release of the middle mouse button, sending relevent event data to
* the server
*
* @param e
* MouseEvent detailing circumstances under which middle button
* was released
*/
protected void middleButtonReleased(MouseEvent e) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e.getX(), e
.getY());
}
class RdesktopMouseAdapter extends MouseAdapter {
public RdesktopMouseAdapter() {
super();
}
@Override
public void mousePressed(MouseEvent e) {
// System.out.println("RdesktopMouseAdapter.mousePressed():" + e);
int time = getTime();
if (rdp != null) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
logger.debug("Mouse Button 1 Pressed.");
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1
| MOUSE_FLAG_DOWN, e.getX(), e.getY());
} else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
logger.debug("Mouse Button 3 Pressed.");
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2
| MOUSE_FLAG_DOWN, e.getX(), e.getY());
} else if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
logger.debug("Middle Mouse Button Pressed.");
middleButtonPressed(e);
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
int time = getTime();
if (rdp != null) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, e
.getX(), e.getY());
} else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, e
.getX(), e.getY());
} else if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e
.getX(), e.getY());
}
}
}
}
class RdesktopMouseMotionAdapter extends MouseMotionAdapter {
public RdesktopMouseMotionAdapter() {
super();
}
@Override
public void mouseMoved(MouseEvent e) {
int time = getTime();
if (rdp != null) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e.getX(),
e.getY());
}
}
@Override
public void mouseDragged(MouseEvent e) {
int time = getTime();
// if(logger.isInfoEnabled()) logger.info("mouseMoved to
// "+e.getX()+", "+e.getY()+" at "+time);
if (rdp != null) {
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e.getX(),
e.getY());
}
}
}
private class RdesktopMouseWheelAdapter implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
int time = getTime();
if (rdp != null) {
if (e.getWheelRotation() < 0) { // up
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4
| MOUSE_FLAG_DOWN, e.getX(), e.getY());
} else { // down
rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5
| MOUSE_FLAG_DOWN, e.getX(), e.getY());
}
}
}
}
}