mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2026-02-16 02:20:42 +00:00
Replace keyboard and mouse handler with evdev
This commit is contained in:
@@ -20,6 +20,8 @@ import com.limelight.settings.PreferencesManager.Preferences.Resolution;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
@@ -46,7 +48,7 @@ public class Limelight implements NvConnectionListener {
|
||||
/*
|
||||
* Creates a connection to the host and starts up the stream.
|
||||
*/
|
||||
private void startUp(StreamConfiguration streamConfig, boolean fullscreen) {
|
||||
private void startUp(StreamConfiguration streamConfig, List<String> inputs) {
|
||||
conn = new NvConnection(host, this, streamConfig);
|
||||
conn.start(PlatformBinding.getDeviceName(), null,
|
||||
VideoDecoderRenderer.FLAG_PREFER_QUALITY,
|
||||
@@ -143,7 +145,7 @@ public class Limelight implements NvConnectionListener {
|
||||
//TODO: make this less jank
|
||||
private static void parseCommandLine(String[] args) {
|
||||
String host = null;
|
||||
boolean fullscreen = false;
|
||||
List<String> inputs = new ArrayList<String>();
|
||||
boolean pair = false;
|
||||
int resolution = 720;
|
||||
int refresh = 30;
|
||||
@@ -157,10 +159,16 @@ public class Limelight implements NvConnectionListener {
|
||||
System.out.println("Syntax error: hostname or ip address expected after -host");
|
||||
System.exit(3);
|
||||
}
|
||||
} else if (args[i].equals("-input")) {
|
||||
if (i + 1 < args.length) {
|
||||
inputs.add(args[i+1]);
|
||||
i++;
|
||||
} else {
|
||||
System.out.println("Syntax error: input device expected after -input");
|
||||
System.exit(3);
|
||||
}
|
||||
} else if (args[i].equals("-pair")) {
|
||||
pair = true;
|
||||
} else if (args[i].equals("-fs")) {
|
||||
fullscreen = true;
|
||||
} else if (args[i].equals("-720")) {
|
||||
resolution = 720;
|
||||
} else if (args[i].equals("-1080")) {
|
||||
@@ -195,7 +203,7 @@ public class Limelight implements NvConnectionListener {
|
||||
|
||||
Limelight limelight = new Limelight(host);
|
||||
if (!pair)
|
||||
limelight.startUp(streamConfig, fullscreen);
|
||||
limelight.startUp(streamConfig, inputs);
|
||||
else
|
||||
limelight.pair();
|
||||
}
|
||||
|
||||
252
src/com/limelight/input/EvdevHandler.java
Normal file
252
src/com/limelight/input/EvdevHandler.java
Normal file
@@ -0,0 +1,252 @@
|
||||
package com.limelight.input;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.KeyboardPacket;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
/**
|
||||
* Class that handles keyboard input using the Evdev interface
|
||||
* @author Iwan Timmer
|
||||
*/
|
||||
public class EvdevHandler implements Runnable {
|
||||
|
||||
private static KeyboardTranslator translator;
|
||||
|
||||
private static final short KEY_CODES[] = {
|
||||
0, //KeyEvent.VK_RESERVED
|
||||
KeyEvent.VK_ESCAPE,
|
||||
KeyEvent.VK_1,
|
||||
KeyEvent.VK_2,
|
||||
KeyEvent.VK_3,
|
||||
KeyEvent.VK_4,
|
||||
KeyEvent.VK_5,
|
||||
KeyEvent.VK_6,
|
||||
KeyEvent.VK_7,
|
||||
KeyEvent.VK_8,
|
||||
KeyEvent.VK_9,
|
||||
KeyEvent.VK_0,
|
||||
KeyEvent.VK_MINUS,
|
||||
KeyEvent.VK_EQUALS,
|
||||
KeyEvent.VK_BACK_SPACE,
|
||||
KeyEvent.VK_TAB,
|
||||
KeyEvent.VK_Q,
|
||||
KeyEvent.VK_W,
|
||||
KeyEvent.VK_E,
|
||||
KeyEvent.VK_R,
|
||||
KeyEvent.VK_T,
|
||||
KeyEvent.VK_Y,
|
||||
KeyEvent.VK_U,
|
||||
KeyEvent.VK_I,
|
||||
KeyEvent.VK_O,
|
||||
KeyEvent.VK_P,
|
||||
0, //KeyEvent.VK_LEFTBRACE,
|
||||
0, //KeyEvent.VK_RIGHTBRACE,
|
||||
KeyEvent.VK_ENTER,
|
||||
KeyEvent.VK_CONTROL, // Left control */
|
||||
KeyEvent.VK_A,
|
||||
KeyEvent.VK_S,
|
||||
KeyEvent.VK_D,
|
||||
KeyEvent.VK_F,
|
||||
KeyEvent.VK_G,
|
||||
KeyEvent.VK_H,
|
||||
KeyEvent.VK_J,
|
||||
KeyEvent.VK_K,
|
||||
KeyEvent.VK_L,
|
||||
KeyEvent.VK_SEMICOLON,
|
||||
0, //KeyEvent.VK_APOSTROPHE,
|
||||
0, //KeyEvent.VK_GRAVE,
|
||||
0, //KeyEvent.VK_LEFTSHIFT,
|
||||
0, //KeyEvent.VK_BACKSLASH,
|
||||
KeyEvent.VK_Z,
|
||||
KeyEvent.VK_X,
|
||||
KeyEvent.VK_C,
|
||||
KeyEvent.VK_V,
|
||||
KeyEvent.VK_B,
|
||||
KeyEvent.VK_N,
|
||||
KeyEvent.VK_M,
|
||||
KeyEvent.VK_COMMA,
|
||||
0, //KeyEvent.VK_DOT,
|
||||
KeyEvent.VK_SLASH,
|
||||
0, //KeyEvent.VK_RIGHTSHIFT,
|
||||
0, //KeyEvent.VK_KPASTERISK,
|
||||
0, //KeyEvent.VK_LEFTALT,
|
||||
KeyEvent.VK_SPACE,
|
||||
0, //KeyEvent.VK_CAPSLOCK,
|
||||
KeyEvent.VK_F1,
|
||||
KeyEvent.VK_F2,
|
||||
KeyEvent.VK_F3,
|
||||
KeyEvent.VK_F4,
|
||||
KeyEvent.VK_F5,
|
||||
KeyEvent.VK_F6,
|
||||
KeyEvent.VK_F7,
|
||||
KeyEvent.VK_F8,
|
||||
KeyEvent.VK_F9,
|
||||
KeyEvent.VK_F10,
|
||||
KeyEvent.VK_NUM_LOCK,
|
||||
KeyEvent.VK_SCROLL_LOCK,
|
||||
KeyEvent.VK_NUMPAD7,
|
||||
KeyEvent.VK_NUMPAD8,
|
||||
KeyEvent.VK_NUMPAD9,
|
||||
0, //KeyEvent.VK_NUMPAD_MINUS,
|
||||
KeyEvent.VK_NUMPAD4,
|
||||
KeyEvent.VK_NUMPAD5,
|
||||
KeyEvent.VK_NUMPAD6,
|
||||
0, //KeyEvent.VK_NUMPADPLUS,
|
||||
KeyEvent.VK_NUMPAD1,
|
||||
KeyEvent.VK_NUMPAD2,
|
||||
KeyEvent.VK_NUMPAD3,
|
||||
KeyEvent.VK_NUMPAD0,
|
||||
0, //KeyEvent.VK_NUMPADDOT,
|
||||
0,
|
||||
0, //KeyEvent.VK_ZENKAKUHANKAKU,
|
||||
0, //KeyEvent.VK_102ND,
|
||||
KeyEvent.VK_F11,
|
||||
KeyEvent.VK_F12,
|
||||
0, //KeyEvent.VK_RO,
|
||||
KeyEvent.VK_KATAKANA,
|
||||
KeyEvent.VK_HIRAGANA,
|
||||
0, //KeyEvent.VK_HENKAN,
|
||||
0, //KeyEvent.VK_KATAKANAHIRAGANA,
|
||||
0, //KeyEvent.VK_MUHENKAN,
|
||||
0, //KeyEvent.VK_KPJPCOMMA,
|
||||
0, //KeyEvent.VK_KPENTER,
|
||||
0, //KeyEvent.VK_RIGHTCTRL,
|
||||
0, //KeyEvent.VK_KPSLASH,
|
||||
0, //KeyEvent.VK_SYSRQ,
|
||||
0, //KeyEvent.VK_RIGHTALT,
|
||||
0, //KeyEvent.VK_LINEFEED,
|
||||
KeyEvent.VK_HOME,
|
||||
KeyEvent.VK_UP,
|
||||
KeyEvent.VK_PAGE_UP,
|
||||
KeyEvent.VK_LEFT,
|
||||
KeyEvent.VK_RIGHT,
|
||||
KeyEvent.VK_END,
|
||||
KeyEvent.VK_DOWN,
|
||||
KeyEvent.VK_PAGE_DOWN,
|
||||
KeyEvent.VK_INSERT,
|
||||
KeyEvent.VK_DELETE,
|
||||
0, //KeyEvent.VK_MACRO,
|
||||
0, //KeyEvent.VK_MUTE,
|
||||
0, //KeyEvent.VK_VOLUMEDOWN,
|
||||
0, //KeyEvent.VK_VOLUMEUP,
|
||||
0, //KeyEvent.VK_POWER, /* SC System Power Down */
|
||||
0, //KeyEvent.VK_KPEQUAL,
|
||||
0, //KeyEvent.VK_KPPLUSMINUS,
|
||||
KeyEvent.VK_PAUSE,
|
||||
0, //KeyEvent.VK_SCALE, /* AL Compiz Scale (Expose) */
|
||||
};
|
||||
|
||||
private static final int STRUCT_SIZE_BYTES = 24;
|
||||
|
||||
/* GFE's prefix for every key code */
|
||||
public static final short KEY_PREFIX = (short) 0x80;
|
||||
|
||||
/* Event types */
|
||||
public static final short EV_KEY = 0x01;
|
||||
public static final short EV_REL = 0x02;
|
||||
|
||||
public static final short REL_X = 0x00;
|
||||
public static final short REL_Y = 0x01;
|
||||
|
||||
public static final short BTN_LEFT = 0x110;
|
||||
public static final short BTN_RIGHT = 0x111;
|
||||
public static final short BTN_MIDDLE = 0x112;
|
||||
|
||||
/* Events */
|
||||
public static final int KEY_RELEASED = 0;
|
||||
public static final int KEY_PRESSED = 1;
|
||||
|
||||
private NvConnection conn;
|
||||
private FileChannel deviceInput;
|
||||
private ByteBuffer inputBuffer;
|
||||
|
||||
public EvdevHandler(NvConnection conn, String device) throws FileNotFoundException {
|
||||
this.conn = conn;
|
||||
FileInputStream in = new FileInputStream(device);
|
||||
deviceInput = in.getChannel();
|
||||
inputBuffer = ByteBuffer.allocate(STRUCT_SIZE_BYTES);
|
||||
inputBuffer.order(ByteOrder.nativeOrder());
|
||||
|
||||
translator = new KeyboardTranslator(conn);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Thread thread = new Thread(this);
|
||||
thread.setDaemon(true);
|
||||
thread.setName("Input - Receiver");
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void parseEvent(ByteBuffer buffer) {
|
||||
long time_sec = buffer.getLong();
|
||||
long time_usec = buffer.getLong();
|
||||
short type = buffer.getShort();
|
||||
short code = buffer.getShort();
|
||||
int value = buffer.getInt();
|
||||
|
||||
if (type==EV_KEY) {
|
||||
if (code<KEY_CODES.length) {
|
||||
short gfCode = translator.translate(KEY_CODES[code]);
|
||||
|
||||
if (value==KEY_PRESSED)
|
||||
conn.sendKeyboardInput(gfCode, KeyboardPacket.KEY_DOWN, (byte) 0);
|
||||
else if (value==KEY_RELEASED)
|
||||
conn.sendKeyboardInput(gfCode, KeyboardPacket.KEY_UP, (byte) 0);
|
||||
} else {
|
||||
byte mouseButton = 0;
|
||||
|
||||
switch (code) {
|
||||
case BTN_LEFT:
|
||||
mouseButton = MouseButtonPacket.BUTTON_1;
|
||||
break;
|
||||
case BTN_MIDDLE:
|
||||
mouseButton = MouseButtonPacket.BUTTON_2;
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
mouseButton = MouseButtonPacket.BUTTON_3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mouseButton>0) {
|
||||
if (value==KEY_PRESSED)
|
||||
conn.sendMouseButtonDown(mouseButton);
|
||||
else if (value==KEY_RELEASED)
|
||||
conn.sendMouseButtonUp(mouseButton);
|
||||
}
|
||||
}
|
||||
} else if (type==EV_REL) {
|
||||
switch (code) {
|
||||
case REL_X:
|
||||
conn.sendMouseMove((short) value, (short) 0);
|
||||
break;
|
||||
case REL_Y:
|
||||
conn.sendMouseMove((short) 0, (short) value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
while(inputBuffer.hasRemaining())
|
||||
deviceInput.read(inputBuffer);
|
||||
|
||||
inputBuffer.flip();
|
||||
parseEvent(inputBuffer);
|
||||
inputBuffer.clear();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package com.limelight.input;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
|
||||
import com.limelight.gui.StreamFrame;
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.KeyboardPacket;
|
||||
|
||||
/**
|
||||
* Class that handles keyboard input
|
||||
* @author Diego Waxemberg
|
||||
*/
|
||||
public class KeyboardHandler implements KeyListener {
|
||||
|
||||
private static KeyboardTranslator translator;
|
||||
private StreamFrame parent;
|
||||
|
||||
/**
|
||||
* Constructs a new keyboard listener that will send key events to the specified connection
|
||||
* and belongs to the specified frame
|
||||
* @param conn the connection to send key events to
|
||||
* @param parent the frame that owns this handler
|
||||
*/
|
||||
public KeyboardHandler(NvConnection conn, StreamFrame parent) {
|
||||
translator = new KeyboardTranslator(conn);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a key is pressed and will send that key-down event to the host
|
||||
* @param event the key-down event
|
||||
*/
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event) {
|
||||
short keyMap = translator.translate(event.getKeyCode());
|
||||
|
||||
byte modifier = 0x0;
|
||||
|
||||
int modifiers = event.getModifiersEx();
|
||||
if ((modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_SHIFT;
|
||||
}
|
||||
if ((modifiers & KeyEvent.CTRL_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_CTRL;
|
||||
}
|
||||
if ((modifiers & KeyEvent.ALT_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_ALT;
|
||||
}
|
||||
|
||||
if ((modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0 &&
|
||||
(modifiers & KeyEvent.ALT_DOWN_MASK) != 0 &&
|
||||
(modifiers & KeyEvent.CTRL_DOWN_MASK) != 0 &&
|
||||
event.getKeyCode() == KeyEvent.VK_Q) {
|
||||
System.out.println("quitting");
|
||||
parent.close();
|
||||
} else if (
|
||||
(modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0 &&
|
||||
(modifiers & KeyEvent.ALT_DOWN_MASK) != 0 &&
|
||||
(modifiers & KeyEvent.CTRL_DOWN_MASK) != 0) {
|
||||
parent.freeMouse();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
translator.sendKeyDown(keyMap, modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a key is released and will send that key-up event to the host
|
||||
* @param event the key-up event
|
||||
*/
|
||||
@Override
|
||||
public void keyReleased(KeyEvent event) {
|
||||
int modifiers = event.getModifiersEx();
|
||||
|
||||
if ((modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0 ||
|
||||
(modifiers & KeyEvent.ALT_DOWN_MASK) != 0 ||
|
||||
(modifiers & KeyEvent.CTRL_DOWN_MASK) != 0) {
|
||||
parent.captureMouse();
|
||||
}
|
||||
|
||||
short keyMap = translator.translate(event.getKeyCode());
|
||||
|
||||
byte modifier = 0x0;
|
||||
|
||||
if ((modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_SHIFT;
|
||||
}
|
||||
if ((modifiers & KeyEvent.CTRL_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_CTRL;
|
||||
}
|
||||
if ((modifiers & KeyEvent.ALT_DOWN_MASK) != 0) {
|
||||
modifier |= KeyboardPacket.MODIFIER_ALT;
|
||||
}
|
||||
|
||||
translator.sendKeyUp(keyMap, modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented
|
||||
* @param event unused
|
||||
*/
|
||||
@Override
|
||||
public void keyTyped(KeyEvent event) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package com.limelight.input;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import com.limelight.gui.StreamFrame;
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
|
||||
/**
|
||||
* Handles mouse input and sends them via the connection to the host
|
||||
* @author Diego Waxemberg
|
||||
*/
|
||||
public class MouseHandler implements MouseListener, MouseMotionListener {
|
||||
private NvConnection conn;
|
||||
private Robot robot;
|
||||
private Dimension size;
|
||||
private StreamFrame parent;
|
||||
private int lastX = 0;
|
||||
private int lastY = 0;
|
||||
private boolean captureMouse = true;
|
||||
|
||||
private final double mouseThresh = 0.45;
|
||||
|
||||
/**
|
||||
* Constructs a new handler for the specified connection and belonging to the specified frame
|
||||
* @param conn the connection to which mouse events will be sent
|
||||
* @param parent the frame that owns this handler
|
||||
*/
|
||||
public MouseHandler(NvConnection conn, StreamFrame parent) {
|
||||
this.conn = conn;
|
||||
this.parent = parent;
|
||||
try {
|
||||
this.robot = new Robot();
|
||||
} catch (AWTException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
size = new Dimension();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the mouse, that is stops capturing events and allows it to move freely
|
||||
*/
|
||||
public void free() {
|
||||
captureMouse = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts capturing mouse events and limits its motion
|
||||
*/
|
||||
public void capture() {
|
||||
moveMouse((int)parent.getLocationOnScreen().getX() + (size.width/2),
|
||||
(int)parent.getLocationOnScreen().getY() + (size.height/2));
|
||||
captureMouse = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only used to hide the cursor when the user clicks back into the frame.
|
||||
* <br>The event is not sent to the host
|
||||
* @param e click event used to know that the cursor should now be hidden
|
||||
*/
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
parent.hideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented
|
||||
* @param e Unused
|
||||
*/
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the mouse leaves the frame.
|
||||
* <br>If this happens when we are capturing the mouse, the mouse is moved back to the center of the frame.
|
||||
* @param e the event created by the mouse leaving the frame
|
||||
*/
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
checkBoundaries(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a mouse button is pressed.
|
||||
* <br>The button pressed is sent to the host if we are capturing the mouse.
|
||||
* @param e event containing the mouse button that was pressed
|
||||
*/
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
byte mouseButton = 0x0;
|
||||
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_1;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isMiddleMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_2;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_3;
|
||||
}
|
||||
|
||||
if (mouseButton > 0) {
|
||||
conn.sendMouseButtonDown(mouseButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a mouse button is released.
|
||||
* <br>The button released is sent to the host if we are capturing the mouse.
|
||||
* @param e event containing the mouse button that was released
|
||||
*/
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
byte mouseButton = 0x0;
|
||||
|
||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_1;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isMiddleMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_2;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
mouseButton = MouseButtonPacket.BUTTON_3;
|
||||
}
|
||||
|
||||
if (mouseButton > 0) {
|
||||
conn.sendMouseButtonUp(mouseButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the mouse is dragged, that is moved while a button is held down.
|
||||
* <br>This method simply calls the <code>mouseMoved()</code> method because GFE handles movements all the same
|
||||
* when a button is held down or not.
|
||||
*/
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
mouseMoved(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the mouse is moved.
|
||||
* <br>The change in position is calculated and sent to the host.
|
||||
* <br>If the mouse moves outside a certain boundary, the mouse is moved back to the center- this gives the user
|
||||
* the illusion that they are controlling the mouse they see rather than their own.
|
||||
* @param e the mouse move event containing the new location of the mouse
|
||||
*/
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (captureMouse) {
|
||||
Point mouse = e.getLocationOnScreen();
|
||||
int x = (int)mouse.getX();
|
||||
int y = (int)mouse.getY();
|
||||
conn.sendMouseMove((short)(x - lastX), (short)(y - lastY));
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
|
||||
checkBoundaries(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the mouse has moved outside the boundaries.
|
||||
* If so, the mouse is moved back to the center.
|
||||
*/
|
||||
private void checkBoundaries(MouseEvent e) {
|
||||
parent.getSize(size);
|
||||
|
||||
int leftEdge = (int) parent.getLocationOnScreen().getX();
|
||||
int rightEdge = leftEdge + size.width;
|
||||
int upperEdge = (int) parent.getLocationOnScreen().getY();
|
||||
int lowerEdge = upperEdge + size.height;
|
||||
|
||||
Point mouse = e.getLocationOnScreen();
|
||||
|
||||
double xThresh = (size.width * mouseThresh);
|
||||
double yThresh = (size.height * mouseThresh);
|
||||
|
||||
int newX = (int)mouse.getX();
|
||||
int newY = (int)mouse.getY();
|
||||
boolean shouldMoveMouse = false;
|
||||
|
||||
if (mouse.getX() < leftEdge + xThresh || mouse.getX() > rightEdge - xThresh) {
|
||||
newX = (leftEdge + rightEdge) / 2;
|
||||
shouldMoveMouse = true;
|
||||
}
|
||||
if (mouse.getY() < upperEdge + yThresh || mouse.getY() > lowerEdge - yThresh) {
|
||||
newY = (upperEdge + lowerEdge) / 2;
|
||||
shouldMoveMouse = true;
|
||||
}
|
||||
|
||||
if (shouldMoveMouse) {
|
||||
moveMouse(newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves the mouse to the specified coordinates on-screen
|
||||
*/
|
||||
private void moveMouse(int x, int y) {
|
||||
robot.mouseMove(x, y);
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user