diff options
Diffstat (limited to 'ash/wm/overview/window_selector_item.cc')
-rw-r--r-- | ash/wm/overview/window_selector_item.cc | 138 |
1 files changed, 132 insertions, 6 deletions
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc index 13b52b7..2559362 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,12 @@ gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() { return bounds; } +void WindowSelectorItem::OverviewLabelButton::OnGestureEvent( + ui::GestureEvent* event) { + selector_item_->OnGestureEvent(event); + views::LabelButton::OnGestureEvent(event); +} + WindowSelectorItem::WindowSelectorItem(aura::Window* window) : dimmed_(false), root_window_(window->GetRootWindow()), @@ -216,6 +260,72 @@ void WindowSelectorItem::ButtonPressed(views::Button* sender, wm::GetWindowState(transform_window_.window())->Activate(); } +void WindowSelectorItem::OnGestureEvent(ui::GestureEvent* event) { + if (Shell::GetInstance()->window_selector_controller()-> + swipe_to_close_disabled()) + return; + + 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: { + // We need to call SetHandled() for the ET_GESTURE_SCROLL_BEGIN event so + // that future ET_GESTURE_SCROLL_* events are sent here. + event->SetHandled(); + close_button_->SetEnabled(false); + SetupFadeOut(close_button_widget_.GetNativeWindow()); + break; + } + case ui::ET_GESTURE_SCROLL_UPDATE: { + event->SetHandled(); + 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); + break; + } + case ui::ET_GESTURE_SCROLL_END: { + event->SetHandled(); + if (abs(delta_x) > GetMinimumCloseDistance()) { + transform_window_.Close(); + break; + } + ResetScrolledWindow(); + break; + } + case ui::ET_SCROLL_FLING_START: { + event->SetHandled(); + if (abs(delta_x) > GetMinimumCloseDistance() || + fabs(event->details().velocity_x()) > kMinimumFlingVelocity) { + transform_window_.Close(); + break; + } + ResetScrolledWindow(); + break; + } + case ui::ET_GESTURE_END: + scroll_x_origin_ = 0; + break; + default: + break; + } +} + void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { window->RemoveObserver(this); transform_window_.OnWindowDestroyed(); @@ -228,6 +338,20 @@ void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { UpdateCloseButtonAccessibilityName(); } +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 +385,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 +434,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 +456,8 @@ void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { GetWindow()->title())); } +int WindowSelectorItem::GetMinimumCloseDistance() const { + return target_bounds_.size().width() / 2; +} + } // namespace ash |