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

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: Addressing mukai's review feedback. Created 6 years, 4 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/wm/public/window_manager.h"
8 #include "base/bind.h"
7 #include "ui/aura/window.h" 9 #include "ui/aura/window.h"
10 #include "ui/compositor/layer_animation_observer.h"
11 #include "ui/compositor/scoped_layer_animation_settings.h"
8 #include "ui/events/event_handler.h" 12 #include "ui/events/event_handler.h"
13 #include "ui/gfx/display.h"
14 #include "ui/gfx/screen.h"
15 #include "ui/wm/core/window_list_provider.h"
9 16
10 namespace athena { 17 namespace athena {
11 18 namespace {
12 SplitViewController::SplitViewController() { 19
20 // An animation observer that runs a callback at the end of the animation, and
21 // destroys itself.
22 class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
23 public:
24 CallbackAnimationObserver(const base::Closure& closure)
oshima 2014/08/06 21:54:09 explicit
mfomitchev 2014/08/08 16:03:22 Done.
25 : closure_(closure) {
26 }
27
28 virtual ~CallbackAnimationObserver() {}
29
30 private:
31 // Overridden from ui::ImplicitAnimationObserver:
32 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
33 if (!closure_.is_null())
34 closure_.Run();
35 delete this;
36 }
37
38 const base::Closure closure_;
39
40 DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
41 };
42
43 } // namespace
44
45 SplitViewController::SplitViewController(
46 aura::Window* container,
47 wm::WindowListProvider* window_list_provider,
48 WindowManager* window_manager)
49 : weak_factory_(this),
50 state_(INACTIVE),
51 container_(container),
52 window_manager_(window_manager),
53 window_list_provider_(window_list_provider),
54 current_window_(NULL),
55 left_window_(NULL),
56 right_window_(NULL),
57 separator_position_(0) {
58 window_manager->AddObserver(this);
13 } 59 }
14 60
15 SplitViewController::~SplitViewController() { 61 SplitViewController::~SplitViewController() {
16 } 62 }
17 63
64 bool SplitViewController::IsSplitViewModeActive() {
65 return state_ == ACTIVE;
66 }
67
68 void SplitViewController::Layout(bool animate) {
69 if (left_window_) {
70 CHECK(right_window_);
71 gfx::Transform left_transform;
72 gfx::Transform right_transform;
73 int container_width = container_->GetBoundsInScreen().width();
oshima 2014/08/06 21:54:09 This should be work area. (there is a small area a
mfomitchev 2014/08/08 16:03:22 Wouldn't the activities' container already set to
oshima 2014/08/08 16:45:34 Container is the same size of the root window. You
mfomitchev 2014/08/08 17:40:50 Ok. How can I get the size of the "work area"? I'd
oshima 2014/08/08 18:00:40 Yes, that's a bug that we need to fix. I'll addres
74 if (state_ == ACTIVE) {
75 left_transform.Scale(.5, 1);
76 right_transform.Scale(.5, 1);
oshima 2014/08/06 21:54:09 doesn't this make window stretched vertically?
mfomitchev 2014/08/08 16:03:22 Yes, but that will be fixed in OnAnimationCOmplete
77 right_transform.Translate(container_width, 0);
78 } else {
79 left_transform.Translate(separator_position_ - container_width, 0);
80 right_transform.Translate(separator_position_, 0);
81 }
82 left_window_->Show();
83 right_window_->Show();
84 SetWindowTransform(left_window_, left_transform, animate);
85 SetWindowTransform(right_window_, right_transform, animate);
86 }
87 }
88
89 void SplitViewController::SetWindowTransform(
90 aura::Window* window, const gfx::Transform& transform, bool animate) {
91 if (animate) {
92 scoped_refptr<ui::LayerAnimator> animator =
93 window->layer()->GetAnimator();
94 ui::ScopedLayerAnimationSettings settings(animator);
95 settings.SetPreemptionStrategy(
96 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
97 settings.AddObserver(new CallbackAnimationObserver(
98 base::Bind(&SplitViewController::AnimationCompleted,
99 weak_factory_.GetWeakPtr())));
100 //settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
101 window->SetTransform(transform);
102
103 // TODO: In the end of the animation we need to hide the window that's off
104 // screen and also set transforms for all windows to gfx::Transform
105 // (for the case where one window is animated off screen).
106 } else {
107 window->SetTransform(transform);
108 }
109 }
110
111 void SplitViewController::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 gfx::Screen* screen = gfx::Screen::GetScreenFor(container_);
135 const gfx::Rect& display_bounds =
136 screen->GetDisplayNearestWindow(container_).bounds();
137 gfx::Rect container_bounds = container_->GetBoundsInScreen();
138 separator_position_ = delta > 0 ?
139 ((int) delta) + display_bounds.x() - container_bounds.x() :
140 display_bounds.right() - container_bounds.x() + delta;
141 }
142
143 aura::Window* SplitViewController::GetCurrentWindow() {
144 if (!current_window_) {
145 aura::Window::Windows windows = window_list_provider_->GetWindowList();
146 if (windows.empty())
147 return NULL;
148 current_window_ = windows.back();
149 }
150 return current_window_;
151 }
152
153 ///////////////////////////////////////////////////////////////////////////////
154 // Begin BezelController::ScrollDelegate overrides.
18 void SplitViewController::ScrollBegin(BezelController::Bezel bezel, 155 void SplitViewController::ScrollBegin(BezelController::Bezel bezel,
19 float delta) { 156 float delta) {
20 } 157 if (!CanScroll())
21 158 return;
159 state_ = SCROLLING;
160 aura::Window* current_window = GetCurrentWindow();
161 CHECK(current_window);
162
163 aura::Window::Windows windows = window_list_provider_->GetWindowList();
164 CHECK(windows.size() >= 2);
165 aura::Window::Windows::const_iterator it = std::find(
166 windows.begin(), windows.end(), current_window);
167 CHECK(it != windows.end());
168
169 if (delta > 0) {
170 right_window_ = current_window;
171 // reverse iterator points to the position before normal iterator |it|
172 aura::Window::Windows::const_reverse_iterator rev_it(it);
173 // circle to end if needed.
174 left_window_ = rev_it == windows.rend() ? windows.back() : *(rev_it);
175 } else {
176 left_window_ = current_window;
177 ++it;
178 // circle to front if needed.
179 right_window_ = it == windows.end() ? windows.front() : *it;
180 }
181
182 CHECK(left_window_);
183 CHECK(right_window_);
184
185 // TODO (mfomitchev):
186 // HACK until we are properly hiding off-screen windows in window manager
187 // Loop through all windows and hide them
oshima 2014/08/06 21:54:09 add me on TODO and crbug.com/388362
mfomitchev 2014/08/08 16:03:22 Done.
188 for (it = windows.begin(); it != windows.end(); ++it) {
189 if (*it != left_window_ && *it != right_window_)
190 (*it)->Hide();
191 }
192 // END HACK
oshima 2014/08/06 21:54:09 remove HACK/END HACK (as it's obvious)
mfomitchev 2014/08/08 16:03:22 Done.
193
194 UpdateSeparatorPositionFromScrollDelta(delta);
195 Layout(false);
196 }
197
198 // Max distance from the scroll end position to the middle of the screen where
199 // we would go into the split view mode.
200 const int kMaxDistanceFromMiddle = 120;
22 void SplitViewController::ScrollEnd() { 201 void SplitViewController::ScrollEnd() {
202 if (state_ != SCROLLING)
203 return;
204
205 int cont_width = container_->GetBoundsInScreen().width();
206 if (abs(cont_width / 2 - separator_position_) <= kMaxDistanceFromMiddle) {
oshima 2014/08/06 21:54:09 std::abs include <cmath>
mfomitchev 2014/08/08 16:03:22 Done.
207 state_ = ACTIVE;
208 separator_position_ = cont_width / 2;
209 } else if (separator_position_ < cont_width / 2) {
210 separator_position_ = 0;
211 current_window_ = right_window_;
212 state_ = INACTIVE;
213 } else {
214 separator_position_ = cont_width;
215 current_window_ = left_window_;
216 state_ = INACTIVE;
217 }
218 Layout(true);
23 } 219 }
24 220
25 void SplitViewController::ScrollUpdate(float delta) { 221 void SplitViewController::ScrollUpdate(float delta) {
222 if (state_ != SCROLLING)
223 return;
224 UpdateSeparatorPositionFromScrollDelta(delta);
225 Layout(false);
26 } 226 }
27 227
28 bool SplitViewController::CanScroll() { 228 bool SplitViewController::CanScroll() {
29 return false; 229 // TODO (mfomitchev): return false in vertical orientation, in full screen.
30 } 230 bool result = (!window_manager_->IsOverviewModeActive() &&
231 !IsSplitViewModeActive() &&
232 window_list_provider_->GetWindowList().size() >= 2);
233 return result;
234 }
235
236 ///////////////////////////////////////////////////////////////////////////////
237 // WindowManagerObserver overrides
238 void SplitViewController::OnOverviewModeEnter() {
239 if (state_ == ACTIVE) {
240 CHECK(left_window_);
241 CHECK(right_window_);
242 window_list_provider_->MoveToFront(right_window_);
243 window_list_provider_->MoveToFront(left_window_);
244 // TODO (mfomitchev): This shouldn't be done here, but the overview mode's
245 // transition animation currently looks bad if the starting transform of
246 // any window is not gfx::Transform().
247 right_window_->SetTransform(gfx::Transform());
248 } else if (current_window_) {
249 window_list_provider_->MoveToFront(current_window_);
250 }
251 current_window_ = NULL;
252 left_window_ = NULL;
253 right_window_ = NULL;
254 state_ = INACTIVE;
255 }
256
257 void SplitViewController::OnOverviewModeExit() {}
31 258
32 } // namespace athena 259 } // namespace athena
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698