| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.graphics.Matrix; | 8 import android.graphics.Matrix; |
| 9 import android.graphics.PointF; | 9 import android.graphics.PointF; |
| 10 import android.graphics.Rect; | 10 import android.graphics.Rect; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 * This class implements fling animation for cursor | 97 * This class implements fling animation for cursor |
| 98 */ | 98 */ |
| 99 private class CursorAnimationJob extends FlingAnimationJob { | 99 private class CursorAnimationJob extends FlingAnimationJob { |
| 100 public CursorAnimationJob(Context context) { | 100 public CursorAnimationJob(Context context) { |
| 101 super(context); | 101 super(context); |
| 102 } | 102 } |
| 103 | 103 |
| 104 @Override | 104 @Override |
| 105 protected void processAction(float deltaX, float deltaY) { | 105 protected void processAction(float deltaX, float deltaY) { |
| 106 float[] delta = {deltaX, deltaY}; | 106 float[] delta = {deltaX, deltaY}; |
| 107 synchronized (mRenderData) { | 107 Matrix canvasToImage = new Matrix(); |
| 108 Matrix canvasToImage = new Matrix(); | 108 mRenderData.transform.invert(canvasToImage); |
| 109 mRenderData.transform.invert(canvasToImage); | 109 canvasToImage.mapVectors(delta); |
| 110 canvasToImage.mapVectors(delta); | |
| 111 } | |
| 112 | 110 |
| 113 moveViewportByOffset(-delta[0], -delta[1]); | 111 moveViewportByOffset(-delta[0], -delta[1]); |
| 114 } | 112 } |
| 115 } | 113 } |
| 116 | 114 |
| 117 /** | 115 /** |
| 118 * This class implements fling animation for scrolling | 116 * This class implements fling animation for scrolling |
| 119 */ | 117 */ |
| 120 private class ScrollAnimationJob extends FlingAnimationJob { | 118 private class ScrollAnimationJob extends FlingAnimationJob { |
| 121 public ScrollAnimationJob(Context context) { | 119 public ScrollAnimationJob(Context context) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 // Unreachable, but required by Google Java style and findbugs. | 291 // Unreachable, but required by Google Java style and findbugs. |
| 294 assert false : "Unreached"; | 292 assert false : "Unreached"; |
| 295 } | 293 } |
| 296 | 294 |
| 297 // Ensure the cursor state is updated appropriately. | 295 // Ensure the cursor state is updated appropriately. |
| 298 mViewer.cursorVisibilityChanged(); | 296 mViewer.cursorVisibilityChanged(); |
| 299 } | 297 } |
| 300 | 298 |
| 301 private void handleSystemUiVisibilityChanged( | 299 private void handleSystemUiVisibilityChanged( |
| 302 SystemUiVisibilityChangedEventParameter parameter) { | 300 SystemUiVisibilityChangedEventParameter parameter) { |
| 303 synchronized (mRenderData) { | 301 if (parameter.softInputMethodVisible) { |
| 304 if (parameter.softInputMethodVisible) { | 302 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter.top
, |
| 305 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter
.top, | 303 mRenderData.screenWidth - parameter.right, |
| 306 mRenderData.screenWidth - parameter.right, | 304 mRenderData.screenHeight - parameter.bottom); |
| 307 mRenderData.screenHeight - parameter.bottom); | 305 } else { |
| 308 } else { | 306 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0); |
| 309 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0); | |
| 310 } | |
| 311 } | 307 } |
| 312 | 308 |
| 313 mDesktopCanvas.repositionImage(true); | 309 mDesktopCanvas.repositionImage(true); |
| 314 } | 310 } |
| 315 | 311 |
| 316 private boolean handleTouchEvent(MotionEvent event) { | 312 private boolean handleTouchEvent(MotionEvent event) { |
| 317 // Give the underlying input strategy a chance to observe the current mo
tion event before | 313 // Give the underlying input strategy a chance to observe the current mo
tion event before |
| 318 // passing it to the gesture detectors. This allows the input strategy
to react to the | 314 // passing it to the gesture detectors. This allows the input strategy
to react to the |
| 319 // event or save the payload for use in recreating the gesture remotely. | 315 // event or save the payload for use in recreating the gesture remotely. |
| 320 mInputStrategy.onMotionEvent(event); | 316 mInputStrategy.onMotionEvent(event); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 } | 348 } |
| 353 | 349 |
| 354 private void handleHostSizeChanged(int width, int height) { | 350 private void handleHostSizeChanged(int width, int height) { |
| 355 resizeImageToFitScreen(); | 351 resizeImageToFitScreen(); |
| 356 } | 352 } |
| 357 | 353 |
| 358 private void resizeImageToFitScreen() { | 354 private void resizeImageToFitScreen() { |
| 359 mDesktopCanvas.resizeImageToFitScreen(); | 355 mDesktopCanvas.resizeImageToFitScreen(); |
| 360 float screenCenterX; | 356 float screenCenterX; |
| 361 float screenCenterY; | 357 float screenCenterY; |
| 362 synchronized (mRenderData) { | |
| 363 screenCenterX = (float) mRenderData.screenWidth / 2; | |
| 364 screenCenterY = (float) mRenderData.screenHeight / 2; | |
| 365 | 358 |
| 366 float[] imagePoint = mapScreenPointToImagePoint(screenCenterX, scree
nCenterY); | 359 screenCenterX = (float) mRenderData.screenWidth / 2; |
| 367 mDesktopCanvas.setViewportPosition(imagePoint[0], imagePoint[1]); | 360 screenCenterY = (float) mRenderData.screenHeight / 2; |
| 368 } | 361 |
| 362 float[] imagePoint = mapScreenPointToImagePoint(screenCenterX, screenCen
terY); |
| 363 mDesktopCanvas.setViewportPosition(imagePoint[0], imagePoint[1]); |
| 364 |
| 369 moveCursorToScreenPoint(screenCenterX, screenCenterY); | 365 moveCursorToScreenPoint(screenCenterX, screenCenterY); |
| 370 mDesktopCanvas.repositionImage(true); | 366 mDesktopCanvas.repositionImage(true); |
| 371 } | 367 } |
| 372 | 368 |
| 373 private void setInputStrategy(InputStrategyInterface inputStrategy) { | 369 private void setInputStrategy(InputStrategyInterface inputStrategy) { |
| 374 // Since the rules for flinging differ between input modes, we want to s
top running the | 370 // Since the rules for flinging differ between input modes, we want to s
top running the |
| 375 // current fling animation when the mode changes to prevent a wonky expe
rience. | 371 // current fling animation when the mode changes to prevent a wonky expe
rience. |
| 376 mCursorAnimationJob.abortAnimation(); | 372 mCursorAnimationJob.abortAnimation(); |
| 377 mScrollAnimationJob.abortAnimation(); | 373 mScrollAnimationJob.abortAnimation(); |
| 378 mInputStrategy = inputStrategy; | 374 mInputStrategy = inputStrategy; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 403 } | 399 } |
| 404 | 400 |
| 405 /** Moves the cursor to the specified position on the screen. */ | 401 /** Moves the cursor to the specified position on the screen. */ |
| 406 private void moveCursorToScreenPoint(float screenX, float screenY) { | 402 private void moveCursorToScreenPoint(float screenX, float screenY) { |
| 407 float[] imagePoint = mapScreenPointToImagePoint(screenX, screenY); | 403 float[] imagePoint = mapScreenPointToImagePoint(screenX, screenY); |
| 408 moveCursor(imagePoint[0], imagePoint[1]); | 404 moveCursor(imagePoint[0], imagePoint[1]); |
| 409 } | 405 } |
| 410 | 406 |
| 411 /** Moves the cursor to the specified position on the remote host. */ | 407 /** Moves the cursor to the specified position on the remote host. */ |
| 412 private void moveCursor(float newX, float newY) { | 408 private void moveCursor(float newX, float newY) { |
| 413 synchronized (mRenderData) { | 409 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); |
| 414 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); | 410 if (cursorMoved) { |
| 415 if (cursorMoved) { | 411 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); |
| 416 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); | |
| 417 } | |
| 418 } | 412 } |
| 413 |
| 419 mViewer.cursorMoved(); | 414 mViewer.cursorMoved(); |
| 420 } | 415 } |
| 421 | 416 |
| 422 /** Processes a (multi-finger) swipe gesture. */ | 417 /** Processes a (multi-finger) swipe gesture. */ |
| 423 private boolean onSwipe() { | 418 private boolean onSwipe() { |
| 424 if (mTotalMotionY > mSwipeThreshold) { | 419 if (mTotalMotionY > mSwipeThreshold) { |
| 425 // Swipe down occurred. | 420 // Swipe down occurred. |
| 426 mViewer.showActionBar(); | 421 mViewer.showActionBar(); |
| 427 } else if (mTotalMotionY < -mSwipeThreshold) { | 422 } else if (mTotalMotionY < -mSwipeThreshold) { |
| 428 // Swipe up occurred. | 423 // Swipe up occurred. |
| 429 mViewer.showKeyboard(); | 424 mViewer.showKeyboard(); |
| 430 } else { | 425 } else { |
| 431 return false; | 426 return false; |
| 432 } | 427 } |
| 433 | 428 |
| 434 mSuppressCursorMovement = true; | 429 mSuppressCursorMovement = true; |
| 435 mSuppressFling = true; | 430 mSuppressFling = true; |
| 436 mSwipeCompleted = true; | 431 mSwipeCompleted = true; |
| 437 return true; | 432 return true; |
| 438 } | 433 } |
| 439 | 434 |
| 440 /** Translates a point in screen coordinates to a location on the desktop im
age. */ | 435 /** Translates a point in screen coordinates to a location on the desktop im
age. */ |
| 441 private float[] mapScreenPointToImagePoint(float screenX, float screenY) { | 436 private float[] mapScreenPointToImagePoint(float screenX, float screenY) { |
| 442 float[] mappedPoints = {screenX, screenY}; | 437 float[] mappedPoints = {screenX, screenY}; |
| 443 Matrix screenToImage = new Matrix(); | 438 Matrix screenToImage = new Matrix(); |
| 444 synchronized (mRenderData) { | 439 |
| 445 mRenderData.transform.invert(screenToImage); | 440 mRenderData.transform.invert(screenToImage); |
| 446 } | 441 |
| 447 screenToImage.mapPoints(mappedPoints); | 442 screenToImage.mapPoints(mappedPoints); |
| 448 | 443 |
| 449 return mappedPoints; | 444 return mappedPoints; |
| 450 } | 445 } |
| 451 | 446 |
| 452 /** Responds to touch events filtered by the gesture detectors. */ | 447 /** Responds to touch events filtered by the gesture detectors. */ |
| 453 private class GestureListener extends GestureDetector.SimpleOnGestureListene
r | 448 private class GestureListener extends GestureDetector.SimpleOnGestureListene
r |
| 454 implements ScaleGestureDetector.OnScaleGestureListener, | 449 implements ScaleGestureDetector.OnScaleGestureListener, |
| 455 TapGestureDetector.OnTapListener { | 450 TapGestureDetector.OnTapListener { |
| 456 /** | 451 /** |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 mSuppressCursorMovement = true; | 483 mSuppressCursorMovement = true; |
| 489 mScrollFling = true; | 484 mScrollFling = true; |
| 490 return true; | 485 return true; |
| 491 } | 486 } |
| 492 | 487 |
| 493 if (pointerCount != 1 || mSuppressCursorMovement) { | 488 if (pointerCount != 1 || mSuppressCursorMovement) { |
| 494 return false; | 489 return false; |
| 495 } | 490 } |
| 496 | 491 |
| 497 float[] delta = {distanceX, distanceY}; | 492 float[] delta = {distanceX, distanceY}; |
| 498 synchronized (mRenderData) { | 493 |
| 499 Matrix canvasToImage = new Matrix(); | 494 Matrix canvasToImage = new Matrix(); |
| 500 mRenderData.transform.invert(canvasToImage); | 495 mRenderData.transform.invert(canvasToImage); |
| 501 canvasToImage.mapVectors(delta); | 496 canvasToImage.mapVectors(delta); |
| 502 } | |
| 503 | 497 |
| 504 moveViewportByOffset(delta[0], delta[1]); | 498 moveViewportByOffset(delta[0], delta[1]); |
| 505 if (!mInputStrategy.isIndirectInputMode() && mIsDragging) { | 499 if (!mInputStrategy.isIndirectInputMode() && mIsDragging) { |
| 506 // Ensure the cursor follows the user's finger when the user is
dragging under | 500 // Ensure the cursor follows the user's finger when the user is
dragging under |
| 507 // direct input mode. | 501 // direct input mode. |
| 508 moveCursorToScreenPoint(e2.getX(), e2.getY()); | 502 moveCursorToScreenPoint(e2.getX(), e2.getY()); |
| 509 } | 503 } |
| 510 return true; | 504 return true; |
| 511 } | 505 } |
| 512 | 506 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 539 } | 533 } |
| 540 | 534 |
| 541 /** Called when the user is in the process of pinch-zooming. */ | 535 /** Called when the user is in the process of pinch-zooming. */ |
| 542 @Override | 536 @Override |
| 543 public boolean onScale(ScaleGestureDetector detector) { | 537 public boolean onScale(ScaleGestureDetector detector) { |
| 544 if (!mSwipePinchDetector.isPinching()) { | 538 if (!mSwipePinchDetector.isPinching()) { |
| 545 return false; | 539 return false; |
| 546 } | 540 } |
| 547 | 541 |
| 548 float scaleFactor = detector.getScaleFactor(); | 542 float scaleFactor = detector.getScaleFactor(); |
| 549 synchronized (mRenderData) { | 543 |
| 550 mRenderData.transform.postScale( | 544 mRenderData.transform.postScale( |
| 551 scaleFactor, scaleFactor, detector.getFocusX(), detector
.getFocusY()); | 545 scaleFactor, scaleFactor, detector.getFocusX(), detector.get
FocusY()); |
| 552 } | 546 |
| 553 // For indirect input modes we want to zoom using the cursor as the
focal point, for | 547 // For indirect input modes we want to zoom using the cursor as the
focal point, for |
| 554 // direct modes we use the actual focal point of the gesture. | 548 // direct modes we use the actual focal point of the gesture. |
| 555 mDesktopCanvas.repositionImageWithZoom(mInputStrategy.isIndirectInpu
tMode()); | 549 mDesktopCanvas.repositionImageWithZoom(mInputStrategy.isIndirectInpu
tMode()); |
| 556 | 550 |
| 557 return true; | 551 return true; |
| 558 } | 552 } |
| 559 | 553 |
| 560 /** Called whenever a gesture starts. Always accepts the gesture so it i
sn't ignored. */ | 554 /** Called whenever a gesture starts. Always accepts the gesture so it i
sn't ignored. */ |
| 561 @Override | 555 @Override |
| 562 public boolean onDown(MotionEvent e) { | 556 public boolean onDown(MotionEvent e) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 587 } | 581 } |
| 588 | 582 |
| 589 if (!mInputStrategy.isIndirectInputMode()) { | 583 if (!mInputStrategy.isIndirectInputMode()) { |
| 590 if (screenPointLiesOutsideImageBoundary(x, y)) { | 584 if (screenPointLiesOutsideImageBoundary(x, y)) { |
| 591 return false; | 585 return false; |
| 592 } | 586 } |
| 593 moveCursorToScreenPoint(x, y); | 587 moveCursorToScreenPoint(x, y); |
| 594 } | 588 } |
| 595 | 589 |
| 596 if (mInputStrategy.onTap(button)) { | 590 if (mInputStrategy.onTap(button)) { |
| 597 PointF pos; | 591 PointF pos = mRenderData.getCursorPosition(); |
| 598 synchronized (mRenderData) { | 592 |
| 599 pos = mRenderData.getCursorPosition(); | |
| 600 } | |
| 601 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy
pe(), pos); | 593 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy
pe(), pos); |
| 602 } | 594 } |
| 603 return true; | 595 return true; |
| 604 } | 596 } |
| 605 | 597 |
| 606 /** Called when a long-press is triggered for one or more fingers. */ | 598 /** Called when a long-press is triggered for one or more fingers. */ |
| 607 @Override | 599 @Override |
| 608 public void onLongPress(int pointerCount, float x, float y) { | 600 public void onLongPress(int pointerCount, float x, float y) { |
| 609 int button = mouseButtonFromPointerCount(pointerCount); | 601 int button = mouseButtonFromPointerCount(pointerCount); |
| 610 if (button == InputStub.BUTTON_UNDEFINED) { | 602 if (button == InputStub.BUTTON_UNDEFINED) { |
| 611 return; | 603 return; |
| 612 } | 604 } |
| 613 | 605 |
| 614 if (!mInputStrategy.isIndirectInputMode()) { | 606 if (!mInputStrategy.isIndirectInputMode()) { |
| 615 if (screenPointLiesOutsideImageBoundary(x, y)) { | 607 if (screenPointLiesOutsideImageBoundary(x, y)) { |
| 616 return; | 608 return; |
| 617 } | 609 } |
| 618 moveCursorToScreenPoint(x, y); | 610 moveCursorToScreenPoint(x, y); |
| 619 } | 611 } |
| 620 | 612 |
| 621 if (mInputStrategy.onPressAndHold(button)) { | 613 if (mInputStrategy.onPressAndHold(button)) { |
| 622 PointF pos; | 614 PointF pos = mRenderData.getCursorPosition(); |
| 623 synchronized (mRenderData) { | 615 |
| 624 pos = mRenderData.getCursorPosition(); | |
| 625 } | |
| 626 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp
e(), pos); | 616 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp
e(), pos); |
| 627 mSuppressFling = true; | 617 mSuppressFling = true; |
| 628 mIsDragging = true; | 618 mIsDragging = true; |
| 629 } | 619 } |
| 630 } | 620 } |
| 631 | 621 |
| 632 /** Maps the number of fingers in a tap or long-press gesture to a mouse
-button. */ | 622 /** Maps the number of fingers in a tap or long-press gesture to a mouse
-button. */ |
| 633 private int mouseButtonFromPointerCount(int pointerCount) { | 623 private int mouseButtonFromPointerCount(int pointerCount) { |
| 634 switch (pointerCount) { | 624 switch (pointerCount) { |
| 635 case 1: | 625 case 1: |
| 636 return InputStub.BUTTON_LEFT; | 626 return InputStub.BUTTON_LEFT; |
| 637 case 2: | 627 case 2: |
| 638 return InputStub.BUTTON_RIGHT; | 628 return InputStub.BUTTON_RIGHT; |
| 639 case 3: | 629 case 3: |
| 640 return InputStub.BUTTON_MIDDLE; | 630 return InputStub.BUTTON_MIDDLE; |
| 641 default: | 631 default: |
| 642 return InputStub.BUTTON_UNDEFINED; | 632 return InputStub.BUTTON_UNDEFINED; |
| 643 } | 633 } |
| 644 } | 634 } |
| 645 | 635 |
| 646 /** Determines whether the given screen point lies outside the desktop i
mage. */ | 636 /** Determines whether the given screen point lies outside the desktop i
mage. */ |
| 647 private boolean screenPointLiesOutsideImageBoundary(float screenX, float
screenY) { | 637 private boolean screenPointLiesOutsideImageBoundary(float screenX, float
screenY) { |
| 648 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); | 638 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); |
| 649 float imageWidth; | 639 float imageWidth; |
| 650 float imageHeight; | 640 float imageHeight; |
| 651 synchronized (mRenderData) { | 641 |
| 652 imageWidth = (float) mRenderData.imageWidth + EPSILON; | 642 imageWidth = (float) mRenderData.imageWidth + EPSILON; |
| 653 imageHeight = (float) mRenderData.imageHeight + EPSILON; | 643 imageHeight = (float) mRenderData.imageHeight + EPSILON; |
| 654 } | |
| 655 | 644 |
| 656 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth | 645 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth |
| 657 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig
ht; | 646 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig
ht; |
| 658 } | 647 } |
| 659 } | 648 } |
| 660 } | 649 } |
| OLD | NEW |