Index: remoting/android/java/src/org/chromium/chromoting/DesktopView.java |
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java |
index b7666b303364faa325f5c534c1f1aab3c4edac87..1d015106f8bd121d4b085b0f2c00f32f954c2801 100644 |
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java |
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java |
@@ -32,13 +32,20 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
* *Square* of the minimum displacement (in pixels) to be recognized as a scroll gesture. |
* Setting this to a lower value forces more frequent canvas redraws during scrolling. |
*/ |
- private static int MIN_SCROLL_DISTANCE = 8 * 8; |
+ private static final int MIN_SCROLL_DISTANCE = 8 * 8; |
/** |
* Minimum change to the scaling factor to be recognized as a zoom gesture. Setting lower |
* values here will result in more frequent canvas redraws during zooming. |
*/ |
- private static double MIN_ZOOM_FACTOR = 0.05; |
+ private static final double MIN_ZOOM_FACTOR = 0.05; |
+ |
+ /* |
+ * These constants must match those in the generated struct protoc::MouseEvent_MouseButton. |
+ */ |
+ private static final int BUTTON_UNDEFINED = 0; |
+ private static final int BUTTON_LEFT = 1; |
+ private static final int BUTTON_RIGHT = 3; |
/** Specifies one dimension of an image. */ |
private static enum Constraint { |
@@ -63,6 +70,9 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
/** Whether the bottom edge of the image was visible on-screen during the last render. */ |
private boolean mBottomUsedToBeOut; |
+ private int mMouseButton; |
+ private boolean mMousePressed; |
+ |
/** Whether the device has just been rotated, necessitating a canvas redraw. */ |
private boolean mJustRotated; |
@@ -81,6 +91,9 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
mRightUsedToBeOut = false; |
mBottomUsedToBeOut = false; |
+ mMouseButton = BUTTON_UNDEFINED; |
+ mMousePressed = false; |
+ |
mJustRotated = false; |
} |
@@ -151,27 +164,37 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
boolean rightEdgeOutOfBounds = bottomright[0] < mScreenWidth; |
boolean bottomEdgeOutOfBounds = bottomright[1] < mScreenHeight; |
+ // Prevent the user from scrolling past the left or right edge of the image. |
if (leftEdgeOutOfBounds != rightEdgeOutOfBounds) { |
if (leftEdgeOutOfBounds != mRightUsedToBeOut) { |
+ // Make the left edge of the image flush with the left screen edge. |
values[Matrix.MTRANS_X] = 0; |
} |
else { |
+ // Make the right edge of the image flush with the right screen edge. |
values[Matrix.MTRANS_X] += mScreenWidth - bottomright[0]; |
} |
} |
- else { // The view would oscillate if this were updated while scrolling off-screen. |
+ else { |
+ // The else prevents this from being updated during the repositioning process, |
+ // in which case the view would begin to oscillate. |
mRightUsedToBeOut = rightEdgeOutOfBounds; |
} |
+ // Prevent the user from scrolling past the top or bottom edge of the image. |
if (topEdgeOutOfBounds != bottomEdgeOutOfBounds) { |
if (topEdgeOutOfBounds != mBottomUsedToBeOut) { |
+ // Make the top edge of the image flush with the top screen edge. |
values[Matrix.MTRANS_Y] = 0; |
} |
else { |
+ // Make the bottom edge of the image flush with the bottom screen edge. |
values[Matrix.MTRANS_Y] += mScreenHeight - bottomright[1]; |
} |
} |
- else { // The view would oscillate if this were updated while scrolling off-screen. |
+ else { |
+ // The else prevents this from being updated during the repositioning process, |
+ // in which case the view would begin to oscillate. |
mBottomUsedToBeOut = bottomEdgeOutOfBounds; |
} |
@@ -224,13 +247,71 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
Log.i("deskview", "DesktopView.surfaceDestroyed(...)"); |
} |
+ /** Called when a mouse action is made. */ |
+ private void handleMouseMovement(float[] coordinates, int button, boolean pressed) { |
+ // Coordinates are relative to the canvas, but we need image coordinates. |
+ Matrix canvasToImage = new Matrix(); |
+ mTransform.invert(canvasToImage); |
+ canvasToImage.mapPoints(coordinates); |
+ |
+ // Coordinates are now relative to the image, so transmit them to the host. |
+ JniInterface.mouseAction((int)coordinates[0], (int)coordinates[1], button, pressed); |
+ } |
+ |
/** |
* Called whenever the user attempts to touch the canvas. Forwards such |
* events to the appropriate gesture detector until one accepts them. |
*/ |
@Override |
public boolean onTouchEvent(MotionEvent event) { |
- return mScroller.onTouchEvent(event) || mZoomer.onTouchEvent(event); |
+ boolean handled = mScroller.onTouchEvent(event) || mZoomer.onTouchEvent(event); |
+ |
+ if (event.getPointerCount()==1) { |
+ float[] coordinates = {event.getRawX(), event.getY()}; |
+ |
+ switch (event.getActionMasked()) { |
+ case MotionEvent.ACTION_DOWN: |
+ Log.i("mouse", "Found a finger"); |
+ mMouseButton = BUTTON_UNDEFINED; |
+ mMousePressed = false; |
+ break; |
+ |
+ case MotionEvent.ACTION_MOVE: |
+ Log.i("mouse", "Finger is dragging"); |
+ if (mMouseButton == BUTTON_UNDEFINED) { |
+ Log.i("mouse", "\tStarting left click"); |
+ mMouseButton = BUTTON_LEFT; |
+ mMousePressed = true; |
+ } |
+ break; |
+ |
+ case MotionEvent.ACTION_UP: |
+ Log.i("mouse", "Lost the finger"); |
+ if (mMouseButton == BUTTON_UNDEFINED) { |
+ // The user pressed and released without moving: do left click and release. |
+ Log.i("mouse", "\tStarting and finishing left click"); |
+ handleMouseMovement(coordinates, BUTTON_LEFT, true); |
+ mMouseButton = BUTTON_LEFT; |
+ mMousePressed = false; |
+ } |
+ else if (mMousePressed) { |
+ Log.i("mouse", "\tReleasing the currently-pressed button"); |
+ mMousePressed = false; |
+ } |
+ else { |
+ Log.w("mouse", "Button already in released state before gesture ended"); |
+ } |
+ break; |
+ |
+ default: |
+ return handled; |
+ } |
+ handleMouseMovement(coordinates, mMouseButton, mMousePressed); |
+ |
+ return true; |
+ } |
+ |
+ return handled; |
} |
/** Responds to touch events filtered by the gesture detectors. */ |
@@ -272,6 +353,12 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
return true; |
} |
+ /** Called whenever a gesture starts. Always accepts the gesture so it isn't ignored. */ |
+ @Override |
+ public boolean onDown(MotionEvent e) { |
+ return true; |
+ } |
+ |
/** |
* Called when the user starts to zoom. Always accepts the zoom so that |
* onScale() can decide whether to respond to it. |
@@ -281,12 +368,31 @@ public class DesktopView extends SurfaceView implements Runnable, SurfaceHolder. |
return true; |
} |
- /** |
- * Called when the user is done zooming. Defers to onScale()'s judgement. |
- */ |
+ /** Called when the user is done zooming. Defers to onScale()'s judgement. */ |
@Override |
public void onScaleEnd(ScaleGestureDetector detector) { |
onScale(detector); |
} |
+ |
+ /** Called when the user holds down on the screen. Starts a right-click. */ |
+ @Override |
+ public void onLongPress(MotionEvent e) { |
+ if (e.getPointerCount() > 1) { |
+ return; |
+ } |
+ |
+ float[] coordinates = new float[] {e.getRawX(), e.getY()}; |
+ |
+ Log.i("mouse", "Finger held down"); |
+ if (mMousePressed) { |
+ Log.i("mouse", "\tReleasing the currently-pressed button"); |
+ handleMouseMovement(coordinates, mMouseButton, false); |
+ } |
+ |
+ Log.i("mouse", "\tStarting right click"); |
+ mMouseButton = BUTTON_RIGHT; |
+ mMousePressed = true; |
+ handleMouseMovement(coordinates, mMouseButton, mMousePressed); |
+ } |
} |
} |