| 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 29 matching lines...) Expand all Loading... |
| 350 mEdgeSlopInPx, mEdgeSlopInPx, width - mEdgeSlopInPx, height - mE
dgeSlopInPx); | 346 mEdgeSlopInPx, mEdgeSlopInPx, width - mEdgeSlopInPx, height - mE
dgeSlopInPx); |
| 351 resizeImageToFitScreen(); | 347 resizeImageToFitScreen(); |
| 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; | |
| 361 float screenCenterY; | |
| 362 synchronized (mRenderData) { | |
| 363 screenCenterX = (float) mRenderData.screenWidth / 2; | |
| 364 screenCenterY = (float) mRenderData.screenHeight / 2; | |
| 365 | 356 |
| 366 float[] imagePoint = mapScreenPointToImagePoint(screenCenterX, scree
nCenterY); | 357 float screenCenterX = (float) mRenderData.screenWidth / 2; |
| 367 mDesktopCanvas.setViewportPosition(imagePoint[0], imagePoint[1]); | 358 float screenCenterY = (float) mRenderData.screenHeight / 2; |
| 368 } | 359 |
| 360 float[] imagePoint = mapScreenPointToImagePoint(screenCenterX, screenCen
terY); |
| 361 mDesktopCanvas.setViewportPosition(imagePoint[0], imagePoint[1]); |
| 362 |
| 369 moveCursorToScreenPoint(screenCenterX, screenCenterY); | 363 moveCursorToScreenPoint(screenCenterX, screenCenterY); |
| 370 mDesktopCanvas.repositionImage(true); | 364 mDesktopCanvas.repositionImage(true); |
| 371 } | 365 } |
| 372 | 366 |
| 373 private void setInputStrategy(InputStrategyInterface inputStrategy) { | 367 private void setInputStrategy(InputStrategyInterface inputStrategy) { |
| 374 // Since the rules for flinging differ between input modes, we want to s
top running the | 368 // 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. | 369 // current fling animation when the mode changes to prevent a wonky expe
rience. |
| 376 mCursorAnimationJob.abortAnimation(); | 370 mCursorAnimationJob.abortAnimation(); |
| 377 mScrollAnimationJob.abortAnimation(); | 371 mScrollAnimationJob.abortAnimation(); |
| 378 mInputStrategy = inputStrategy; | 372 mInputStrategy = inputStrategy; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 403 } | 397 } |
| 404 | 398 |
| 405 /** Moves the cursor to the specified position on the screen. */ | 399 /** Moves the cursor to the specified position on the screen. */ |
| 406 private void moveCursorToScreenPoint(float screenX, float screenY) { | 400 private void moveCursorToScreenPoint(float screenX, float screenY) { |
| 407 float[] imagePoint = mapScreenPointToImagePoint(screenX, screenY); | 401 float[] imagePoint = mapScreenPointToImagePoint(screenX, screenY); |
| 408 moveCursor(imagePoint[0], imagePoint[1]); | 402 moveCursor(imagePoint[0], imagePoint[1]); |
| 409 } | 403 } |
| 410 | 404 |
| 411 /** Moves the cursor to the specified position on the remote host. */ | 405 /** Moves the cursor to the specified position on the remote host. */ |
| 412 private void moveCursor(float newX, float newY) { | 406 private void moveCursor(float newX, float newY) { |
| 413 synchronized (mRenderData) { | 407 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); |
| 414 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); | 408 if (cursorMoved) { |
| 415 if (cursorMoved) { | 409 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); |
| 416 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); | |
| 417 } | |
| 418 } | 410 } |
| 411 |
| 419 mViewer.cursorMoved(); | 412 mViewer.cursorMoved(); |
| 420 } | 413 } |
| 421 | 414 |
| 422 /** Processes a (multi-finger) swipe gesture. */ | 415 /** Processes a (multi-finger) swipe gesture. */ |
| 423 private boolean onSwipe() { | 416 private boolean onSwipe() { |
| 424 if (mTotalMotionY > mSwipeThreshold) { | 417 if (mTotalMotionY > mSwipeThreshold) { |
| 425 // Swipe down occurred. | 418 // Swipe down occurred. |
| 426 mViewer.showActionBar(); | 419 mViewer.showActionBar(); |
| 427 } else if (mTotalMotionY < -mSwipeThreshold) { | 420 } else if (mTotalMotionY < -mSwipeThreshold) { |
| 428 // Swipe up occurred. | 421 // Swipe up occurred. |
| 429 mViewer.showKeyboard(); | 422 mViewer.showKeyboard(); |
| 430 } else { | 423 } else { |
| 431 return false; | 424 return false; |
| 432 } | 425 } |
| 433 | 426 |
| 434 mSuppressCursorMovement = true; | 427 mSuppressCursorMovement = true; |
| 435 mSuppressFling = true; | 428 mSuppressFling = true; |
| 436 mSwipeCompleted = true; | 429 mSwipeCompleted = true; |
| 437 return true; | 430 return true; |
| 438 } | 431 } |
| 439 | 432 |
| 440 /** Translates a point in screen coordinates to a location on the desktop im
age. */ | 433 /** Translates a point in screen coordinates to a location on the desktop im
age. */ |
| 441 private float[] mapScreenPointToImagePoint(float screenX, float screenY) { | 434 private float[] mapScreenPointToImagePoint(float screenX, float screenY) { |
| 442 float[] mappedPoints = {screenX, screenY}; | 435 float[] mappedPoints = {screenX, screenY}; |
| 443 Matrix screenToImage = new Matrix(); | 436 Matrix screenToImage = new Matrix(); |
| 444 synchronized (mRenderData) { | 437 |
| 445 mRenderData.transform.invert(screenToImage); | 438 mRenderData.transform.invert(screenToImage); |
| 446 } | 439 |
| 447 screenToImage.mapPoints(mappedPoints); | 440 screenToImage.mapPoints(mappedPoints); |
| 448 | 441 |
| 449 return mappedPoints; | 442 return mappedPoints; |
| 450 } | 443 } |
| 451 | 444 |
| 452 /** Responds to touch events filtered by the gesture detectors. */ | 445 /** Responds to touch events filtered by the gesture detectors. */ |
| 453 private class GestureListener extends GestureDetector.SimpleOnGestureListene
r | 446 private class GestureListener extends GestureDetector.SimpleOnGestureListene
r |
| 454 implements ScaleGestureDetector.OnScaleGestureListener, | 447 implements ScaleGestureDetector.OnScaleGestureListener, |
| 455 TapGestureDetector.OnTapListener { | 448 TapGestureDetector.OnTapListener { |
| 456 /** | 449 /** |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 mSuppressCursorMovement = true; | 481 mSuppressCursorMovement = true; |
| 489 mScrollFling = true; | 482 mScrollFling = true; |
| 490 return true; | 483 return true; |
| 491 } | 484 } |
| 492 | 485 |
| 493 if (pointerCount != 1 || mSuppressCursorMovement) { | 486 if (pointerCount != 1 || mSuppressCursorMovement) { |
| 494 return false; | 487 return false; |
| 495 } | 488 } |
| 496 | 489 |
| 497 float[] delta = {distanceX, distanceY}; | 490 float[] delta = {distanceX, distanceY}; |
| 498 synchronized (mRenderData) { | 491 |
| 499 Matrix canvasToImage = new Matrix(); | 492 Matrix canvasToImage = new Matrix(); |
| 500 mRenderData.transform.invert(canvasToImage); | 493 mRenderData.transform.invert(canvasToImage); |
| 501 canvasToImage.mapVectors(delta); | 494 canvasToImage.mapVectors(delta); |
| 502 } | |
| 503 | 495 |
| 504 moveViewportByOffset(delta[0], delta[1]); | 496 moveViewportByOffset(delta[0], delta[1]); |
| 505 if (!mInputStrategy.isIndirectInputMode() && mIsDragging) { | 497 if (!mInputStrategy.isIndirectInputMode() && mIsDragging) { |
| 506 // Ensure the cursor follows the user's finger when the user is
dragging under | 498 // Ensure the cursor follows the user's finger when the user is
dragging under |
| 507 // direct input mode. | 499 // direct input mode. |
| 508 moveCursorToScreenPoint(e2.getX(), e2.getY()); | 500 moveCursorToScreenPoint(e2.getX(), e2.getY()); |
| 509 } | 501 } |
| 510 return true; | 502 return true; |
| 511 } | 503 } |
| 512 | 504 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 539 } | 531 } |
| 540 | 532 |
| 541 /** Called when the user is in the process of pinch-zooming. */ | 533 /** Called when the user is in the process of pinch-zooming. */ |
| 542 @Override | 534 @Override |
| 543 public boolean onScale(ScaleGestureDetector detector) { | 535 public boolean onScale(ScaleGestureDetector detector) { |
| 544 if (!mSwipePinchDetector.isPinching()) { | 536 if (!mSwipePinchDetector.isPinching()) { |
| 545 return false; | 537 return false; |
| 546 } | 538 } |
| 547 | 539 |
| 548 float scaleFactor = detector.getScaleFactor(); | 540 float scaleFactor = detector.getScaleFactor(); |
| 549 synchronized (mRenderData) { | 541 |
| 550 mRenderData.transform.postScale( | 542 mRenderData.transform.postScale( |
| 551 scaleFactor, scaleFactor, detector.getFocusX(), detector
.getFocusY()); | 543 scaleFactor, scaleFactor, detector.getFocusX(), detector.get
FocusY()); |
| 552 } | 544 |
| 553 // For indirect input modes we want to zoom using the cursor as the
focal point, for | 545 // 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. | 546 // direct modes we use the actual focal point of the gesture. |
| 555 mDesktopCanvas.repositionImageWithZoom(mInputStrategy.isIndirectInpu
tMode()); | 547 mDesktopCanvas.repositionImageWithZoom(mInputStrategy.isIndirectInpu
tMode()); |
| 556 | 548 |
| 557 return true; | 549 return true; |
| 558 } | 550 } |
| 559 | 551 |
| 560 /** Called whenever a gesture starts. Always accepts the gesture so it i
sn't ignored. */ | 552 /** Called whenever a gesture starts. Always accepts the gesture so it i
sn't ignored. */ |
| 561 @Override | 553 @Override |
| 562 public boolean onDown(MotionEvent e) { | 554 public boolean onDown(MotionEvent e) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 587 } | 579 } |
| 588 | 580 |
| 589 if (!mInputStrategy.isIndirectInputMode()) { | 581 if (!mInputStrategy.isIndirectInputMode()) { |
| 590 if (screenPointLiesOutsideImageBoundary(x, y)) { | 582 if (screenPointLiesOutsideImageBoundary(x, y)) { |
| 591 return false; | 583 return false; |
| 592 } | 584 } |
| 593 moveCursorToScreenPoint(x, y); | 585 moveCursorToScreenPoint(x, y); |
| 594 } | 586 } |
| 595 | 587 |
| 596 if (mInputStrategy.onTap(button)) { | 588 if (mInputStrategy.onTap(button)) { |
| 597 PointF pos; | 589 PointF pos = mRenderData.getCursorPosition(); |
| 598 synchronized (mRenderData) { | 590 |
| 599 pos = mRenderData.getCursorPosition(); | |
| 600 } | |
| 601 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy
pe(), pos); | 591 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy
pe(), pos); |
| 602 } | 592 } |
| 603 return true; | 593 return true; |
| 604 } | 594 } |
| 605 | 595 |
| 606 /** Called when a long-press is triggered for one or more fingers. */ | 596 /** Called when a long-press is triggered for one or more fingers. */ |
| 607 @Override | 597 @Override |
| 608 public void onLongPress(int pointerCount, float x, float y) { | 598 public void onLongPress(int pointerCount, float x, float y) { |
| 609 int button = mouseButtonFromPointerCount(pointerCount); | 599 int button = mouseButtonFromPointerCount(pointerCount); |
| 610 if (button == InputStub.BUTTON_UNDEFINED) { | 600 if (button == InputStub.BUTTON_UNDEFINED) { |
| 611 return; | 601 return; |
| 612 } | 602 } |
| 613 | 603 |
| 614 if (!mInputStrategy.isIndirectInputMode()) { | 604 if (!mInputStrategy.isIndirectInputMode()) { |
| 615 if (screenPointLiesOutsideImageBoundary(x, y)) { | 605 if (screenPointLiesOutsideImageBoundary(x, y)) { |
| 616 return; | 606 return; |
| 617 } | 607 } |
| 618 moveCursorToScreenPoint(x, y); | 608 moveCursorToScreenPoint(x, y); |
| 619 } | 609 } |
| 620 | 610 |
| 621 if (mInputStrategy.onPressAndHold(button)) { | 611 if (mInputStrategy.onPressAndHold(button)) { |
| 622 PointF pos; | 612 PointF pos = mRenderData.getCursorPosition(); |
| 623 synchronized (mRenderData) { | 613 |
| 624 pos = mRenderData.getCursorPosition(); | |
| 625 } | |
| 626 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp
e(), pos); | 614 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp
e(), pos); |
| 627 mSuppressFling = true; | 615 mSuppressFling = true; |
| 628 mIsDragging = true; | 616 mIsDragging = true; |
| 629 } | 617 } |
| 630 } | 618 } |
| 631 | 619 |
| 632 /** Maps the number of fingers in a tap or long-press gesture to a mouse
-button. */ | 620 /** Maps the number of fingers in a tap or long-press gesture to a mouse
-button. */ |
| 633 private int mouseButtonFromPointerCount(int pointerCount) { | 621 private int mouseButtonFromPointerCount(int pointerCount) { |
| 634 switch (pointerCount) { | 622 switch (pointerCount) { |
| 635 case 1: | 623 case 1: |
| 636 return InputStub.BUTTON_LEFT; | 624 return InputStub.BUTTON_LEFT; |
| 637 case 2: | 625 case 2: |
| 638 return InputStub.BUTTON_RIGHT; | 626 return InputStub.BUTTON_RIGHT; |
| 639 case 3: | 627 case 3: |
| 640 return InputStub.BUTTON_MIDDLE; | 628 return InputStub.BUTTON_MIDDLE; |
| 641 default: | 629 default: |
| 642 return InputStub.BUTTON_UNDEFINED; | 630 return InputStub.BUTTON_UNDEFINED; |
| 643 } | 631 } |
| 644 } | 632 } |
| 645 | 633 |
| 646 /** Determines whether the given screen point lies outside the desktop i
mage. */ | 634 /** Determines whether the given screen point lies outside the desktop i
mage. */ |
| 647 private boolean screenPointLiesOutsideImageBoundary(float screenX, float
screenY) { | 635 private boolean screenPointLiesOutsideImageBoundary(float screenX, float
screenY) { |
| 648 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); | 636 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); |
| 649 float imageWidth; | 637 |
| 650 float imageHeight; | 638 float imageWidth = (float) mRenderData.imageWidth + EPSILON; |
| 651 synchronized (mRenderData) { | 639 float imageHeight = (float) mRenderData.imageHeight + EPSILON; |
| 652 imageWidth = (float) mRenderData.imageWidth + EPSILON; | |
| 653 imageHeight = (float) mRenderData.imageHeight + EPSILON; | |
| 654 } | |
| 655 | 640 |
| 656 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth | 641 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth |
| 657 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig
ht; | 642 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig
ht; |
| 658 } | 643 } |
| 659 } | 644 } |
| 660 } | 645 } |
| OLD | NEW |