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 13b52b7856fe51df29935df38d369ac7848b1f63..08c87a22e137e3f4b613c70221cd50cde8a82369 100644 |
| --- a/ash/wm/overview/window_selector_item.cc |
| +++ b/ash/wm/overview/window_selector_item.cc |
| @@ -37,6 +37,13 @@ namespace ash { |
| namespace { |
| +// The minimum fling velocity which will cause a window to be closed. Unit is |
| +// pixels per second. |
| +const float kMinimumFlingVelocity = 4000.0f; |
| + |
| +// The minimum opacity used during touch scroll gestures. |
| +const float kMinimumOpacity = 0.2f; |
| + |
| // In the conceptual overview table, the window margin is the space reserved |
| // around the window within the cell. This margin does not overlap so the |
| // closest distance between adjacent windows will be twice this amount. |
| @@ -72,6 +79,36 @@ gfx::Rect GetTransformedBounds(aura::Window* window) { |
| return ToEnclosingRect(bounds); |
| } |
| +// Convenvience 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. |
| +void SetupFadeInAfterLayout(aura::Window* window) { |
| + ui::Layer* layer = window->layer(); |
| + layer->SetOpacity(0.0f); |
| + ScopedOverviewAnimationSettings animation_settings( |
| + OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, |
| + window); |
| + layer->SetOpacity(1.0f); |
| +} |
| + |
| +// Convenience method to fade out a window using the animation settings defined |
| +// by OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT. |
| +void SetupFadeOut(aura::Window* window) { |
| + ScopedOverviewAnimationSettings animation_settings( |
| + OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT, |
| + window); |
| + window->layer()->SetOpacity(0.0f); |
| +} |
| + |
| +// Calculates the window opacity from the given scroll |distance| and the |
| +// |min opacity_distance|. |
| +float CalculateOpacityFromScrollDistance(int distance, |
| + int min_opacity_distance) { |
| + float opacity = |
| + 1.0f - static_cast<float>(abs(distance)) / min_opacity_distance; |
| + return std::min(1.0f, std::max(kMinimumOpacity, opacity)); |
| +} |
| + |
| // An image button with a close window icon. |
| class OverviewCloseButton : public views::ImageButton { |
| public: |
| @@ -99,9 +136,10 @@ OverviewCloseButton::~OverviewCloseButton() { |
| } // namespace |
| WindowSelectorItem::OverviewLabelButton::OverviewLabelButton( |
| - views::ButtonListener* listener, |
| + WindowSelectorItem* selector_item, |
| const base::string16& text) |
| - : LabelButton(listener, text), |
| + : LabelButton(selector_item, text), |
| + selector_item_(selector_item), |
| top_padding_(0) { |
| } |
| @@ -114,6 +152,41 @@ gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() { |
| return bounds; |
| } |
| +void WindowSelectorItem::OverviewLabelButton::OnGestureEvent( |
| + ui::GestureEvent* event) { |
| + |
| + if (!Shell::GetInstance()->window_selector_controller()-> |
| + swipe_to_close_disabled()) { |
| + int delta_x = 0; |
| + if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| + scroll_x_origin_ = event->x(); |
| + else |
| + delta_x = event->x() - scroll_x_origin_; |
| + |
| + switch (event->type()) { |
| + case ui::ET_GESTURE_SCROLL_BEGIN: |
| + event->SetHandled(); |
|
flackr
2015/02/12 18:52:43
Only the scroll begin is handled, but not the scro
bruthig
2015/02/12 20:34:15
Done.
|
| + selector_item_->OnScrollBegin(); |
| + break; |
| + case ui::ET_GESTURE_SCROLL_UPDATE: |
| + selector_item_->OnScrollUpdate(delta_x); |
| + break; |
| + case ui::ET_GESTURE_SCROLL_END: |
| + selector_item_->OnScrollEnd(delta_x); |
| + break; |
| + case ui::ET_SCROLL_FLING_START: |
| + selector_item_->OnFling(delta_x, fabs(event->details().velocity_x())); |
| + break; |
| + case ui::ET_GESTURE_END: |
| + scroll_x_origin_ = 0; |
| + break; |
| + default: |
| + break; |
| + } |
| + } |
| + views::LabelButton::OnGestureEvent(event); |
| +} |
| + |
| WindowSelectorItem::WindowSelectorItem(aura::Window* window) |
| : dimmed_(false), |
| root_window_(window->GetRootWindow()), |
| @@ -228,6 +301,58 @@ void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { |
| UpdateCloseButtonAccessibilityName(); |
| } |
| +void WindowSelectorItem::OnScrollBegin() { |
| + close_button_->SetEnabled(false); |
| + SetupFadeOut(close_button_widget_.GetNativeWindow()); |
| +} |
| + |
| +void WindowSelectorItem::OnScrollUpdate(int delta_x) { |
| + ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings; |
| + transform_window_.BeginScopedAnimation( |
| + OverviewAnimationType::OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM, |
| + &animation_settings); |
| + |
| + gfx::Transform new_transform; |
| + new_transform.Translate(delta_x, 0); |
| + new_transform.PreconcatTransform(transform_window_.get_overview_transform()); |
| + transform_window_.SetTransform(root_window(), new_transform); |
| + |
| + const float opacity = CalculateOpacityFromScrollDistance(delta_x, |
| + GetMinimumCloseDistance()); |
| + transform_window_.SetOpacity(opacity); |
| +} |
| + |
| +void WindowSelectorItem::OnScrollEnd(int delta_x) { |
| + if (abs(delta_x) > GetMinimumCloseDistance()) { |
| + transform_window_.Close(); |
| + return; |
| + } |
| + ResetScrolledWindow(); |
| +} |
| + |
| +void WindowSelectorItem::OnFling(int delta_x, float velocity_x) { |
| + if (abs(delta_x) > GetMinimumCloseDistance() || |
| + velocity_x > kMinimumFlingVelocity) { |
| + transform_window_.Close(); |
| + return; |
| + } |
| + ResetScrolledWindow(); |
| +} |
| + |
| +void WindowSelectorItem::ResetScrolledWindow() { |
| + ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings; |
| + transform_window_.BeginScopedAnimation( |
| + OverviewAnimationType::OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL, |
| + &animation_settings); |
| + |
| + transform_window_.SetTransform(root_window(), |
| + transform_window_.get_overview_transform()); |
| + transform_window_.SetOpacity(1.0); |
| + |
| + SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow()); |
| + close_button_->SetEnabled(true); |
| +} |
| + |
| void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, |
| OverviewAnimationType animation_type) { |
| DCHECK(root_window_ == GetWindow()->GetRootWindow()); |
| @@ -261,8 +386,7 @@ void WindowSelectorItem::UpdateWindowLabel( |
| if (!window_label_->IsVisible()) { |
| window_label_->Show(); |
| - ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( |
| - window_label_->GetNativeWindow()); |
| + SetupFadeInAfterLayout(window_label_->GetNativeWindow()); |
| } |
| gfx::Rect converted_bounds = |
| @@ -311,8 +435,7 @@ void WindowSelectorItem::UpdateCloseButtonLayout( |
| OverviewAnimationType animation_type) { |
| if (!close_button_->visible()) { |
| close_button_->SetVisible(true); |
| - ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( |
| - close_button_widget_.GetNativeWindow()); |
| + SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow()); |
| } |
| ScopedOverviewAnimationSettings animation_settings(animation_type, |
| close_button_widget_.GetNativeWindow()); |
| @@ -334,4 +457,8 @@ void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { |
| GetWindow()->title())); |
| } |
| +int WindowSelectorItem::GetMinimumCloseDistance() const { |
| + return target_bounds_.size().width() / 2; |
| +} |
| + |
| } // namespace ash |