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