1 // Copyright 2017 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_SPLITVIEW_SPLIT_VIEW_UTILS_H_
6 #define ASH_WM_SPLITVIEW_SPLIT_VIEW_UTILS_H_
7 
8 #include "ash/ash_export.h"
9 #include "ash/wm/splitview/split_view_controller.h"
10 #include "base/optional.h"
11 #include "ui/aura/window_observer.h"
12 #include "ui/compositor/layer_animation_observer.h"
13 #include "ui/gfx/transform.h"
14 
15 namespace aura {
16 class Window;
17 }  // namespace aura
18 
19 namespace ui {
20 class Layer;
21 }  // namespace ui
22 
23 namespace ash {
24 
25 // Enum of the different splitview mode animations. Sorted by property
26 // (opacity/transform) and then alphabetically.
27 enum SplitviewAnimationType {
28   // Used to fade in and out the highlights on either side which indicate where
29   // to drag a selector item.
30   SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN,
31   SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN_CANNOT_SNAP,
32   SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT,
33   // Used to fade in and out the other highlight. There are normally two
34   // highlights, one on each side. When entering a state with a preview
35   // highlight, one highlight is the preview highlight, and the other highlight
36   // is the other highlight.
37   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_FADE_IN,
38   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_FADE_IN_CANNOT_SNAP,
39   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_FADE_OUT,
40   // Used to fade in and out the label on the overview item which warns users
41   // the item cannot be snapped. The label appears on the overview item after
42   // another window has been snapped.
43   SPLITVIEW_ANIMATION_OVERVIEW_ITEM_FADE_IN,
44   SPLITVIEW_ANIMATION_OVERVIEW_ITEM_FADE_OUT,
45   // Used to fade in and out the preview area highlight which indicates the
46   // bounds of the window that is about to get snapped.
47   SPLITVIEW_ANIMATION_PREVIEW_AREA_FADE_IN,
48   SPLITVIEW_ANIMATION_PREVIEW_AREA_FADE_OUT,
49   // Used to fade in and out the labels which appear on either side of overview
50   // mode when a overview item is selected. They indicate where to drag the
51   // selector item if it is snappable, or if an item cannot be snapped.
52   SPLITVIEW_ANIMATION_TEXT_FADE_IN,
53   SPLITVIEW_ANIMATION_TEXT_FADE_OUT,
54   // Used when the text fades in or out with the highlights, as opposed to
55   // fading in when the highlights change bounds. Has slightly different
56   // animation values.
57   SPLITVIEW_ANIMATION_TEXT_FADE_IN_WITH_HIGHLIGHT,
58   SPLITVIEW_ANIMATION_TEXT_FADE_OUT_WITH_HIGHLIGHT,
59   // Used to slide in and out the other highlight.
60   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN,
61   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT,
62   // Used to slide in and out the text label on the other highlight.
63   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN,
64   SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT,
65   // Used to animate the inset of the preview area to nothing.
66   SPLITVIEW_ANIMATION_PREVIEW_AREA_NIX_INSET,
67   // Used to slide in and out the preview area highlight.
68   SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN,
69   SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_OUT,
70   // Used to slide in and out the text label on the preview area highlight.
71   SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN,
72   SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT,
73   // Used to apply window transform on the selector item after it gets snapped
74   // or on the dragged window after the drag ends.
75   SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM,
76 };
77 
78 // This class observes the window transform animation and relayout the window's
79 // transient bubble dialogs when animation is completed. This is needed in some
80 // splitview and overview cases as in splitview or overview, the window can have
81 // an un-identity transform in place when its bounds changed. And when this
82 // happens, its transient bubble dialogs won't have the correct bounds as the
83 // bounds are calculated based on the transformed window bounds. We'll need to
84 // manually relayout the bubble dialogs after the window's transform reset to
85 // the identity transform so that the bubble dialogs can have correct bounds.
86 class ASH_EXPORT WindowTransformAnimationObserver
87     : public ui::ImplicitAnimationObserver,
88       public aura::WindowObserver {
89  public:
90   explicit WindowTransformAnimationObserver(aura::Window* window);
91   ~WindowTransformAnimationObserver() override;
92 
93   // ui::ImplicitAnimationObserver:
94   void OnImplicitAnimationsCompleted() override;
95 
96   // aura::WindowObserver:
97   void OnWindowDestroying(aura::Window* window) override;
98 
99  private:
100   aura::Window* const window_;
101 
102   WindowTransformAnimationObserver(const WindowTransformAnimationObserver&) =
103       delete;
104   WindowTransformAnimationObserver& operator=(
105       const WindowTransformAnimationObserver&) = delete;
106 };
107 
108 // Animates |layer|'s opacity based on |type|.
109 void DoSplitviewOpacityAnimation(ui::Layer* layer, SplitviewAnimationType type);
110 
111 // Animates |layer|'s transform based on |type|.
112 void DoSplitviewTransformAnimation(
113     ui::Layer* layer,
114     SplitviewAnimationType type,
115     const gfx::Transform& target_transform,
116     std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer);
117 
118 // Animates |layer|'s clip rect based on |type|.
119 void DoSplitviewClipRectAnimation(
120     ui::Layer* layer,
121     SplitviewAnimationType type,
122     const gfx::Rect& target_clip_rect,
123     std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer);
124 
125 // Restores split view and overview based on the current split view's state.
126 // If |refresh_snapped_windows| is true, it will update the left and right
127 // snapped windows based on the MRU windows snapped states.
128 void MaybeRestoreSplitView(bool refresh_snapped_windows);
129 
130 // Returns true if we allow dragging an overview window to snap to split view in
131 // clamshell mode.
132 ASH_EXPORT bool IsClamshellSplitViewModeEnabled();
133 
134 // Checks multi-display support for overview and split view.
135 ASH_EXPORT bool AreMultiDisplayOverviewAndSplitViewEnabled();
136 
137 // Returns true if split view mode is supported.
138 ASH_EXPORT bool ShouldAllowSplitView();
139 
140 // Displays a toast notifying users the application selected for split view is
141 // not compatible.
142 ASH_EXPORT void ShowAppCannotSnapToast();
143 
144 // Calculates the snap position for a dragged window at |location_in_screen|,
145 // ignoring any properties of the window itself. The |root_window| is of the
146 // current screen. |initial_location_in_screen| is the location at drag start if
147 // the drag began in |root_window|, and is empty otherwise. To be snappable
148 // (meaning the return value is not |SplitViewController::NONE|),
149 // |location_in_screen| must be either inside |snap_distance_from_edge| or
150 // dragged toward the edge for at least |minimum_drag_distance| distance until
151 // it's dragged into a suitable edge of the work area of |root_window| (i.e.,
152 // |horizontal_edge_inset| if dragged horizontally to snap, or
153 // |vertical_edge_inset| if dragged vertically).
154 ASH_EXPORT SplitViewController::SnapPosition GetSnapPositionForLocation(
155     aura::Window* root_window,
156     const gfx::Point& location_in_screen,
157     const base::Optional<gfx::Point>& initial_location_in_screen,
158     int snap_distance_from_edge,
159     int minimum_drag_distance,
160     int horizontal_edge_inset,
161     int vertical_edge_inset);
162 
163 // Returns the desired snap position. To be snappable, |window| must 1)
164 // satisfy |SplitViewController::CanSnapWindow| for |root_window|, and
165 // 2) be snappable according to |GetSnapPositionForLocation| above.
166 // |initial_location_in_screen| is the window location at drag start in
167 // its initial window. Otherwise, the arguments are the same as above.
168 ASH_EXPORT SplitViewController::SnapPosition GetSnapPosition(
169     aura::Window* root_window,
170     aura::Window* window,
171     const gfx::Point& location_in_screen,
172     const gfx::Point& initial_location_in_screen,
173     int snap_distance_from_edge,
174     int minimum_drag_distance,
175     int horizontal_edge_inset,
176     int vertical_edge_inset);
177 
178 }  // namespace ash
179 
180 #endif  // ASH_WM_SPLITVIEW_SPLIT_VIEW_UTILS_H_
181