1 // Copyright 2014 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 ATHENA_WM_SPLIT_VIEW_CONTROLLER_H_ 6 #define ATHENA_WM_SPLIT_VIEW_CONTROLLER_H_ 7 8 #include "athena/athena_export.h" 9 #include "athena/util/drag_handle.h" 10 #include "athena/wm/bezel_controller.h" 11 #include "athena/wm/public/window_manager_observer.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 15 namespace gfx { 16 class Rect; 17 class Transform; 18 } 19 20 namespace aura { 21 class ScopedWindowTargeter; 22 class Window; 23 class WindowTargeter; 24 } 25 26 namespace views { 27 class ViewTargeterDelegate; 28 class Widget; 29 } 30 31 namespace athena { 32 class WindowListProvider; 33 34 // Responsible for entering split view mode, exiting from split view mode, and 35 // laying out the windows in split view mode. 36 class ATHENA_EXPORT SplitViewController 37 : public BezelController::ScrollDelegate, 38 public DragHandleScrollDelegate, 39 public WindowManagerObserver { 40 public: 41 SplitViewController(aura::Window* container, 42 WindowListProvider* window_list_provider); 43 44 virtual ~SplitViewController(); 45 46 bool CanActivateSplitViewMode() const; 47 bool IsSplitViewModeActive() const; 48 49 // Activates split-view mode with |left| and |right| windows. If |left| and/or 50 // |right| is NULL, then the first window in the window-list (which is neither 51 // |left| nor |right|) is selected instead. |to_activate| indicates which of 52 // |left| or |right| should be activated. If |to_activate| is NULL, the 53 // currently active window is kept active if it is one of the split-view 54 // windows. 55 void ActivateSplitMode(aura::Window* left, 56 aura::Window* right, 57 aura::Window* to_activate); 58 59 // Resets the internal state to an inactive state. 60 void DeactivateSplitMode(); 61 62 // Replaces |window| in split-view mode with |replace_with|. Adjusts 63 // |replace_with|'s visibility, transform and bounds. Resets |window|'s 64 // visibility and transform but does not change its bounds. 65 void ReplaceWindow(aura::Window* window, 66 aura::Window* replace_with); 67 68 // Returns the bounds of the left and right parts of the |container_| based 69 // on the current value of |divider_position_|. 70 gfx::Rect GetLeftAreaBounds(); 71 gfx::Rect GetRightAreaBounds(); 72 73 aura::Window* left_window() { return left_window_; } 74 aura::Window* right_window() { return right_window_; } 75 76 private: 77 enum State { 78 // Split View mode is not active. |left_window_| and |right_window| are 79 // NULL. 80 INACTIVE, 81 // Two windows |left_window_| and |right_window| are shown side by side and 82 // there is a horizontal scroll in progress which is dragging the divider 83 // between the two windows. 84 SCROLLING, 85 // Split View mode is active with |left_window_| and |right_window| showing 86 // side by side each occupying half the screen. No scroll in progress. 87 ACTIVE 88 }; 89 90 void SetState(State state); 91 92 void InitializeDivider(); 93 void HideDivider(); 94 void ShowDivider(); 95 96 void UpdateLayout(bool animate); 97 98 void SetWindowTransforms(const gfx::Transform& left_transform, 99 const gfx::Transform& right_transform, 100 const gfx::Transform& divider_transform, 101 bool animate); 102 103 // Called when the animation initiated by SetWindowTransforms() completes. 104 void OnAnimationCompleted(); 105 106 // Returns the default divider position for when the split view mode is 107 // active and the divider is not being dragged. 108 int GetDefaultDividerPosition(); 109 110 // BezelController::ScrollDelegate: 111 virtual void BezelScrollBegin(BezelController::Bezel bezel, 112 float delta) OVERRIDE; 113 virtual void BezelScrollEnd() OVERRIDE; 114 virtual void BezelScrollUpdate(float delta) OVERRIDE; 115 virtual bool BezelCanScroll() OVERRIDE; 116 117 // DragHandleScrollDelegate: 118 virtual void HandleScrollBegin(float delta) OVERRIDE; 119 virtual void HandleScrollEnd() OVERRIDE; 120 virtual void HandleScrollUpdate(float delta) OVERRIDE; 121 122 // WindowManagerObserver: 123 virtual void OnOverviewModeEnter() OVERRIDE; 124 virtual void OnOverviewModeExit() OVERRIDE; 125 virtual void OnSplitViewModeEnter() OVERRIDE; 126 virtual void OnSplitViewModeExit() OVERRIDE; 127 128 State state_; 129 130 aura::Window* container_; 131 132 // Provider of the list of windows to cycle through. Not owned. 133 WindowListProvider* window_list_provider_; 134 135 // Windows for the left and right activities shown in SCROLLING and ACTIVE 136 // states. In INACTIVE state these are NULL. 137 aura::Window* left_window_; 138 aura::Window* right_window_; 139 140 // X-Coordinate of the (center of the) divider between left_window_ and 141 // right_window_ in |container_| coordinates. 142 int divider_position_; 143 144 // Meaningful only when state_ is SCROLLING. 145 // X-Coordinate of the divider when the scroll started. 146 int divider_scroll_start_position_; 147 148 // Visually separates the windows and contains the drag handle. 149 views::Widget* divider_widget_; 150 151 // The drag handle which can be used when split view is active to exit the 152 // split view mode. 153 views::View* drag_handle_; 154 155 scoped_ptr<aura::ScopedWindowTargeter> window_targeter_; 156 scoped_ptr<views::ViewTargeterDelegate> view_targeter_delegate_; 157 158 // Windows which should be hidden when the animation initiated by 159 // UpdateLayout() completes. 160 std::vector<aura::Window*> to_hide_; 161 162 base::WeakPtrFactory<SplitViewController> weak_factory_; 163 164 DISALLOW_COPY_AND_ASSIGN(SplitViewController); 165 }; 166 167 } // namespace athena 168 169 #endif // ATHENA_WM_SPLIT_VIEW_CONTROLLER_H_ 170