Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(787)

Side by Side Diff: athena/wm/window_overview_mode.cc

Issue 442263004: athena: Slide a window offscreen in overview mode to close it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "athena/wm/window_overview_mode.h" 5 #include "athena/wm/window_overview_mode.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h"
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "ui/aura/scoped_window_targeter.h" 13 #include "ui/aura/scoped_window_targeter.h"
13 #include "ui/aura/window.h" 14 #include "ui/aura/window.h"
14 #include "ui/aura/window_delegate.h" 15 #include "ui/aura/window_delegate.h"
15 #include "ui/aura/window_property.h" 16 #include "ui/aura/window_property.h"
16 #include "ui/aura/window_targeter.h" 17 #include "ui/aura/window_targeter.h"
17 #include "ui/aura/window_tree_host.h" 18 #include "ui/aura/window_tree_host.h"
18 #include "ui/compositor/compositor.h" 19 #include "ui/compositor/compositor.h"
19 #include "ui/compositor/compositor_animation_observer.h" 20 #include "ui/compositor/compositor_animation_observer.h"
20 #include "ui/compositor/scoped_layer_animation_settings.h" 21 #include "ui/compositor/scoped_layer_animation_settings.h"
21 #include "ui/events/event_handler.h" 22 #include "ui/events/event_handler.h"
22 #include "ui/events/gestures/fling_curve.h" 23 #include "ui/events/gestures/fling_curve.h"
23 #include "ui/gfx/frame_time.h" 24 #include "ui/gfx/frame_time.h"
24 #include "ui/gfx/transform.h" 25 #include "ui/gfx/transform.h"
26 #include "ui/gfx/transform_util.h"
25 #include "ui/wm/core/shadow.h" 27 #include "ui/wm/core/shadow.h"
26 28
27 namespace { 29 namespace {
28 30
29 struct WindowOverviewState { 31 struct WindowOverviewState {
30 // The transform for when the window is at the topmost position. 32 // The transform for when the window is at the topmost position.
31 gfx::Transform top; 33 gfx::Transform top;
32 34
33 // The transform for when the window is at the bottom-most position. 35 // The transform for when the window is at the bottom-most position.
34 gfx::Transform bottom; 36 gfx::Transform bottom;
35 37
36 // The current overview state of the window. 0.f means the window is at the 38 // The current overview state of the window. 0.f means the window is at the
37 // topmost position. 1.f means the window is at the bottom-most position. 39 // topmost position. 1.f means the window is at the bottom-most position.
38 float progress; 40 float progress;
39 41
40 scoped_ptr<wm::Shadow> shadow; 42 scoped_ptr<wm::Shadow> shadow;
41 }; 43 };
42 44
45 // Runs a callback at the end of the animation. This observe also destroys
46 // itself afterwards.
47 class ClosureAnimationObserver : public ui::ImplicitAnimationObserver {
48 public:
49 explicit ClosureAnimationObserver(const base::Closure& closure)
50 : closure_(closure) {}
Jun Mukai 2014/08/07 21:00:30 Can you add DCHECK(!closure.is_null()) here? Your
sadrul 2014/08/07 21:15:36 Done.
51 private:
52 virtual ~ClosureAnimationObserver() {
53 }
54
55 // ui::ImplicitAnimationObserver:
56 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
57 if (!closure_.is_null())
58 closure_.Run();
59 delete this;
60 }
61
62 base::Closure closure_;
63
64 DISALLOW_COPY_AND_ASSIGN(ClosureAnimationObserver);
65 };
66
43 } // namespace 67 } // namespace
44 68
45 DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*) 69 DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*)
46 DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowOverviewState, 70 DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowOverviewState,
47 kWindowOverviewState, 71 kWindowOverviewState,
48 NULL) 72 NULL)
49 namespace athena { 73 namespace athena {
50 74
51 namespace { 75 namespace {
52 76
53 bool ShouldShowWindowInOverviewMode(aura::Window* window) { 77 bool ShouldShowWindowInOverviewMode(aura::Window* window) {
54 return window->type() == ui::wm::WINDOW_TYPE_NORMAL; 78 return window->type() == ui::wm::WINDOW_TYPE_NORMAL;
55 } 79 }
56 80
81 // Gets the transform for the window in its current state.
82 gfx::Transform GetTransformForState(WindowOverviewState* state) {
83 return gfx::Tween::TransformValueBetween(state->progress,
84 state->top,
85 state->bottom);
86 }
87
57 // Sets the progress-state for the window in the overview mode. 88 // Sets the progress-state for the window in the overview mode.
58 void SetWindowProgress(aura::Window* window, float progress) { 89 void SetWindowProgress(aura::Window* window, float progress) {
59 WindowOverviewState* state = window->GetProperty(kWindowOverviewState); 90 WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
60 gfx::Transform transform =
61 gfx::Tween::TransformValueBetween(progress, state->top, state->bottom);
62 window->SetTransform(transform);
63 state->progress = progress; 91 state->progress = progress;
92 window->SetTransform(GetTransformForState(state));
64 } 93 }
65 94
66 // Resets the overview-related state for |window|. 95 // Resets the overview-related state for |window|.
67 void RestoreWindowState(aura::Window* window) { 96 void RestoreWindowState(aura::Window* window) {
68 window->ClearProperty(kWindowOverviewState); 97 window->ClearProperty(kWindowOverviewState);
69 98
70 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); 99 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
71 settings.SetPreemptionStrategy( 100 settings.SetPreemptionStrategy(
72 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 101 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
73 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); 102 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
(...skipping 27 matching lines...) Expand all
101 public ui::EventHandler, 130 public ui::EventHandler,
102 public ui::CompositorAnimationObserver { 131 public ui::CompositorAnimationObserver {
103 public: 132 public:
104 WindowOverviewModeImpl(aura::Window* container, 133 WindowOverviewModeImpl(aura::Window* container,
105 WindowOverviewModeDelegate* delegate) 134 WindowOverviewModeDelegate* delegate)
106 : container_(container), 135 : container_(container),
107 delegate_(delegate), 136 delegate_(delegate),
108 scoped_targeter_(new aura::ScopedWindowTargeter( 137 scoped_targeter_(new aura::ScopedWindowTargeter(
109 container, 138 container,
110 scoped_ptr<ui::EventTargeter>( 139 scoped_ptr<ui::EventTargeter>(
111 new StaticWindowTargeter(container)))) { 140 new StaticWindowTargeter(container)))),
141 dragged_window_(NULL) {
112 container_->set_target_handler(this); 142 container_->set_target_handler(this);
113 143
114 // Prepare the desired transforms for all the windows, and set the initial 144 // Prepare the desired transforms for all the windows, and set the initial
115 // state on the windows. 145 // state on the windows.
116 ComputeTerminalStatesForAllWindows(); 146 ComputeTerminalStatesForAllWindows();
117 SetInitialWindowStates(); 147 SetInitialWindowStates();
118 } 148 }
119 149
120 virtual ~WindowOverviewModeImpl() { 150 virtual ~WindowOverviewModeImpl() {
121 container_->set_target_handler(container_->delegate()); 151 container_->set_target_handler(container_->delegate());
(...skipping 14 matching lines...) Expand all
136 void ComputeTerminalStatesForAllWindows() { 166 void ComputeTerminalStatesForAllWindows() {
137 const aura::Window::Windows& windows = container_->children(); 167 const aura::Window::Windows& windows = container_->children();
138 size_t window_count = std::count_if(windows.begin(), windows.end(), 168 size_t window_count = std::count_if(windows.begin(), windows.end(),
139 ShouldShowWindowInOverviewMode); 169 ShouldShowWindowInOverviewMode);
140 170
141 size_t index = 0; 171 size_t index = 0;
142 const gfx::Size container_size = container_->bounds().size(); 172 const gfx::Size container_size = container_->bounds().size();
143 173
144 const int kGapBetweenWindowsBottom = 10; 174 const int kGapBetweenWindowsBottom = 10;
145 const int kGapBetweenWindowsTop = 5; 175 const int kGapBetweenWindowsTop = 5;
146 const float kMinScale = 0.6f;
147 const float kMaxScale = 0.95f;
148 176
149 for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin(); 177 for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
150 iter != windows.rend(); 178 iter != windows.rend();
151 ++iter) { 179 ++iter) {
152 aura::Window* window = (*iter); 180 aura::Window* window = (*iter);
153 if (!ShouldShowWindowInOverviewMode(window)) 181 if (!ShouldShowWindowInOverviewMode(window))
154 continue; 182 continue;
155 183
156 gfx::Transform top_transform; 184 gfx::Transform top_transform;
157 int top = (window_count - index - 1) * kGapBetweenWindowsTop; 185 int top = (window_count - index - 1) * kGapBetweenWindowsTop;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 if (!compositor->HasAnimationObserver(this)) 332 if (!compositor->HasAnimationObserver(this))
305 compositor->AddAnimationObserver(this); 333 compositor->AddAnimationObserver(this);
306 } 334 }
307 335
308 void RemoveAnimationObserver() { 336 void RemoveAnimationObserver() {
309 ui::Compositor* compositor = container_->GetHost()->compositor(); 337 ui::Compositor* compositor = container_->GetHost()->compositor();
310 if (compositor->HasAnimationObserver(this)) 338 if (compositor->HasAnimationObserver(this))
311 compositor->RemoveAnimationObserver(this); 339 compositor->RemoveAnimationObserver(this);
312 } 340 }
313 341
342 void DragWindow(const ui::GestureEvent& event) {
343 CHECK(dragged_window_);
344 CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type());
345 gfx::Vector2dF dragged_distance =
346 dragged_start_location_ - event.location();
347 WindowOverviewState* dragged_state =
348 dragged_window_->GetProperty(kWindowOverviewState);
349 CHECK(dragged_state);
350 gfx::Transform transform = GetTransformForState(dragged_state);
351 transform.Translate(-dragged_distance.x(), 0);
352 dragged_window_->SetTransform(transform);
353
354 float ratio = std::min(
355 1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal);
356 float opacity =
357 gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity);
358 dragged_window_->layer()->SetOpacity(opacity);
359 }
360
361 bool ShouldCloseDragWindow(const ui::GestureEvent& event) const {
362 gfx::Vector2dF dragged_distance =
363 dragged_start_location_ - event.location();
364 if (event.type() == ui::ET_GESTURE_SCROLL_END)
365 return std::abs(dragged_distance.x()) >= kMinDistanceForDismissal;
366 CHECK_EQ(ui::ET_SCROLL_FLING_START, event.type());
367 const bool dragging_towards_right = dragged_distance.x() < 0;
368 const bool swipe_towards_right = event.details().velocity_x() > 0;
369 if (dragging_towards_right != swipe_towards_right)
370 return false;
371 const float kMinVelocityForDismissal = 500.f;
372 return std::abs(event.details().velocity_x()) > kMinVelocityForDismissal;
373 }
374
375 void CloseDragWindow(const ui::GestureEvent& gesture) {
376 // Animate |dragged_window_| offscreen first, then destroy it.
377 ui::ScopedLayerAnimationSettings settings(
378 dragged_window_->layer()->GetAnimator());
379 settings.SetPreemptionStrategy(
380 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
381 settings.AddObserver(new ClosureAnimationObserver(
382 base::Bind(&base::DeletePointer<aura::Window>, dragged_window_)));
383
384 WindowOverviewState* dragged_state =
385 dragged_window_->GetProperty(kWindowOverviewState);
386 CHECK(dragged_state);
387 gfx::Transform transform = dragged_window_->layer()->transform();
388 gfx::RectF transformed_bounds = dragged_window_->bounds();
389 transform.TransformRect(&transformed_bounds);
390 float transform_x = 0.f;
391 if (gesture.location().x() > dragged_start_location_.x())
392 transform_x = container_->bounds().right() - transformed_bounds.x();
393 else
394 transform_x = -(transformed_bounds.x() + transformed_bounds.width());
395 float scale = gfx::Tween::FloatValueBetween(
396 dragged_state->progress, kMinScale, kMaxScale);
397 transform.Translate(transform_x / scale, 0);
398 dragged_window_->SetTransform(transform);
399 dragged_window_->layer()->SetOpacity(kMinOpacity);
400
401 // Move the windows behind |dragged_window_| in the stack forward one step.
402 const aura::Window::Windows& list = container_->children();
403 aura::Window::Windows::const_reverse_iterator find =
404 std::find(list.rbegin(), list.rend(), dragged_window_);
405 CHECK(list.rend() != find);
406 float progress = (*find)->GetProperty(kWindowOverviewState)->progress;
407 for (++find; find != list.rend(); ++find) {
408 aura::Window* window = *find;
409 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
410 settings.SetPreemptionStrategy(
411 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
412 float next_progress = window->GetProperty(kWindowOverviewState)->progress;
413 SetWindowProgress(window, progress);
414 progress = next_progress;
415 }
416
417 dragged_window_ = NULL;
418 }
419
420 void RestoreDragWindow() {
421 CHECK(dragged_window_);
422 WindowOverviewState* dragged_state =
423 dragged_window_->GetProperty(kWindowOverviewState);
424 CHECK(dragged_state);
425
426 ui::ScopedLayerAnimationSettings settings(
427 dragged_window_->layer()->GetAnimator());
428 settings.SetPreemptionStrategy(
429 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
430 dragged_window_->SetTransform(GetTransformForState(dragged_state));
431 dragged_window_->layer()->SetOpacity(1.f);
Jun Mukai 2014/08/07 21:00:30 should reset dragged_window_ here?
sadrul 2014/08/07 21:15:36 Done.
432 }
433
314 // ui::EventHandler: 434 // ui::EventHandler:
315 virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE { 435 virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
316 if (mouse->type() == ui::ET_MOUSE_PRESSED) { 436 if (mouse->type() == ui::ET_MOUSE_PRESSED) {
317 aura::Window* select = SelectWindowAt(mouse); 437 aura::Window* select = SelectWindowAt(mouse);
318 if (select) { 438 if (select) {
319 mouse->SetHandled(); 439 mouse->SetHandled();
320 delegate_->OnSelectWindow(select); 440 delegate_->OnSelectWindow(select);
321 } 441 }
322 } else if (mouse->type() == ui::ET_MOUSEWHEEL) { 442 } else if (mouse->type() == ui::ET_MOUSEWHEEL) {
323 DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset()); 443 DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset());
324 } 444 }
325 } 445 }
326 446
327 virtual void OnScrollEvent(ui::ScrollEvent* scroll) OVERRIDE { 447 virtual void OnScrollEvent(ui::ScrollEvent* scroll) OVERRIDE {
328 if (scroll->type() == ui::ET_SCROLL) 448 if (scroll->type() == ui::ET_SCROLL)
329 DoScroll(scroll->y_offset()); 449 DoScroll(scroll->y_offset());
330 } 450 }
331 451
332 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE { 452 virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
333 if (gesture->type() == ui::ET_GESTURE_TAP) { 453 if (gesture->type() == ui::ET_GESTURE_TAP) {
334 aura::Window* select = SelectWindowAt(gesture); 454 aura::Window* select = SelectWindowAt(gesture);
335 if (select) { 455 if (select) {
336 gesture->SetHandled(); 456 gesture->SetHandled();
337 delegate_->OnSelectWindow(select); 457 delegate_->OnSelectWindow(select);
338 } 458 }
459 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
460 if (std::abs(gesture->details().scroll_x_hint()) >
461 std::abs(gesture->details().scroll_y_hint()) * 2) {
462 dragged_start_location_ = gesture->location();
463 dragged_window_ = SelectWindowAt(gesture);
464 }
339 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { 465 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
340 DoScroll(gesture->details().scroll_y()); 466 if (dragged_window_)
467 DragWindow(*gesture);
468 else
469 DoScroll(gesture->details().scroll_y());
470 gesture->SetHandled();
471 } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
472 if (dragged_window_) {
473 if (ShouldCloseDragWindow(*gesture))
474 CloseDragWindow(*gesture);
475 else
476 RestoreDragWindow();
477 }
341 gesture->SetHandled(); 478 gesture->SetHandled();
342 } else if (gesture->type() == ui::ET_SCROLL_FLING_START) { 479 } else if (gesture->type() == ui::ET_SCROLL_FLING_START) {
343 CreateFlingerFor(*gesture); 480 if (dragged_window_) {
344 AddAnimationObserver(); 481 if (ShouldCloseDragWindow(*gesture))
482 CloseDragWindow(*gesture);
483 else
484 RestoreDragWindow();
485 } else {
486 CreateFlingerFor(*gesture);
487 AddAnimationObserver();
488 }
345 gesture->SetHandled(); 489 gesture->SetHandled();
346 } else if (gesture->type() == ui::ET_GESTURE_TAP_DOWN && fling_) { 490 } else if (gesture->type() == ui::ET_GESTURE_TAP_DOWN) {
347 fling_.reset(); 491 if (fling_) {
348 RemoveAnimationObserver(); 492 fling_.reset();
349 gesture->SetHandled(); 493 RemoveAnimationObserver();
494 gesture->SetHandled();
495 }
496 dragged_window_ = NULL;
350 } 497 }
351 } 498 }
352 499
353 // ui::CompositorAnimationObserver: 500 // ui::CompositorAnimationObserver:
354 virtual void OnAnimationStep(base::TimeTicks timestamp) OVERRIDE { 501 virtual void OnAnimationStep(base::TimeTicks timestamp) OVERRIDE {
355 CHECK(fling_); 502 CHECK(fling_);
356 if (fling_->start_timestamp() > timestamp) 503 if (fling_->start_timestamp() > timestamp)
357 return; 504 return;
358 gfx::Vector2dF scroll = fling_->GetScrollAmountAtTime(timestamp); 505 gfx::Vector2dF scroll = fling_->GetScrollAmountAtTime(timestamp);
359 if (scroll.IsZero()) { 506 if (scroll.IsZero()) {
360 fling_.reset(); 507 fling_.reset();
361 RemoveAnimationObserver(); 508 RemoveAnimationObserver();
362 } else { 509 } else {
363 DoScroll(scroll.y()); 510 DoScroll(scroll.y());
364 } 511 }
365 } 512 }
366 513
514 const int kMinDistanceForDismissal = 300;
515 const float kMinScale = 0.6f;
516 const float kMaxScale = 0.95f;
517 const float kMaxOpacity = 1.0f;
518 const float kMinOpacity = 0.2f;
519
367 aura::Window* container_; 520 aura::Window* container_;
368 WindowOverviewModeDelegate* delegate_; 521 WindowOverviewModeDelegate* delegate_;
369 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_; 522 scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_;
370 scoped_ptr<ui::FlingCurve> fling_; 523 scoped_ptr<ui::FlingCurve> fling_;
371 524
525 aura::Window* dragged_window_;
526 gfx::Point dragged_start_location_;
527
372 DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl); 528 DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl);
373 }; 529 };
374 530
375 } // namespace 531 } // namespace
376 532
377 // static 533 // static
378 scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create( 534 scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create(
379 aura::Window* container, 535 aura::Window* container,
380 WindowOverviewModeDelegate* delegate) { 536 WindowOverviewModeDelegate* delegate) {
381 return scoped_ptr<WindowOverviewMode>( 537 return scoped_ptr<WindowOverviewMode>(
382 new WindowOverviewModeImpl(container, delegate)); 538 new WindowOverviewModeImpl(container, delegate));
383 } 539 }
384 540
385 } // namespace athena 541 } // namespace athena
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698