Index: chrome/browser/ui/views/immersive_mode_controller.cc |
diff --git a/chrome/browser/ui/views/immersive_mode_controller.cc b/chrome/browser/ui/views/immersive_mode_controller.cc |
deleted file mode 100644 |
index e57a228bf7b7ce4cc70f827c1eaa44979e48cbbb..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/views/immersive_mode_controller.cc |
+++ /dev/null |
@@ -1,422 +0,0 @@ |
-// Copyright 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/ui/views/immersive_mode_controller.h" |
- |
-#include "chrome/browser/ui/views/frame/browser_view.h" |
-#include "chrome/browser/ui/views/frame/top_container_view.h" |
-#include "chrome/browser/ui/views/tabs/tab_strip.h" |
-#include "chrome/common/chrome_switches.h" |
-#include "ui/compositor/layer_animation_observer.h" |
-#include "ui/compositor/scoped_layer_animation_settings.h" |
-#include "ui/gfx/transform.h" |
-#include "ui/views/view.h" |
-#include "ui/views/widget/widget.h" |
-#include "ui/views/window/non_client_view.h" |
- |
-#if defined(USE_ASH) |
-#include "ash/ash_switches.h" |
-#include "ash/shell.h" |
-#include "ash/wm/window_properties.h" |
-#include "base/command_line.h" |
-#endif |
- |
-#if defined(USE_AURA) |
-#include "ui/aura/client/aura_constants.h" |
-#include "ui/aura/window.h" |
-#include "ui/aura/window_observer.h" |
-#endif |
- |
-using views::View; |
- |
-namespace { |
- |
-// Time after which the edge trigger fires and top-chrome is revealed. This is |
-// after the mouse stops moving. |
-const int kTopEdgeRevealDelayMs = 200; |
- |
-// Duration for the reveal show/hide slide animation. The slower duration is |
-// used for the initial slide out to give the user more change to see what |
-// happened. |
-const int kRevealSlowAnimationDurationMs = 400; |
-const int kRevealFastAnimationDurationMs = 200; |
- |
-} // namespace |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-#if defined(USE_AURA) |
-// Observer to watch for window restore. views::Widget does not provide a hook |
-// to observe for window restore, so do this at the Aura level. |
-class ImmersiveModeController::WindowObserver : public aura::WindowObserver { |
- public: |
- explicit WindowObserver(ImmersiveModeController* controller) |
- : controller_(controller) { |
- controller_->native_window_->AddObserver(this); |
- } |
- |
- virtual ~WindowObserver() { |
- controller_->native_window_->RemoveObserver(this); |
- } |
- |
- // aura::WindowObserver overrides: |
- virtual void OnWindowPropertyChanged(aura::Window* window, |
- const void* key, |
- intptr_t old) OVERRIDE { |
- using aura::client::kShowStateKey; |
- if (key == kShowStateKey) { |
- // Disable immersive mode when leaving the fullscreen state. |
- if (window->GetProperty(kShowStateKey) != ui::SHOW_STATE_FULLSCREEN) |
- controller_->SetEnabled(false); |
- return; |
- } |
-#if defined(USE_ASH) |
- using ash::internal::kImmersiveModeKey; |
- if (key == kImmersiveModeKey) { |
- // Another component has toggled immersive mode. |
- controller_->SetEnabled(window->GetProperty(kImmersiveModeKey)); |
- return; |
- } |
-#endif |
- } |
- |
- private: |
- ImmersiveModeController* controller_; // Not owned. |
- |
- DISALLOW_COPY_AND_ASSIGN(WindowObserver); |
-}; |
-#endif // defined(USE_AURA) |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-class ImmersiveModeController::AnimationObserver |
- : public ui::ImplicitAnimationObserver { |
- public: |
- enum AnimationType { |
- SLIDE_OPEN, |
- SLIDE_CLOSED, |
- }; |
- |
- AnimationObserver(ImmersiveModeController* controller, AnimationType type) |
- : controller_(controller), animation_type_(type) {} |
- virtual ~AnimationObserver() {} |
- |
- // ui::ImplicitAnimationObserver overrides: |
- virtual void OnImplicitAnimationsCompleted() OVERRIDE { |
- if (animation_type_ == SLIDE_OPEN) |
- controller_->OnSlideOpenAnimationCompleted(); |
- else if (animation_type_ == SLIDE_CLOSED) |
- controller_->OnSlideClosedAnimationCompleted(); |
- else |
- NOTREACHED(); |
- } |
- |
- private: |
- ImmersiveModeController* controller_; |
- AnimationType animation_type_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AnimationObserver); |
-}; |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-ImmersiveModeController::ImmersiveModeController() |
- : browser_view_(NULL), |
- enabled_(false), |
- reveal_state_(CLOSED), |
- reveal_locked_(false), |
- hide_tab_indicators_(false), |
- reveal_hovered_(false), |
- native_window_(NULL) { |
-} |
- |
-ImmersiveModeController::~ImmersiveModeController() { |
- // The browser view is being destroyed so there's no need to update its |
- // layout or layers, even if the top views are revealed. But the window |
- // observers still need to be removed. |
- EnableWindowObservers(false); |
-} |
- |
-void ImmersiveModeController::Init(BrowserView* browser_view) { |
- browser_view_ = browser_view; |
- // Browser view is detached from its widget during destruction. Cache the |
- // window pointer so |this| can stop observing during destruction. |
- native_window_ = browser_view_->GetNativeWindow(); |
- DCHECK(native_window_); |
- EnableWindowObservers(true); |
- |
- slide_open_observer_.reset( |
- new AnimationObserver(this, AnimationObserver::SLIDE_OPEN)); |
- slide_closed_observer_.reset( |
- new AnimationObserver(this, AnimationObserver::SLIDE_CLOSED)); |
- |
-#if defined(USE_ASH) |
- // Optionally allow the tab indicators to be hidden. |
- hide_tab_indicators_ = CommandLine::ForCurrentProcess()-> |
- HasSwitch(ash::switches::kAshImmersiveHideTabIndicators); |
-#endif |
-} |
- |
-// static |
-bool ImmersiveModeController::UseImmersiveFullscreen() { |
-#if defined(OS_CHROMEOS) |
- // Kiosk mode needs the whole screen. |
- CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- return !command_line->HasSwitch(switches::kKioskMode) && |
- !command_line->HasSwitch(ash::switches::kAshDisableImmersiveMode); |
-#endif |
- return false; |
-} |
- |
-void ImmersiveModeController::SetEnabled(bool enabled) { |
- DCHECK(browser_view_) << "Must initialize before enabling"; |
- if (enabled_ == enabled) |
- return; |
- enabled_ = enabled; |
- |
- TopContainerView* top_container = browser_view_->top_container(); |
- if (enabled_) { |
- // Slide closed the reveal view on enable by slamming it to revealed then |
- // triggering an end-reveal animation. |
- reveal_state_ = REVEALED; |
- top_container->SetPaintToLayer(true); |
- top_container->SetFillsBoundsOpaquely(true); |
- // Layout updates at the end of the slide closed. |
- EndReveal(ANIMATE_SLOW); |
- } else { |
- // Stop cursor-at-top tracking. |
- top_timer_.Stop(); |
- // Snap immediately to the closed state. |
- reveal_state_ = CLOSED; |
- top_container->SetFillsBoundsOpaquely(false); |
- top_container->SetPaintToLayer(false); |
- browser_view_->GetWidget()->non_client_view()->frame_view()-> |
- ResetWindowControls(); |
- browser_view_->tabstrip()->SetImmersiveStyle(false); |
- // Don't need explicit layout because we're inside a fullscreen transition |
- // and it blocks layout calls. |
- } |
- |
-#if defined(USE_ASH) |
- // This causes a no-op call to SetEnabled() since enabled_ is already set. |
- native_window_->SetProperty(ash::internal::kImmersiveModeKey, enabled_); |
- // Ash on Windows may not have a shell. |
- if (ash::Shell::HasInstance()) { |
- // Shelf auto-hides in immersive mode. |
- ash::Shell::GetInstance()->UpdateShelfVisibility(); |
- } |
-#endif |
-} |
- |
-void ImmersiveModeController::MaybeStackViewAtTop() { |
-#if defined(USE_AURA) |
- if (enabled_ && reveal_state_ != CLOSED) { |
- ui::Layer* reveal_layer = browser_view_->top_container()->layer(); |
- if (reveal_layer) |
- reveal_layer->parent()->StackAtTop(reveal_layer); |
- } |
-#endif |
-} |
- |
-void ImmersiveModeController::MaybeStartReveal() { |
- if (enabled_ && reveal_state_ != REVEALED) |
- StartReveal(ANIMATE_FAST); |
-} |
- |
-void ImmersiveModeController::CancelReveal() { |
- EndReveal(ANIMATE_NO); |
-} |
- |
-void ImmersiveModeController::RevealAndLock(bool reveal) { |
- if (!enabled_) |
- return; |
- reveal_locked_ = reveal; |
- if (reveal_locked_ && reveal_state_ != REVEALED) |
- StartReveal(ANIMATE_FAST); |
- else if (!reveal_locked_ && reveal_state_ != CLOSED) |
- EndReveal(ANIMATE_FAST); |
-} |
- |
-void ImmersiveModeController::OnRevealViewLostFocus() { |
- // Stop the reveal if the mouse is outside the reveal view. |
- if (!reveal_locked_ && !reveal_hovered_) |
- EndReveal(ANIMATE_FAST); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-// ui::EventHandler overrides: |
-void ImmersiveModeController::OnMouseEvent(ui::MouseEvent* event) { |
- if (!enabled_ || event->type() != ui::ET_MOUSE_MOVED) |
- return; |
- if (event->location().y() == 0) { |
- // Start a reveal if the mouse touches the top of the screen and then stops |
- // moving for a little while. This mirrors the Ash launcher behavior. |
- top_timer_.Stop(); |
- // Timer is stopped when |this| is destroyed, hence Unretained() is safe. |
- top_timer_.Start(FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kTopEdgeRevealDelayMs), |
- base::Bind(&ImmersiveModeController::StartReveal, |
- base::Unretained(this), |
- ANIMATE_FAST)); |
- } else { |
- // Cursor left the top edge. |
- top_timer_.Stop(); |
- } |
- |
- if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) { |
- // Look for the mouse leaving the bottom edge of the revealed view. |
- int bottom_edge = browser_view_->top_container()->bounds().bottom(); |
- if (event->location().y() > bottom_edge) { |
- reveal_hovered_ = false; |
- OnRevealViewLostMouse(); |
- } else { |
- reveal_hovered_ = true; |
- } |
- } |
- |
- // Pass along event for further handling. |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Testing interface: |
- |
-void ImmersiveModeController::SetHideTabIndicatorsForTest(bool hide) { |
- hide_tab_indicators_ = hide; |
-} |
- |
-void ImmersiveModeController::StartRevealForTest() { |
- StartReveal(ANIMATE_NO); |
-} |
- |
-void ImmersiveModeController::OnRevealViewLostMouseForTest() { |
- OnRevealViewLostMouse(); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// private: |
- |
-void ImmersiveModeController::EnableWindowObservers(bool enable) { |
- if (!native_window_) { |
- NOTREACHED() << "ImmersiveModeController not initialized"; |
- return; |
- } |
-#if defined(USE_AURA) |
- // TODO(jamescook): Porting immersive mode to non-Aura views will require |
- // a method to monitor incoming mouse move events without handling them. |
- // Currently views uses GetEventHandlerForPoint() to route events directly |
- // to either a tab or the caption area, bypassing pre-target handlers and |
- // intermediate views. |
- if (enable) |
- native_window_->AddPreTargetHandler(this); |
- else |
- native_window_->RemovePreTargetHandler(this); |
- |
- // The window observer adds and removes itself from the native window. |
- // TODO(jamescook): Porting to non-Aura will also require a method to monitor |
- // for window restore, which is not provided by views Widget. |
- window_observer_.reset(enable ? new WindowObserver(this) : NULL); |
-#endif // defined(USE_AURA) |
-} |
- |
-void ImmersiveModeController::StartReveal(Animate animate) { |
- DCHECK_NE(ANIMATE_SLOW, animate); |
- if (reveal_state_ == CLOSED) { |
- reveal_state_ = SLIDING_OPEN; |
- // Turn on layer painting so we can smoothly animate. |
- TopContainerView* top_container = browser_view_->top_container(); |
- top_container->SetPaintToLayer(true); |
- top_container->SetFillsBoundsOpaquely(true); |
- |
- // Ensure window caption buttons are updated and the view bounds are |
- // computed at normal (non-immersive-style) size. |
- LayoutBrowserView(false); |
- |
- // Slide in the reveal view. |
- if (animate != ANIMATE_NO) |
- AnimateSlideOpen(); // Show is always fast. |
- } else if (reveal_state_ == SLIDING_CLOSED) { |
- reveal_state_ = SLIDING_OPEN; |
- // Reverse the animation. |
- AnimateSlideOpen(); |
- } |
-} |
- |
-void ImmersiveModeController::LayoutBrowserView(bool immersive_style) { |
- // Update the window caption buttons. |
- browser_view_->GetWidget()->non_client_view()->frame_view()-> |
- ResetWindowControls(); |
- browser_view_->tabstrip()->SetImmersiveStyle(immersive_style); |
- browser_view_->Layout(); |
-} |
- |
-void ImmersiveModeController::AnimateSlideOpen() { |
- ui::Layer* layer = browser_view_->top_container()->layer(); |
- // Stop any slide closed animation in progress. |
- layer->GetAnimator()->AbortAllAnimations(); |
- |
- gfx::Transform transform; |
- transform.Translate(0, -layer->bounds().height()); |
- layer->SetTransform(transform); |
- |
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); |
- settings.AddObserver(slide_open_observer_.get()); |
- settings.SetTweenType(ui::Tween::EASE_OUT); |
- settings.SetTransitionDuration( |
- base::TimeDelta::FromMilliseconds(kRevealFastAnimationDurationMs)); |
- layer->SetTransform(gfx::Transform()); |
-} |
- |
-void ImmersiveModeController::OnSlideOpenAnimationCompleted() { |
- if (reveal_state_ == SLIDING_OPEN) |
- reveal_state_ = REVEALED; |
-} |
- |
-void ImmersiveModeController::OnRevealViewLostMouse() { |
- // Stop the reveal if the top view's children don't have focus. |
- views::View* focused = browser_view_->GetFocusManager()->GetFocusedView(); |
- if (!reveal_locked_ && |
- !browser_view_->top_container()->Contains(focused)) |
- EndReveal(ANIMATE_FAST); |
-} |
- |
-void ImmersiveModeController::EndReveal(Animate animate) { |
- if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) { |
- reveal_state_ = SLIDING_CLOSED; |
- if (animate == ANIMATE_FAST) |
- AnimateSlideClosed(kRevealFastAnimationDurationMs); |
- else if (animate == ANIMATE_SLOW) |
- AnimateSlideClosed(kRevealSlowAnimationDurationMs); |
- else |
- OnSlideClosedAnimationCompleted(); |
- } |
-} |
- |
-void ImmersiveModeController::AnimateSlideClosed(int duration_ms) { |
- // Stop any slide open animation in progress, but don't skip to the end. This |
- // avoids a visual "pop" when starting a hide in the middle of a show. |
- ui::Layer* layer = browser_view_->top_container()->layer(); |
- layer->GetAnimator()->AbortAllAnimations(); |
- |
- ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); |
- settings.SetTweenType(ui::Tween::EASE_OUT); |
- settings.SetTransitionDuration( |
- base::TimeDelta::FromMilliseconds(duration_ms)); |
- settings.AddObserver(slide_closed_observer_.get()); |
- gfx::Transform transform; |
- transform.Translate(0, -layer->bounds().height()); |
- layer->SetTransform(transform); |
-} |
- |
-void ImmersiveModeController::OnSlideClosedAnimationCompleted() { |
- if (reveal_state_ == SLIDING_CLOSED) { |
- reveal_state_ = CLOSED; |
- TopContainerView* top_container = browser_view_->top_container(); |
- // Layer isn't needed after animation completes. |
- top_container->SetFillsBoundsOpaquely(false); |
- top_container->SetPaintToLayer(false); |
- // Update tabstrip for closed state. |
- LayoutBrowserView(true); |
- } |
-} |