Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: athena/wm/split_view_controller.cc

Issue 420603011: Split Screen mode implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@split_view
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "athena/wm/split_view_controller.h" 5 #include "athena/wm/split_view_controller.h"
6 6
7 #include "athena/common/drag_handle.h"
8 #include "athena/wm/public/window_manager.h"
9 #include "athena/wm/window_stack_provider.h"
10 #include "base/bind.h"
7 #include "ui/aura/window.h" 11 #include "ui/aura/window.h"
12 #include "ui/compositor/layer_animation_observer.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h"
8 #include "ui/events/event_handler.h" 14 #include "ui/events/event_handler.h"
9 15
10 namespace athena { 16 namespace athena {
11 17 namespace {
12 SplitViewController::SplitViewController() { 18
19 // An animation observer that runs a callback at the end of the animation, and
20 // destroys itself.
21 class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
22 public:
23 CallbackAnimationObserver(const base::Closure& closure)
24 : closure_(closure) {
25 }
26
27 virtual ~CallbackAnimationObserver() {}
28
29 private:
30 // Overridden from ui::ImplicitAnimationObserver:
31 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
32 if (!closure_.is_null())
33 closure_.Run();
34 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
oshima 2014/07/25 21:41:10 can't you remove immediately?
mfomitchev 2014/08/05 19:56:57 Yup, looks like I can. I think this used to cause
35 }
36
37 const base::Closure closure_;
38
39 DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
40 };
41
42 } // namespace
43
44 SplitViewController::SplitViewController(
45 aura::Window* container,
46 WindowStackProvider* window_stack_provider,
47 WindowManager* window_manager)
48 : weak_factory_(this),
49 state_(INACTIVE),
50 container_(container),
51 window_manager_(window_manager),
52 window_stack_provider_(window_stack_provider),
53 current_window_(NULL),
54 left_window_(NULL),
55 right_window_(NULL),
56 separator_position_(0) {
57 window_manager->AddObserver(this);
13 } 58 }
14 59
15 SplitViewController::~SplitViewController() { 60 SplitViewController::~SplitViewController() {
16 } 61 }
17 62
63 bool SplitViewController::IsSplitViewModeActive() {
64 return state_ == ACTIVE;
65 }
66
67 void SplitViewController::Layout(bool animate) {
68 if (left_window_) {
69 CHECK(right_window_);
70 gfx::Transform left_transform;
71 gfx::Transform right_transform;
72 int container_width = container_->GetBoundsInScreen().width();
73 if (state_ == ACTIVE) {
74 left_transform.Scale(.5, 1);
75 right_transform.Scale(.5, 1);
76 right_transform.Translate(container_width, 0);
77 } else {
78 left_transform.Translate(separator_position_ - container_width, 0);
79 right_transform.Translate(separator_position_, 0);
80 }
81 left_window_->Show();
82 right_window_->Show();
83 SetWindowTransform(left_window_, left_transform, animate);
84 SetWindowTransform(right_window_, right_transform, animate);
85 }
86 }
87
88 void SplitViewController::SetWindowTransform(
89 aura::Window* window, const gfx::Transform& transform, bool animate) {
90 if (animate) {
91 scoped_refptr<ui::LayerAnimator> animator =
92 window->layer()->GetAnimator();
93 ui::ScopedLayerAnimationSettings settings(animator);
94 settings.SetPreemptionStrategy(
95 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
96 settings.AddObserver(new CallbackAnimationObserver(
97 base::Bind(&SplitViewController::AnimationCompleted,
98 weak_factory_.GetWeakPtr())));
99 //settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
100 window->SetTransform(transform);
101
102 // TODO: In the end of the animation we need to hide the window that's off
103 // screen and also set transforms for all windows to gfx::Transform
104 // (for the case where one window is animated off screen).
105 } else {
106 window->SetTransform(transform);
107 }
108 }
109
110 void SplitViewController::AnimationCompleted() {
111 LOG(ERROR) << "AnimationCompleted";
112 if (state_ == ACTIVE) {
113 gfx::Rect bounds_size = gfx::Rect(container_->GetBoundsInScreen().size());
114 int container_width = bounds_size.width();
115 bounds_size.set_width(container_width / 2);
116 left_window_->SetBounds(bounds_size);
117 left_window_->SetTransform(gfx::Transform());
118 right_window_->SetBounds(bounds_size);
119 gfx::Transform right_transform;
120 right_transform.Translate(container_width / 2, 0);
121 right_window_->SetTransform(right_transform);
122 } else {
123 int container_width = container_->GetBoundsInScreen().width();
124 left_window_->SetTransform(gfx::Transform());
125 right_window_->SetTransform(gfx::Transform());
126 if (separator_position_ == 0)
127 left_window_->Hide();
128 else if (separator_position_ == container_width)
129 right_window_->Hide();
130 }
131 }
132
133 void SplitViewController::UpdateSeparatorPositionFromScrollDelta(float delta) {
134 int container_width = container_->GetBoundsInScreen().width();
135 separator_position_ = delta > 0 ? (int) delta : container_width + delta;
136 }
137
138 aura::Window* SplitViewController::GetCurrentWindow() {
139 const aura::Window::Windows& windows =
140 window_stack_provider_->GetWindowStack();
141
142 LOG(ERROR) << "GetCurrentWindow: current_window_=" << current_window_;
143 LOG(ERROR) << "All Windows:";
144 int i = 0;
145 aura::Window::Windows::const_iterator it;
146 for (it = windows.begin(); it != windows.end(); ++it) {
147 LOG(ERROR) << " Window " << i << ": " << *it;
148 ++i;
149 }
150
151 if (windows.empty())
152 return NULL;
153 if (!current_window_)
154 current_window_ = windows.back();
155 return current_window_;
156 }
157
158 ///////////////////////////////////////////////////////////////////////////////
159 // Begin BezelController::ScrollDelegate overrides.
18 void SplitViewController::ScrollBegin(BezelController::Bezel bezel, 160 void SplitViewController::ScrollBegin(BezelController::Bezel bezel,
19 float delta) { 161 float delta) {
20 } 162 LOG(ERROR) << "ScrollBegin";
21 163 if (!CanScroll())
164 return;
165 state_ = SCROLLING;
166 aura::Window* current_window = GetCurrentWindow();
167 CHECK(current_window);
168
169 const aura::Window::Windows& windows =
170 window_stack_provider_->GetWindowStack();
171 CHECK(windows.size() >= 2);
172 aura::Window::Windows::const_iterator it = std::find(
173 windows.begin(), windows.end(), current_window);
174 CHECK(it != windows.end());
175
176 if (delta > 0) {
177 right_window_ = current_window;
178 // reverse iterator points to the position before normal iterator |it|
179 aura::Window::Windows::const_reverse_iterator rev_it(it);
180 // circle to end if needed.
181 left_window_ = rev_it == windows.rend() ? windows.back() : *(rev_it);
182 } else {
183 left_window_ = current_window;
184 ++it;
185 // circle to front if needed.
186 right_window_ = it == windows.end() ? windows.front() : *it;
187 }
188
189 CHECK(left_window_);
190 CHECK(right_window_);
191
192 // HACK until we are properly hiding windows in window manager
193 // Loop through all windows and hide them
194 for (it = windows.begin(); it != windows.end(); ++it) {
195 if (*it != left_window_ && *it != right_window_)
196 (*it)->Hide();
197 }
198
199 LOG(ERROR) << "left_window_=" << left_window_
200 << ", right_window_=" << right_window_;
201
202 // END HACK
203 /*
204 it = std::find(windows.begin(), windows.end(), left_window_);
205 size_t index_left = std::distance(windows.begin(), it);
206 it = std::find(windows.begin(), windows.end(), right_window_);
207 size_t index_right = std::distance(windows.begin(), it);
208 LOG(ERROR) << "IndexLeft=" << index_left
209 << ", IndexRight=" << index_right;
210 */
211
212 UpdateSeparatorPositionFromScrollDelta(delta);
213 Layout(false);
214 }
215
216 // Max distance from the scroll end position to the middle of the screen where
217 // we would go into the split view mode.
218 const int kMaxDistanceFromMiddle = 120;
22 void SplitViewController::ScrollEnd() { 219 void SplitViewController::ScrollEnd() {
220 LOG(ERROR) << "ScrollEnd";
221 if (state_ != SCROLLING)
222 return;
223
224 int cont_width = container_->GetBoundsInScreen().width();
225 if (abs(cont_width / 2 - separator_position_) <= kMaxDistanceFromMiddle) {
226 state_ = ACTIVE;
227 separator_position_ = cont_width / 2;
228 LOG(ERROR) << "Entering split view mode!";
229 } else if (separator_position_ < cont_width / 2) {
230 separator_position_ = 0;
231 current_window_ = right_window_;
232 state_ = INACTIVE;
233 } else {
234 separator_position_ = cont_width;
235 current_window_ = left_window_;
236 state_ = INACTIVE;
237 }
238 Layout(true);
23 } 239 }
24 240
25 void SplitViewController::ScrollUpdate(float delta) { 241 void SplitViewController::ScrollUpdate(float delta) {
242 if (state_ != SCROLLING)
243 return;
244 UpdateSeparatorPositionFromScrollDelta(delta);
245 Layout(false);
26 } 246 }
27 247
28 bool SplitViewController::CanScroll() { 248 bool SplitViewController::CanScroll() {
29 return false; 249 // TODO (mfomitchev): return false in vertical orientation, in full screen.
250 bool result = (!window_manager_->IsOverviewModeActive() &&
251 !IsSplitViewModeActive() &&
252 window_stack_provider_->GetWindowStack().size() >= 2);
253 return result;
254 }
255
256 ///////////////////////////////////////////////////////////////////////////////
257 // WindowManagerObserver overrides
258 void SplitViewController::OnOverviewModeEnter() {
259 if (state_ == ACTIVE) {
260 CHECK(left_window_);
261 CHECK(right_window_);
262 window_stack_provider_->MoveWindowToFront(right_window_);
263 window_stack_provider_->MoveWindowToFront(left_window_);
264 // TODO (mfomitchev): This shouldn't be done here, but the overview mode's
265 // transition animation currently looks bad if the starting transform of
266 // any window is not gfx::Transform().
267 right_window_->SetTransform(gfx::Transform());
268 } else if (current_window_) {
269 window_stack_provider_->MoveWindowToFront(current_window_);
270 }
271 current_window_ = NULL;
272 left_window_ = NULL;
273 right_window_ = NULL;
274 state_ = INACTIVE;
30 } 275 }
31 276
32 } // namespace athena 277 } // namespace athena
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698