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

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

Issue 545393002: Adding split view divider widget. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing sadrul's feedback Created 6 years, 3 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 <cmath> 7 #include <cmath>
8 8
9 #include "athena/screen/public/screen_manager.h" 9 #include "athena/screen/public/screen_manager.h"
10 #include "athena/wm/public/window_list_provider.h" 10 #include "athena/wm/public/window_list_provider.h"
11 #include "athena/wm/public/window_manager.h" 11 #include "athena/wm/public/window_manager.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "ui/aura/scoped_window_targeter.h"
13 #include "ui/aura/window.h" 14 #include "ui/aura/window.h"
15 #include "ui/aura/window_delegate.h"
16 #include "ui/aura/window_targeter.h"
17 #include "ui/base/cursor/cursor.h"
18 #include "ui/base/hit_test.h"
14 #include "ui/compositor/closure_animation_observer.h" 19 #include "ui/compositor/closure_animation_observer.h"
15 #include "ui/compositor/layer_animation_observer.h" 20 #include "ui/compositor/layer.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h" 21 #include "ui/compositor/scoped_layer_animation_settings.h"
17 #include "ui/events/event_handler.h" 22 #include "ui/events/event_handler.h"
18 #include "ui/gfx/display.h" 23 #include "ui/gfx/display.h"
19 #include "ui/gfx/screen.h" 24 #include "ui/gfx/screen.h"
25 #include "ui/views/widget/root_view.h"
26 #include "ui/views/widget/root_view_targeter.h"
27 #include "ui/views/widget/widget.h"
20 #include "ui/wm/core/window_util.h" 28 #include "ui/wm/core/window_util.h"
29 #include "ui/wm/public/window_types.h"
21 30
22 namespace athena { 31 namespace athena {
23 32
24 namespace { 33 namespace {
25 34
26 // Returns a target transform which is suitable for animating a windows's 35 const int kDragHandleWidth = 4;
27 // bounds. 36 const int kDragHandleHeight = 80;
28 gfx::Transform GetTargetTransformForBoundsAnimation(const gfx::Rect& from, 37 const int kDividerWidth = 6;
29 const gfx::Rect& to) { 38
39 // TODO(mfomitchev): Should this be moved to ui/views?
40
41 // Always returns the same target.
42 class StaticViewTargeterDelegate : public views::ViewTargeterDelegate {
43 public:
44 explicit StaticViewTargeterDelegate(views::View* target) : target_(target) {}
45
46 virtual ~StaticViewTargeterDelegate() {}
47
48 private:
49 // views::ViewTargeterDelegate
tdanderson 2014/09/15 17:48:19 nit: missing : at end.
mfomitchev 2014/09/15 21:43:47 Done.
50 virtual views::View* TargetForRect(views::View* root,
51 const gfx::Rect& rect) OVERRIDE {
52 return target_;
53 }
54
55 // Not owned.
56 views::View* target_;
57
58 DISALLOW_COPY_AND_ASSIGN(StaticViewTargeterDelegate);
59 };
60
61 // TODO(mfomitchev): This is a copy of EmptyWindowDelegate in
62 // ash/root_window_controller.cc. Should we move this somewhere we can reuse in
63 // both ash and athena? It looks like mojo::DummyDelegate could use this as
64 // well.
65 // Perhaps we could have ui/aura/empty_window_delegate.h or
66 // aura::CreateEmptyWIndowDelegate() in ui/aura/window_delegate.h
67
68 // A window delegate which does nothing. Used to create a window that
69 // is a event target, but do nothing.
70 class EmptyWindowDelegate : public aura::WindowDelegate {
71 public:
72 EmptyWindowDelegate() {}
73 virtual ~EmptyWindowDelegate() {}
74
75 // aura::WindowDelegate overrides:
76 virtual gfx::Size GetMinimumSize() const OVERRIDE {
77 return gfx::Size();
78 }
79 virtual gfx::Size GetMaximumSize() const OVERRIDE {
80 return gfx::Size();
81 }
82 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
83 const gfx::Rect& new_bounds) OVERRIDE {}
84 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
85 return gfx::kNullCursor;
86 }
87 virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
88 return HTNOWHERE;
89 }
90 virtual bool ShouldDescendIntoChildForEventHandling(
91 aura::Window* child,
92 const gfx::Point& location) OVERRIDE {
93 return false;
94 }
95 virtual bool CanFocus() OVERRIDE {
96 return false;
97 }
98 virtual void OnCaptureLost() OVERRIDE {}
99 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {}
100 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
101 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
102 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
103 delete this;
104 }
105 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
106 virtual bool HasHitTestMask() const OVERRIDE {
107 return false;
108 }
109 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
110
111 private:
112 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
113 };
114
115 // Expands the effective target area of a window ensuring it is easy to touch.
116 // If the window is big enough to begin with, there should be no change from
117 // the default targeting behavior.
118 class PriorityWindowTargeter : public aura::WindowTargeter,
119 public aura::WindowObserver {
120 public:
121 explicit PriorityWindowTargeter(aura::Window* priority_window)
122 : priority_window_(priority_window) {
123 DCHECK(priority_window);
124 priority_window->AddObserver(this);
125 }
126
127 virtual ~PriorityWindowTargeter() {
128 priority_window_->RemoveObserver(this);
129 }
130
131 private:
132 bool ShouldProcessEvent(ui::EventType event_type) {
133 return event_type == ui::ET_TOUCH_PRESSED;
134 }
135
136 // aura::WindowTargeter:
137 virtual ui::EventTarget* FindTargetForLocatedEvent(
138 ui::EventTarget* root,
139 ui::LocatedEvent* event) OVERRIDE {
140 if (!priority_window_ || (event->type() != ui::ET_TOUCH_PRESSED))
141 return WindowTargeter::FindTargetForLocatedEvent(root, event);
142
143 gfx::Rect window_bounds = priority_window_->GetBoundsInRootWindow();
144 gfx::Transform window_transform = priority_window_->layer()->transform();
145 gfx::RectF transformed_bounds_f = window_bounds;
146 window_transform.TransformRect(&transformed_bounds_f);
147 gfx::Rect transformed_bounds = gfx::Rect(transformed_bounds_f.x(),
148 transformed_bounds_f.y(),
149 transformed_bounds_f.width(),
150 transformed_bounds_f.height());
151
152 gfx::Point window_center = transformed_bounds.CenterPoint();
153 gfx::Rect extension_rect = gfx::Rect(
154 window_center.x() - kMinTouchDimension / 2,
155 window_center.y() - kMinTouchDimension / 2,
156 kMinTouchDimension,
157 kMinTouchDimension);
158 gfx::Rect extended_bounds =
159 gfx::UnionRects(transformed_bounds, extension_rect);
160 if (extended_bounds.Contains(event->root_location().x(),
161 event->root_location().y())) {
162 root->ConvertEventToTarget(priority_window_, event);
163 return priority_window_;
164 }
165
166 return WindowTargeter::FindTargetForLocatedEvent(root, event);
167 }
168
169 // aura::WindowObserver:
170 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
171 DCHECK_EQ(window, priority_window_);
172 priority_window_->RemoveObserver(this);
173 priority_window_ = NULL;
174 }
175
176 // Minimum dimension of a target to be comfortably touchable.
177 // The effective touch target area of |priority_window_| gets expanded so
178 // that it's width and height is ayt least |kMinTouchDimension|.
179 int const kMinTouchDimension = 26;
180
181 aura::Window* priority_window_;
182
183 DISALLOW_COPY_AND_ASSIGN(PriorityWindowTargeter);
184 };
185
186 // Returns a target transform required to transform |from| to |to|.
187 gfx::Transform GetTransformForBounds(const gfx::Rect& from,
188 const gfx::Rect& to) {
30 gfx::Transform transform; 189 gfx::Transform transform;
31 transform.Translate(to.x() - from.x(), to.y() - from.y()); 190 transform.Translate(to.x() - from.x(), to.y() - from.y());
32 transform.Scale(to.width() / static_cast<float>(from.width()), 191 transform.Scale(to.width() / static_cast<float>(from.width()),
33 to.height() / static_cast<float>(from.height())); 192 to.height() / static_cast<float>(from.height()));
34 return transform; 193 return transform;
35 } 194 }
36 195
37 bool IsLandscapeOrientation(gfx::Display::Rotation rotation) { 196 bool IsLandscapeOrientation(gfx::Display::Rotation rotation) {
38 return rotation == gfx::Display::ROTATE_0 || 197 return rotation == gfx::Display::ROTATE_0 ||
39 rotation == gfx::Display::ROTATE_180; 198 rotation == gfx::Display::ROTATE_180;
40 } 199 }
41 200
42 } // namespace 201 } // namespace
43 202
44 SplitViewController::SplitViewController( 203 SplitViewController::SplitViewController(
45 aura::Window* container, 204 aura::Window* container,
46 WindowListProvider* window_list_provider) 205 WindowListProvider* window_list_provider)
47 : state_(INACTIVE), 206 : state_(INACTIVE),
48 container_(container), 207 container_(container),
49 window_list_provider_(window_list_provider), 208 window_list_provider_(window_list_provider),
50 left_window_(NULL), 209 left_window_(NULL),
51 right_window_(NULL), 210 right_window_(NULL),
52 separator_position_(0), 211 divider_position_(0),
212 divider_widget_(NULL),
53 weak_factory_(this) { 213 weak_factory_(this) {
54 } 214 }
55 215
56 SplitViewController::~SplitViewController() { 216 SplitViewController::~SplitViewController() {
57 } 217 }
58 218
59 bool SplitViewController::IsSplitViewModeActive() const { 219 bool SplitViewController::IsSplitViewModeActive() const {
60 return state_ == ACTIVE; 220 return state_ == ACTIVE;
61 } 221 }
62 222
(...skipping 24 matching lines...) Expand all
87 247
88 if (!right && iter != windows.rend()) { 248 if (!right && iter != windows.rend()) {
89 right = *iter; 249 right = *iter;
90 iter++; 250 iter++;
91 if (right == left && iter != windows.rend()) { 251 if (right == left && iter != windows.rend()) {
92 right = *iter; 252 right = *iter;
93 iter++; 253 iter++;
94 } 254 }
95 } 255 }
96 256
257 int container_width = container_->GetBoundsInScreen().width();
258 divider_position_ = container_width / 2;
97 SetState(ACTIVE); 259 SetState(ACTIVE);
98 right_window_ = right; 260 right_window_ = right;
99 left_window_ = left; 261 left_window_ = left;
100 UpdateLayout(true); 262 UpdateLayout(true);
101 } 263 }
102 264
103 void SplitViewController::ReplaceWindow(aura::Window* window, 265 void SplitViewController::ReplaceWindow(aura::Window* window,
104 aura::Window* replace_with) { 266 aura::Window* replace_with) {
105 CHECK(IsSplitViewModeActive()); 267 CHECK(IsSplitViewModeActive());
106 CHECK(replace_with); 268 CHECK(replace_with);
(...skipping 15 matching lines...) Expand all
122 window->Hide(); 284 window->Hide();
123 } 285 }
124 286
125 void SplitViewController::DeactivateSplitMode() { 287 void SplitViewController::DeactivateSplitMode() {
126 CHECK_EQ(ACTIVE, state_); 288 CHECK_EQ(ACTIVE, state_);
127 SetState(INACTIVE); 289 SetState(INACTIVE);
128 UpdateLayout(false); 290 UpdateLayout(false);
129 left_window_ = right_window_ = NULL; 291 left_window_ = right_window_ = NULL;
130 } 292 }
131 293
132 gfx::Rect SplitViewController::GetLeftTargetBounds() { 294 void SplitViewController::InitializeDivider() {
133 gfx::Rect work_area = 295 CHECK(!divider_widget_);
134 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area(); 296 CHECK(!divider_window_);
135 return gfx::Rect(0, 0, container_->bounds().width() / 2, work_area.height()); 297
298 divider_window_.reset(new aura::Window(new EmptyWindowDelegate()));
299 divider_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
300 divider_window_->Init(aura::WINDOW_LAYER_SOLID_COLOR);
301 divider_window_->layer()->SetColor(SK_ColorBLACK);
302 int container_height = container_->bounds().height();
303 divider_window_->SetBounds(
304 gfx::Rect(-kDividerWidth / 2, 0, kDividerWidth, container_height));
305 container_->AddChild(divider_window_.get());
306 container_->StackChildAtTop(divider_window_.get());
307
308 views::View* divider_view = CreateDragHandleView(DragHandle::HORIZONTAL,
309 this,
310 kDragHandleWidth,
311 kDragHandleHeight,
312 1);
313 divider_widget_ = new views::Widget();
314 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
315 params.parent = container_;
316 params.accept_events = true;
317 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
318 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
319 params.bounds = gfx::Rect(-kDragHandleWidth / 2,
320 container_height / 2 - kDragHandleHeight / 2,
321 kDragHandleWidth,
322 kDragHandleHeight);
323 divider_widget_->Init(params);
324 divider_widget_->SetContentsView(divider_view);
325
326 // Install a static view targeter on the root view which always targets
327 // divider_view.
328 // TODO(mfomitchev,tdanderson): This should not be needed:
329 // 1. divider_view is the only view and it completely overlaps the root view,
330 // 2. The logic in ViewTargeterDelegate::TargetForRect could be improved to
331 // work better for views that are narrow in one dimension and long in
332 // another dimension.
333 views::internal::RootView* root_view =
334 static_cast<views::internal::RootView*>(divider_widget_->GetRootView());
335 views::View* target_view = divider_view;
336 views::ViewTargeter* targeter = new views::RootViewTargeter(
337 new StaticViewTargeterDelegate(target_view),
338 root_view);
339 divider_widget_->GetRootView()->SetEventTargeter(
340 scoped_ptr<views::ViewTargeter>(targeter));
136 } 341 }
137 342
138 gfx::Rect SplitViewController::GetRightTargetBounds() { 343 void SplitViewController::HideDivider() {
139 gfx::Rect work_area = 344 divider_widget_->Hide();
140 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area(); 345 divider_window_->Hide();
346 window_targeter_.reset();
347 }
348
349 void SplitViewController::ShowDivider() {
350 divider_widget_->Show();
351 divider_window_->Show();
352 if (!window_targeter_) {
353 scoped_ptr<ui::EventTargeter> window_targeter =
354 scoped_ptr<ui::EventTargeter>(
355 new PriorityWindowTargeter(divider_widget_->GetNativeWindow()));
356 window_targeter_.reset(
357 new aura::ScopedWindowTargeter(container_, window_targeter.Pass()));
358 }
359 }
360
361 gfx::Rect SplitViewController::GetLeftAreaBounds() {
362 int container_height = container_->bounds().height();
363 return gfx::Rect(
364 0, 0, divider_position_ - kDividerWidth / 2, container_height);
365 }
366
367 gfx::Rect SplitViewController::GetRightAreaBounds() {
141 int container_width = container_->bounds().width(); 368 int container_width = container_->bounds().width();
142 return gfx::Rect( 369 int container_height = container_->bounds().height();
143 container_width / 2, 0, container_width / 2, work_area.height()); 370 return gfx::Rect(divider_position_ + kDividerWidth / 2,
371 0,
372 container_width - divider_position_ - kDividerWidth / 2,
373 container_height);
144 } 374 }
145 375
146 void SplitViewController::SetState(SplitViewController::State state) { 376 void SplitViewController::SetState(SplitViewController::State state) {
147 if (state_ == state) 377 if (state_ == state)
148 return; 378 return;
149 379
380 if (divider_widget_ == NULL) {
381 InitializeDivider();
sadrul 2014/09/15 16:53:31 Remove {}
mfomitchev 2014/09/15 17:44:20 Done.
382 }
383
150 state_ = state; 384 state_ = state;
385
151 ScreenManager::Get()->SetRotationLocked(state_ != INACTIVE); 386 ScreenManager::Get()->SetRotationLocked(state_ != INACTIVE);
387 if (state == INACTIVE)
388 HideDivider();
389 else
390 ShowDivider();
152 } 391 }
153 392
154 void SplitViewController::UpdateLayout(bool animate) { 393 void SplitViewController::UpdateLayout(bool animate) {
155 CHECK(left_window_); 394 CHECK(left_window_);
156 CHECK(right_window_); 395 CHECK(right_window_);
157
158 // Splitview can be activated from SplitViewController::ActivateSplitMode or 396 // Splitview can be activated from SplitViewController::ActivateSplitMode or
159 // SplitViewController::ScrollEnd. Additionally we don't want to rotate the 397 // SplitViewController::ScrollEnd. Additionally we don't want to rotate the
160 // screen while engaging splitview (i.e. state_ == SCROLLING). 398 // screen while engaging splitview (i.e. state_ == SCROLLING).
161 if (state_ == INACTIVE && !animate) { 399 if (state_ == INACTIVE && !animate) {
162 if (!wm::IsActiveWindow(left_window_)) 400 aura::Window* active_window = window_list_provider_->GetWindowList().back();
401 if (active_window != left_window_) {
163 left_window_->Hide(); 402 left_window_->Hide();
164 if (!wm::IsActiveWindow(right_window_)) 403 right_window_->SetBounds(gfx::Rect(container_->bounds()));
404 }
405 if (active_window != right_window_) {
406 left_window_->SetBounds(gfx::Rect(container_->bounds()));
165 right_window_->Hide(); 407 right_window_->Hide();
166 SetWindowTransforms(gfx::Transform(), gfx::Transform(), false); 408 }
409 SetWindowTransforms(
410 gfx::Transform(), gfx::Transform(), gfx::Transform(), false);
167 return; 411 return;
168 } 412 }
169 413
170 left_window_->Show(); 414 left_window_->Show();
171 right_window_->Show(); 415 right_window_->Show();
172 window_list_provider_->MoveToFront(right_window_); 416 window_list_provider_->MoveToFront(right_window_);
173 window_list_provider_->MoveToFront(left_window_); 417 window_list_provider_->MoveToFront(left_window_);
174 418
419 gfx::Transform divider_transform;
420 divider_transform.Translate(divider_position_, 0);
175 if (state_ == ACTIVE) { 421 if (state_ == ACTIVE) {
176 if (animate) { 422 if (animate) {
177 gfx::Transform left_transform = GetTargetTransformForBoundsAnimation( 423 gfx::Transform left_transform =
178 left_window_->bounds(), GetLeftTargetBounds()); 424 GetTransformForBounds(left_window_->bounds(), GetLeftAreaBounds());
179 gfx::Transform right_transform = GetTargetTransformForBoundsAnimation( 425 gfx::Transform right_transform =
180 right_window_->bounds(), GetRightTargetBounds()); 426 GetTransformForBounds(right_window_->bounds(), GetRightAreaBounds());
181 SetWindowTransforms(left_transform, right_transform, true); 427 SetWindowTransforms(
428 left_transform, right_transform, divider_transform, true);
182 } else { 429 } else {
183 left_window_->SetBounds(GetLeftTargetBounds()); 430 left_window_->SetBounds(GetLeftAreaBounds());
184 right_window_->SetBounds(GetRightTargetBounds()); 431 right_window_->SetBounds(GetRightAreaBounds());
185 SetWindowTransforms(gfx::Transform(), gfx::Transform(), false); 432 SetWindowTransforms(
433 gfx::Transform(), gfx::Transform(), divider_transform, false);
186 } 434 }
187 } else { 435 } else {
188 gfx::Transform left_transform; 436 gfx::Transform left_transform;
189 left_transform.Translate(separator_position_ - container_->bounds().width(),
190 0);
191 gfx::Transform right_transform; 437 gfx::Transform right_transform;
192 right_transform.Translate(separator_position_, 0); 438 gfx::Rect left_area_bounds = GetLeftAreaBounds();
193 SetWindowTransforms(left_transform, right_transform, animate); 439 gfx::Rect right_area_bounds = GetRightAreaBounds();
440 // If the width of the window is greater than the width of the area which it
441 // is supposed to occupy - translate the window. Otherwise scale the window
442 // up to fill the target area.
443 if (left_window_->bounds().width() >= left_area_bounds.width()) {
444 left_transform.Translate(
445 left_area_bounds.right() - left_window_->bounds().right(), 0);
446 } else {
447 left_transform =
448 GetTransformForBounds(left_window_->bounds(), left_area_bounds);
449 }
450 if (right_window_->bounds().width() >= right_area_bounds.width()) {
451 right_transform.Translate(
452 right_area_bounds.x() - right_window_->bounds().x(), 0);
453 } else {
454 right_transform =
455 GetTransformForBounds(right_window_->bounds(), right_area_bounds);
456 }
457 SetWindowTransforms(
458 left_transform, right_transform, divider_transform, animate);
194 } 459 }
195 // Note: |left_window_| and |right_window_| may be NULL if calling 460 // Note: |left_window_| and |right_window_| may be NULL if calling
196 // SetWindowTransforms(): 461 // SetWindowTransforms():
197 // - caused the in-progress animation to abort. 462 // - caused the in-progress animation to abort.
198 // - started a zero duration animation. 463 // - started a zero duration animation.
199 } 464 }
200 465
201 void SplitViewController::SetWindowTransforms( 466 void SplitViewController::SetWindowTransforms(
202 const gfx::Transform& left_transform, 467 const gfx::Transform& left_transform,
203 const gfx::Transform& right_transform, 468 const gfx::Transform& right_transform,
469 const gfx::Transform& divider_transform,
204 bool animate) { 470 bool animate) {
205 if (animate) { 471 if (animate) {
206 ui::ScopedLayerAnimationSettings left_settings( 472 ui::ScopedLayerAnimationSettings left_settings(
207 left_window_->layer()->GetAnimator()); 473 left_window_->layer()->GetAnimator());
208 left_settings.SetPreemptionStrategy( 474 left_settings.SetPreemptionStrategy(
209 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 475 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
210 left_window_->SetTransform(left_transform); 476 left_window_->SetTransform(left_transform);
211 477
478 ui::ScopedLayerAnimationSettings divider_widget_settings(
479 divider_widget_->GetNativeWindow()->layer()->GetAnimator());
480 divider_widget_settings.SetPreemptionStrategy(
481 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
482 divider_widget_->GetNativeWindow()->SetTransform(divider_transform);
483
484 ui::ScopedLayerAnimationSettings divider_layer_settings(
485 divider_window_->layer()->GetAnimator());
486 divider_layer_settings.SetPreemptionStrategy(
487 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
488 divider_window_->SetTransform(divider_transform);
489
212 ui::ScopedLayerAnimationSettings right_settings( 490 ui::ScopedLayerAnimationSettings right_settings(
213 right_window_->layer()->GetAnimator()); 491 right_window_->layer()->GetAnimator());
214 right_settings.SetPreemptionStrategy( 492 right_settings.SetPreemptionStrategy(
215 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 493 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
216 right_settings.AddObserver(new ui::ClosureAnimationObserver( 494 right_settings.AddObserver(new ui::ClosureAnimationObserver(
217 base::Bind(&SplitViewController::OnAnimationCompleted, 495 base::Bind(&SplitViewController::OnAnimationCompleted,
218 weak_factory_.GetWeakPtr()))); 496 weak_factory_.GetWeakPtr())));
219 right_window_->SetTransform(right_transform); 497 right_window_->SetTransform(right_transform);
220 } else { 498 } else {
221 left_window_->SetTransform(left_transform); 499 left_window_->SetTransform(left_transform);
222 right_window_->SetTransform(right_transform); 500 right_window_->SetTransform(right_transform);
501 divider_widget_->GetNativeWindow()->SetTransform(divider_transform);
502 divider_window_->SetTransform(divider_transform);
223 } 503 }
224 } 504 }
225 505
226 void SplitViewController::OnAnimationCompleted() { 506 void SplitViewController::OnAnimationCompleted() {
227 // Animation can be cancelled when deactivated. 507 // Animation can be cancelled when deactivated.
228 if (left_window_ == NULL) 508 if (left_window_ == NULL)
229 return; 509 return;
230 UpdateLayout(false); 510 UpdateLayout(false);
231 511
232 if (state_ == INACTIVE) { 512 if (state_ == INACTIVE) {
233 left_window_ = NULL; 513 left_window_ = NULL;
234 right_window_ = NULL; 514 right_window_ = NULL;
235 } 515 }
236 } 516 }
237 517
238 void SplitViewController::UpdateSeparatorPositionFromScrollDelta(float delta) { 518 void SplitViewController::UpdateSeparatorPositionFromScrollDelta(float delta) {
239 gfx::Screen* screen = gfx::Screen::GetScreenFor(container_); 519 gfx::Screen* screen = gfx::Screen::GetScreenFor(container_);
240 const gfx::Rect& display_bounds = 520 const gfx::Rect& display_bounds =
241 screen->GetDisplayNearestWindow(container_).bounds(); 521 screen->GetDisplayNearestWindow(container_).bounds();
242 gfx::Rect container_bounds = container_->GetBoundsInScreen(); 522 gfx::Rect container_bounds = container_->GetBoundsInScreen();
243 separator_position_ = 523 divider_position_ =
244 delta > 0 ? ((int)delta) + display_bounds.x() - container_bounds.x() 524 delta > 0 ? ((int)delta) + display_bounds.x() - container_bounds.x()
245 : display_bounds.right() - container_bounds.x() + delta; 525 : display_bounds.right() - container_bounds.x() + delta;
246 } 526 }
247 527
248 /////////////////////////////////////////////////////////////////////////////// 528 ///////////////////////////////////////////////////////////////////////////////
249 // BezelController::ScrollDelegate: 529 // BezelController::ScrollDelegate:
250 530
251 void SplitViewController::ScrollBegin(BezelController::Bezel bezel, 531 void SplitViewController::ScrollBegin(BezelController::Bezel bezel,
252 float delta) { 532 float delta) {
253 if (!CanScroll()) 533 if (!CanScroll())
254 return; 534 return;
535
255 SetState(SCROLLING); 536 SetState(SCROLLING);
256 537
257 aura::Window::Windows windows = window_list_provider_->GetWindowList(); 538 aura::Window::Windows windows = window_list_provider_->GetWindowList();
258 CHECK(windows.size() >= 2); 539 CHECK(windows.size() >= 2);
259 aura::Window::Windows::const_reverse_iterator iter = windows.rbegin(); 540 aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
260 aura::Window* current_window = *(iter); 541 aura::Window* current_window = *(iter);
261 CHECK(wm::IsActiveWindow(current_window));
262 542
263 if (delta > 0) { 543 if (delta > 0) {
264 right_window_ = current_window; 544 right_window_ = current_window;
265 left_window_ = *(iter + 1); 545 left_window_ = *(iter + 1);
266 } else { 546 } else {
267 left_window_ = current_window; 547 left_window_ = current_window;
268 right_window_ = *(iter + 1); 548 right_window_ = *(iter + 1);
269 } 549 }
270 550
271 CHECK(left_window_); 551 CHECK(left_window_);
272 CHECK(right_window_); 552 CHECK(right_window_);
273 553
274 UpdateSeparatorPositionFromScrollDelta(delta); 554 UpdateSeparatorPositionFromScrollDelta(delta);
275 UpdateLayout(false); 555 UpdateLayout(false);
276 } 556 }
277 557
278 void SplitViewController::ScrollEnd() { 558 void SplitViewController::ScrollEnd() {
279 if (state_ != SCROLLING) 559 if (state_ != SCROLLING)
280 return; 560 return;
281 561
282 // Max distance from the scroll end position to the middle of the screen where 562 // Max distance from the scroll end position to the middle of the screen where
283 // we would go into the split view mode. 563 // we would go into the split view mode.
284 const int kMaxDistanceFromMiddle = 120; 564 const int kMaxDistanceFromMiddle = 120;
285 int container_width = container_->GetBoundsInScreen().width(); 565 int container_width = container_->GetBoundsInScreen().width();
286 if (std::abs(container_width / 2 - separator_position_) <= 566 if (std::abs(container_width / 2 - divider_position_) <=
287 kMaxDistanceFromMiddle) { 567 kMaxDistanceFromMiddle) {
568 divider_position_ = container_width / 2;
288 SetState(ACTIVE); 569 SetState(ACTIVE);
289 separator_position_ = container_width / 2; 570 } else if (divider_position_ < container_width / 2) {
290 } else if (separator_position_ < container_width / 2) { 571 divider_position_ = 0;
291 separator_position_ = 0;
292 SetState(INACTIVE); 572 SetState(INACTIVE);
293 wm::ActivateWindow(right_window_); 573 wm::ActivateWindow(right_window_);
294 } else { 574 } else {
295 separator_position_ = container_width; 575 divider_position_ = container_width;
296 SetState(INACTIVE); 576 SetState(INACTIVE);
297 wm::ActivateWindow(left_window_); 577 wm::ActivateWindow(left_window_);
298 } 578 }
299 UpdateLayout(true); 579 UpdateLayout(true);
300 } 580 }
301 581
302 void SplitViewController::ScrollUpdate(float delta) { 582 void SplitViewController::ScrollUpdate(float delta) {
303 if (state_ != SCROLLING) 583 if (state_ != SCROLLING)
304 return; 584 return;
305 UpdateSeparatorPositionFromScrollDelta(delta); 585 UpdateSeparatorPositionFromScrollDelta(delta);
306 UpdateLayout(false); 586 UpdateLayout(false);
307 } 587 }
308 588
309 bool SplitViewController::CanScroll() { 589 bool SplitViewController::CanScroll() {
310 // TODO(mfomitchev): return false in full screen. 590 // TODO(mfomitchev): return false in full screen.
311 bool result = (!IsSplitViewModeActive() && 591 bool result = (!IsSplitViewModeActive() &&
312 window_list_provider_->GetWindowList().size() >= 2 && 592 window_list_provider_->GetWindowList().size() >= 2 &&
313 IsLandscapeOrientation(gfx::Screen::GetNativeScreen()-> 593 IsLandscapeOrientation(gfx::Screen::GetNativeScreen()->
314 GetDisplayNearestWindow(container_).rotation())); 594 GetDisplayNearestWindow(container_).rotation()));
315 return result; 595 return result;
316 } 596 }
317 597
598 ///////////////////////////////////////////////////////////////////////////////
599 // ScrollHandle::ScrollDelegate:
600
601 void SplitViewController::HandleScrollBegin(float delta) {
602 CHECK(state_ == ACTIVE);
603 state_ = SCROLLING;
604 divider_position_ = delta + divider_position_;
605 UpdateLayout(false);
606 }
607
608 void SplitViewController::HandleScrollEnd() {
609 ScrollEnd();
610 }
611
612 void SplitViewController::HandleScrollUpdate(float delta) {
613 if (state_ != SCROLLING)
614 return;
615 divider_position_ = delta + container_->GetBoundsInScreen().width() / 2;
616 UpdateLayout(false);
617 }
618
619 bool SplitViewController::HandleCanScroll() {
620 CHECK(IsLandscapeOrientation(gfx::Screen::GetNativeScreen()
621 ->GetDisplayNearestWindow(container_)
622 .rotation()));
623 return true;
624 }
625
626 ///////////////////////////////////////////////////////////////////////////////
627 // WindowManagerObserver:
628
629 void SplitViewController::OnOverviewModeEnter() {
630 if (divider_widget_)
631 HideDivider();
632 }
633
634 void SplitViewController::OnOverviewModeExit() {
635 if (state_ != INACTIVE)
636 ShowDivider();
637 }
638
639 void SplitViewController::OnSplitViewModeEnter() {
640 }
641
642 void SplitViewController::OnSplitViewModeExit() {
643 }
644
318 } // namespace athena 645 } // namespace athena
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698