Chromium Code Reviews| 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/public/cpp/shell_window_ids.h" | 11 #include "ash/public/cpp/shell_window_ids.h" |
| 12 #include "ash/resources/vector_icons/vector_icons.h" | 12 #include "ash/resources/vector_icons/vector_icons.h" |
| 13 #include "ash/root_window_controller.h" | 13 #include "ash/root_window_controller.h" |
| 14 #include "ash/shell.h" | 14 #include "ash/shell.h" |
| 15 #include "ash/shell_port.h" | 15 #include "ash/shell_port.h" |
| 16 #include "ash/wm/maximize_mode/maximize_mode_controller.h" | 16 #include "ash/wm/maximize_mode/maximize_mode_controller.h" |
| 17 #include "ash/wm/overview/cleanup_animation_observer.h" | 17 #include "ash/wm/overview/cleanup_animation_observer.h" |
| 18 #include "ash/wm/overview/overview_animation_type.h" | 18 #include "ash/wm/overview/overview_animation_type.h" |
| 19 #include "ash/wm/overview/scoped_overview_animation_settings.h" | 19 #include "ash/wm/overview/scoped_overview_animation_settings.h" |
| 20 #include "ash/wm/overview/scoped_transform_overview_window.h" | 20 #include "ash/wm/overview/scoped_transform_overview_window.h" |
| 21 #include "ash/wm/overview/window_grid.h" | |
| 21 #include "ash/wm/overview/window_selector.h" | 22 #include "ash/wm/overview/window_selector.h" |
| 22 #include "ash/wm/overview/window_selector_controller.h" | 23 #include "ash/wm/overview/window_selector_controller.h" |
| 23 #include "ash/wm/window_state.h" | 24 #include "ash/wm/window_state.h" |
| 24 #include "base/auto_reset.h" | 25 #include "base/auto_reset.h" |
| 25 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 27 #include "base/time/time.h" | 28 #include "base/time/time.h" |
| 28 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 29 #include "ui/compositor/layer_animation_sequence.h" | 30 #include "ui/compositor/layer_animation_sequence.h" |
| 30 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 31 #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. | 95 // Duration of background opacity transition for the selected label. |
| 95 static const int kSelectorFadeInMilliseconds = 350; | 96 static const int kSelectorFadeInMilliseconds = 350; |
| 96 | 97 |
| 97 // Duration of background opacity transition when exiting overview mode. | 98 // Duration of background opacity transition when exiting overview mode. |
| 98 static const int kExitFadeInMilliseconds = 30; | 99 static const int kExitFadeInMilliseconds = 30; |
| 99 | 100 |
| 100 // Before closing a window animate both the window and the caption to shrink by | 101 // Before closing a window animate both the window and the caption to shrink by |
| 101 // this fraction of size. | 102 // this fraction of size. |
| 102 static const float kPreCloseScale = 0.02f; | 103 static const float kPreCloseScale = 0.02f; |
| 103 | 104 |
| 105 // Before dragging an overview window, the window will scale up |kPreDragScale| | |
| 106 // to indicate its selection. | |
| 107 static const float kDragWindowScale = 0.04f; | |
| 108 | |
| 104 // Convenience method to fade in a Window with predefined animation settings. | 109 // Convenience method to fade in a Window with predefined animation settings. |
| 105 // Note: The fade in animation will occur after a delay where the delay is how | 110 // Note: The fade in animation will occur after a delay where the delay is how |
| 106 // long the lay out animations take. | 111 // long the lay out animations take. |
| 107 void SetupFadeInAfterLayout(views::Widget* widget) { | 112 void SetupFadeInAfterLayout(views::Widget* widget) { |
| 108 aura::Window* window = widget->GetNativeWindow(); | 113 aura::Window* window = widget->GetNativeWindow(); |
| 109 window->layer()->SetOpacity(0.0f); | 114 window->layer()->SetOpacity(0.0f); |
| 110 ScopedOverviewAnimationSettings scoped_overview_animation_settings( | 115 ScopedOverviewAnimationSettings scoped_overview_animation_settings( |
| 111 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, | 116 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, |
| 112 window); | 117 window); |
| 113 window->layer()->SetOpacity(1.0f); | 118 window->layer()->SetOpacity(1.0f); |
| 114 } | 119 } |
| 115 | 120 |
| 116 // A Button that has a listener and listens to mouse clicks on the visible part | 121 // A Button that has a listener and listens to mouse / gesture events on the |
| 117 // of an overview window. | 122 // visible part of an overview window. Note that the drag events are only |
| 123 // handled in maximized mode. | |
| 118 class ShieldButton : public views::CustomButton { | 124 class ShieldButton : public views::CustomButton { |
| 119 public: | 125 public: |
| 120 ShieldButton(views::ButtonListener* listener, const base::string16& name) | 126 ShieldButton(views::ButtonListener* listener, const base::string16& name) |
| 121 : views::CustomButton(listener) { | 127 : views::CustomButton(listener) { |
| 122 SetAccessibleName(name); | 128 SetAccessibleName(name); |
| 123 } | 129 } |
| 124 ~ShieldButton() override {} | 130 ~ShieldButton() override {} |
| 125 | 131 |
| 126 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its | 132 // When WindowSelectorItem (which is a ButtonListener) is destroyed, its |
| 127 // |item_widget_| is allowed to stay around to complete any animations. | 133 // |item_widget_| is allowed to stay around to complete any animations. |
| 128 // Resetting the listener in all views that are targeted by events is | 134 // Resetting the listener in all views that are targeted by events is |
| 129 // necessary to prevent a crash when a user clicks on the fading out widget | 135 // necessary to prevent a crash when a user clicks on the fading out widget |
| 130 // after the WindowSelectorItem has been destroyed. | 136 // after the WindowSelectorItem has been destroyed. |
| 131 void ResetListener() { listener_ = nullptr; } | 137 void ResetListener() { listener_ = nullptr; } |
| 132 | 138 |
| 139 // views::CustomButton: | |
| 140 bool OnMousePressed(const ui::MouseEvent& event) override { | |
| 141 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
| 142 gfx::Point location(event.location()); | |
| 143 views::View::ConvertPointToScreen(this, &location); | |
| 144 listener()->HandlePressEvent(location); | |
| 145 return true; | |
| 146 } | |
| 147 return views::CustomButton::OnMousePressed(event); | |
| 148 } | |
| 149 | |
| 150 void OnMouseReleased(const ui::MouseEvent& event) override { | |
| 151 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
| 152 gfx::Point location(event.location()); | |
| 153 views::View::ConvertPointToScreen(this, &location); | |
| 154 listener()->HandleReleaseEvent(location); | |
| 155 return; | |
| 156 } | |
| 157 views::CustomButton::OnMouseReleased(event); | |
| 158 } | |
| 159 | |
| 160 bool OnMouseDragged(const ui::MouseEvent& event) override { | |
| 161 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
| 162 gfx::Point location(event.location()); | |
| 163 views::View::ConvertPointToScreen(this, &location); | |
| 164 listener()->HandleDragEvent(location); | |
| 165 return true; | |
| 166 } | |
| 167 return views::CustomButton::OnMouseDragged(event); | |
| 168 } | |
| 169 | |
| 170 void OnGestureEvent(ui::GestureEvent* event) override { | |
| 171 if (listener() && SplitViewController::ShouldAllowSplitView()) { | |
| 172 gfx::Point location(event->location()); | |
| 173 views::View::ConvertPointToScreen(this, &location); | |
| 174 switch (event->type()) { | |
| 175 case ui::ET_GESTURE_SCROLL_BEGIN: | |
| 176 case ui::ET_GESTURE_TAP_DOWN: | |
| 177 listener()->HandlePressEvent(location); | |
| 178 break; | |
| 179 case ui::ET_GESTURE_SCROLL_UPDATE: | |
| 180 listener()->HandleDragEvent(location); | |
| 181 break; | |
| 182 case ui::ET_GESTURE_END: | |
| 183 listener()->HandleReleaseEvent(location); | |
| 184 break; | |
| 185 default: | |
| 186 break; | |
| 187 } | |
| 188 event->SetHandled(); | |
| 189 return; | |
| 190 } | |
| 191 views::CustomButton::OnGestureEvent(event); | |
| 192 } | |
| 193 | |
| 194 WindowSelectorItem* listener() { | |
| 195 return static_cast<WindowSelectorItem*>(listener_); | |
| 196 } | |
| 197 | |
| 133 protected: | 198 protected: |
| 134 // views::View: | 199 // views::View: |
| 135 const char* GetClassName() const override { return "ShieldButton"; } | 200 const char* GetClassName() const override { return "ShieldButton"; } |
| 136 | 201 |
| 137 private: | 202 private: |
| 138 DISALLOW_COPY_AND_ASSIGN(ShieldButton); | 203 DISALLOW_COPY_AND_ASSIGN(ShieldButton); |
| 139 }; | 204 }; |
| 140 | 205 |
| 141 } // namespace | 206 } // namespace |
| 142 | 207 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 private: | 455 private: |
| 391 ShieldButton* listener_button_; | 456 ShieldButton* listener_button_; |
| 392 WindowSelectorItem::RoundedContainerView* background_; | 457 WindowSelectorItem::RoundedContainerView* background_; |
| 393 views::Label* label_; | 458 views::Label* label_; |
| 394 views::ImageButton* close_button_; | 459 views::ImageButton* close_button_; |
| 395 | 460 |
| 396 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); | 461 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); |
| 397 }; | 462 }; |
| 398 | 463 |
| 399 WindowSelectorItem::WindowSelectorItem(aura::Window* window, | 464 WindowSelectorItem::WindowSelectorItem(aura::Window* window, |
| 400 WindowSelector* window_selector) | 465 WindowSelector* window_selector, |
| 466 WindowGrid* window_grid) | |
| 401 : dimmed_(false), | 467 : dimmed_(false), |
| 402 root_window_(window->GetRootWindow()), | 468 root_window_(window->GetRootWindow()), |
| 403 transform_window_(window), | 469 transform_window_(this, window), |
| 404 in_bounds_update_(false), | 470 in_bounds_update_(false), |
| 405 selected_(false), | 471 selected_(false), |
| 406 caption_container_view_(nullptr), | 472 caption_container_view_(nullptr), |
| 407 label_view_(nullptr), | 473 label_view_(nullptr), |
| 408 close_button_(new OverviewCloseButton(this)), | 474 close_button_(new OverviewCloseButton(this)), |
| 409 window_selector_(window_selector), | 475 window_selector_(window_selector), |
| 410 background_view_(nullptr) { | 476 background_view_(nullptr), |
| 477 window_grid_(window_grid) { | |
| 411 CreateWindowLabel(window->GetTitle()); | 478 CreateWindowLabel(window->GetTitle()); |
| 412 GetWindow()->AddObserver(this); | 479 GetWindow()->AddObserver(this); |
| 413 } | 480 } |
| 414 | 481 |
| 415 WindowSelectorItem::~WindowSelectorItem() { | 482 WindowSelectorItem::~WindowSelectorItem() { |
| 416 GetWindow()->RemoveObserver(this); | 483 GetWindow()->RemoveObserver(this); |
| 417 } | 484 } |
| 418 | 485 |
| 419 aura::Window* WindowSelectorItem::GetWindow() { | 486 aura::Window* WindowSelectorItem::GetWindow() { |
| 420 return transform_window_.window(); | 487 return transform_window_.window(); |
| (...skipping 114 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::ShellPort::Get()->RecordUserMetricsAction( | 605 ash::ShellPort::Get()->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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 } | 834 } |
| 749 | 835 |
| 750 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { | 836 gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() { |
| 751 return background_view_ ? background_view_->animation() : nullptr; | 837 return background_view_ ? background_view_->animation() : nullptr; |
| 752 } | 838 } |
| 753 | 839 |
| 754 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { | 840 aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { |
| 755 return transform_window_.GetOverviewWindowForMinimizedState(); | 841 return transform_window_.GetOverviewWindowForMinimizedState(); |
| 756 } | 842 } |
| 757 | 843 |
| 844 void WindowSelectorItem::StartDrag() { | |
| 845 gfx::Rect scaled_bounds(target_bounds_); | |
| 846 scaled_bounds.Inset(-target_bounds_.width() * kDragWindowScale, | |
| 847 -target_bounds_.height() * kDragWindowScale); | |
| 848 OverviewAnimationType animation_type = | |
| 849 OverviewAnimationType::OVERVIEW_ANIMATION_CLOSING_SELECTOR_ITEM; | |
| 850 SetBounds(scaled_bounds, animation_type); | |
| 851 | |
| 852 aura::Window* widget_window = item_widget_->GetNativeWindow(); | |
| 853 if (widget_window && widget_window->parent() == GetWindow()->parent()) { | |
| 854 // TODO(xdai): This might not work if there is an always on top window. | |
| 855 // See crbug.com/733760. | |
| 856 widget_window->parent()->StackChildAtTop(widget_window); | |
| 857 widget_window->parent()->StackChildBelow(GetWindow(), widget_window); | |
| 858 } | |
| 859 } | |
| 860 | |
| 861 void WindowSelectorItem::EndDrag() { | |
| 862 // First stack this item's window below the snapped window if split view mode | |
| 863 // is active. | |
| 864 aura::Window* dragged_window = GetWindow(); | |
| 865 aura::Window* dragged_widget_window = item_widget_->GetNativeWindow(); | |
| 866 if (Shell::Get()->IsSplitViewModeActive()) { | |
| 867 aura::Window* snapped_window = | |
| 868 Shell::Get()->split_view_controller()->GetDefaultSnappedWindow(); | |
|
varkha
2017/06/26 16:40:07
nit: you could cache the parent here (e.g. dragged
xdai1
2017/06/26 21:44:00
Done.
| |
| 869 if (snapped_window->parent() == dragged_widget_window->parent() && | |
| 870 snapped_window->parent() == dragged_window->parent()) { | |
| 871 dragged_widget_window->parent()->StackChildBelow(dragged_widget_window, | |
| 872 snapped_window); | |
| 873 dragged_widget_window->parent()->StackChildBelow(dragged_window, | |
| 874 dragged_widget_window); | |
| 875 } | |
| 876 } | |
| 877 | |
| 878 // Then find the window which is stacked right above this selector item's | |
|
varkha
2017/06/26 16:40:07
nit: is -> was
xdai1
2017/06/26 21:44:00
Done.
| |
| 879 // window before dragging and stack this selector item's window below it. | |
| 880 const std::vector<std::unique_ptr<WindowSelectorItem>>& selector_items = | |
| 881 window_grid_->window_list(); | |
| 882 size_t position_in_grid = 0; | |
| 883 for (size_t index = 0; index < selector_items.size(); index++) { | |
| 884 if (selector_items[index].get() == this) { | |
| 885 position_in_grid = index; | |
| 886 break; | |
| 887 } | |
| 888 } | |
|
varkha
2017/06/26 16:40:07
See the comment below, but just a concern here. Ha
xdai1
2017/06/26 21:44:00
I checked the scenario you described here (ctrl-o
| |
| 889 for (int i = position_in_grid - 1; i >= 0; i--) { | |
|
varkha
2017/06/26 16:40:07
Since you are breaking out of the for loop first t
xdai1
2017/06/26 21:44:00
Sorry, I intended to put "break;" in the if-clause
| |
| 890 aura::Window* stacking_target = selector_items[i].get()->GetWindow(); | |
| 891 if (stacking_target->parent() == dragged_widget_window->parent() && | |
| 892 stacking_target->parent() == dragged_window->parent()) { | |
| 893 dragged_widget_window->parent()->StackChildBelow(dragged_widget_window, | |
| 894 stacking_target); | |
| 895 dragged_widget_window->parent()->StackChildBelow(dragged_window, | |
| 896 dragged_widget_window); | |
| 897 } | |
| 898 break; | |
| 899 } | |
| 900 } | |
| 901 | |
| 758 } // namespace ash | 902 } // namespace ash |
| OLD | NEW |