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" |
20 #include "ash/wm/overview/window_selector.h" | 21 #include "ash/wm/overview/window_selector.h" |
21 #include "ash/wm/overview/window_selector_controller.h" | 22 #include "ash/wm/overview/window_selector_controller.h" |
22 #include "ash/wm/window_state.h" | 23 #include "ash/wm/window_state.h" |
23 #include "base/auto_reset.h" | 24 #include "base/auto_reset.h" |
24 #include "base/strings/string_util.h" | 25 #include "base/strings/string_util.h" |
25 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
26 #include "base/time/time.h" | 27 #include "base/time/time.h" |
27 #include "ui/base/l10n/l10n_util.h" | 28 #include "ui/base/l10n/l10n_util.h" |
28 #include "ui/compositor/layer_animation_sequence.h" | 29 #include "ui/compositor/layer_animation_sequence.h" |
29 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 30 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // Duration of background opacity transition for the selected label. | 94 // Duration of background opacity transition for the selected label. |
94 static const int kSelectorFadeInMilliseconds = 350; | 95 static const int kSelectorFadeInMilliseconds = 350; |
95 | 96 |
96 // Duration of background opacity transition when exiting overview mode. | 97 // Duration of background opacity transition when exiting overview mode. |
97 static const int kExitFadeInMilliseconds = 30; | 98 static const int kExitFadeInMilliseconds = 30; |
98 | 99 |
99 // Before closing a window animate both the window and the caption to shrink by | 100 // Before closing a window animate both the window and the caption to shrink by |
100 // this fraction of size. | 101 // this fraction of size. |
101 static const float kPreCloseScale = 0.02f; | 102 static const float kPreCloseScale = 0.02f; |
102 | 103 |
| 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 |
103 // Convenience method to fade in a Window with predefined animation settings. | 108 // Convenience method to fade in a Window with predefined animation settings. |
104 // Note: The fade in animation will occur after a delay where the delay is how | 109 // Note: The fade in animation will occur after a delay where the delay is how |
105 // long the lay out animations take. | 110 // long the lay out animations take. |
106 void SetupFadeInAfterLayout(views::Widget* widget) { | 111 void SetupFadeInAfterLayout(views::Widget* widget) { |
107 aura::Window* window = widget->GetNativeWindow(); | 112 aura::Window* window = widget->GetNativeWindow(); |
108 window->layer()->SetOpacity(0.0f); | 113 window->layer()->SetOpacity(0.0f); |
109 ScopedOverviewAnimationSettings scoped_overview_animation_settings( | 114 ScopedOverviewAnimationSettings scoped_overview_animation_settings( |
110 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, | 115 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, |
111 window); | 116 window); |
112 window->layer()->SetOpacity(1.0f); | 117 window->layer()->SetOpacity(1.0f); |
113 } | 118 } |
114 | 119 |
115 // A Button that has a listener and listens to mouse clicks on the visible part | 120 // A Button that has a listener and listens to mouse / gesture events on the |
116 // of an overview window. | 121 // visible part of an overview window. Note that the drag events are only |
| 122 // handled in maximized mode. |
117 class ShieldButton : public views::CustomButton { | 123 class ShieldButton : public views::CustomButton { |
118 public: | 124 public: |
119 ShieldButton(views::ButtonListener* listener, const base::string16& name) | 125 ShieldButton(views::ButtonListener* listener, const base::string16& name) |
120 : views::CustomButton(listener) { | 126 : views::CustomButton(listener) { |
121 SetAccessibleName(name); | 127 SetAccessibleName(name); |
122 } | 128 } |
123 ~ShieldButton() override {} | 129 ~ShieldButton() override {} |
124 | 130 |
125 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its | 131 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its |
126 // |item_widget_| is allowed to stay around to complete any animations. | 132 // |item_widget_| is allowed to stay around to complete any animations. |
127 // Resetting the listener in all views that are targeted by events is | 133 // Resetting the listener in all views that are targeted by events is |
128 // necessary to prevent a crash when a user clicks on the fading out widget | 134 // necessary to prevent a crash when a user clicks on the fading out widget |
129 // after the WindowSelectorItem has been destroyed. | 135 // after the WindowSelectorItem has been destroyed. |
130 void ResetListener() { listener_ = nullptr; } | 136 void ResetListener() { listener_ = nullptr; } |
131 | 137 |
| 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 |
132 protected: | 197 protected: |
133 // views::View: | 198 // views::View: |
134 const char* GetClassName() const override { return "ShieldButton"; } | 199 const char* GetClassName() const override { return "ShieldButton"; } |
135 | 200 |
136 private: | 201 private: |
137 DISALLOW_COPY_AND_ASSIGN(ShieldButton); | 202 DISALLOW_COPY_AND_ASSIGN(ShieldButton); |
138 }; | 203 }; |
139 | 204 |
140 } // namespace | 205 } // namespace |
141 | 206 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 private: | 454 private: |
390 ShieldButton* listener_button_; | 455 ShieldButton* listener_button_; |
391 WindowSelectorItem::RoundedContainerView* background_; | 456 WindowSelectorItem::RoundedContainerView* background_; |
392 views::Label* label_; | 457 views::Label* label_; |
393 views::ImageButton* close_button_; | 458 views::ImageButton* close_button_; |
394 | 459 |
395 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); | 460 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); |
396 }; | 461 }; |
397 | 462 |
398 WindowSelectorItem::WindowSelectorItem(aura::Window* window, | 463 WindowSelectorItem::WindowSelectorItem(aura::Window* window, |
399 WindowSelector* window_selector) | 464 WindowSelector* window_selector, |
| 465 WindowGrid* window_grid) |
400 : dimmed_(false), | 466 : dimmed_(false), |
401 root_window_(window->GetRootWindow()), | 467 root_window_(window->GetRootWindow()), |
402 transform_window_(window), | 468 transform_window_(this, window), |
403 in_bounds_update_(false), | 469 in_bounds_update_(false), |
404 selected_(false), | 470 selected_(false), |
405 caption_container_view_(nullptr), | 471 caption_container_view_(nullptr), |
406 label_view_(nullptr), | 472 label_view_(nullptr), |
407 close_button_(new OverviewCloseButton(this)), | 473 close_button_(new OverviewCloseButton(this)), |
408 window_selector_(window_selector), | 474 window_selector_(window_selector), |
409 background_view_(nullptr) { | 475 background_view_(nullptr), |
| 476 window_grid_(window_grid) { |
410 CreateWindowLabel(window->GetTitle()); | 477 CreateWindowLabel(window->GetTitle()); |
411 GetWindow()->AddObserver(this); | 478 GetWindow()->AddObserver(this); |
412 } | 479 } |
413 | 480 |
414 WindowSelectorItem::~WindowSelectorItem() { | 481 WindowSelectorItem::~WindowSelectorItem() { |
415 GetWindow()->RemoveObserver(this); | 482 GetWindow()->RemoveObserver(this); |
416 } | 483 } |
417 | 484 |
418 aura::Window* WindowSelectorItem::GetWindow() { | 485 aura::Window* WindowSelectorItem::GetWindow() { |
419 return transform_window_.window(); | 486 return transform_window_.window(); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 if (ash::Shell::Get() | 602 if (ash::Shell::Get() |
536 ->maximize_mode_controller() | 603 ->maximize_mode_controller() |
537 ->IsMaximizeModeWindowManagerEnabled()) { | 604 ->IsMaximizeModeWindowManagerEnabled()) { |
538 ash::Shell::Get()->metrics()->RecordUserMetricsAction( | 605 ash::Shell::Get()->metrics()->RecordUserMetricsAction( |
539 ash::UMA_TABLET_WINDOW_CLOSE_THROUGH_OVERVIEW_CLOSE_BUTTON); | 606 ash::UMA_TABLET_WINDOW_CLOSE_THROUGH_OVERVIEW_CLOSE_BUTTON); |
540 } | 607 } |
541 CloseWindow(); | 608 CloseWindow(); |
542 return; | 609 return; |
543 } | 610 } |
544 CHECK(sender == caption_container_view_->listener_button()); | 611 CHECK(sender == caption_container_view_->listener_button()); |
545 window_selector_->SelectWindow(this); | 612 |
| 613 // For other cases, the event is handled in OverviewWindowDragController. |
| 614 if (!SplitViewController::ShouldAllowSplitView()) |
| 615 window_selector_->SelectWindow(this); |
546 } | 616 } |
547 | 617 |
548 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { | 618 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { |
549 window->RemoveObserver(this); | 619 window->RemoveObserver(this); |
550 transform_window_.OnWindowDestroyed(); | 620 transform_window_.OnWindowDestroyed(); |
551 } | 621 } |
552 | 622 |
553 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { | 623 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { |
554 // TODO(flackr): Maybe add the new title to a vector of titles so that we can | 624 // TODO(flackr): Maybe add the new title to a vector of titles so that we can |
555 // filter any of the titles the window had while in the overview session. | 625 // filter any of the titles the window had while in the overview session. |
556 label_view_->SetText(window->GetTitle()); | 626 label_view_->SetText(window->GetTitle()); |
557 UpdateAccessibilityName(); | 627 UpdateAccessibilityName(); |
558 } | 628 } |
559 | 629 |
560 float WindowSelectorItem::GetItemScale(const gfx::Size& size) { | 630 float WindowSelectorItem::GetItemScale(const gfx::Size& size) { |
561 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMargin); | 631 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMargin); |
562 return ScopedTransformOverviewWindow::GetItemScale( | 632 return ScopedTransformOverviewWindow::GetItemScale( |
563 transform_window_.GetTargetBoundsInScreen().size(), inset_size, | 633 transform_window_.GetTargetBoundsInScreen().size(), inset_size, |
564 transform_window_.GetTopInset(), | 634 transform_window_.GetTopInset(), |
565 close_button_->GetPreferredSize().height()); | 635 close_button_->GetPreferredSize().height()); |
566 } | 636 } |
567 | 637 |
| 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 |
568 gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { | 654 gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { |
569 return transform_window_.GetTargetBoundsInScreen(); | 655 return transform_window_.GetTargetBoundsInScreen(); |
570 } | 656 } |
571 | 657 |
572 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, | 658 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, |
573 OverviewAnimationType animation_type) { | 659 OverviewAnimationType animation_type) { |
574 DCHECK(root_window_ == GetWindow()->GetRootWindow()); | 660 DCHECK(root_window_ == GetWindow()->GetRootWindow()); |
575 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); | 661 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); |
576 | 662 |
577 // Avoid division by zero by ensuring screen bounds is not empty. | 663 // Avoid division by zero by ensuring screen bounds is not empty. |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 } | 831 } |
746 | 832 |
747 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { | 833 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { |
748 return background_view_ ? background_view_->animation() : nullptr; | 834 return background_view_ ? background_view_->animation() : nullptr; |
749 } | 835 } |
750 | 836 |
751 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { | 837 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { |
752 return transform_window_.GetOverviewWindowForMinimizedState(); | 838 return transform_window_.GetOverviewWindowForMinimizedState(); |
753 } | 839 } |
754 | 840 |
| 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 |
755 } // namespace ash | 895 } // namespace ash |
OLD | NEW |