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 3 // found in the LICENSE file. 4 5 #ifndef ASH_WM_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ 6 #define ASH_WM_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ 7 8 #include <vector> 9 10 #include "ash/ash_export.h" 11 #include "ash/wm/immersive_revealed_lock.h" 12 #include "base/timer/timer.h" 13 #include "ui/aura/window_observer.h" 14 #include "ui/events/event_handler.h" 15 #include "ui/gfx/animation/animation_delegate.h" 16 #include "ui/views/focus/focus_manager.h" 17 #include "ui/views/widget/widget_observer.h" 18 19 namespace aura { 20 class Window; 21 } 22 23 namespace gfx { 24 class Point; 25 class Rect; 26 class SlideAnimation; 27 } 28 29 namespace ui { 30 class LocatedEvent; 31 } 32 33 namespace views { 34 class View; 35 class Widget; 36 } 37 38 namespace ash { 39 40 class ASH_EXPORT ImmersiveFullscreenController 41 : public gfx::AnimationDelegate, 42 public ui::EventHandler, 43 public views::FocusChangeListener, 44 public views::WidgetObserver, 45 public aura::WindowObserver, 46 public ImmersiveRevealedLock::Delegate { 47 public: 48 // The enum is used for an enumerated histogram. New items should be only 49 // added to the end. 50 enum WindowType { 51 WINDOW_TYPE_OTHER, 52 WINDOW_TYPE_BROWSER, 53 WINDOW_TYPE_HOSTED_APP, 54 WINDOW_TYPE_PACKAGED_APP, 55 WINDOW_TYPE_COUNT 56 }; 57 58 class Delegate { 59 public: 60 // Called when a reveal of the top-of-window views starts. 61 virtual void OnImmersiveRevealStarted() = 0; 62 63 // Called when the top-of-window views have finished closing. This call 64 // implies a visible fraction of 0. SetVisibleFraction(0) may not be called 65 // prior to OnImmersiveRevealEnded(). 66 virtual void OnImmersiveRevealEnded() = 0; 67 68 // Called as a result of disabling immersive fullscreen via SetEnabled(). 69 virtual void OnImmersiveFullscreenExited() = 0; 70 71 // Called to update the fraction of the top-of-window views height which is 72 // visible. 73 virtual void SetVisibleFraction(double visible_fraction) = 0; 74 75 // Returns a list of rects whose union makes up the top-of-window views. 76 // The returned list is used for hittesting when the top-of-window views 77 // are revealed. GetVisibleBoundsInScreen() must return a valid value when 78 // not in immersive fullscreen for the sake of SetupForTest(). 79 virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const = 0; 80 81 protected: 82 virtual ~Delegate() {} 83 }; 84 85 ImmersiveFullscreenController(); 86 virtual ~ImmersiveFullscreenController(); 87 88 // Initializes the controller. Must be called prior to enabling immersive 89 // fullscreen via SetEnabled(). |top_container| is used to keep the 90 // top-of-window views revealed when a child of |top_container| has focus. 91 // |top_container| does not affect which mouse and touch events keep the 92 // top-of-window views revealed. 93 void Init(Delegate* delegate, 94 views::Widget* widget, 95 views::View* top_container); 96 97 // Enables or disables immersive fullscreen. 98 // |window_type| is the type of window which is put in immersive fullscreen. 99 // It is only used for histogramming. 100 void SetEnabled(WindowType window_type, bool enable); 101 102 // Returns true if |native_window_| is in immersive fullscreen. 103 bool IsEnabled() const; 104 105 // Returns true if |native_window_| is in immersive fullscreen and the 106 // top-of-window views are fully or partially visible. 107 bool IsRevealed() const; 108 109 // Returns a lock which will keep the top-of-window views revealed for its 110 // lifetime. Several locks can be obtained. When all of the locks are 111 // destroyed, if immersive fullscreen is enabled and there is nothing else 112 // keeping the top-of-window views revealed, the top-of-window views will be 113 // closed. This method always returns a valid lock regardless of whether 114 // immersive fullscreen is enabled. The lock's lifetime can span immersive 115 // fullscreen being enabled / disabled. If acquiring the lock causes a reveal, 116 // the top-of-window views will animate according to |animate_reveal|. The 117 // caller takes ownership of the returned lock. 118 ImmersiveRevealedLock* GetRevealedLock( 119 AnimateReveal animate_reveal) WARN_UNUSED_RESULT; 120 121 // Disables animations and moves the mouse so that it is not over the 122 // top-of-window views for the sake of testing. 123 void SetupForTest(); 124 125 // ui::EventHandler overrides: 126 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; 127 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; 128 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 129 130 // views::FocusChangeObserver overrides: 131 virtual void OnWillChangeFocus(views::View* focused_before, 132 views::View* focused_now) OVERRIDE; 133 virtual void OnDidChangeFocus(views::View* focused_before, 134 views::View* focused_now) OVERRIDE; 135 136 // views::WidgetObserver overrides: 137 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; 138 virtual void OnWidgetActivationChanged(views::Widget* widget, 139 bool active) OVERRIDE; 140 141 // gfx::AnimationDelegate overrides: 142 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 143 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 144 145 // aura::WindowObserver overrides: 146 virtual void OnAddTransientChild(aura::Window* window, 147 aura::Window* transient) OVERRIDE; 148 virtual void OnRemoveTransientChild(aura::Window* window, 149 aura::Window* transient) OVERRIDE; 150 151 // ash::ImmersiveRevealedLock::Delegate overrides: 152 virtual void LockRevealedState(AnimateReveal animate_reveal) OVERRIDE; 153 virtual void UnlockRevealedState() OVERRIDE; 154 155 private: 156 friend class ImmersiveFullscreenControllerTest; 157 158 enum Animate { 159 ANIMATE_NO, 160 ANIMATE_SLOW, 161 ANIMATE_FAST, 162 }; 163 enum RevealState { 164 CLOSED, 165 SLIDING_OPEN, 166 REVEALED, 167 SLIDING_CLOSED, 168 }; 169 enum SwipeType { 170 SWIPE_OPEN, 171 SWIPE_CLOSE, 172 SWIPE_NONE 173 }; 174 175 // Enables or disables observers for mouse, touch, focus, and activation. 176 void EnableWindowObservers(bool enable); 177 178 // Updates |top_edge_hover_timer_| based on a mouse |event|. If the mouse is 179 // hovered at the top of the screen the timer is started. If the mouse moves 180 // away from the top edge, or moves too much in the x direction, the timer is 181 // stopped. 182 void UpdateTopEdgeHoverTimer(ui::MouseEvent* event); 183 184 // Updates |located_event_revealed_lock_| based on the current mouse state and 185 // the current touch state. 186 // |event| is NULL if the source event is not known. 187 void UpdateLocatedEventRevealedLock(ui::LocatedEvent* event); 188 189 // Acquires |located_event_revealed_lock_| if it is not already held. 190 void AcquireLocatedEventRevealedLock(); 191 192 // Updates |focus_revealed_lock_| based on the currently active view and the 193 // currently active widget. 194 void UpdateFocusRevealedLock(); 195 196 // Update |located_event_revealed_lock_| and |focus_revealed_lock_| as a 197 // result of a gesture of |swipe_type|. Returns true if any locks were 198 // acquired or released. 199 bool UpdateRevealedLocksForSwipe(SwipeType swipe_type); 200 201 // Returns the animation duration given |animate|. 202 int GetAnimationDuration(Animate animate) const; 203 204 // Temporarily reveals the top-of-window views while in immersive mode, 205 // hiding them when the cursor exits the area of the top views. If |animate| 206 // is not ANIMATE_NO, slides in the view, otherwise shows it immediately. 207 void MaybeStartReveal(Animate animate); 208 209 // Called when the animation to slide open the top-of-window views has 210 // completed. 211 void OnSlideOpenAnimationCompleted(); 212 213 // Hides the top-of-window views if immersive mode is enabled and nothing is 214 // keeping them revealed. Optionally animates. 215 void MaybeEndReveal(Animate animate); 216 217 // Called when the animation to slide out the top-of-window views has 218 // completed. 219 void OnSlideClosedAnimationCompleted(); 220 221 // Returns the type of swipe given |event|. 222 SwipeType GetSwipeType(ui::GestureEvent* event) const; 223 224 // Returns true if a mouse event at |location_in_screen| should be ignored. 225 // Ignored mouse events should not contribute to revealing or unrevealing the 226 // top-of-window views. 227 bool ShouldIgnoreMouseEventAtLocation( 228 const gfx::Point& location_in_screen) const; 229 230 // True when |location| is "near" to the top container. When the top container 231 // is not closed "near" means within the displayed bounds or above it. When 232 // the top container is closed "near" means either within the displayed 233 // bounds, above it, or within a few pixels below it. This allow the container 234 // to steal enough pixels to detect a swipe in and handles the case that there 235 // is a bezel sensor above the top container. 236 bool ShouldHandleGestureEvent(const gfx::Point& location) const; 237 238 // Recreate |bubble_manager_| and start observing any bubbles anchored to a 239 // child of |top_container_|. 240 void RecreateBubbleManager(); 241 242 // Not owned. 243 Delegate* delegate_; 244 views::View* top_container_; 245 views::Widget* widget_; 246 aura::Window* native_window_; 247 248 // True if the observers have been enabled. 249 bool observers_enabled_; 250 251 // True when in immersive fullscreen. 252 bool enabled_; 253 254 // State machine for the revealed/closed animations. 255 RevealState reveal_state_; 256 257 int revealed_lock_count_; 258 259 // Timer to track cursor being held at the top edge of the screen. 260 base::OneShotTimer<ImmersiveFullscreenController> top_edge_hover_timer_; 261 262 // The cursor x position in screen coordinates when the cursor first hit the 263 // top edge of the screen. 264 int mouse_x_when_hit_top_in_screen_; 265 266 // Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the 267 // following events. 268 bool gesture_begun_; 269 270 // Lock which keeps the top-of-window views revealed based on the current 271 // mouse state and the current touch state. Acquiring the lock is used to 272 // trigger a reveal when the user moves the mouse to the top of the screen 273 // and when the user does a SWIPE_OPEN edge gesture. 274 scoped_ptr<ImmersiveRevealedLock> located_event_revealed_lock_; 275 276 // Lock which keeps the top-of-window views revealed based on the focused view 277 // and the active widget. Acquiring the lock never triggers a reveal because 278 // a view is not focusable till a reveal has made it visible. 279 scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_; 280 281 // The animation which controls sliding the top-of-window views in and out. 282 scoped_ptr<gfx::SlideAnimation> animation_; 283 284 // Whether the animations are disabled for testing. 285 bool animations_disabled_for_test_; 286 287 // Manages bubbles which are anchored to a child of |top_container_|. 288 class BubbleManager; 289 scoped_ptr<BubbleManager> bubble_manager_; 290 291 base::WeakPtrFactory<ImmersiveFullscreenController> weak_ptr_factory_; 292 293 DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenController); 294 }; 295 296 } // namespace ash 297 298 #endif // ASH_WM_IMMERSIVE_FULLSCREEN_CONTROLLER_H_ 299