Chromium Code Reviews| Index: ash/wm/overview/window_selector_item.cc |
| diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc |
| index 723e54bbaeb3811fa62c5cb4153177db84fc7efc..144fae5e06b333e446478dddbcb8a5290b16d56f 100644 |
| --- a/ash/wm/overview/window_selector_item.cc |
| +++ b/ash/wm/overview/window_selector_item.cc |
| @@ -18,6 +18,7 @@ |
| #include "ash/wm/overview/overview_animation_type.h" |
| #include "ash/wm/overview/scoped_overview_animation_settings.h" |
| #include "ash/wm/overview/scoped_transform_overview_window.h" |
| +#include "ash/wm/overview/window_grid.h" |
| #include "ash/wm/overview/window_selector.h" |
| #include "ash/wm/overview/window_selector_controller.h" |
| #include "ash/wm/window_state.h" |
| @@ -101,6 +102,10 @@ static const int kExitFadeInMilliseconds = 30; |
| // this fraction of size. |
| static const float kPreCloseScale = 0.02f; |
| +// Before dragging an overview window, the window will scale up |kPreDragScale| |
| +// to indicate its selection. |
| +static const float kDragWindowScale = 0.04f; |
| + |
| // Convenience method to fade in a Window with predefined animation settings. |
| // Note: The fade in animation will occur after a delay where the delay is how |
| // long the lay out animations take. |
| @@ -113,8 +118,9 @@ void SetupFadeInAfterLayout(views::Widget* widget) { |
| window->layer()->SetOpacity(1.0f); |
| } |
| -// A Button that has a listener and listens to mouse clicks on the visible part |
| -// of an overview window. |
| +// A Button that has a listener and listens to mouse / gesture events on the |
| +// visible part of an overview window. Note that the drag events are only |
| +// handled in maximized mode. |
| class ShieldButton : public views::CustomButton { |
| public: |
| ShieldButton(views::ButtonListener* listener, const base::string16& name) |
| @@ -130,6 +136,65 @@ class ShieldButton : public views::CustomButton { |
| // after the WindowSelectorItem has been destroyed. |
| void ResetListener() { listener_ = nullptr; } |
| + // views::CustomButton: |
| + bool OnMousePressed(const ui::MouseEvent& event) override { |
| + if (listener() && SplitViewController::ShouldAllowSplitView()) { |
| + gfx::Point location(event.location()); |
| + views::View::ConvertPointToScreen(this, &location); |
| + listener()->HandlePressEvent(location); |
| + return true; |
| + } |
| + return views::CustomButton::OnMousePressed(event); |
| + } |
| + |
| + void OnMouseReleased(const ui::MouseEvent& event) override { |
| + if (listener() && SplitViewController::ShouldAllowSplitView()) { |
| + gfx::Point location(event.location()); |
| + views::View::ConvertPointToScreen(this, &location); |
| + listener()->HandleReleaseEvent(location); |
| + return; |
| + } |
| + views::CustomButton::OnMouseReleased(event); |
| + } |
| + |
| + bool OnMouseDragged(const ui::MouseEvent& event) override { |
| + if (listener() && SplitViewController::ShouldAllowSplitView()) { |
| + gfx::Point location(event.location()); |
| + views::View::ConvertPointToScreen(this, &location); |
| + listener()->HandleDragEvent(location); |
| + return true; |
| + } |
| + return views::CustomButton::OnMouseDragged(event); |
| + } |
| + |
| + void OnGestureEvent(ui::GestureEvent* event) override { |
| + if (listener() && SplitViewController::ShouldAllowSplitView()) { |
| + gfx::Point location(event->location()); |
| + views::View::ConvertPointToScreen(this, &location); |
| + switch (event->type()) { |
| + case ui::ET_GESTURE_SCROLL_BEGIN: |
| + case ui::ET_GESTURE_TAP_DOWN: |
| + listener()->HandlePressEvent(location); |
| + break; |
| + case ui::ET_GESTURE_SCROLL_UPDATE: |
| + listener()->HandleDragEvent(location); |
| + break; |
| + case ui::ET_GESTURE_END: |
| + listener()->HandleReleaseEvent(location); |
| + break; |
| + default: |
| + break; |
| + } |
| + event->SetHandled(); |
| + return; |
| + } |
| + views::CustomButton::OnGestureEvent(event); |
| + } |
| + |
| + WindowSelectorItem* listener() { |
| + return static_cast<WindowSelectorItem*>(listener_); |
| + } |
| + |
| protected: |
| // views::View: |
| const char* GetClassName() const override { return "ShieldButton"; } |
| @@ -397,17 +462,19 @@ class WindowSelectorItem::CaptionContainerView : public views::View { |
| }; |
| WindowSelectorItem::WindowSelectorItem(aura::Window* window, |
| - WindowSelector* window_selector) |
| + WindowSelector* window_selector, |
| + WindowGrid* window_grid) |
| : dimmed_(false), |
| root_window_(window->GetRootWindow()), |
| - transform_window_(window), |
| + transform_window_(this, window), |
| in_bounds_update_(false), |
| selected_(false), |
| caption_container_view_(nullptr), |
| label_view_(nullptr), |
| close_button_(new OverviewCloseButton(this)), |
| window_selector_(window_selector), |
| - background_view_(nullptr) { |
| + background_view_(nullptr), |
| + window_grid_(window_grid) { |
| CreateWindowLabel(window->GetTitle()); |
| GetWindow()->AddObserver(this); |
| } |
| @@ -542,7 +609,10 @@ void WindowSelectorItem::ButtonPressed(views::Button* sender, |
| return; |
| } |
| CHECK(sender == caption_container_view_->listener_button()); |
| - window_selector_->SelectWindow(this); |
| + |
| + // For other cases, the event is handled in OverviewWindowDragController. |
| + if (!SplitViewController::ShouldAllowSplitView()) |
| + window_selector_->SelectWindow(this); |
| } |
| void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { |
| @@ -565,6 +635,22 @@ float WindowSelectorItem::GetItemScale(const gfx::Size& size) { |
| close_button_->GetPreferredSize().height()); |
| } |
| +void WindowSelectorItem::HandlePressEvent( |
| + const gfx::Point& location_in_screen) { |
| + StartDrag(); |
| + window_selector_->InitiateDrag(this, location_in_screen); |
| +} |
| + |
| +void WindowSelectorItem::HandleReleaseEvent( |
| + const gfx::Point& location_in_screen) { |
| + EndDrag(); |
| + window_selector_->CompleteDrag(this); |
| +} |
| + |
| +void WindowSelectorItem::HandleDragEvent(const gfx::Point& location_in_screen) { |
| + window_selector_->Drag(this, location_in_screen); |
| +} |
| + |
| gfx::Rect WindowSelectorItem::GetTargetBoundsInScreen() const { |
| return transform_window_.GetTargetBoundsInScreen(); |
| } |
| @@ -755,4 +841,62 @@ aura::Window* WindowSelectorItem::GetOverviewWindowForMinimizedStateForTest() { |
| return transform_window_.GetOverviewWindowForMinimizedState(); |
| } |
| +void WindowSelectorItem::StartDrag() { |
| + gfx::Rect scaled_bounds(target_bounds_); |
| + scaled_bounds.Inset(-target_bounds_.width() * kDragWindowScale, |
| + -target_bounds_.height() * kDragWindowScale); |
| + OverviewAnimationType animation_type = |
| + OverviewAnimationType::OVERVIEW_ANIMATION_CLOSING_SELECTOR_ITEM; |
| + SetBounds(scaled_bounds, animation_type); |
| + |
| + aura::Window* widget_window = item_widget_->GetNativeWindow(); |
| + if (widget_window && widget_window->parent() == GetWindow()->parent()) { |
| + // TODO(xdai): This might not work if there is an always on top window. |
| + // See crbug.com/733760. |
| + widget_window->parent()->StackChildAtTop(widget_window); |
| + widget_window->parent()->StackChildBelow(GetWindow(), widget_window); |
| + } |
| +} |
| + |
| +void WindowSelectorItem::EndDrag() { |
| + // First stack this item's window below the snapped window if split view mode |
| + // is active. |
| + aura::Window* dragged_window = GetWindow(); |
| + aura::Window* dragged_widget_window = item_widget_->GetNativeWindow(); |
| + if (Shell::Get()->IsSplitViewModeActive()) { |
| + aura::Window* snapped_window = |
| + 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.
|
| + if (snapped_window->parent() == dragged_widget_window->parent() && |
| + snapped_window->parent() == dragged_window->parent()) { |
| + dragged_widget_window->parent()->StackChildBelow(dragged_widget_window, |
| + snapped_window); |
| + dragged_widget_window->parent()->StackChildBelow(dragged_window, |
| + dragged_widget_window); |
| + } |
| + } |
| + |
| + // 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.
|
| + // window before dragging and stack this selector item's window below it. |
| + const std::vector<std::unique_ptr<WindowSelectorItem>>& selector_items = |
| + window_grid_->window_list(); |
| + size_t position_in_grid = 0; |
| + for (size_t index = 0; index < selector_items.size(); index++) { |
| + if (selector_items[index].get() == this) { |
| + position_in_grid = index; |
| + break; |
| + } |
| + } |
|
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
|
| + 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
|
| + aura::Window* stacking_target = selector_items[i].get()->GetWindow(); |
| + if (stacking_target->parent() == dragged_widget_window->parent() && |
| + stacking_target->parent() == dragged_window->parent()) { |
| + dragged_widget_window->parent()->StackChildBelow(dragged_widget_window, |
| + stacking_target); |
| + dragged_widget_window->parent()->StackChildBelow(dragged_window, |
| + dragged_widget_window); |
| + } |
| + break; |
| + } |
| +} |
| + |
| } // namespace ash |