| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.chrome.browser.fullscreen; | 5 package org.chromium.chrome.browser.fullscreen; |
| 6 | 6 |
| 7 import android.animation.Animator; | 7 import android.animation.Animator; |
| 8 import android.animation.AnimatorListenerAdapter; | 8 import android.animation.AnimatorListenerAdapter; |
| 9 import android.animation.ObjectAnimator; | 9 import android.animation.ObjectAnimator; |
| 10 import android.app.Activity; | 10 import android.app.Activity; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 private final int mControlContainerHeight; | 65 private final int mControlContainerHeight; |
| 66 | 66 |
| 67 private final TabModelSelector mTabModelSelector; | 67 private final TabModelSelector mTabModelSelector; |
| 68 private final TabModelSelectorTabModelObserver mTabModelObserver; | 68 private final TabModelSelectorTabModelObserver mTabModelObserver; |
| 69 | 69 |
| 70 private final ControlContainer mControlContainer; | 70 private final ControlContainer mControlContainer; |
| 71 | 71 |
| 72 private long mMinShowNotificationMs = MINIMUM_SHOW_DURATION_MS; | 72 private long mMinShowNotificationMs = MINIMUM_SHOW_DURATION_MS; |
| 73 private long mMaxAnimationDurationMs = MAX_ANIMATION_DURATION_MS; | 73 private long mMaxAnimationDurationMs = MAX_ANIMATION_DURATION_MS; |
| 74 | 74 |
| 75 private float mBrowserControlOffset = Float.NaN; | 75 // The shown ratio for the browser controls animated by this class as oppose
d to what is |
| 76 // computed by the renderer. |
| 77 private float mBrowserControlShownRatio = Float.NaN; |
| 78 |
| 76 private float mRendererTopControlOffset = Float.NaN; | 79 private float mRendererTopControlOffset = Float.NaN; |
| 77 private float mRendererBottomControlOffset = Float.NaN; | 80 private float mRendererBottomControlOffset = Float.NaN; |
| 78 private float mRendererTopContentOffset; | 81 private float mRendererTopContentOffset; |
| 79 private float mPreviousContentOffset = Float.NaN; | 82 private float mPreviousContentOffset = Float.NaN; |
| 80 private float mControlOffset; | 83 private float mControlOffsetRatio; |
| 81 private float mPreviousControlOffset; | 84 private float mPreviousControlOffset; |
| 82 private boolean mIsEnteringPersistentModeState; | 85 private boolean mIsEnteringPersistentModeState; |
| 83 | 86 |
| 84 private boolean mInGesture; | 87 private boolean mInGesture; |
| 85 private boolean mContentViewScrolling; | 88 private boolean mContentViewScrolling; |
| 86 | 89 |
| 87 private int mPersistentControlsCurrentToken; | 90 private int mPersistentControlsCurrentToken; |
| 88 private long mCurrentShowTime; | 91 private long mCurrentShowTime; |
| 89 private int mActivityShowToken = INVALID_TOKEN; | 92 private int mActivityShowToken = INVALID_TOKEN; |
| 90 | 93 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 118 | 121 |
| 119 /** | 122 /** |
| 120 * Called when a ContentVideoView is created/destroyed. | 123 * Called when a ContentVideoView is created/destroyed. |
| 121 * @param enabled Whether to enter or leave overlay video mode. | 124 * @param enabled Whether to enter or leave overlay video mode. |
| 122 */ | 125 */ |
| 123 public void onToggleOverlayVideoMode(boolean enabled); | 126 public void onToggleOverlayVideoMode(boolean enabled); |
| 124 } | 127 } |
| 125 | 128 |
| 126 private class ControlsOffsetProperty extends Property<ChromeFullscreenManage
r, Float> { | 129 private class ControlsOffsetProperty extends Property<ChromeFullscreenManage
r, Float> { |
| 127 public ControlsOffsetProperty() { | 130 public ControlsOffsetProperty() { |
| 128 super(Float.class, "controlsOffset"); | 131 super(Float.class, "controlsOffsetRatio"); |
| 129 } | 132 } |
| 130 | 133 |
| 131 @Override | 134 @Override |
| 132 public Float get(ChromeFullscreenManager object) { | 135 public Float get(ChromeFullscreenManager object) { |
| 133 return getControlOffset(); | 136 return getBrowserControlHiddenRatio(); |
| 134 } | 137 } |
| 135 | 138 |
| 136 @Override | 139 @Override |
| 137 public void set(ChromeFullscreenManager manager, Float offset) { | 140 public void set(ChromeFullscreenManager manager, Float ratio) { |
| 138 if (mDisableBrowserOverride) return; | 141 if (mDisableBrowserOverride) return; |
| 139 float browserOffset = offset.floatValue(); | 142 float browserRatio = ratio.floatValue(); |
| 140 if (Float.compare(mBrowserControlOffset, browserOffset) == 0) return
; | 143 if (Float.compare(mBrowserControlShownRatio, browserRatio) == 0) ret
urn; |
| 141 mBrowserControlOffset = browserOffset; | 144 mBrowserControlShownRatio = browserRatio; |
| 142 manager.updateControlOffset(); | 145 manager.updateControlOffset(); |
| 143 manager.updateVisuals(); | 146 manager.updateVisuals(); |
| 144 } | 147 } |
| 145 } | 148 } |
| 146 | 149 |
| 147 private final Runnable mUpdateVisibilityRunnable = new Runnable() { | 150 private final Runnable mUpdateVisibilityRunnable = new Runnable() { |
| 148 @Override | 151 @Override |
| 149 public void run() { | 152 public void run() { |
| 150 int visibility = shouldShowAndroidControls() ? View.VISIBLE : View.I
NVISIBLE; | 153 int visibility = shouldShowAndroidControls() ? View.VISIBLE : View.I
NVISIBLE; |
| 151 if (mControlContainer.getView().getVisibility() == visibility) retur
n; | 154 if (mControlContainer.getView().getVisibility() == visibility) retur
n; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 178 chromeFullscreenManager.update(false); | 181 chromeFullscreenManager.update(false); |
| 179 break; | 182 break; |
| 180 default: | 183 default: |
| 181 assert false : "Unexpected message for ID: " + msg.what; | 184 assert false : "Unexpected message for ID: " + msg.what; |
| 182 break; | 185 break; |
| 183 } | 186 } |
| 184 } | 187 } |
| 185 } | 188 } |
| 186 | 189 |
| 187 /** | 190 /** |
| 191 * @return The ratio that the browser controls are off screen; this will be
a number [0,1] |
| 192 * where 1 is completely hidden and 0 is completely shown. |
| 193 */ |
| 194 private float getBrowserControlHiddenRatio() { |
| 195 return mControlOffsetRatio; |
| 196 } |
| 197 |
| 198 /** |
| 188 * Creates an instance of the fullscreen mode manager. | 199 * Creates an instance of the fullscreen mode manager. |
| 189 * @param activity The activity that supports fullscreen. | 200 * @param activity The activity that supports fullscreen. |
| 190 * @param controlContainer Container holding the controls (Toolbar). | 201 * @param controlContainer Container holding the controls (Toolbar). |
| 191 * @param modelSelector The tab model selector that will be monitored for ta
b changes. | 202 * @param modelSelector The tab model selector that will be monitored for ta
b changes. |
| 192 * @param resControlContainerHeight The dimension resource ID for the contro
l container height. | 203 * @param resControlContainerHeight The dimension resource ID for the contro
l container height. |
| 193 * @param supportsBrowserOverride Whether we want to disable the token syste
m used by the | 204 * @param supportsBrowserOverride Whether we want to disable the token syste
m used by the |
| 194 browser. | 205 browser. |
| 195 */ | 206 */ |
| 196 public ChromeFullscreenManager(Activity activity, ControlContainer controlCo
ntainer, | 207 public ChromeFullscreenManager(Activity activity, ControlContainer controlCo
ntainer, |
| 197 TabModelSelector modelSelector, int resControlContainerHeight, | 208 TabModelSelector modelSelector, int resControlContainerHeight, |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 public void disableBrowserOverrideForTest() { | 325 public void disableBrowserOverrideForTest() { |
| 315 ThreadUtils.assertOnUiThread(); | 326 ThreadUtils.assertOnUiThread(); |
| 316 | 327 |
| 317 mDisableBrowserOverride = true; | 328 mDisableBrowserOverride = true; |
| 318 mPersistentControlTokens.clear(); | 329 mPersistentControlTokens.clear(); |
| 319 mHandler.removeMessages(MSG_ID_HIDE_CONTROLS); | 330 mHandler.removeMessages(MSG_ID_HIDE_CONTROLS); |
| 320 if (mControlAnimation != null) { | 331 if (mControlAnimation != null) { |
| 321 mControlAnimation.cancel(); | 332 mControlAnimation.cancel(); |
| 322 mControlAnimation = null; | 333 mControlAnimation = null; |
| 323 } | 334 } |
| 324 mBrowserControlOffset = Float.NaN; | 335 mBrowserControlShownRatio = Float.NaN; |
| 325 updateVisuals(); | 336 updateVisuals(); |
| 326 } | 337 } |
| 327 | 338 |
| 328 /** | 339 /** |
| 329 * Allows tests to override the animation durations for faster tests. | 340 * Allows tests to override the animation durations for faster tests. |
| 330 * @param minShowDuration The minimum time the controls must be shown. | 341 * @param minShowDuration The minimum time the controls must be shown. |
| 331 * @param maxAnimationDuration The maximum animation time to show/hide the c
ontrols. | 342 * @param maxAnimationDuration The maximum animation time to show/hide the c
ontrols. |
| 332 */ | 343 */ |
| 333 @VisibleForTesting | 344 @VisibleForTesting |
| 334 public void setAnimationDurationsForTest(long minShowDuration, long maxAnima
tionDuration) { | 345 public void setAnimationDurationsForTest(long minShowDuration, long maxAnima
tionDuration) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 * @return Whether or not the toolbar is forcefully being removed. | 390 * @return Whether or not the toolbar is forcefully being removed. |
| 380 */ | 391 */ |
| 381 public boolean areBrowserControlsPermanentlyHidden() { | 392 public boolean areBrowserControlsPermanentlyHidden() { |
| 382 return mBrowserControlsPermanentlyHidden; | 393 return mBrowserControlsPermanentlyHidden; |
| 383 } | 394 } |
| 384 | 395 |
| 385 /** | 396 /** |
| 386 * @return Whether the browser controls should be drawn as a texture. | 397 * @return Whether the browser controls should be drawn as a texture. |
| 387 */ | 398 */ |
| 388 public boolean drawControlsAsTexture() { | 399 public boolean drawControlsAsTexture() { |
| 389 return getControlOffset() > -mControlContainerHeight; | 400 return getBrowserControlHiddenRatio() > 0; |
| 390 } | 401 } |
| 391 | 402 |
| 392 @Override | 403 @Override |
| 393 public int getBrowserControlsHeight() { | 404 public int getBrowserControlsHeight() { |
| 394 return mControlContainerHeight; | 405 return mControlContainerHeight; |
| 395 } | 406 } |
| 396 | 407 |
| 397 @Override | 408 @Override |
| 398 public float getContentOffset() { | 409 public float getContentOffset() { |
| 399 if (mBrowserControlsPermanentlyHidden) return 0; | 410 if (mBrowserControlsPermanentlyHidden) return 0; |
| 400 return rendererContentOffset(); | 411 return rendererContentOffset(); |
| 401 } | 412 } |
| 402 | 413 |
| 403 /** | 414 /** |
| 404 * @return The offset of the controls from the top of the screen. | 415 * @return The offset of the controls from the top of the screen. |
| 405 */ | 416 */ |
| 406 public float getControlOffset() { | 417 public float getControlOffset() { |
| 407 if (mBrowserControlsPermanentlyHidden) return -getBrowserControlsHeight(
); | 418 if (mBrowserControlsPermanentlyHidden) return -getBrowserControlsHeight(
); |
| 408 return mControlOffset; | 419 // This is to avoid a problem with -0f in tests. |
| 420 if (mControlOffsetRatio == 0f) return 0f; |
| 421 return mControlOffsetRatio * -getBrowserControlsHeight(); |
| 409 } | 422 } |
| 410 | 423 |
| 411 /** | 424 /** |
| 412 * @return The toolbar control container. | 425 * @return The toolbar control container. |
| 413 */ | 426 */ |
| 414 public ControlContainer getControlContainer() { | 427 public ControlContainer getControlContainer() { |
| 415 return mControlContainer; | 428 return mControlContainer; |
| 416 } | 429 } |
| 417 | 430 |
| 418 @SuppressWarnings("SelfEquality") | |
| 419 private void updateControlOffset() { | 431 private void updateControlOffset() { |
| 420 float offset = 0; | 432 float topOffsetRatio = 0; |
| 433 |
| 421 // Inline Float.isNan with "x != x": | 434 // Inline Float.isNan with "x != x": |
| 422 final boolean isNaNBrowserControlOffset = mBrowserControlOffset != mBrow
serControlOffset; | 435 final boolean isNaNBrowserControlOffset = Float.isNaN(mBrowserControlSho
wnRatio); |
| 423 final float rendererControlOffset = rendererControlOffset(); | 436 final float rendererControlOffset = |
| 424 final boolean isNaNRendererControlOffset = rendererControlOffset != rend
ererControlOffset; | 437 Math.abs(rendererControlOffset() / controlContainerHeight()); |
| 438 final boolean isNaNRendererControlOffset = Float.isNaN(rendererControlOf
fset); |
| 425 if (!isNaNBrowserControlOffset || !isNaNRendererControlOffset) { | 439 if (!isNaNBrowserControlOffset || !isNaNRendererControlOffset) { |
| 426 offset = Math.max( | 440 topOffsetRatio = Math.min( |
| 427 isNaNBrowserControlOffset ? -mControlContainerHeight : mBrow
serControlOffset, | 441 isNaNBrowserControlOffset ? 1 : mBrowserControlShownRatio, |
| 428 isNaNRendererControlOffset ? -mControlContainerHeight : rend
ererControlOffset); | 442 isNaNRendererControlOffset ? 1 : rendererControlOffset); |
| 429 } | 443 } |
| 430 mControlOffset = offset; | 444 mControlOffsetRatio = topOffsetRatio; |
| 431 } | 445 } |
| 432 | 446 |
| 433 @Override | 447 @Override |
| 434 public void setOverlayVideoMode(boolean enabled) { | 448 public void setOverlayVideoMode(boolean enabled) { |
| 435 super.setOverlayVideoMode(enabled); | 449 super.setOverlayVideoMode(enabled); |
| 436 | 450 |
| 437 for (int i = 0; i < mListeners.size(); i++) { | 451 for (int i = 0; i < mListeners.size(); i++) { |
| 438 mListeners.get(i).onToggleOverlayVideoMode(enabled); | 452 mListeners.get(i).onToggleOverlayVideoMode(enabled); |
| 439 } | 453 } |
| 440 } | 454 } |
| 441 | 455 |
| 442 /** | 456 /** |
| 443 * @return Whether the browser has a control offset override. | 457 * @return Whether the browser has a control offset override. |
| 444 */ | 458 */ |
| 445 @VisibleForTesting | 459 @VisibleForTesting |
| 446 public boolean hasBrowserControlOffsetOverride() { | 460 public boolean hasBrowserControlOffsetOverride() { |
| 447 return !Float.isNaN(mBrowserControlOffset) || mControlAnimation != null | 461 return !Float.isNaN(mBrowserControlShownRatio) || mControlAnimation != n
ull |
| 448 || !mPersistentControlTokens.isEmpty(); | 462 || !mPersistentControlTokens.isEmpty(); |
| 449 } | 463 } |
| 450 | 464 |
| 451 /** | 465 /** |
| 452 * Returns how tall the opaque portion of the control container is. | 466 * Returns how tall the opaque portion of the control container is. |
| 453 */ | 467 */ |
| 454 public float controlContainerHeight() { | 468 public float controlContainerHeight() { |
| 455 return mControlContainerHeight; | 469 return mControlContainerHeight; |
| 456 } | 470 } |
| 457 | 471 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 */ | 585 */ |
| 572 public void setHideBrowserControlsAndroidView(boolean hide) { | 586 public void setHideBrowserControlsAndroidView(boolean hide) { |
| 573 if (mBrowserControlsAndroidViewHidden == hide) return; | 587 if (mBrowserControlsAndroidViewHidden == hide) return; |
| 574 mBrowserControlsAndroidViewHidden = hide; | 588 mBrowserControlsAndroidViewHidden = hide; |
| 575 scheduleVisibilityUpdate(); | 589 scheduleVisibilityUpdate(); |
| 576 } | 590 } |
| 577 | 591 |
| 578 private boolean shouldShowAndroidControls() { | 592 private boolean shouldShowAndroidControls() { |
| 579 if (mBrowserControlsAndroidViewHidden) return false; | 593 if (mBrowserControlsAndroidViewHidden) return false; |
| 580 | 594 |
| 581 boolean showControls = getControlOffset() == 0; | 595 boolean showControls = !drawControlsAsTexture(); |
| 582 ContentViewCore contentViewCore = getActiveContentViewCore(); | 596 ContentViewCore contentViewCore = getActiveContentViewCore(); |
| 583 if (contentViewCore == null) return showControls; | 597 if (contentViewCore == null) return showControls; |
| 584 ViewGroup contentView = contentViewCore.getContainerView(); | 598 ViewGroup contentView = contentViewCore.getContainerView(); |
| 585 | 599 |
| 586 for (int i = 0; i < contentView.getChildCount(); i++) { | 600 for (int i = 0; i < contentView.getChildCount(); i++) { |
| 587 View child = contentView.getChildAt(i); | 601 View child = contentView.getChildAt(i); |
| 588 if (!(child.getLayoutParams() instanceof FrameLayout.LayoutParams))
continue; | 602 if (!(child.getLayoutParams() instanceof FrameLayout.LayoutParams))
continue; |
| 589 | 603 |
| 590 FrameLayout.LayoutParams layoutParams = | 604 FrameLayout.LayoutParams layoutParams = |
| 591 (FrameLayout.LayoutParams) child.getLayoutParams(); | 605 (FrameLayout.LayoutParams) child.getLayoutParams(); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 private void animateIfNecessary(final boolean show, long startDelay) { | 754 private void animateIfNecessary(final boolean show, long startDelay) { |
| 741 if (mControlAnimation != null) { | 755 if (mControlAnimation != null) { |
| 742 if (!mControlAnimation.isRunning() || mCurrentAnimationIsShowing !=
show) { | 756 if (!mControlAnimation.isRunning() || mCurrentAnimationIsShowing !=
show) { |
| 743 mControlAnimation.cancel(); | 757 mControlAnimation.cancel(); |
| 744 mControlAnimation = null; | 758 mControlAnimation = null; |
| 745 } else { | 759 } else { |
| 746 return; | 760 return; |
| 747 } | 761 } |
| 748 } | 762 } |
| 749 | 763 |
| 750 float destination = show ? 0 : -mControlContainerHeight; | 764 float destination = show ? 0 : 1; |
| 751 long duration = (long) (mMaxAnimationDurationMs | 765 long duration = (long) (mMaxAnimationDurationMs |
| 752 * Math.abs((destination - getControlOffset()) / mControlContaine
rHeight)); | 766 * Math.abs(destination - getBrowserControlHiddenRatio())); |
| 753 mControlAnimation = ObjectAnimator.ofFloat(this, new ControlsOffsetPrope
rty(), destination); | 767 mControlAnimation = ObjectAnimator.ofFloat(this, new ControlsOffsetPrope
rty(), destination); |
| 754 mControlAnimation.addListener(new AnimatorListenerAdapter() { | 768 mControlAnimation.addListener(new AnimatorListenerAdapter() { |
| 755 private boolean mCanceled = false; | 769 private boolean mCanceled = false; |
| 756 | 770 |
| 757 @Override | 771 @Override |
| 758 public void onAnimationCancel(Animator anim) { | 772 public void onAnimationCancel(Animator anim) { |
| 759 mCanceled = true; | 773 mCanceled = true; |
| 760 } | 774 } |
| 761 | 775 |
| 762 @Override | 776 @Override |
| 763 public void onAnimationEnd(Animator animation) { | 777 public void onAnimationEnd(Animator animation) { |
| 764 if (!show && !mCanceled) mBrowserControlOffset = Float.NaN; | 778 if (!show && !mCanceled) mBrowserControlShownRatio = Float.NaN; |
| 765 mControlAnimation = null; | 779 mControlAnimation = null; |
| 766 } | 780 } |
| 767 }); | 781 }); |
| 768 mControlAnimation.setStartDelay(startDelay); | 782 mControlAnimation.setStartDelay(startDelay); |
| 769 mControlAnimation.setDuration(duration); | 783 mControlAnimation.setDuration(duration); |
| 770 mControlAnimation.start(); | 784 mControlAnimation.start(); |
| 771 mCurrentAnimationIsShowing = show; | 785 mCurrentAnimationIsShowing = show; |
| 772 } | 786 } |
| 773 | 787 |
| 774 @Override | 788 @Override |
| 775 public void onContentViewScrollingStateChanged(boolean scrolling) { | 789 public void onContentViewScrollingStateChanged(boolean scrolling) { |
| 776 mContentViewScrolling = scrolling; | 790 mContentViewScrolling = scrolling; |
| 777 if (!scrolling) updateVisuals(); | 791 if (!scrolling) updateVisuals(); |
| 778 } | 792 } |
| 779 } | 793 } |
| OLD | NEW |