OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "ash/wm/overview/window_selector_item.h" | 5 #include "ash/wm/overview/window_selector_item.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "ash/metrics/user_metrics_action.h" | 10 #include "ash/metrics/user_metrics_action.h" |
11 #include "ash/metrics/user_metrics_recorder.h" | 11 #include "ash/metrics/user_metrics_recorder.h" |
12 #include "ash/public/cpp/shell_window_ids.h" | 12 #include "ash/public/cpp/shell_window_ids.h" |
13 #include "ash/resources/vector_icons/vector_icons.h" | 13 #include "ash/resources/vector_icons/vector_icons.h" |
14 #include "ash/shell.h" | 14 #include "ash/shell.h" |
15 #include "ash/wm/maximize_mode/maximize_mode_controller.h" | 15 #include "ash/wm/maximize_mode/maximize_mode_controller.h" |
16 #include "ash/wm/overview/cleanup_animation_observer.h" | 16 #include "ash/wm/overview/cleanup_animation_observer.h" |
17 #include "ash/wm/overview/overview_animation_type.h" | 17 #include "ash/wm/overview/overview_animation_type.h" |
18 #include "ash/wm/overview/scoped_overview_animation_settings.h" | 18 #include "ash/wm/overview/scoped_overview_animation_settings.h" |
19 #include "ash/wm/overview/scoped_transform_overview_window.h" | 19 #include "ash/wm/overview/scoped_transform_overview_window.h" |
20 #include "ash/wm/overview/window_grid.h" | |
21 #include "ash/wm/overview/window_selector.h" | 20 #include "ash/wm/overview/window_selector.h" |
22 #include "ash/wm/overview/window_selector_controller.h" | 21 #include "ash/wm/overview/window_selector_controller.h" |
23 #include "ash/wm/window_state.h" | 22 #include "ash/wm/window_state.h" |
24 #include "base/auto_reset.h" | 23 #include "base/auto_reset.h" |
25 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
26 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
27 #include "base/time/time.h" | 26 #include "base/time/time.h" |
28 #include "ui/base/l10n/l10n_util.h" | 27 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/compositor/layer_animation_sequence.h" | 28 #include "ui/compositor/layer_animation_sequence.h" |
30 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 29 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 // Duration of background opacity transition for the selected label. | 93 // Duration of background opacity transition for the selected label. |
95 static const int kSelectorFadeInMilliseconds = 350; | 94 static const int kSelectorFadeInMilliseconds = 350; |
96 | 95 |
97 // Duration of background opacity transition when exiting overview mode. | 96 // Duration of background opacity transition when exiting overview mode. |
98 static const int kExitFadeInMilliseconds = 30; | 97 static const int kExitFadeInMilliseconds = 30; |
99 | 98 |
100 // Before closing a window animate both the window and the caption to shrink by | 99 // Before closing a window animate both the window and the caption to shrink by |
101 // this fraction of size. | 100 // this fraction of size. |
102 static const float kPreCloseScale = 0.02f; | 101 static const float kPreCloseScale = 0.02f; |
103 | 102 |
104 // Before dragging an overview window, the window will scale up |kPreDragScale| | |
105 // to indicate its selection. | |
106 static const float kDragWindowScale = 0.04f; | |
107 | |
108 // Convenience method to fade in a Window with predefined animation settings. | 103 // Convenience method to fade in a Window with predefined animation settings. |
109 // Note: The fade in animation will occur after a delay where the delay is how | 104 // Note: The fade in animation will occur after a delay where the delay is how |
110 // long the lay out animations take. | 105 // long the lay out animations take. |
111 void SetupFadeInAfterLayout(views::Widget* widget) { | 106 void SetupFadeInAfterLayout(views::Widget* widget) { |
112 aura::Window* window = widget->GetNativeWindow(); | 107 aura::Window* window = widget->GetNativeWindow(); |
113 window->layer()->SetOpacity(0.0f); | 108 window->layer()->SetOpacity(0.0f); |
114 ScopedOverviewAnimationSettings scoped_overview_animation_settings( | 109 ScopedOverviewAnimationSettings scoped_overview_animation_settings( |
115 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, | 110 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, |
116 window); | 111 window); |
117 window->layer()->SetOpacity(1.0f); | 112 window->layer()->SetOpacity(1.0f); |
118 } | 113 } |
119 | 114 |
120 // A Button that has a listener and listens to mouse / gesture events on the | 115 // A Button that has a listener and listens to mouse clicks on the visible part |
121 // visible part of an overview window. Note that the drag events are only | 116 // of an overview window. |
122 // handled in maximized mode. | |
123 class ShieldButton : public views::CustomButton { | 117 class ShieldButton : public views::CustomButton { |
124 public: | 118 public: |
125 ShieldButton(views::ButtonListener* listener, const base::string16& name) | 119 ShieldButton(views::ButtonListener* listener, const base::string16& name) |
126 : views::CustomButton(listener) { | 120 : views::CustomButton(listener) { |
127 SetAccessibleName(name); | 121 SetAccessibleName(name); |
128 } | 122 } |
129 ~ShieldButton() override {} | 123 ~ShieldButton() override {} |
130 | 124 |
131 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its | 125 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its |
132 // |item_widget_| is allowed to stay around to complete any animations. | 126 // |item_widget_| is allowed to stay around to complete any animations. |
133 // Resetting the listener in all views that are targeted by events is | 127 // Resetting the listener in all views that are targeted by events is |
134 // necessary to prevent a crash when a user clicks on the fading out widget | 128 // necessary to prevent a crash when a user clicks on the fading out widget |
135 // after the WindowSelectorItem has been destroyed. | 129 // after the WindowSelectorItem has been destroyed. |
136 void ResetListener() { listener_ = nullptr; } | 130 void ResetListener() { listener_ = nullptr; } |
137 | 131 |
138 // views::CustomButton: | |
139 bool OnMousePressed(const ui::MouseEvent& event) override { | |
140 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
141 gfx::Point location(event.location()); | |
142 views::View::ConvertPointToScreen(this, &location); | |
143 listener()->HandlePressEvent(location); | |
144 return true; | |
145 } | |
146 return views::CustomButton::OnMousePressed(event); | |
147 } | |
148 | |
149 void OnMouseReleased(const ui::MouseEvent& event) override { | |
150 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
151 gfx::Point location(event.location()); | |
152 views::View::ConvertPointToScreen(this, &location); | |
153 listener()->HandleReleaseEvent(location); | |
154 return; | |
155 } | |
156 views::CustomButton::OnMouseReleased(event); | |
157 } | |
158 | |
159 bool OnMouseDragged(const ui::MouseEvent& event) override { | |
160 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
161 gfx::Point location(event.location()); | |
162 views::View::ConvertPointToScreen(this, &location); | |
163 listener()->HandleDragEvent(location); | |
164 return true; | |
165 } | |
166 return views::CustomButton::OnMouseDragged(event); | |
167 } | |
168 | |
169 void OnGestureEvent(ui::GestureEvent* event) override { | |
170 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
171 gfx::Point location(event->location()); | |
172 views::View::ConvertPointToScreen(this, &location); | |
173 switch (event->type()) { | |
174 case ui::ET_GESTURE_SCROLL_BEGIN: | |
175 case ui::ET_GESTURE_TAP_DOWN: | |
176 listener()->HandlePressEvent(location); | |
177 break; | |
178 case ui::ET_GESTURE_SCROLL_UPDATE: | |
179 listener()->HandleDragEvent(location); | |
180 break; | |
181 case ui::ET_GESTURE_END: | |
182 listener()->HandleReleaseEvent(location); | |
183 break; | |
184 default: | |
185 break; | |
186 } | |
187 event->SetHandled(); | |
188 return; | |
189 } | |
190 views::CustomButton::OnGestureEvent(event); | |
191 } | |
192 | |
193 WindowSelectorItem* listener() { | |
194 return static_cast<WindowSelectorItem*>(listener_); | |
195 } | |
196 | |
197 protected: | 132 protected: |
198 // views::View: | 133 // views::View: |
199 const char* GetClassName() const override { return "ShieldButton"; } | 134 const char* GetClassName() const override { return "ShieldButton"; } |
200 | 135 |
201 private: | 136 private: |
202 DISALLOW_COPY_AND_ASSIGN(ShieldButton); | 137 DISALLOW_COPY_AND_ASSIGN(ShieldButton); |
203 }; | 138 }; |
204 | 139 |
205 } // namespace | 140 } // namespace |
206 | 141 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 private: | 389 private: |
455 ShieldButton* listener_button_; | 390 ShieldButton* listener_button_; |
456 WindowSelectorItem::RoundedContainerView* background_; | 391 WindowSelectorItem::RoundedContainerView* background_; |
457 views::Label* label_; | 392 views::Label* label_; |
458 views::ImageButton* close_button_; | 393 views::ImageButton* close_button_; |
459 | 394 |
460 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); | 395 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); |
461 }; | 396 }; |
462 | 397 |
463 WindowSelectorItem::WindowSelectorItem(aura::Window* window, | 398 WindowSelectorItem::WindowSelectorItem(aura::Window* window, |
464 WindowSelector* window_selector, | 399 WindowSelector* window_selector) |
465 WindowGrid* window_grid) | |
466 : dimmed_(false), | 400 : dimmed_(false), |
467 root_window_(window->GetRootWindow()), | 401 root_window_(window->GetRootWindow()), |
468 transform_window_(this, window), | 402 transform_window_(window), |
469 in_bounds_update_(false), | 403 in_bounds_update_(false), |
470 selected_(false), | 404 selected_(false), |
471 caption_container_view_(nullptr), | 405 caption_container_view_(nullptr), |
472 label_view_(nullptr), | 406 label_view_(nullptr), |
473 close_button_(new OverviewCloseButton(this)), | 407 close_button_(new OverviewCloseButton(this)), |
474 window_selector_(window_selector), | 408 window_selector_(window_selector), |
475 background_view_(nullptr), | 409 background_view_(nullptr) { |
476 window_grid_(window_grid) { | |
477 CreateWindowLabel(window->GetTitle()); | 410 CreateWindowLabel(window->GetTitle()); |
478 GetWindow()->AddObserver(this); | 411 GetWindow()->AddObserver(this); |
479 } | 412 } |
480 | 413 |
481 WindowSelectorItem::~WindowSelectorItem() { | 414 WindowSelectorItem::~WindowSelectorItem() { |
482 GetWindow()->RemoveObserver(this); | 415 GetWindow()->RemoveObserver(this); |
483 } | 416 } |
484 | 417 |
485 aura::Window* WindowSelectorItem::GetWindow() { | 418 aura::Window* WindowSelectorItem::GetWindow() { |
486 return transform_window_.window(); | 419 return transform_window_.window(); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 if (ash::Shell::Get() | 535 if (ash::Shell::Get() |
603 ->maximize_mode_controller() | 536 ->maximize_mode_controller() |
604 ->IsMaximizeModeWindowManagerEnabled()) { | 537 ->IsMaximizeModeWindowManagerEnabled()) { |
605 ash::Shell::Get()->metrics()->RecordUserMetricsAction( | 538 ash::Shell::Get()->metrics()->RecordUserMetricsAction( |
606 ash::UMA_TABLET_WINDOW_CLOSE_THROUGH_OVERVIEW_CLOSE_BUTTON); | 539 ash::UMA_TABLET_WINDOW_CLOSE_THROUGH_OVERVIEW_CLOSE_BUTTON); |
607 } | 540 } |
608 CloseWindow(); | 541 CloseWindow(); |
609 return; | 542 return; |
610 } | 543 } |
611 CHECK(sender == caption_container_view_->listener_button()); | 544 CHECK(sender == caption_container_view_->listener_button()); |
612 | 545 window_selector_->SelectWindow(this); |
613 // For other cases, the event is handled in OverviewWindowDragController. | |
614 if (!SplitViewController::ShouldAllowSplitView()) | |
615 window_selector_->SelectWindow(this); | |
616 } | 546 } |
617 | 547 |
618 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { | 548 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { |
619 window->RemoveObserver(this); | 549 window->RemoveObserver(this); |
620 transform_window_.OnWindowDestroyed(); | 550 transform_window_.OnWindowDestroyed(); |
621 } | 551 } |
622 | 552 |
623 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { | 553 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { |
624 // TODO(flackr): Maybe add the new title to a vector of titles so that we can | 554 // TODO(flackr): Maybe add the new title to a vector of titles so that we can |
625 // filter any of the titles the window had while in the overview session. | 555 // filter any of the titles the window had while in the overview session. |
626 label_view_->SetText(window->GetTitle()); | 556 label_view_->SetText(window->GetTitle()); |
627 UpdateAccessibilityName(); | 557 UpdateAccessibilityName(); |
628 } | 558 } |
629 | 559 |
630 float WindowSelectorItem::GetItemScale(const gfx::Size& size) { | 560 float WindowSelectorItem::GetItemScale(const gfx::Size& size) { |
631 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMargin); | 561 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMargin); |
632 return ScopedTransformOverviewWindow::GetItemScale( | 562 return ScopedTransformOverviewWindow::GetItemScale( |
633 transform_window_.GetTargetBoundsInScreen().size(), inset_size, | 563 transform_window_.GetTargetBoundsInScreen().size(), inset_size, |
634 transform_window_.GetTopInset(), | 564 transform_window_.GetTopInset(), |
635 close_button_->GetPreferredSize().height()); | 565 close_button_->GetPreferredSize().height()); |
636 } | 566 } |
637 | 567 |
638 void WindowSelectorItem::HandlePressEvent( | |
639 const gfx::Point& location_in_screen) { | |
640 StartDrag(); | |
641 window_selector_->InitiateDrag(this, location_in_screen); | |
642 } | |
643 | |
644 void WindowSelectorItem::HandleReleaseEvent( | |
645 const gfx::Point& location_in_screen) { | |
646 EndDrag(); | |
647 window_selector_->CompleteDrag(this); | |
648 } | |
649 | |
650 void WindowSelectorItem::HandleDragEvent(const gfx::Point& location_in_screen) { | |
651 window_selector_->Drag(this, location_in_screen); | |
652 } | |
653 | |
654 gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { | 568 gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { |
655 return transform_window_.GetTargetBoundsInScreen(); | 569 return transform_window_.GetTargetBoundsInScreen(); |
656 } | 570 } |
657 | 571 |
658 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, | 572 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, |
659 OverviewAnimationType animation_type) { | 573 OverviewAnimationType animation_type) { |
660 DCHECK(root_window_ == GetWindow()->GetRootWindow()); | 574 DCHECK(root_window_ == GetWindow()->GetRootWindow()); |
661 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); | 575 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); |
662 | 576 |
663 // Avoid division by zero by ensuring screen bounds is not empty. | 577 // Avoid division by zero by ensuring screen bounds is not empty. |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 } | 745 } |
832 | 746 |
833 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { | 747 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { |
834 return background_view_ ? background_view_->animation() : nullptr; | 748 return background_view_ ? background_view_->animation() : nullptr; |
835 } | 749 } |
836 | 750 |
837 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { | 751 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { |
838 return transform_window_.GetOverviewWindowForMinimizedState(); | 752 return transform_window_.GetOverviewWindowForMinimizedState(); |
839 } | 753 } |
840 | 754 |
841 void WindowSelectorItem::StartDrag() { | |
842 gfx::Rect scaled_bounds(target_bounds_); | |
843 scaled_bounds.Inset(-target_bounds_.width() * kDragWindowScale, | |
844 -target_bounds_.height() * kDragWindowScale); | |
845 OverviewAnimationType animation_type = | |
846 OverviewAnimationType::OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM; | |
847 SetBounds(scaled_bounds, animation_type); | |
848 | |
849 aura::Window* widget_window = item_widget_->GetNativeWindow(); | |
850 if (widget_window && widget_window->parent() == GetWindow()->parent()) { | |
851 // TODO(xdai): This might not work if there is an always on top window. | |
852 // See crbug.com/733760. | |
853 widget_window->parent()->StackChildAtTop(widget_window); | |
854 widget_window->parent()->StackChildBelow(GetWindow(), widget_window); | |
855 } | |
856 } | |
857 | |
858 void WindowSelectorItem::EndDrag() { | |
859 // First stack this item's window below the snapped window if split view mode | |
860 // is active. | |
861 aura::Window* dragged_window = GetWindow(); | |
862 aura::Window* dragged_widget_window = item_widget_->GetNativeWindow(); | |
863 aura::Window* parent_window = dragged_widget_window->parent(); | |
864 if (Shell::Get()->IsSplitViewModeActive()) { | |
865 aura::Window* snapped_window = | |
866 Shell::Get()->split_view_controller()->GetDefaultSnappedWindow(); | |
867 if (snapped_window->parent() == parent_window && | |
868 dragged_window->parent() == parent_window) { | |
869 parent_window->StackChildBelow(dragged_widget_window, snapped_window); | |
870 parent_window->StackChildBelow(dragged_window, dragged_widget_window); | |
871 } | |
872 } | |
873 | |
874 // Then find the window which was stacked right above this selector item's | |
875 // window before dragging and stack this selector item's window below it. | |
876 const std::vector<std::unique_ptr<WindowSelectorItem>>& selector_items = | |
877 window_grid_->window_list(); | |
878 aura::Window* stacking_target = nullptr; | |
879 for (size_t index = 0; index < selector_items.size(); index++) { | |
880 if (index > 0) { | |
881 aura::Window* window = selector_items[index - 1].get()->GetWindow(); | |
882 if (window->parent() == parent_window && | |
883 dragged_window->parent() == parent_window) { | |
884 stacking_target = window; | |
885 } | |
886 } | |
887 if (selector_items[index].get() == this && stacking_target) { | |
888 parent_window->StackChildBelow(dragged_widget_window, stacking_target); | |
889 parent_window->StackChildBelow(dragged_window, dragged_widget_window); | |
890 break; | |
891 } | |
892 } | |
893 } | |
894 | |
895 } // namespace ash | 755 } // namespace ash |
OLD | NEW |