|  | // Copyright 2016 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_controller.h" | 
|  |  | 
|  | #include "base/functional/bind.h" | 
|  | #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h" | 
|  | #include "content/public/browser/web_contents.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // If the fullscreen toolbar is hidden, it is difficult for the user to see | 
|  | // changes in the tabstrip. As a result, if a tab is inserted or the current | 
|  | // tab switched to a new one, the toolbar must animate in and out to display | 
|  | // the tabstrip changes to the user. The animation drops down the toolbar and | 
|  | // then wait for 0.75 seconds before it hides the toolbar. | 
|  | const NSTimeInterval kTabStripChangesDelay = 750; | 
|  |  | 
|  | }  // end namespace | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////// | 
|  | // FullscreenToolbarAnimationController, public: | 
|  |  | 
|  | FullscreenToolbarAnimationController::FullscreenToolbarAnimationController( | 
|  | FullscreenToolbarController* owner) | 
|  | : WebContentsObserver(nullptr), | 
|  | owner_(owner), | 
|  | animation_(this), | 
|  | hide_toolbar_timer_( | 
|  | FROM_HERE, | 
|  | base::Milliseconds(kTabStripChangesDelay), | 
|  | base::BindRepeating(&FullscreenToolbarAnimationController:: | 
|  | AnimateToolbarOutIfPossible, | 
|  | base::Unretained(this))), | 
|  | animation_start_value_(0), | 
|  | should_hide_toolbar_after_delay_(false) { | 
|  | animation_.SetSlideDuration(base::Milliseconds(200)); | 
|  | animation_.SetTweenType(gfx::Tween::EASE_OUT); | 
|  | } | 
|  |  | 
|  | FullscreenToolbarAnimationController::~FullscreenToolbarAnimationController() = | 
|  | default; | 
|  |  | 
|  | void FullscreenToolbarAnimationController::ToolbarDidUpdate() { | 
|  | animation_start_value_ = [owner_ toolbarFraction]; | 
|  | } | 
|  |  | 
|  | void FullscreenToolbarAnimationController::StopAnimationAndTimer() { | 
|  | animation_.Stop(); | 
|  | hide_toolbar_timer_.Stop(); | 
|  | } | 
|  |  | 
|  | void FullscreenToolbarAnimationController::AnimateToolbarForTabstripChanges( | 
|  | content::WebContents* contents, | 
|  | bool in_foreground) { | 
|  | // Don't kickstart the animation if the toolbar is already displayed. | 
|  | if ([owner_ mustShowFullscreenToolbar]) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (animation_.IsShowing()) { | 
|  | hide_toolbar_timer_.Reset(); | 
|  | Observe(nullptr); | 
|  | return; | 
|  | } | 
|  |  | 
|  | should_hide_toolbar_after_delay_ = true; | 
|  | if (in_foreground && contents && | 
|  | !contents->CompletedFirstVisuallyNonEmptyPaint()) { | 
|  | Observe(contents); | 
|  | } | 
|  |  | 
|  | AnimateToolbarIn(); | 
|  | } | 
|  |  | 
|  | void FullscreenToolbarAnimationController::AnimateToolbarIn() { | 
|  | if (![owner_ isInFullscreen]) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | animation_.Reset(animation_start_value_); | 
|  | animation_.Show(); | 
|  | } | 
|  |  | 
|  | void FullscreenToolbarAnimationController::AnimateToolbarOutIfPossible() { | 
|  | if (![owner_ isInFullscreen] || [owner_ mustShowFullscreenToolbar]) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (animation_.IsClosing()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | animation_.Stop(); | 
|  | animation_.Hide(); | 
|  | } | 
|  |  | 
|  | CGFloat FullscreenToolbarAnimationController::GetToolbarFractionFromProgress() | 
|  | const { | 
|  | return animation_.GetCurrentValue(); | 
|  | } | 
|  |  | 
|  | bool FullscreenToolbarAnimationController::IsAnimationRunning() const { | 
|  | return animation_.is_animating(); | 
|  | } | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////// | 
|  | // FullscreenToolbarAnimationController::WebContentsObserver: | 
|  |  | 
|  | void FullscreenToolbarAnimationController::DidFirstVisuallyNonEmptyPaint() { | 
|  | StartHideTimerIfPossible(); | 
|  | Observe(nullptr); | 
|  | } | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////// | 
|  | // FullscreenToolbarAnimationController::AnimationDelegate: | 
|  |  | 
|  | void FullscreenToolbarAnimationController::AnimationProgressed( | 
|  | const gfx::Animation* animation) { | 
|  | [owner_ layoutToolbar]; | 
|  | } | 
|  |  | 
|  | void FullscreenToolbarAnimationController::AnimationEnded( | 
|  | const gfx::Animation* animation) { | 
|  | if (!web_contents() && animation_.IsShowing()) { | 
|  | StartHideTimerIfPossible(); | 
|  | } | 
|  | } | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////// | 
|  | // FullscreenToolbarAnimationController, private: | 
|  |  | 
|  | void FullscreenToolbarAnimationController::StartHideTimerIfPossible() { | 
|  | DCHECK(animation_.IsShowing()); | 
|  | if (should_hide_toolbar_after_delay_) { | 
|  | hide_toolbar_timer_.Reset(); | 
|  | should_hide_toolbar_after_delay_ = false; | 
|  | } | 
|  | } |