Add support for mouse drag using long press

This commit is contained in:
Cameron Gutman 2015-10-15 01:50:05 -07:00
parent 8938f51292
commit f15bfe3038

View File

@ -3,6 +3,9 @@ package com.limelight.binding.input;
import com.limelight.nvstream.NvConnection; import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.MouseButtonPacket; import com.limelight.nvstream.input.MouseButtonPacket;
import java.util.Timer;
import java.util.TimerTask;
public class TouchContext { public class TouchContext {
private int lastTouchX = 0; private int lastTouchX = 0;
private int lastTouchY = 0; private int lastTouchY = 0;
@ -10,14 +13,20 @@ public class TouchContext {
private int originalTouchY = 0; private int originalTouchY = 0;
private long originalTouchTime = 0; private long originalTouchTime = 0;
private boolean cancelled; private boolean cancelled;
private boolean confirmedMove;
private boolean confirmedDrag;
private Timer dragTimer;
private double distanceMoved;
private final NvConnection conn; private final NvConnection conn;
private final int actionIndex; private final int actionIndex;
private final double xFactor; private final double xFactor;
private final double yFactor; private final double yFactor;
private static final int TAP_MOVEMENT_THRESHOLD = 10; private static final int TAP_MOVEMENT_THRESHOLD = 20;
private static final int TAP_DISTANCE_THRESHOLD = 25;
private static final int TAP_TIME_THRESHOLD = 250; private static final int TAP_TIME_THRESHOLD = 250;
private static final int DRAG_TIME_THRESHOLD = 650;
public TouchContext(NvConnection conn, int actionIndex, double xFactor, double yFactor) public TouchContext(NvConnection conn, int actionIndex, double xFactor, double yFactor)
{ {
@ -32,15 +41,19 @@ public class TouchContext {
return actionIndex; return actionIndex;
} }
private boolean isWithinTapBounds(int touchX, int touchY)
{
int xDelta = Math.abs(touchX - originalTouchX);
int yDelta = Math.abs(touchY - originalTouchY);
return xDelta <= TAP_MOVEMENT_THRESHOLD &&
yDelta <= TAP_MOVEMENT_THRESHOLD;
}
private boolean isTap() private boolean isTap()
{ {
int xDelta = Math.abs(lastTouchX - originalTouchX);
int yDelta = Math.abs(lastTouchY - originalTouchY);
long timeDelta = System.currentTimeMillis() - originalTouchTime; long timeDelta = System.currentTimeMillis() - originalTouchTime;
return xDelta <= TAP_MOVEMENT_THRESHOLD && return isWithinTapBounds(lastTouchX, lastTouchY) && timeDelta <= TAP_TIME_THRESHOLD;
yDelta <= TAP_MOVEMENT_THRESHOLD &&
timeDelta <= TAP_TIME_THRESHOLD;
} }
private byte getMouseButtonIndex() private byte getMouseButtonIndex()
@ -58,7 +71,13 @@ public class TouchContext {
originalTouchX = lastTouchX = eventX; originalTouchX = lastTouchX = eventX;
originalTouchY = lastTouchY = eventY; originalTouchY = lastTouchY = eventY;
originalTouchTime = System.currentTimeMillis(); originalTouchTime = System.currentTimeMillis();
cancelled = false; cancelled = confirmedDrag = confirmedMove = false;
distanceMoved = 0;
if (actionIndex == 0) {
// Start the timer for engaging a drag
startDragTimer();
}
return true; return true;
} }
@ -69,10 +88,17 @@ public class TouchContext {
return; return;
} }
if (isTap()) // Cancel the drag timer
{ cancelDragTimer();
byte buttonIndex = getMouseButtonIndex();
byte buttonIndex = getMouseButtonIndex();
if (confirmedDrag) {
// Raise the button after a drag
conn.sendMouseButtonUp(buttonIndex);
}
else if (isTap())
{
// Lower the mouse button // Lower the mouse button
conn.sendMouseButtonDown(buttonIndex); conn.sendMouseButtonDown(buttonIndex);
@ -87,12 +113,70 @@ public class TouchContext {
} }
} }
private synchronized void startDragTimer() {
dragTimer = new Timer(true);
dragTimer.schedule(new TimerTask() {
@Override
public void run() {
synchronized (TouchContext.this) {
// Check if someone already set move
if (confirmedMove) {
return;
}
// Check if someone cancelled us
if (dragTimer == null) {
return;
}
// Uncancellable now
dragTimer = null;
// We haven't been cancelled before the timer expired so begin dragging
confirmedDrag = true;
conn.sendMouseButtonDown(getMouseButtonIndex());
}
}
}, DRAG_TIME_THRESHOLD);
}
private synchronized void cancelDragTimer() {
if (dragTimer != null) {
dragTimer.cancel();
dragTimer = null;
}
}
private synchronized void checkForConfirmedMove(int eventX, int eventY) {
// If we've already confirmed something, get out now
if (confirmedMove || confirmedDrag) {
return;
}
// If it leaves the tap bounds before the drag time expires, it's a move.
if (!isWithinTapBounds(eventX, eventY)) {
confirmedMove = true;
cancelDragTimer();
return;
}
// Check if we've exceeded the maximum distance moved
distanceMoved += Math.sqrt(Math.pow(eventX - lastTouchX, 2) + Math.pow(eventY - lastTouchY, 2));
if (distanceMoved >= TAP_DISTANCE_THRESHOLD) {
confirmedMove = true;
cancelDragTimer();
return;
}
}
public boolean touchMoveEvent(int eventX, int eventY) public boolean touchMoveEvent(int eventX, int eventY)
{ {
if (eventX != lastTouchX || eventY != lastTouchY) if (eventX != lastTouchX || eventY != lastTouchY)
{ {
// We only send moves for the primary touch point // We only send moves and drags for the primary touch point
if (actionIndex == 0) { if (actionIndex == 0) {
checkForConfirmedMove(eventX, eventY);
int deltaX = eventX - lastTouchX; int deltaX = eventX - lastTouchX;
int deltaY = eventY - lastTouchY; int deltaY = eventY - lastTouchY;
@ -131,6 +215,14 @@ public class TouchContext {
public void cancelTouch() { public void cancelTouch() {
cancelled = true; cancelled = true;
// Cancel the drag timer
cancelDragTimer();
// If it was a confirmed drag, we'll need to raise the button now
if (confirmedDrag) {
conn.sendMouseButtonUp(getMouseButtonIndex());
}
} }
public boolean isCancelled() { public boolean isCancelled() {