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

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

Powered by Google App Engine
This is Rietveld 408576698