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_OVERVIEW_OVERVIEW_SESSION_H_ 6 #define ASH_WM_OVERVIEW_OVERVIEW_SESSION_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <vector> 13 14 #include "ash/ash_export.h" 15 #include "ash/public/cpp/shelf_types.h" 16 #include "ash/shell_observer.h" 17 #include "ash/wm/overview/overview_types.h" 18 #include "ash/wm/overview/scoped_overview_hide_windows.h" 19 #include "ash/wm/splitview/split_view_controller.h" 20 #include "ash/wm/splitview/split_view_drag_indicators.h" 21 #include "ash/wm/splitview/split_view_observer.h" 22 #include "base/containers/flat_set.h" 23 #include "base/macros.h" 24 #include "base/time/time.h" 25 #include "ui/aura/window_observer.h" 26 #include "ui/display/display_observer.h" 27 #include "ui/events/event_handler.h" 28 #include "ui/wm/public/activation_change_observer.h" 29 30 namespace gfx { 31 class PointF; 32 } // namespace gfx 33 34 namespace ui { 35 class KeyEvent; 36 } // namespace ui 37 38 namespace views { 39 class Widget; 40 } // namespace views 41 42 namespace ash { 43 class OverviewDelegate; 44 class OverviewGrid; 45 class OverviewHighlightController; 46 class OverviewItem; 47 class OverviewWindowDragController; 48 class RoundedLabelWidget; 49 50 // The Overview shows a grid of all of your windows, allowing to select 51 // one by clicking or tapping on it. 52 class ASH_EXPORT OverviewSession : public display::DisplayObserver, 53 public aura::WindowObserver, 54 public ui::EventHandler, 55 public ShellObserver, 56 public SplitViewObserver { 57 public: 58 using WindowList = std::vector<aura::Window*>; 59 60 explicit OverviewSession(OverviewDelegate* delegate); 61 ~OverviewSession() override; 62 63 // Initialize with the windows that can be selected. 64 void Init(const WindowList& windows, const WindowList& hide_windows); 65 66 // Perform cleanup that cannot be done in the destructor. 67 void Shutdown(); 68 69 // Called when the last overview item from a grid is deleted. 70 void OnGridEmpty(); 71 72 // Moves the current selection forwards or backwards. 73 void IncrementSelection(bool forward); 74 75 // Accepts current selection if any. Returns true if a selection was made, 76 // false otherwise. 77 bool AcceptSelection(); 78 79 // Activates |item's| window. 80 void SelectWindow(OverviewItem* item); 81 82 // Sets the dragged window on the split view drag indicators. 83 void SetSplitViewDragIndicatorsDraggedWindow(aura::Window* dragged_window); 84 85 // If |state_on_root_window_being_dragged_in| is kNoDrag, this function sets 86 // the state on every root window to kNoDrag. Otherwise it sets the state on 87 // |root_window_being_dragged_in| to |state_on_root_window_being_dragged_in|, 88 // and sets the state on other root windows to kOtherDisplay. 89 void UpdateSplitViewDragIndicatorsWindowDraggingStates( 90 const aura::Window* root_window_being_dragged_in, 91 SplitViewDragIndicators::WindowDraggingState 92 state_on_root_window_being_dragged_in); 93 94 // Sets the state on every root window to kNoDrag. 95 void ResetSplitViewDragIndicatorsWindowDraggingStates(); 96 97 // See |OverviewGrid::RearrangeDuringDrag|. 98 void RearrangeDuringDrag(OverviewItem* dragged_item); 99 100 // Updates the appearance of each drop target to visually indicate when the 101 // dragged window is being dragged over it. 102 void UpdateDropTargetsBackgroundVisibilities( 103 OverviewItem* dragged_item, 104 const gfx::PointF& location_in_screen); 105 106 // Retrieves the window grid whose root window matches |root_window|. Returns 107 // nullptr if the window grid is not found. 108 OverviewGrid* GetGridWithRootWindow(aura::Window* root_window); 109 110 // Adds |window| at the specified |index| into the grid with the same root 111 // window. Does nothing if that grid does not exist in |grid_list_| or already 112 // contains |window|. If |reposition| is true, repositions all items in the 113 // target grid (unless it already contained |window|), except those in 114 // |ignored_items|. If |animate| is true, animates the repositioning. 115 // |animate| has no effect if |reposition| is false. 116 void AddItem(aura::Window* window, 117 bool reposition, 118 bool animate, 119 const base::flat_set<OverviewItem*>& ignored_items, 120 size_t index); 121 122 // Similar to the above function, but adds the window at the end of the grid. 123 // This will use the spawn-item animation. 124 // TODO(afakhry): Expose |use_spawn_animation| if needed. 125 void AppendItem(aura::Window* window, bool reposition, bool animate); 126 127 // Like |AddItem|, but adds |window| at the correct position according to MRU 128 // order. If |reposition|, |animate|, and |restack| are all true, the stacking 129 // order will be adjusted after the animation. If |restack| is true but at 130 // least one of |reposition| and |animate| is false, the stacking order will 131 // be adjusted immediately. 132 void AddItemInMruOrder(aura::Window* window, 133 bool reposition, 134 bool animate, 135 bool restack); 136 137 // Removes |overview_item| from the corresponding grid. 138 void RemoveItem(OverviewItem* overview_item); 139 void RemoveItem(OverviewItem* overview_item, 140 bool item_destroying, 141 bool reposition); 142 143 void RemoveDropTargets(); 144 145 void InitiateDrag(OverviewItem* item, 146 const gfx::PointF& location_in_screen, 147 bool is_touch_dragging); 148 void Drag(OverviewItem* item, const gfx::PointF& location_in_screen); 149 void CompleteDrag(OverviewItem* item, const gfx::PointF& location_in_screen); 150 void StartNormalDragMode(const gfx::PointF& location_in_screen); 151 void Fling(OverviewItem* item, 152 const gfx::PointF& location_in_screen, 153 float velocity_x, 154 float velocity_y); 155 void ActivateDraggedWindow(); 156 void ResetDraggedWindowGesture(); 157 158 // Called when a window (either it's browser window or an app window) 159 // start/continue/end being dragged in tablet mode by swiping from the top 160 // of the screen to drag from top or by swiping from the shelf to drag from 161 // bottom . 162 // TODO(xdai): Currently it doesn't work for multi-display scenario. 163 void OnWindowDragStarted(aura::Window* dragged_window, bool animate); 164 void OnWindowDragContinued( 165 aura::Window* dragged_window, 166 const gfx::PointF& location_in_screen, 167 SplitViewDragIndicators::WindowDraggingState window_dragging_state); 168 void OnWindowDragEnded(aura::Window* dragged_window, 169 const gfx::PointF& location_in_screen, 170 bool should_drop_window_into_overview, 171 bool snap); 172 // Shows or Hides all windows (including drop target window & desk widget) in 173 // overview. It's used when dragging a window from bottom, when the user slows 174 // down or stops dragging the window, shows overview windows and when the user 175 // resumes dragging, hides overview windows. 176 void SetVisibleDuringWindowDragging(bool visible, bool animate); 177 178 // Positions all overview items except those in |ignored_items|. 179 void PositionWindows(bool animate, 180 const base::flat_set<OverviewItem*>& ignored_items = {}); 181 182 // Returns true if |window| is currently showing in overview. 183 bool IsWindowInOverview(const aura::Window* window); 184 185 // Returns the overview item for |window|, or nullptr if |window| doesn't have 186 // a corresponding item in overview mode. 187 OverviewItem* GetOverviewItemForWindow(const aura::Window* window); 188 189 // Set the window grid that's displaying in |root_window| not animate when 190 // exiting overview mode, i.e., all window items in the grid will not animate 191 // when exiting overview mode. It may be called in two cases: 1) When a window 192 // gets snapped (either from overview or not) and thus cause the end of the 193 // overview mode, we should not do the exiting animation; 2) When a window 194 // is dragged around and when released, it causes the end of the overview 195 // mode, we also should not do the exiting animation. 196 void SetWindowListNotAnimatedWhenExiting(aura::Window* root_window); 197 198 // Shifts and fades the grid in |grid_list_| associated with |location|. 199 200 // Updates all the overview items' mask and shadow. 201 void UpdateRoundedCornersAndShadow(); 202 203 // Called when the overview mode starting animation completes. |canceled| is 204 // true when the starting animation is interrupted by ending overview mode. If 205 // |canceled| is false and |should_focus_overview| is true, then 206 // |overview_focus_widget_| shall gain focus. |should_focus_overview| has no 207 // effect when |canceled| is true. 208 void OnStartingAnimationComplete(bool canceled, bool should_focus_overview); 209 210 // Called when windows are being activated/deactivated during 211 // overview mode. 212 void OnWindowActivating( 213 ::wm::ActivationChangeObserver::ActivationReason reason, 214 aura::Window* gained_active, 215 aura::Window* lost_active); 216 217 // Gets the window which keeps focus for the duration of overview mode. 218 aura::Window* GetOverviewFocusWindow(); 219 220 // Returns the window highlighted by the selector widget. 221 aura::Window* GetHighlightedWindow(); 222 223 // Suspends/Resumes window re-positiong in overview. 224 void SuspendReposition(); 225 void ResumeReposition(); 226 227 // Returns true if all its window grids don't have any window item. 228 bool IsEmpty() const; 229 230 // If |focus| is true, restores focus to |restore_focus_window_|. Sets 231 // |restore_focus_window_| to null regardless of |focus|. 232 void ResetFocusRestoreWindow(bool focus); 233 234 // Handles requests to active or close the currently highlighted |item|. 235 void OnHighlightedItemActivated(OverviewItem* item); 236 void OnHighlightedItemClosed(OverviewItem* item); 237 238 // Called explicitly (with no list of observers) by the |RootWindowController| 239 // of |root|, so that the associated grid is properly removed and destroyed. 240 // Note: Usually, when a display is removed, it causes a window activation 241 // which ends overview mode, and then this function does not get called. This 242 // function is only needed for when overview mode cannot be ended (see 243 // |OverviewController::CanEndOverview| and https://crbug.com/1024325). 244 void OnRootWindowClosing(aura::Window* root); 245 246 // Returns the current dragged overview item if any. Note that windows that 247 // are dragged into overview from the shelf don't have an OverviewItem while 248 // dragging. 249 OverviewItem* GetCurrentDraggedOverviewItem() const; 250 251 // Overview objects which handle events (OverviewItemView, 252 // OverviewGridEventHandler) should call this function to check if they can 253 // process an event. Returns false if an overview item other than |sender| 254 // (which may be nullptr in the case of events on the wallpaper) is already 255 // being dragged, or if a window is currently being dragged from the bottom. 256 // This is so we can allow switching finger while dragging, but not allow 257 // dragging two or more items. The first |CanProcessEvent()| calls the second 258 // with |sender| as nullptr (i.e. event processed by 259 // OverviewGridEventHandler). When |sender| is nullptr, |from_touch_gesture| 260 // does not matter. 261 bool CanProcessEvent() const; 262 bool CanProcessEvent(OverviewItem* sender, bool from_touch_gesture) const; 263 264 // display::DisplayObserver: 265 void OnDisplayAdded(const display::Display& display) override; 266 void OnDisplayMetricsChanged(const display::Display& display, 267 uint32_t metrics) override; 268 269 // aura::WindowObserver: 270 void OnWindowDestroying(aura::Window* window) override; 271 272 // ShelObserver: 273 void OnShellDestroying() override; 274 void OnShelfAlignmentChanged(aura::Window* root_window, 275 ShelfAlignment old_alignment) override; 276 277 // ui::EventHandler: 278 void OnKeyEvent(ui::KeyEvent* event) override; 279 280 // SplitViewObserver: 281 void OnSplitViewStateChanged(SplitViewController::State previous_state, 282 SplitViewController::State state) override; 283 void OnSplitViewDividerPositionChanged() override; 284 delegate()285 OverviewDelegate* delegate() { return delegate_; } 286 is_shutting_down()287 bool is_shutting_down() const { return is_shutting_down_; } set_is_shutting_down(bool is_shutting_down)288 void set_is_shutting_down(bool is_shutting_down) { 289 is_shutting_down_ = is_shutting_down; 290 } 291 grid_list()292 const std::vector<std::unique_ptr<OverviewGrid>>& grid_list() const { 293 return grid_list_; 294 } 295 num_items()296 size_t num_items() const { return num_items_; } 297 enter_exit_overview_type()298 OverviewEnterExitType enter_exit_overview_type() const { 299 return enter_exit_overview_type_; 300 } set_enter_exit_overview_type(OverviewEnterExitType val)301 void set_enter_exit_overview_type(OverviewEnterExitType val) { 302 enter_exit_overview_type_ = val; 303 } 304 window_drag_controller()305 OverviewWindowDragController* window_drag_controller() { 306 return window_drag_controller_.get(); 307 } 308 highlight_controller()309 OverviewHighlightController* highlight_controller() { 310 return highlight_controller_.get(); 311 } 312 no_windows_widget_for_testing()313 RoundedLabelWidget* no_windows_widget_for_testing() { 314 return no_windows_widget_.get(); 315 } 316 317 private: 318 friend class DesksAcceleratorsTest; 319 friend class OverviewSessionTest; 320 class AccessibilityFocusAnnotator; 321 322 // Helper function that moves the highlight forward or backward on the 323 // corresponding window grid. 324 void Move(bool reverse); 325 326 // Helper function that processes a key event and maybe scrolls the overview 327 // grid on the primary display. 328 bool ProcessForScrolling(const ui::KeyEvent& event); 329 330 // Removes all observers that were registered during construction and/or 331 // initialization. 332 void RemoveAllObservers(); 333 334 void UpdateNoWindowsWidget(); 335 336 void RefreshNoWindowsWidgetBounds(bool animate); 337 338 void OnItemAdded(aura::Window* window); 339 340 // Weak pointer to the overview delegate which will be called when a selection 341 // is made. 342 OverviewDelegate* delegate_; 343 344 // A weak pointer to the window which was focused on starting overview. If 345 // overview is canceled the focus should be restored to this window. 346 aura::Window* restore_focus_window_ = nullptr; 347 348 // A hidden window that receives focus while in overview mode. It is needed 349 // because accessibility needs something focused for it to work and we cannot 350 // use one of the overview windows otherwise wm::ActivateWindow will not 351 // work. 352 // TODO(sammiequon): Focus the grid desks widget if it is always available, or 353 // we may be able to add some mechanism to trigger accessibility events 354 // without a focused window. 355 std::unique_ptr<views::Widget> overview_focus_widget_; 356 357 // A widget that is shown if we entered overview without any windows opened. 358 std::unique_ptr<RoundedLabelWidget> no_windows_widget_; 359 360 // True when performing operations that may cause window activations. This is 361 // used to prevent handling the resulting expected activation. This is 362 // initially true until this is initialized. 363 bool ignore_activations_ = true; 364 365 // True when overview mode is exiting. 366 bool is_shutting_down_ = false; 367 368 // List of all the window overview grids, one for each root window. 369 std::vector<std::unique_ptr<OverviewGrid>> grid_list_; 370 371 // The following variables are used for metric collection purposes. All of 372 // them refer to this particular overview session and are not cumulative: 373 // The time when overview was started. 374 base::Time overview_start_time_; 375 376 // The number of arrow key presses. 377 size_t num_key_presses_ = 0; 378 379 // The number of items in the overview. 380 size_t num_items_ = 0; 381 382 // True if we are currently using keyboard (control + left/right) to scroll 383 // through the grid. 384 bool is_keyboard_scrolling_grid_ = false; 385 386 // Stores the overview enter/exit type. See the enum declaration for 387 // information on how these types affect overview mode. 388 OverviewEnterExitType enter_exit_overview_type_ = 389 OverviewEnterExitType::kNormal; 390 391 // The selected item when exiting overview mode. nullptr if no window 392 // selected. 393 OverviewItem* selected_item_ = nullptr; 394 395 // The drag controller for a window in the overview mode. 396 std::unique_ptr<OverviewWindowDragController> window_drag_controller_; 397 398 std::unique_ptr<ScopedOverviewHideWindows> hide_overview_windows_; 399 400 std::unique_ptr<OverviewHighlightController> highlight_controller_; 401 402 // Updates accessibility with the correct focus order among all overview 403 // widgets. 404 std::unique_ptr<AccessibilityFocusAnnotator> accessibility_focus_annotator_; 405 406 DISALLOW_COPY_AND_ASSIGN(OverviewSession); 407 }; 408 409 } // namespace ash 410 411 #endif // ASH_WM_OVERVIEW_OVERVIEW_SESSION_H_ 412