1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_ 6 #define CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_ 7 8 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" 9 10 #include "base/timer/timer.h" 11 #include "content/public/browser/notification_observer.h" 12 #include "content/public/browser/notification_registrar.h" 13 #include "ui/aura/window_observer.h" 14 #include "ui/base/animation/animation_delegate.h" 15 #include "ui/base/events/event_handler.h" 16 #include "ui/gfx/rect.h" 17 #include "ui/views/focus/focus_manager.h" 18 #include "ui/views/widget/widget_observer.h" 19 20 class BrowserView; 21 class BookmarkBarView; 22 23 namespace aura { 24 class Window; 25 } 26 27 namespace gfx { 28 class Transform; 29 } 30 31 namespace ui { 32 class Layer; 33 class LocatedEvent; 34 class SlideAnimation; 35 } 36 37 namespace views { 38 class View; 39 } 40 41 class ImmersiveModeControllerAsh : public ImmersiveModeController, 42 public content::NotificationObserver, 43 public ui::AnimationDelegate, 44 public ui::EventHandler, 45 public views::FocusChangeListener, 46 public views::WidgetObserver, 47 public aura::WindowObserver { 48 public: 49 ImmersiveModeControllerAsh(); 50 virtual ~ImmersiveModeControllerAsh(); 51 52 // These methods are used to increment and decrement |revealed_lock_count_|. 53 // If immersive mode is enabled, a transition from 1 to 0 in 54 // |revealed_lock_count_| closes the top-of-window views and a transition 55 // from 0 to 1 in |revealed_lock_count_| reveals the top-of-window views. 56 void LockRevealedState(AnimateReveal animate_reveal); 57 void UnlockRevealedState(); 58 59 // Exits immersive fullscreen based on |native_window_|'s show state. 60 void MaybeExitImmersiveFullscreen(); 61 62 // ImmersiveModeController overrides: 63 virtual void Init(Delegate* delegate, 64 views::Widget* widget, 65 views::View* top_container) OVERRIDE; 66 virtual void SetEnabled(bool enabled) OVERRIDE; 67 virtual bool IsEnabled() const OVERRIDE; 68 virtual bool ShouldHideTabIndicators() const OVERRIDE; 69 virtual bool ShouldHideTopViews() const OVERRIDE; 70 virtual bool IsRevealed() const OVERRIDE; 71 virtual int GetTopContainerVerticalOffset( 72 const gfx::Size& top_container_size) const OVERRIDE; 73 virtual ImmersiveRevealedLock* GetRevealedLock( 74 AnimateReveal animate_reveal) OVERRIDE WARN_UNUSED_RESULT; 75 virtual void OnFindBarVisibleBoundsChanged( 76 const gfx::Rect& new_visible_bounds_in_screen) OVERRIDE; 77 78 // content::NotificationObserver override: 79 virtual void Observe(int type, 80 const content::NotificationSource& source, 81 const content::NotificationDetails& details) OVERRIDE; 82 83 // ui::EventHandler overrides: 84 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; 85 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; 86 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 87 88 // views::FocusChangeObserver overrides: 89 virtual void OnWillChangeFocus(views::View* focused_before, 90 views::View* focused_now) OVERRIDE; 91 virtual void OnDidChangeFocus(views::View* focused_before, 92 views::View* focused_now) OVERRIDE; 93 94 // views::WidgetObserver overrides: 95 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; 96 virtual void OnWidgetActivationChanged(views::Widget* widget, 97 bool active) OVERRIDE; 98 99 // ui::AnimationDelegate overrides: 100 virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; 101 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; 102 103 // aura::WindowObserver overrides: 104 virtual void OnWindowPropertyChanged(aura::Window* window, 105 const void* key, 106 intptr_t old) OVERRIDE; 107 virtual void OnAddTransientChild(aura::Window* window, 108 aura::Window* transient) OVERRIDE; 109 virtual void OnRemoveTransientChild(aura::Window* window, 110 aura::Window* transient) OVERRIDE; 111 112 // Testing interface. 113 void SetForceHideTabIndicatorsForTest(bool force); 114 void StartRevealForTest(bool hovered); 115 void SetMouseHoveredForTest(bool hovered); 116 void DisableAnimationsForTest(); 117 118 private: 119 friend class ImmersiveModeControllerAshTest; 120 121 enum AllowRevealWhileClosing { 122 ALLOW_REVEAL_WHILE_CLOSING_YES, 123 ALLOW_REVEAL_WHILE_CLOSING_NO 124 }; 125 enum Animate { 126 ANIMATE_NO, 127 ANIMATE_SLOW, 128 ANIMATE_FAST, 129 }; 130 enum Layout { 131 LAYOUT_YES, 132 LAYOUT_NO 133 }; 134 enum RevealState { 135 CLOSED, // Top container only showing tabstrip, y = 0. 136 SLIDING_OPEN, // All views showing, y animating from -height to 0. 137 REVEALED, // All views showing, y = 0. 138 SLIDING_CLOSED, // All views showing, y animating from 0 to -height. 139 }; 140 enum TabIndicatorVisibility { 141 TAB_INDICATORS_FORCE_HIDE, 142 TAB_INDICATORS_HIDE, 143 TAB_INDICATORS_SHOW 144 }; 145 enum SwipeType { 146 SWIPE_OPEN, 147 SWIPE_CLOSE, 148 SWIPE_NONE 149 }; 150 151 // Enables or disables observers for mouse move, focus, and window restore. 152 void EnableWindowObservers(bool enable); 153 154 // Updates |top_edge_hover_timer_| based on a mouse |event|. If the mouse is 155 // hovered at the top of the screen the timer is started. If the mouse moves 156 // away from the top edge, or moves too much in the x direction, the timer is 157 // stopped. 158 void UpdateTopEdgeHoverTimer(ui::MouseEvent* event); 159 160 // Updates |located_event_revealed_lock_| based on the current mouse state and 161 // the current touch state. 162 // |event| is NULL if the source event is not known. 163 // |allow_reveal_while_closing| indicates whether the mouse and touch 164 // are allowed to initiate a reveal while the top-of-window views are sliding 165 // closed. 166 void UpdateLocatedEventRevealedLock( 167 ui::LocatedEvent* event, 168 AllowRevealWhileClosing allow_reveal_while_closing); 169 170 // Acquires |located_event_revealed_lock_| if it is not already held. 171 void AcquireLocatedEventRevealedLock(); 172 173 // Updates |focus_revealed_lock_| based on the currently active view and the 174 // currently active widget. 175 void UpdateFocusRevealedLock(); 176 177 // Update |located_event_revealed_lock_| and |focus_revealed_lock_| as a 178 // result of a gesture of |swipe_type|. Returns true if any locks were 179 // acquired or released. 180 bool UpdateRevealedLocksForSwipe(SwipeType swipe_type); 181 182 // Updates whether fullscreen uses any chrome at all. When using minimal 183 // chrome, a 'light bar' is permanently visible for the launcher and possibly 184 // for the tabstrip. 185 void UpdateUseMinimalChrome(Layout layout); 186 187 // Returns the animation duration given |animate|. 188 int GetAnimationDuration(Animate animate) const; 189 190 // Temporarily reveals the top-of-window views while in immersive mode, 191 // hiding them when the cursor exits the area of the top views. If |animate| 192 // is not ANIMATE_NO, slides in the view, otherwise shows it immediately. 193 void MaybeStartReveal(Animate animate); 194 195 // Enables or disables layer-based painting to allow smooth animations. 196 void EnablePaintToLayer(bool enable); 197 198 // Updates the browser root view's layout including window caption controls. 199 void LayoutBrowserRootView(); 200 201 // Called when the animation to slide open the top-of-window views has 202 // completed. 203 void OnSlideOpenAnimationCompleted(Layout layout); 204 205 // Hides the top-of-window views if immersive mode is enabled and nothing is 206 // keeping them revealed. Optionally animates. 207 void MaybeEndReveal(Animate animate); 208 209 // Called when the animation to slide out the top-of-window views has 210 // completed. 211 void OnSlideClosedAnimationCompleted(); 212 213 // Returns whether immersive fullscreen should be exited based on 214 // |native_window_|'s show state. This handles cases where the user has 215 // exited immersive fullscreen without going through 216 // FullscreenController::ToggleFullscreenMode(). This is the case if the 217 // user exits fullscreen via the restore button. 218 bool ShouldExitImmersiveFullscreen() const; 219 220 // Returns the type of swipe given |event|. 221 SwipeType GetSwipeType(ui::GestureEvent* event) const; 222 223 // Returns true if a mouse event at |location_in_screen| should be ignored. 224 // Ignored mouse events should not contribute to revealing or unrevealing the 225 // top-of-window views. 226 bool ShouldIgnoreMouseEventAtLocation( 227 const gfx::Point& location_in_screen) const; 228 229 // True when |location| is "near" to the top container. When the top container 230 // is not closed "near" means within the displayed bounds or above it. When 231 // the top container is closed "near" means either within the displayed 232 // bounds, above it, or within a few pixels below it. This allow the container 233 // to steal enough pixels to detect a swipe in and handles the case that there 234 // is a bezel sensor above the top container. 235 bool ShouldHandleGestureEvent(const gfx::Point& location) const; 236 237 // Recreate |bubble_manager_| and start observing any bubbles anchored to a 238 // child of |top_container_|. 239 void RecreateBubbleManager(); 240 241 // Shrinks or expands the touch hit test by updating insets for the render 242 // window depending on if top_inset is positive or negative respectively. 243 // Used to ensure that touch events at the top of the screen go to the top 244 // container so a slide gesture can be generated when the content window is 245 // consuming all touch events sent to it. 246 void SetRenderWindowTopInsetsForTouch(int top_inset); 247 248 // Injected dependencies. Not owned. 249 Delegate* delegate_; 250 views::Widget* widget_; 251 views::View* top_container_; 252 253 // True if the window observers are enabled. 254 bool observers_enabled_; 255 256 // True when in immersive mode. 257 bool enabled_; 258 259 // State machine for the revealed/closed animations. 260 RevealState reveal_state_; 261 262 int revealed_lock_count_; 263 264 // The visibility of the miniature "tab indicators" in the main browser view 265 // when immersive mode is enabled and the top-of-window views are closed. 266 TabIndicatorVisibility tab_indicator_visibility_; 267 268 // Timer to track cursor being held at the top edge of the screen. 269 base::OneShotTimer<ImmersiveModeController> top_edge_hover_timer_; 270 271 // The cursor x position in screen coordinates when the cursor first hit the 272 // top edge of the screen. 273 int mouse_x_when_hit_top_in_screen_; 274 275 // Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the 276 // following events. 277 bool gesture_begun_; 278 279 // The current visible bounds of the find bar, in screen coordinates. This is 280 // an empty rect if the find bar is not visible. 281 gfx::Rect find_bar_visible_bounds_in_screen_; 282 283 // Lock which keeps the top-of-window views revealed based on the current 284 // mouse state and the current touch state. Acquiring the lock is used to 285 // trigger a reveal when the user moves the mouse to the top of the screen 286 // and when the user does a SWIPE_OPEN edge gesture. 287 scoped_ptr<ImmersiveRevealedLock> located_event_revealed_lock_; 288 289 // Lock which keeps the top-of-window views revealed based on the focused view 290 // and the active widget. Acquiring the lock never triggers a reveal because 291 // a view is not focusable till a reveal has made it visible. 292 scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_; 293 294 // Native window for the browser. 295 aura::Window* native_window_; 296 297 // The animation which controls sliding the top-of-window views in and out. 298 scoped_ptr<ui::SlideAnimation> animation_; 299 300 // Whether the animations are disabled for testing. 301 bool animations_disabled_for_test_; 302 303 // Manages bubbles which are anchored to a child of |top_container_|. 304 class BubbleManager; 305 scoped_ptr<BubbleManager> bubble_manager_; 306 307 content::NotificationRegistrar registrar_; 308 309 base::WeakPtrFactory<ImmersiveModeControllerAsh> weak_ptr_factory_; 310 311 DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAsh); 312 }; 313 314 #endif // CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_ 315