OLD | NEW |
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/window_overview_mode.h" | 5 #include "athena/wm/window_overview_mode.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 91 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
92 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); | 92 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); |
93 | 93 |
94 settings.AddObserver(new ui::ClosureAnimationObserver( | 94 settings.AddObserver(new ui::ClosureAnimationObserver( |
95 base::Bind(&HideWindowIfNotVisible, window, split_view_controller))); | 95 base::Bind(&HideWindowIfNotVisible, window, split_view_controller))); |
96 | 96 |
97 window->SetTransform(gfx::Transform()); | 97 window->SetTransform(gfx::Transform()); |
98 wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); | 98 wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); |
99 } | 99 } |
100 | 100 |
| 101 gfx::RectF GetTransformedBounds(aura::Window* window) { |
| 102 gfx::Transform transform; |
| 103 gfx::RectF bounds = window->bounds(); |
| 104 transform.Translate(bounds.x(), bounds.y()); |
| 105 transform.PreconcatTransform(window->layer()->transform()); |
| 106 transform.Translate(-bounds.x(), -bounds.y()); |
| 107 transform.TransformRect(&bounds); |
| 108 return bounds; |
| 109 } |
| 110 |
| 111 gfx::Transform GetTransformForSplitWindow(aura::Window* window, float scale) { |
| 112 int x_translate = window->bounds().width() * (1 - scale) / 2; |
| 113 gfx::Transform transform; |
| 114 transform.Translate(x_translate, window->bounds().height() * 0.65); |
| 115 transform.Scale(scale, scale); |
| 116 return transform; |
| 117 } |
| 118 |
| 119 void TransformSplitWindowScale(aura::Window* window, float scale) { |
| 120 gfx::Transform transform = window->layer()->GetTargetTransform(); |
| 121 if (transform.Scale2d() == gfx::Vector2dF(scale, scale)) |
| 122 return; |
| 123 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); |
| 124 window->SetTransform(GetTransformForSplitWindow(window, scale)); |
| 125 } |
| 126 |
101 // Always returns the same target. | 127 // Always returns the same target. |
102 class StaticWindowTargeter : public aura::WindowTargeter { | 128 class StaticWindowTargeter : public aura::WindowTargeter { |
103 public: | 129 public: |
104 explicit StaticWindowTargeter(aura::Window* target) : target_(target) {} | 130 explicit StaticWindowTargeter(aura::Window* target) : target_(target) {} |
105 virtual ~StaticWindowTargeter() {} | 131 virtual ~StaticWindowTargeter() {} |
106 | 132 |
107 private: | 133 private: |
108 // aura::WindowTargeter: | 134 // aura::WindowTargeter: |
109 virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root, | 135 virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root, |
110 ui::Event* event) OVERRIDE { | 136 ui::Event* event) OVERRIDE { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 ++iter, ++index) { | 197 ++iter, ++index) { |
172 aura::Window* window = (*iter); | 198 aura::Window* window = (*iter); |
173 wm::SetShadowType(window, wm::SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE); | 199 wm::SetShadowType(window, wm::SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE); |
174 | 200 |
175 WindowOverviewState* state = new WindowOverviewState; | 201 WindowOverviewState* state = new WindowOverviewState; |
176 window->SetProperty(kWindowOverviewState, state); | 202 window->SetProperty(kWindowOverviewState, state); |
177 if (split_view_controller_->IsSplitViewModeActive() && | 203 if (split_view_controller_->IsSplitViewModeActive() && |
178 (window == split_view_controller_->left_window() || | 204 (window == split_view_controller_->left_window() || |
179 window == split_view_controller_->right_window())) { | 205 window == split_view_controller_->right_window())) { |
180 // Do not let the left/right windows be scrolled. | 206 // Do not let the left/right windows be scrolled. |
181 int x_translate = window->bounds().width() * (1 - kMaxScale) / 2; | 207 state->top = GetTransformForSplitWindow(window, kMaxScale); |
182 state->top.Translate(x_translate, window->bounds().height() * 0.65); | |
183 state->top.Scale(kMaxScale, kMaxScale); | |
184 state->bottom = state->top; | 208 state->bottom = state->top; |
185 --index; | 209 --index; |
186 continue; | 210 continue; |
187 } | 211 } |
188 UpdateTerminalStateForWindowAtIndex(window, index, windows.size()); | 212 UpdateTerminalStateForWindowAtIndex(window, index, windows.size()); |
189 } | 213 } |
190 } | 214 } |
191 | 215 |
192 void UpdateTerminalStateForWindowAtIndex(aura::Window* window, | 216 void UpdateTerminalStateForWindowAtIndex(aura::Window* window, |
193 size_t index, | 217 size_t index, |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 if (!compositor->HasAnimationObserver(this)) | 360 if (!compositor->HasAnimationObserver(this)) |
337 compositor->AddAnimationObserver(this); | 361 compositor->AddAnimationObserver(this); |
338 } | 362 } |
339 | 363 |
340 void RemoveAnimationObserver() { | 364 void RemoveAnimationObserver() { |
341 ui::Compositor* compositor = container_->GetHost()->compositor(); | 365 ui::Compositor* compositor = container_->GetHost()->compositor(); |
342 if (compositor->HasAnimationObserver(this)) | 366 if (compositor->HasAnimationObserver(this)) |
343 compositor->RemoveAnimationObserver(this); | 367 compositor->RemoveAnimationObserver(this); |
344 } | 368 } |
345 | 369 |
| 370 aura::Window* GetSplitWindowDropTarget(const ui::GestureEvent& event) const { |
| 371 if (!split_view_controller_->IsSplitViewModeActive()) |
| 372 return NULL; |
| 373 CHECK(dragged_window_); |
| 374 CHECK_NE(split_view_controller_->left_window(), dragged_window_); |
| 375 CHECK_NE(split_view_controller_->right_window(), dragged_window_); |
| 376 aura::Window* window = split_view_controller_->left_window(); |
| 377 if (GetTransformedBounds(window).Contains(event.location())) |
| 378 return window; |
| 379 window = split_view_controller_->right_window(); |
| 380 if (GetTransformedBounds(window).Contains(event.location())) |
| 381 return window; |
| 382 return NULL; |
| 383 } |
| 384 |
346 void DragWindow(const ui::GestureEvent& event) { | 385 void DragWindow(const ui::GestureEvent& event) { |
347 CHECK(dragged_window_); | 386 CHECK(dragged_window_); |
348 CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); | 387 CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); |
349 CHECK(overview_toolbar_); | 388 CHECK(overview_toolbar_); |
350 gfx::Vector2dF dragged_distance = | 389 gfx::Vector2dF dragged_distance = |
351 dragged_start_location_ - event.location(); | 390 dragged_start_location_ - event.location(); |
352 WindowOverviewState* dragged_state = | 391 WindowOverviewState* dragged_state = |
353 dragged_window_->GetProperty(kWindowOverviewState); | 392 dragged_window_->GetProperty(kWindowOverviewState); |
354 CHECK(dragged_state); | 393 CHECK(dragged_state); |
355 gfx::Transform transform = GetTransformForState(dragged_state); | 394 gfx::Transform transform = GetTransformForState(dragged_state); |
(...skipping 17 matching lines...) Expand all Loading... |
373 if (new_action == OverviewToolbar::ACTION_TYPE_NONE) { | 412 if (new_action == OverviewToolbar::ACTION_TYPE_NONE) { |
374 if (fabs(dragged_distance.x()) > kMinDistanceForDismissal) | 413 if (fabs(dragged_distance.x()) > kMinDistanceForDismissal) |
375 new_action = OverviewToolbar::ACTION_TYPE_CLOSE; | 414 new_action = OverviewToolbar::ACTION_TYPE_CLOSE; |
376 else | 415 else |
377 new_action = OverviewToolbar::ACTION_TYPE_NONE; | 416 new_action = OverviewToolbar::ACTION_TYPE_NONE; |
378 } | 417 } |
379 OverviewToolbar::ActionType previous_action = | 418 OverviewToolbar::ActionType previous_action = |
380 overview_toolbar_->current_action(); | 419 overview_toolbar_->current_action(); |
381 overview_toolbar_->SetHighlightAction(new_action); | 420 overview_toolbar_->SetHighlightAction(new_action); |
382 | 421 |
| 422 aura::Window* split_drop = GetSplitWindowDropTarget(event); |
| 423 |
383 // If the user has selected to get into split-view mode, then show the | 424 // If the user has selected to get into split-view mode, then show the |
384 // window with full opacity. Otherwise, fade it out as it closes. Animate | 425 // window with full opacity. Otherwise, fade it out as it closes. Animate |
385 // the opacity if transitioning to/from the split-view button. | 426 // the opacity if transitioning to/from the split-view button. |
386 bool animate_opacity = | 427 bool animate_opacity = |
387 (new_action != previous_action) && | 428 (new_action != previous_action) && |
388 ((new_action == OverviewToolbar::ACTION_TYPE_SPLIT) || | 429 ((new_action == OverviewToolbar::ACTION_TYPE_SPLIT) || |
389 (previous_action == OverviewToolbar::ACTION_TYPE_SPLIT)); | 430 (previous_action == OverviewToolbar::ACTION_TYPE_SPLIT)); |
390 float ratio = std::min( | 431 float ratio = std::min( |
391 1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal); | 432 1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal); |
392 float opacity = | 433 float opacity = |
393 (new_action == OverviewToolbar::ACTION_TYPE_SPLIT) | 434 (new_action == OverviewToolbar::ACTION_TYPE_SPLIT || split_drop) |
394 ? 1 | 435 ? 1 |
395 : gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity); | 436 : gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity); |
396 if (animate_opacity) { | 437 if (animate_opacity) { |
397 ui::ScopedLayerAnimationSettings settings( | 438 ui::ScopedLayerAnimationSettings settings( |
398 dragged_window_->layer()->GetAnimator()); | 439 dragged_window_->layer()->GetAnimator()); |
399 dragged_window_->layer()->SetOpacity(opacity); | 440 dragged_window_->layer()->SetOpacity(opacity); |
400 } else { | 441 } else { |
401 dragged_window_->layer()->SetOpacity(opacity); | 442 dragged_window_->layer()->SetOpacity(opacity); |
402 } | 443 } |
| 444 |
| 445 if (split_view_controller_->IsSplitViewModeActive()) { |
| 446 float scale = kMaxScale; |
| 447 if (split_drop == split_view_controller_->left_window()) |
| 448 scale = kMaxScaleForSplitTarget; |
| 449 TransformSplitWindowScale(split_view_controller_->left_window(), scale); |
| 450 |
| 451 scale = kMaxScale; |
| 452 if (split_drop == split_view_controller_->right_window()) |
| 453 scale = kMaxScaleForSplitTarget; |
| 454 TransformSplitWindowScale(split_view_controller_->right_window(), scale); |
| 455 } |
403 } | 456 } |
404 | 457 |
405 bool ShouldCloseDragWindow(const ui::GestureEvent& event) const { | 458 bool ShouldCloseDragWindow(const ui::GestureEvent& event) const { |
406 gfx::Vector2dF dragged_distance = | 459 gfx::Vector2dF dragged_distance = |
407 dragged_start_location_ - event.location(); | 460 dragged_start_location_ - event.location(); |
408 if (event.type() == ui::ET_GESTURE_SCROLL_END) | 461 if (event.type() == ui::ET_GESTURE_SCROLL_END) |
409 return std::abs(dragged_distance.x()) >= kMinDistanceForDismissal; | 462 return std::abs(dragged_distance.x()) >= kMinDistanceForDismissal; |
410 CHECK_EQ(ui::ET_SCROLL_FLING_START, event.type()); | 463 CHECK_EQ(ui::ET_SCROLL_FLING_START, event.type()); |
411 const bool dragging_towards_right = dragged_distance.x() < 0; | 464 const bool dragging_towards_right = dragged_distance.x() < 0; |
412 const bool swipe_towards_right = event.details().velocity_x() > 0; | 465 const bool swipe_towards_right = event.details().velocity_x() > 0; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 dragged_window_->SetTransform(GetTransformForState(dragged_state)); | 528 dragged_window_->SetTransform(GetTransformForState(dragged_state)); |
476 dragged_window_->layer()->SetOpacity(1.f); | 529 dragged_window_->layer()->SetOpacity(1.f); |
477 dragged_window_ = NULL; | 530 dragged_window_ = NULL; |
478 } | 531 } |
479 | 532 |
480 void EndDragWindow(const ui::GestureEvent& gesture) { | 533 void EndDragWindow(const ui::GestureEvent& gesture) { |
481 CHECK(dragged_window_); | 534 CHECK(dragged_window_); |
482 CHECK(overview_toolbar_); | 535 CHECK(overview_toolbar_); |
483 OverviewToolbar::ActionType action = overview_toolbar_->current_action(); | 536 OverviewToolbar::ActionType action = overview_toolbar_->current_action(); |
484 overview_toolbar_.reset(); | 537 overview_toolbar_.reset(); |
485 if (action == OverviewToolbar::ACTION_TYPE_SPLIT) | 538 if (action == OverviewToolbar::ACTION_TYPE_SPLIT) { |
486 delegate_->OnSplitViewMode(NULL, dragged_window_); | 539 delegate_->OnSplitViewMode(NULL, dragged_window_); |
487 else if (ShouldCloseDragWindow(gesture)) | 540 return; |
| 541 } |
| 542 |
| 543 // If the window is dropped on one of the left/right windows in split-mode, |
| 544 // then switch that window. |
| 545 aura::Window* split_drop = GetSplitWindowDropTarget(gesture); |
| 546 if (split_drop) { |
| 547 aura::Window* left = split_view_controller_->left_window(); |
| 548 aura::Window* right = split_view_controller_->right_window(); |
| 549 if (left == split_drop) |
| 550 left = dragged_window_; |
| 551 else |
| 552 right = dragged_window_; |
| 553 delegate_->OnSplitViewMode(left, right); |
| 554 return; |
| 555 } |
| 556 |
| 557 if (ShouldCloseDragWindow(gesture)) |
488 CloseDragWindow(gesture); | 558 CloseDragWindow(gesture); |
489 else | 559 else |
490 RestoreDragWindow(); | 560 RestoreDragWindow(); |
491 } | 561 } |
492 | 562 |
493 void SelectWindow(aura::Window* window) { | 563 void SelectWindow(aura::Window* window) { |
494 if (!split_view_controller_->IsSplitViewModeActive()) { | 564 if (!split_view_controller_->IsSplitViewModeActive()) { |
495 delegate_->OnSelectWindow(window); | 565 delegate_->OnSelectWindow(window); |
496 } else { | 566 } else { |
497 // If the selected window is one of the left/right windows, then keep the | 567 // If the selected window is one of the left/right windows, then keep the |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 aura::Window* select = SelectWindowAt(gesture); | 599 aura::Window* select = SelectWindowAt(gesture); |
530 if (select) { | 600 if (select) { |
531 gesture->SetHandled(); | 601 gesture->SetHandled(); |
532 SelectWindow(select); | 602 SelectWindow(select); |
533 } | 603 } |
534 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { | 604 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
535 if (std::abs(gesture->details().scroll_x_hint()) > | 605 if (std::abs(gesture->details().scroll_x_hint()) > |
536 std::abs(gesture->details().scroll_y_hint()) * 2) { | 606 std::abs(gesture->details().scroll_y_hint()) * 2) { |
537 dragged_start_location_ = gesture->location(); | 607 dragged_start_location_ = gesture->location(); |
538 dragged_window_ = SelectWindowAt(gesture); | 608 dragged_window_ = SelectWindowAt(gesture); |
539 if (dragged_window_) | 609 if (split_view_controller_->IsSplitViewModeActive() && |
| 610 (dragged_window_ == split_view_controller_->left_window() || |
| 611 dragged_window_ == split_view_controller_->right_window())) { |
| 612 // TODO(sad): Allow closing the left/right window. Closing one of |
| 613 // these windows will terminate the split-view mode. Until then, do |
| 614 // not allow closing these (since otherwise it gets into an undefined |
| 615 // state). |
| 616 dragged_window_ = NULL; |
| 617 } |
| 618 |
| 619 if (dragged_window_) { |
| 620 // Show the toolbar (for closing a window, or going into split-view |
| 621 // mode). If already in split-view mode, then do not show the 'Split' |
| 622 // option. |
540 overview_toolbar_.reset(new OverviewToolbar(container_)); | 623 overview_toolbar_.reset(new OverviewToolbar(container_)); |
| 624 if (split_view_controller_->IsSplitViewModeActive()) { |
| 625 overview_toolbar_->DisableAction( |
| 626 OverviewToolbar::ACTION_TYPE_SPLIT); |
| 627 } |
| 628 } |
541 } | 629 } |
542 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { | 630 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { |
543 if (dragged_window_) | 631 if (dragged_window_) |
544 DragWindow(*gesture); | 632 DragWindow(*gesture); |
545 else | 633 else |
546 DoScroll(gesture->details().scroll_y()); | 634 DoScroll(gesture->details().scroll_y()); |
547 gesture->SetHandled(); | 635 gesture->SetHandled(); |
548 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) { | 636 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) { |
549 if (dragged_window_) | 637 if (dragged_window_) |
550 EndDragWindow(*gesture); | 638 EndDragWindow(*gesture); |
(...skipping 28 matching lines...) Expand all Loading... |
579 } else { | 667 } else { |
580 DoScroll(scroll.y()); | 668 DoScroll(scroll.y()); |
581 } | 669 } |
582 } | 670 } |
583 | 671 |
584 const int kMinDistanceForDismissal = 300; | 672 const int kMinDistanceForDismissal = 300; |
585 const float kMinScale = 0.6f; | 673 const float kMinScale = 0.6f; |
586 const float kMaxScale = 0.75f; | 674 const float kMaxScale = 0.75f; |
587 const float kMaxOpacity = 1.0f; | 675 const float kMaxOpacity = 1.0f; |
588 const float kMinOpacity = 0.2f; | 676 const float kMinOpacity = 0.2f; |
| 677 const float kMaxScaleForSplitTarget = 0.9f; |
589 | 678 |
590 aura::Window* container_; | 679 aura::Window* container_; |
591 // Provider of the stack of windows to show in the overview mode. Not owned. | 680 // Provider of the stack of windows to show in the overview mode. Not owned. |
592 const WindowListProvider* window_list_provider_; | 681 const WindowListProvider* window_list_provider_; |
593 SplitViewController* split_view_controller_; | 682 SplitViewController* split_view_controller_; |
594 | 683 |
595 WindowOverviewModeDelegate* delegate_; | 684 WindowOverviewModeDelegate* delegate_; |
596 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_; | 685 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_; |
597 scoped_ptr<ui::FlingCurve> fling_; | 686 scoped_ptr<ui::FlingCurve> fling_; |
598 | 687 |
(...skipping 11 matching lines...) Expand all Loading... |
610 aura::Window* container, | 699 aura::Window* container, |
611 const WindowListProvider* window_list_provider, | 700 const WindowListProvider* window_list_provider, |
612 SplitViewController* split_view_controller, | 701 SplitViewController* split_view_controller, |
613 WindowOverviewModeDelegate* delegate) { | 702 WindowOverviewModeDelegate* delegate) { |
614 return scoped_ptr<WindowOverviewMode>( | 703 return scoped_ptr<WindowOverviewMode>( |
615 new WindowOverviewModeImpl(container, window_list_provider, | 704 new WindowOverviewModeImpl(container, window_list_provider, |
616 split_view_controller, delegate)); | 705 split_view_controller, delegate)); |
617 } | 706 } |
618 | 707 |
619 } // namespace athena | 708 } // namespace athena |
OLD | NEW |