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 |
11 #include "athena/wm/overview_toolbar.h" | 11 #include "athena/wm/overview_toolbar.h" |
12 #include "athena/wm/public/window_list_provider.h" | 12 #include "athena/wm/public/window_list_provider.h" |
13 #include "athena/wm/split_view_controller.h" | 13 #include "athena/wm/split_view_controller.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "ui/aura/scoped_window_targeter.h" | 16 #include "ui/aura/scoped_window_targeter.h" |
17 #include "ui/aura/window.h" | 17 #include "ui/aura/window.h" |
18 #include "ui/aura/window_delegate.h" | 18 #include "ui/aura/window_delegate.h" |
19 #include "ui/aura/window_property.h" | 19 #include "ui/aura/window_property.h" |
20 #include "ui/aura/window_targeter.h" | 20 #include "ui/aura/window_targeter.h" |
21 #include "ui/aura/window_tree_host.h" | 21 #include "ui/aura/window_tree_host.h" |
22 #include "ui/compositor/closure_animation_observer.h" | 22 #include "ui/compositor/closure_animation_observer.h" |
23 #include "ui/compositor/compositor.h" | 23 #include "ui/compositor/compositor.h" |
24 #include "ui/compositor/compositor_animation_observer.h" | 24 #include "ui/compositor/compositor_animation_observer.h" |
| 25 #include "ui/compositor/layer_animation_observer.h" |
25 #include "ui/compositor/scoped_layer_animation_settings.h" | 26 #include "ui/compositor/scoped_layer_animation_settings.h" |
26 #include "ui/events/event_handler.h" | 27 #include "ui/events/event_handler.h" |
27 #include "ui/events/gestures/fling_curve.h" | 28 #include "ui/events/gestures/fling_curve.h" |
28 #include "ui/gfx/frame_time.h" | 29 #include "ui/gfx/frame_time.h" |
29 #include "ui/gfx/transform.h" | 30 #include "ui/gfx/transform.h" |
30 #include "ui/wm/core/shadow_types.h" | 31 #include "ui/wm/core/shadow_types.h" |
31 #include "ui/wm/core/window_util.h" | 32 #include "ui/wm/core/window_util.h" |
32 | 33 |
33 namespace { | 34 namespace { |
34 | 35 |
(...skipping 26 matching lines...) Expand all Loading... |
61 state->bottom); | 62 state->bottom); |
62 } | 63 } |
63 | 64 |
64 // Sets the progress-state for the window in the overview mode. | 65 // Sets the progress-state for the window in the overview mode. |
65 void SetWindowProgress(aura::Window* window, float progress) { | 66 void SetWindowProgress(aura::Window* window, float progress) { |
66 WindowOverviewState* state = window->GetProperty(kWindowOverviewState); | 67 WindowOverviewState* state = window->GetProperty(kWindowOverviewState); |
67 state->progress = progress; | 68 state->progress = progress; |
68 window->SetTransform(GetTransformForState(state)); | 69 window->SetTransform(GetTransformForState(state)); |
69 } | 70 } |
70 | 71 |
71 void HideWindowIfNotVisible(aura::Window* window, | 72 void HideWindowIfTransparent(aura::Window* window) { |
72 SplitViewController* split_view_controller) { | 73 if (window->layer()->opacity() == 0.0f) { |
73 bool should_hide = true; | 74 window->Hide(); |
74 if (split_view_controller->IsSplitViewModeActive()) { | 75 window->layer()->SetOpacity(1.0f); |
75 should_hide = window != split_view_controller->left_window() && | |
76 window != split_view_controller->right_window(); | |
77 } else { | |
78 should_hide = !wm::IsActiveWindow(window); | |
79 } | 76 } |
80 if (should_hide) | |
81 window->Hide(); | |
82 } | 77 } |
83 | 78 |
84 // Resets the overview-related state for |window|. | 79 // Resets the overview-related state for |window|. |
85 void RestoreWindowState(aura::Window* window, | 80 void RestoreWindowState(aura::Window* window) { |
86 SplitViewController* split_view_controller) { | |
87 window->ClearProperty(kWindowOverviewState); | 81 window->ClearProperty(kWindowOverviewState); |
| 82 wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); |
88 | 83 |
89 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | 84 { |
90 settings.SetPreemptionStrategy( | 85 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); |
91 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 86 settings.SetPreemptionStrategy( |
92 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); | 87 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 88 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); |
| 89 window->SetTransform(gfx::Transform()); |
| 90 } |
93 | 91 |
94 settings.AddObserver(new ui::ClosureAnimationObserver( | 92 { |
95 base::Bind(&HideWindowIfNotVisible, window, split_view_controller))); | 93 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); |
| 94 settings.SetPreemptionStrategy( |
| 95 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 96 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); |
| 97 settings.AddObserver(new ui::ClosureAnimationObserver( |
| 98 base::Bind(&HideWindowIfTransparent, base::Unretained(window)))); |
96 | 99 |
97 window->SetTransform(gfx::Transform()); | 100 // The window opacity may not be 1.0f if the user was dragging a window. |
| 101 window->layer()->SetOpacity(1.0f); |
98 | 102 |
99 // Reset the window opacity in case the user is dragging a window. | 103 // Ideally we would animate the window's visibility. However, animating the |
100 window->layer()->SetOpacity(1.0f); | 104 // window's visibility causes the web contents to hide before the animation |
101 | 105 // completes. Enqueue a zero duration opacity animation and hide |window| if |
102 wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); | 106 // the opacity animation is not aborted. |
| 107 settings.SetPreemptionStrategy( |
| 108 ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); |
| 109 settings.SetTransitionDuration(base::TimeDelta()); |
| 110 window->layer()->SetOpacity(0.0f); |
| 111 } |
103 } | 112 } |
104 | 113 |
105 gfx::RectF GetTransformedBounds(aura::Window* window) { | 114 gfx::RectF GetTransformedBounds(aura::Window* window) { |
106 gfx::Transform transform; | 115 gfx::Transform transform; |
107 gfx::RectF bounds = window->bounds(); | 116 gfx::RectF bounds = window->bounds(); |
108 transform.Translate(bounds.x(), bounds.y()); | 117 transform.Translate(bounds.x(), bounds.y()); |
109 transform.PreconcatTransform(window->layer()->transform()); | 118 transform.PreconcatTransform(window->layer()->transform()); |
110 transform.Translate(-bounds.x(), -bounds.y()); | 119 transform.Translate(-bounds.x(), -bounds.y()); |
111 transform.TransformRect(&bounds); | 120 transform.TransformRect(&bounds); |
112 return bounds; | 121 return bounds; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 SplitViewController* split_view_controller, | 169 SplitViewController* split_view_controller, |
161 WindowOverviewModeDelegate* delegate) | 170 WindowOverviewModeDelegate* delegate) |
162 : container_(container), | 171 : container_(container), |
163 window_list_provider_(window_list_provider), | 172 window_list_provider_(window_list_provider), |
164 split_view_controller_(split_view_controller), | 173 split_view_controller_(split_view_controller), |
165 delegate_(delegate), | 174 delegate_(delegate), |
166 scoped_targeter_(new aura::ScopedWindowTargeter( | 175 scoped_targeter_(new aura::ScopedWindowTargeter( |
167 container, | 176 container, |
168 scoped_ptr<ui::EventTargeter>( | 177 scoped_ptr<ui::EventTargeter>( |
169 new StaticWindowTargeter(container)))), | 178 new StaticWindowTargeter(container)))), |
170 dragged_window_(NULL) { | 179 dragged_window_(NULL), |
| 180 selected_window_(false) { |
171 CHECK(delegate_); | 181 CHECK(delegate_); |
172 container_->set_target_handler(this); | 182 container_->set_target_handler(this); |
173 | 183 |
174 // Prepare the desired transforms for all the windows, and set the initial | 184 // Prepare the desired transforms for all the windows, and set the initial |
175 // state on the windows. | 185 // state on the windows. |
176 ComputeTerminalStatesForAllWindows(); | 186 ComputeTerminalStatesForAllWindows(); |
177 SetInitialWindowStates(); | 187 SetInitialWindowStates(); |
178 } | 188 } |
179 | 189 |
180 virtual ~WindowOverviewModeImpl() { | 190 virtual ~WindowOverviewModeImpl() { |
181 container_->set_target_handler(container_->delegate()); | 191 container_->set_target_handler(container_->delegate()); |
182 RemoveAnimationObserver(); | 192 RemoveAnimationObserver(); |
| 193 |
| 194 // Abort any in progress animations. This can have significant consequences |
| 195 // such as deleting one of |windows|. |
183 aura::Window::Windows windows = window_list_provider_->GetWindowList(); | 196 aura::Window::Windows windows = window_list_provider_->GetWindowList(); |
| 197 for (size_t i = 0; i < windows.size(); ++i) |
| 198 windows[i]->layer()->GetAnimator()->AbortAllAnimations(); |
| 199 |
| 200 windows = window_list_provider_->GetWindowList(); |
184 if (windows.empty()) | 201 if (windows.empty()) |
185 return; | 202 return; |
186 std::for_each(windows.begin(), windows.end(), | 203 std::for_each(windows.begin(), windows.end(), &RestoreWindowState); |
187 std::bind2nd(std::ptr_fun(&RestoreWindowState), | 204 |
188 split_view_controller_)); | 205 if (!selected_window_) { |
| 206 aura::Window* to_select = *windows.rbegin(); |
| 207 SelectWindow(to_select, GetDefaultSplitType(to_select)); |
| 208 } |
189 } | 209 } |
190 | 210 |
191 private: | 211 private: |
192 // Computes the transforms for all windows in both the topmost and bottom-most | 212 // Computes the transforms for all windows in both the topmost and bottom-most |
193 // positions. The transforms are set in the |kWindowOverviewState| property of | 213 // positions. The transforms are set in the |kWindowOverviewState| property of |
194 // the windows. | 214 // the windows. |
195 void ComputeTerminalStatesForAllWindows() { | 215 void ComputeTerminalStatesForAllWindows() { |
196 aura::Window::Windows windows = window_list_provider_->GetWindowList(); | 216 aura::Window::Windows windows = window_list_provider_->GetWindowList(); |
197 size_t index = 0; | 217 size_t index = 0; |
198 | 218 |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 dragged_window_->layer()->SetOpacity(1.f); | 584 dragged_window_->layer()->SetOpacity(1.f); |
565 dragged_window_ = NULL; | 585 dragged_window_ = NULL; |
566 } | 586 } |
567 | 587 |
568 void EndDragWindow(const ui::GestureEvent& gesture) { | 588 void EndDragWindow(const ui::GestureEvent& gesture) { |
569 CHECK(dragged_window_); | 589 CHECK(dragged_window_); |
570 CHECK(overview_toolbar_); | 590 CHECK(overview_toolbar_); |
571 OverviewToolbar::ActionType action = overview_toolbar_->current_action(); | 591 OverviewToolbar::ActionType action = overview_toolbar_->current_action(); |
572 overview_toolbar_.reset(); | 592 overview_toolbar_.reset(); |
573 if (action == OverviewToolbar::ACTION_TYPE_SPLIT) { | 593 if (action == OverviewToolbar::ACTION_TYPE_SPLIT) { |
574 delegate_->OnSplitViewMode(NULL, dragged_window_); | 594 SelectWindow(dragged_window_, |
| 595 WindowOverviewModeDelegate::SPLIT_RIGHT); |
575 return; | 596 return; |
576 } | 597 } |
577 | 598 |
578 // If the window is dropped on one of the left/right windows in split-mode, | 599 // If the window is dropped on one of the left/right windows in split-mode, |
579 // then switch that window. | 600 // then switch that window. |
580 aura::Window* split_drop = GetSplitWindowDropTarget(gesture); | 601 aura::Window* split_drop = GetSplitWindowDropTarget(gesture); |
581 if (split_drop) { | 602 if (split_drop) { |
582 aura::Window* left = split_view_controller_->left_window(); | 603 WindowOverviewModeDelegate::SplitType split_type = |
583 aura::Window* right = split_view_controller_->right_window(); | 604 (split_view_controller_->left_window() == split_drop) |
584 if (left == split_drop) | 605 ? WindowOverviewModeDelegate::SPLIT_LEFT |
585 left = dragged_window_; | 606 : WindowOverviewModeDelegate::SPLIT_RIGHT; |
586 else | 607 SelectWindow(dragged_window_, split_type); |
587 right = dragged_window_; | |
588 delegate_->OnSplitViewMode(left, right); | |
589 return; | 608 return; |
590 } | 609 } |
591 | 610 |
592 if (ShouldCloseDragWindow(gesture)) | 611 if (ShouldCloseDragWindow(gesture)) |
593 CloseDragWindow(gesture); | 612 CloseDragWindow(gesture); |
594 else | 613 else |
595 RestoreDragWindow(); | 614 RestoreDragWindow(); |
596 } | 615 } |
597 | 616 |
598 void SelectWindow(aura::Window* window) { | 617 WindowOverviewModeDelegate::SplitType GetDefaultSplitType( |
599 if (!split_view_controller_->IsSplitViewModeActive()) { | 618 aura::Window* window) { |
600 delegate_->OnSelectWindow(window); | 619 if (split_view_controller_->IsSplitViewModeActive()) { |
601 } else { | 620 // Do not exit split view if the split view's left/right window was |
602 // If the selected window is one of the left/right windows, then keep the | 621 // selected. |
603 // current state. | 622 if (window == split_view_controller_->left_window()) |
604 if (window == split_view_controller_->left_window() || | 623 return WindowOverviewModeDelegate::SPLIT_LEFT; |
605 window == split_view_controller_->right_window()) { | 624 else if (window == split_view_controller_->right_window()) |
606 delegate_->OnSplitViewMode(split_view_controller_->left_window(), | 625 return WindowOverviewModeDelegate::SPLIT_RIGHT; |
607 split_view_controller_->right_window()); | |
608 } else { | |
609 delegate_->OnSelectWindow(window); | |
610 } | |
611 } | 626 } |
| 627 return WindowOverviewModeDelegate::SPLIT_NONE; |
| 628 } |
| 629 |
| 630 void SelectWindow(aura::Window* window, |
| 631 WindowOverviewModeDelegate::SplitType split_type) { |
| 632 selected_window_ = true; |
| 633 delegate_->OnSelectWindow(window, split_type); |
612 } | 634 } |
613 | 635 |
614 // ui::EventHandler: | 636 // ui::EventHandler: |
615 virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE { | 637 virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE { |
616 if (mouse->type() == ui::ET_MOUSE_PRESSED) { | 638 if (mouse->type() == ui::ET_MOUSE_PRESSED) { |
617 aura::Window* select = SelectWindowAt(mouse); | 639 aura::Window* select = SelectWindowAt(mouse); |
618 if (select) { | 640 if (select) { |
619 mouse->SetHandled(); | 641 mouse->SetHandled(); |
620 SelectWindow(select); | 642 SelectWindow(select, GetDefaultSplitType(select)); |
621 } | 643 } |
622 } else if (mouse->type() == ui::ET_MOUSEWHEEL) { | 644 } else if (mouse->type() == ui::ET_MOUSEWHEEL) { |
623 DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset()); | 645 DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset()); |
624 } | 646 } |
625 } | 647 } |
626 | 648 |
627 virtual void OnScrollEvent(ui::ScrollEvent* scroll) OVERRIDE { | 649 virtual void OnScrollEvent(ui::ScrollEvent* scroll) OVERRIDE { |
628 if (scroll->type() == ui::ET_SCROLL) | 650 if (scroll->type() == ui::ET_SCROLL) |
629 DoScroll(scroll->y_offset()); | 651 DoScroll(scroll->y_offset()); |
630 } | 652 } |
631 | 653 |
632 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE { | 654 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE { |
633 if (gesture->type() == ui::ET_GESTURE_TAP) { | 655 if (gesture->type() == ui::ET_GESTURE_TAP) { |
634 aura::Window* select = SelectWindowAt(gesture); | 656 aura::Window* select = SelectWindowAt(gesture); |
635 if (select) { | 657 if (select) { |
636 gesture->SetHandled(); | 658 gesture->SetHandled(); |
637 SelectWindow(select); | 659 SelectWindow(select, GetDefaultSplitType(select)); |
638 } | 660 } |
639 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { | 661 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
640 if (std::abs(gesture->details().scroll_x_hint()) > | 662 if (std::abs(gesture->details().scroll_x_hint()) > |
641 std::abs(gesture->details().scroll_y_hint()) * 2) { | 663 std::abs(gesture->details().scroll_y_hint()) * 2) { |
642 dragged_start_location_ = gesture->location(); | 664 dragged_start_location_ = gesture->location(); |
643 dragged_window_ = SelectWindowAt(gesture); | 665 dragged_window_ = SelectWindowAt(gesture); |
644 if (split_view_controller_->IsSplitViewModeActive() && | 666 if (split_view_controller_->IsSplitViewModeActive() && |
645 (dragged_window_ == split_view_controller_->left_window() || | 667 (dragged_window_ == split_view_controller_->left_window() || |
646 dragged_window_ == split_view_controller_->right_window())) { | 668 dragged_window_ == split_view_controller_->right_window())) { |
647 // TODO(sad): Allow closing the left/right window. Closing one of | 669 // TODO(sad): Allow closing the left/right window. Closing one of |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 SplitViewController* split_view_controller_; | 739 SplitViewController* split_view_controller_; |
718 | 740 |
719 WindowOverviewModeDelegate* delegate_; | 741 WindowOverviewModeDelegate* delegate_; |
720 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_; | 742 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_; |
721 scoped_ptr<ui::FlingCurve> fling_; | 743 scoped_ptr<ui::FlingCurve> fling_; |
722 | 744 |
723 aura::Window* dragged_window_; | 745 aura::Window* dragged_window_; |
724 gfx::Point dragged_start_location_; | 746 gfx::Point dragged_start_location_; |
725 scoped_ptr<OverviewToolbar> overview_toolbar_; | 747 scoped_ptr<OverviewToolbar> overview_toolbar_; |
726 | 748 |
| 749 // Whether a window was selected. |
| 750 bool selected_window_; |
| 751 |
727 DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl); | 752 DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl); |
728 }; | 753 }; |
729 | 754 |
730 } // namespace | 755 } // namespace |
731 | 756 |
732 // static | 757 // static |
733 scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create( | 758 scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create( |
734 aura::Window* container, | 759 aura::Window* container, |
735 const WindowListProvider* window_list_provider, | 760 const WindowListProvider* window_list_provider, |
736 SplitViewController* split_view_controller, | 761 SplitViewController* split_view_controller, |
737 WindowOverviewModeDelegate* delegate) { | 762 WindowOverviewModeDelegate* delegate) { |
738 return scoped_ptr<WindowOverviewMode>( | 763 return scoped_ptr<WindowOverviewMode>( |
739 new WindowOverviewModeImpl(container, window_list_provider, | 764 new WindowOverviewModeImpl(container, window_list_provider, |
740 split_view_controller, delegate)); | 765 split_view_controller, delegate)); |
741 } | 766 } |
742 | 767 |
743 } // namespace athena | 768 } // namespace athena |
OLD | NEW |