summaryrefslogtreecommitdiffstats
path: root/athena
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 12:01:42 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-08 12:03:03 +0000
commit1899fa47c3fdc3a7867bb8d8e2a6e0b540446860 (patch)
tree1967eb10c518cd38cbbbdef3b0fd41f61ef79f49 /athena
parent7eb95f2ab22789ab500c8da17d21c7366f14d1fa (diff)
downloadchromium_src-1899fa47c3fdc3a7867bb8d8e2a6e0b540446860.zip
chromium_src-1899fa47c3fdc3a7867bb8d8e2a6e0b540446860.tar.gz
chromium_src-1899fa47c3fdc3a7867bb8d8e2a6e0b540446860.tar.bz2
athena: Slide a window offscreen in overview mode to close it.
BUG=401526 R=mukai@chromium.org Review URL: https://codereview.chromium.org/442263004 Cr-Commit-Position: refs/heads/master@{#288335} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288335 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'athena')
-rw-r--r--athena/wm/window_overview_mode.cc185
1 files changed, 172 insertions, 13 deletions
diff --git a/athena/wm/window_overview_mode.cc b/athena/wm/window_overview_mode.cc
index a294cde..e04858a 100644
--- a/athena/wm/window_overview_mode.cc
+++ b/athena/wm/window_overview_mode.cc
@@ -8,6 +8,7 @@
#include <functional>
#include <vector>
+#include "base/bind.h"
#include "base/macros.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window.h"
@@ -40,6 +41,29 @@ struct WindowOverviewState {
scoped_ptr<wm::Shadow> shadow;
};
+// Runs a callback at the end of the animation. This observe also destroys
+// itself afterwards.
+class ClosureAnimationObserver : public ui::ImplicitAnimationObserver {
+ public:
+ explicit ClosureAnimationObserver(const base::Closure& closure)
+ : closure_(closure) {
+ DCHECK(!closure_.is_null());
+ }
+ private:
+ virtual ~ClosureAnimationObserver() {
+ }
+
+ // ui::ImplicitAnimationObserver:
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ closure_.Run();
+ delete this;
+ }
+
+ const base::Closure closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClosureAnimationObserver);
+};
+
} // namespace
DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*)
@@ -54,13 +78,18 @@ bool ShouldShowWindowInOverviewMode(aura::Window* window) {
return window->type() == ui::wm::WINDOW_TYPE_NORMAL;
}
+// Gets the transform for the window in its current state.
+gfx::Transform GetTransformForState(WindowOverviewState* state) {
+ return gfx::Tween::TransformValueBetween(state->progress,
+ state->top,
+ state->bottom);
+}
+
// Sets the progress-state for the window in the overview mode.
void SetWindowProgress(aura::Window* window, float progress) {
WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
- gfx::Transform transform =
- gfx::Tween::TransformValueBetween(progress, state->top, state->bottom);
- window->SetTransform(transform);
state->progress = progress;
+ window->SetTransform(GetTransformForState(state));
}
// Resets the overview-related state for |window|.
@@ -108,7 +137,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
scoped_targeter_(new aura::ScopedWindowTargeter(
container,
scoped_ptr<ui::EventTargeter>(
- new StaticWindowTargeter(container)))) {
+ new StaticWindowTargeter(container)))),
+ dragged_window_(NULL) {
container_->set_target_handler(this);
// Prepare the desired transforms for all the windows, and set the initial
@@ -143,8 +173,6 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
const int kGapBetweenWindowsBottom = 10;
const int kGapBetweenWindowsTop = 5;
- const float kMinScale = 0.6f;
- const float kMaxScale = 0.95f;
for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
iter != windows.rend();
@@ -311,6 +339,101 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
compositor->RemoveAnimationObserver(this);
}
+ void DragWindow(const ui::GestureEvent& event) {
+ CHECK(dragged_window_);
+ CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type());
+ gfx::Vector2dF dragged_distance =
+ dragged_start_location_ - event.location();
+ WindowOverviewState* dragged_state =
+ dragged_window_->GetProperty(kWindowOverviewState);
+ CHECK(dragged_state);
+ gfx::Transform transform = GetTransformForState(dragged_state);
+ transform.Translate(-dragged_distance.x(), 0);
+ dragged_window_->SetTransform(transform);
+
+ float ratio = std::min(
+ 1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal);
+ float opacity =
+ gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity);
+ dragged_window_->layer()->SetOpacity(opacity);
+ }
+
+ bool ShouldCloseDragWindow(const ui::GestureEvent& event) const {
+ gfx::Vector2dF dragged_distance =
+ dragged_start_location_ - event.location();
+ if (event.type() == ui::ET_GESTURE_SCROLL_END)
+ return std::abs(dragged_distance.x()) >= kMinDistanceForDismissal;
+ CHECK_EQ(ui::ET_SCROLL_FLING_START, event.type());
+ const bool dragging_towards_right = dragged_distance.x() < 0;
+ const bool swipe_towards_right = event.details().velocity_x() > 0;
+ if (dragging_towards_right != swipe_towards_right)
+ return false;
+ const float kMinVelocityForDismissal = 500.f;
+ return std::abs(event.details().velocity_x()) > kMinVelocityForDismissal;
+ }
+
+ void CloseDragWindow(const ui::GestureEvent& gesture) {
+ // Animate |dragged_window_| offscreen first, then destroy it.
+ ui::ScopedLayerAnimationSettings settings(
+ dragged_window_->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.AddObserver(new ClosureAnimationObserver(
+ base::Bind(&base::DeletePointer<aura::Window>, dragged_window_)));
+
+ WindowOverviewState* dragged_state =
+ dragged_window_->GetProperty(kWindowOverviewState);
+ CHECK(dragged_state);
+ gfx::Transform transform = dragged_window_->layer()->transform();
+ gfx::RectF transformed_bounds = dragged_window_->bounds();
+ transform.TransformRect(&transformed_bounds);
+ float transform_x = 0.f;
+ if (gesture.location().x() > dragged_start_location_.x())
+ transform_x = container_->bounds().right() - transformed_bounds.x();
+ else
+ transform_x = -(transformed_bounds.x() + transformed_bounds.width());
+ float scale = gfx::Tween::FloatValueBetween(
+ dragged_state->progress, kMinScale, kMaxScale);
+ transform.Translate(transform_x / scale, 0);
+ dragged_window_->SetTransform(transform);
+ dragged_window_->layer()->SetOpacity(kMinOpacity);
+
+ // Move the windows behind |dragged_window_| in the stack forward one step.
+ const aura::Window::Windows& list = container_->children();
+ for (aura::Window::Windows::const_iterator iter = list.begin();
+ iter != list.end() && *iter != dragged_window_;
+ ++iter) {
+ aura::Window* window = *iter;
+ ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
+
+ aura::Window* next = *(iter + 1);
+ WindowOverviewState* next_state = next->GetProperty(kWindowOverviewState);
+ state->top = next_state->top;
+ state->bottom = next_state->bottom;
+ SetWindowProgress(window, next_state->progress);
+ }
+
+ dragged_window_ = NULL;
+ }
+
+ void RestoreDragWindow() {
+ CHECK(dragged_window_);
+ WindowOverviewState* dragged_state =
+ dragged_window_->GetProperty(kWindowOverviewState);
+ CHECK(dragged_state);
+
+ ui::ScopedLayerAnimationSettings settings(
+ dragged_window_->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ dragged_window_->SetTransform(GetTransformForState(dragged_state));
+ dragged_window_->layer()->SetOpacity(1.f);
+ dragged_window_ = NULL;
+ }
+
// ui::EventHandler:
virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
if (mouse->type() == ui::ET_MOUSE_PRESSED) {
@@ -336,17 +459,44 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
gesture->SetHandled();
delegate_->OnSelectWindow(select);
}
+ } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
+ if (std::abs(gesture->details().scroll_x_hint()) >
+ std::abs(gesture->details().scroll_y_hint()) * 2) {
+ dragged_start_location_ = gesture->location();
+ dragged_window_ = SelectWindowAt(gesture);
+ }
} else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
- DoScroll(gesture->details().scroll_y());
+ if (dragged_window_)
+ DragWindow(*gesture);
+ else
+ DoScroll(gesture->details().scroll_y());
gesture->SetHandled();
- } else if (gesture->type() == ui::ET_SCROLL_FLING_START) {
- CreateFlingerFor(*gesture);
- AddAnimationObserver();
+ } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
+ if (dragged_window_) {
+ if (ShouldCloseDragWindow(*gesture))
+ CloseDragWindow(*gesture);
+ else
+ RestoreDragWindow();
+ }
gesture->SetHandled();
- } else if (gesture->type() == ui::ET_GESTURE_TAP_DOWN && fling_) {
- fling_.reset();
- RemoveAnimationObserver();
+ } else if (gesture->type() == ui::ET_SCROLL_FLING_START) {
+ if (dragged_window_) {
+ if (ShouldCloseDragWindow(*gesture))
+ CloseDragWindow(*gesture);
+ else
+ RestoreDragWindow();
+ } else {
+ CreateFlingerFor(*gesture);
+ AddAnimationObserver();
+ }
gesture->SetHandled();
+ } else if (gesture->type() == ui::ET_GESTURE_TAP_DOWN) {
+ if (fling_) {
+ fling_.reset();
+ RemoveAnimationObserver();
+ gesture->SetHandled();
+ }
+ dragged_window_ = NULL;
}
}
@@ -364,11 +514,20 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
}
}
+ const int kMinDistanceForDismissal = 300;
+ const float kMinScale = 0.6f;
+ const float kMaxScale = 0.95f;
+ const float kMaxOpacity = 1.0f;
+ const float kMinOpacity = 0.2f;
+
aura::Window* container_;
WindowOverviewModeDelegate* delegate_;
scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_;
scoped_ptr<ui::FlingCurve> fling_;
+ aura::Window* dragged_window_;
+ gfx::Point dragged_start_location_;
+
DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl);
};