Skip to content

Commit

Permalink
Implemented swipe to close in overview mode.
Browse files Browse the repository at this point in the history
BUG=393668

Review URL: https://codereview.chromium.org/690103008

Cr-Commit-Position: refs/heads/master@{#316217}
  • Loading branch information
bruthig-chromium authored and Commit bot committed Feb 13, 2015
1 parent da598af commit 7ec5114
Show file tree
Hide file tree
Showing 14 changed files with 478 additions and 60 deletions.
4 changes: 4 additions & 0 deletions ash/ash_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const char kAshDisableScreenOrientationLock[] =
"ash-disable-screen-orientation-lock";
#endif

// Disables gesture swipe to close windows while in Overview mode.
const char kAshDisableSwipeToCloseInOverviewMode[] =
"ash-disable-swipe-to-close-in-overview-mode";

// Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be
// turned on automatically when spoken feedback is enabled when this flag is
// set.
Expand Down
1 change: 1 addition & 0 deletions ash/ash_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ASH_EXPORT extern const char kAshConstrainPointerToRoot[];
ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[];
ASH_EXPORT extern const char kAshDebugShortcuts[];
ASH_EXPORT extern const char kAshDisableLockLayoutManager[];
ASH_EXPORT extern const char kAshDisableSwipeToCloseInOverviewMode[];
#if defined(OS_CHROMEOS)
ASH_EXPORT extern const char kAshDisableScreenOrientationLock[];
#endif
Expand Down
11 changes: 9 additions & 2 deletions ash/wm/overview/overview_animation_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@ enum OverviewAnimationType {
// TODO(bruthig): Remove OVERVIEW_ANIMATION_NONE value and replace it with
// correct animation type actions.
OVERVIEW_ANIMATION_NONE,
// Used to fade in the close button and label when entering overview mode.
// Used to fade in the close button and label.
OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN,
// Used to fade out the close button.
OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT,
// Used to position windows when entering/exiting overview mode and when a
// window is closed while overview mode is active.
OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS,
// Used to hide non-overview mode windows.
OVERVIEW_ANIMATION_HIDE_WINDOW,
// Used to restore windows to their original position when exiting overview
// mode.
OVERVIEW_ANIMATION_RESTORE_WINDOW
OVERVIEW_ANIMATION_RESTORE_WINDOW,
// Used to animate windows when a user performs a touch drag gesture.
OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM,
// Used to animate windows back in to position when a touch drag gesture is
// cancelled.
OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL
};

} // namespace ash
Expand Down
28 changes: 17 additions & 11 deletions ash/wm/overview/scoped_overview_animation_settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,22 @@ const int kTransitionMilliseconds = 200;
// The time duration for widgets to fade in.
const int kFadeInMilliseconds = 80;

// The time duration for widgets to fade out.
const int kFadeOutMilliseconds = 100;

base::TimeDelta GetAnimationDuration(OverviewAnimationType animation_type) {
switch (animation_type) {
case OVERVIEW_ANIMATION_NONE:
case OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM:
return base::TimeDelta();
case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN:
return base::TimeDelta::FromMilliseconds(kFadeInMilliseconds);
case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT:
return base::TimeDelta::FromMilliseconds(kFadeOutMilliseconds);
case OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS:
case OVERVIEW_ANIMATION_RESTORE_WINDOW:
case OVERVIEW_ANIMATION_HIDE_WINDOW:
case OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL:
return base::TimeDelta::FromMilliseconds(kTransitionMilliseconds);
}
NOTREACHED();
Expand All @@ -44,6 +51,7 @@ ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(

switch (animation_type) {
case OVERVIEW_ANIMATION_NONE:
case OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM:
animation_settings_.SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
break;
Expand All @@ -55,6 +63,10 @@ ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
animation_settings_.SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
break;
case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT:
animation_settings_.SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
break;
case OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS:
case OVERVIEW_ANIMATION_RESTORE_WINDOW:
animation_settings_.SetPreemptionStrategy(
Expand All @@ -65,6 +77,11 @@ ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
animation_settings_.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
case OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL:
animation_settings_.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
animation_settings_.SetTweenType(gfx::Tween::EASE_IN_OUT);
break;
}
animation_settings_.SetTransitionDuration(
GetAnimationDuration(animation_type));
Expand All @@ -73,15 +90,4 @@ ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
ScopedOverviewAnimationSettings::~ScopedOverviewAnimationSettings() {
}

// static:
void ScopedOverviewAnimationSettings::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);
}

} // namespace ash
5 changes: 0 additions & 5 deletions ash/wm/overview/scoped_overview_animation_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ class ScopedOverviewAnimationSettings {
aura::Window* window);
virtual ~ScopedOverviewAnimationSettings();

// 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.
static void SetupFadeInAfterLayout(aura::Window* window);

private:
// The managed animation settings.
ui::ScopedLayerAnimationSettings animation_settings_;
Expand Down
1 change: 1 addition & 0 deletions ash/wm/overview/window_selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ash/wm/overview/window_selector.h"

#include <algorithm>
#include <functional>
#include <set>
#include <vector>

Expand Down
6 changes: 5 additions & 1 deletion ash/wm/overview/window_selector_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <vector>

#include "ash/ash_switches.h"
#include "ash/metrics/user_metrics_recorder.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_state_delegate.h"
Expand All @@ -15,12 +16,15 @@
#include "ash/wm/overview/window_selector.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "ui/aura/window.h"

namespace ash {

WindowSelectorController::WindowSelectorController() {
WindowSelectorController::WindowSelectorController()
: swipe_to_close_disabled_(base::CommandLine::ForCurrentProcess()->
HasSwitch(switches::kAshDisableSwipeToCloseInOverviewMode)) {
}

WindowSelectorController::~WindowSelectorController() {
Expand Down
5 changes: 5 additions & 0 deletions ash/wm/overview/window_selector_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ASH_EXPORT WindowSelectorController
// are visible during overview mode.
bool IsRestoringMinimizedWindows() const;

bool swipe_to_close_disabled() const { return swipe_to_close_disabled_; }

// WindowSelectorDelegate:
void OnSelectionEnded() override;

Expand All @@ -60,6 +62,9 @@ class ASH_EXPORT WindowSelectorController
scoped_ptr<WindowSelector> window_selector_;
base::Time last_selection_time_;

// Tracks whether the "Swipe-to-close" feature is disabled.
bool swipe_to_close_disabled_;

DISALLOW_COPY_AND_ASSIGN(WindowSelectorController);
};

Expand Down
138 changes: 132 additions & 6 deletions ash/wm/overview/window_selector_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
}

Expand All @@ -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()),
Expand Down Expand Up @@ -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();
Expand All @@ -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());
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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());
Expand All @@ -334,4 +456,8 @@ void WindowSelectorItem::UpdateCloseButtonAccessibilityName() {
GetWindow()->title()));
}

int WindowSelectorItem::GetMinimumCloseDistance() const {
return target_bounds_.size().width() / 2;
}

} // namespace ash
Loading

0 comments on commit 7ec5114

Please sign in to comment.