| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "athena/wm/title_drag_controller.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "ui/aura/window.h" | |
| 9 #include "ui/aura/window_delegate.h" | |
| 10 #include "ui/base/hit_test.h" | |
| 11 #include "ui/compositor/closure_animation_observer.h" | |
| 12 #include "ui/compositor/layer.h" | |
| 13 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 14 #include "ui/wm/core/shadow.h" | |
| 15 #include "ui/wm/core/window_util.h" | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // The minimum amount to drag to confirm a window switch at the end of the | |
| 20 // non-fling gesture. | |
| 21 const int kMinDragDistanceForSwitch = 300; | |
| 22 // The minimum velocity to confirm a window switch for a fling (only applicable | |
| 23 // if the amount dragged was not sufficient, i.e. smaller than | |
| 24 // kMinDragDistanceForSwitch). | |
| 25 const int kMinDragVelocityForSwitch = 5000; | |
| 26 | |
| 27 } | |
| 28 | |
| 29 namespace athena { | |
| 30 | |
| 31 TitleDragController::TitleDragController(aura::Window* container, | |
| 32 TitleDragControllerDelegate* delegate) | |
| 33 : container_(container), | |
| 34 delegate_(delegate), | |
| 35 weak_ptr_(this) { | |
| 36 CHECK(container_); | |
| 37 CHECK(delegate_); | |
| 38 container_->AddPreTargetHandler(this); | |
| 39 } | |
| 40 | |
| 41 TitleDragController::~TitleDragController() { | |
| 42 container_->RemovePreTargetHandler(this); | |
| 43 } | |
| 44 | |
| 45 void TitleDragController::EndTransition(aura::Window* window, bool complete) { | |
| 46 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 47 settings.SetPreemptionStrategy( | |
| 48 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
| 49 settings.AddObserver(new ui::ClosureAnimationObserver( | |
| 50 base::Bind(&TitleDragController::OnTransitionEnd, | |
| 51 weak_ptr_.GetWeakPtr(), | |
| 52 window, | |
| 53 complete))); | |
| 54 gfx::Transform transform; | |
| 55 transform.Translate(0, complete ? window->bounds().height() : 0); | |
| 56 window->SetTransform(transform); | |
| 57 } | |
| 58 | |
| 59 void TitleDragController::OnTransitionEnd(aura::Window* window, bool complete) { | |
| 60 weak_ptr_.InvalidateWeakPtrs(); | |
| 61 if (!tracker_.Contains(window)) | |
| 62 window = nullptr; | |
| 63 shadow_.reset(); | |
| 64 if (window) { | |
| 65 window->SetTransform(gfx::Transform()); | |
| 66 tracker_.Remove(window); | |
| 67 } | |
| 68 if (complete && window && wm::IsActiveWindow(window)) | |
| 69 delegate_->OnTitleDragCompleted(window); | |
| 70 else | |
| 71 delegate_->OnTitleDragCanceled(window); | |
| 72 } | |
| 73 | |
| 74 void TitleDragController::OnGestureEvent(ui::GestureEvent* gesture) { | |
| 75 // Do not process any gesture events if an animation is still in progress from | |
| 76 // a previous drag. | |
| 77 if (weak_ptr_.HasWeakPtrs()) | |
| 78 return; | |
| 79 | |
| 80 if (gesture->type() == ui::ET_GESTURE_TAP_DOWN) { | |
| 81 // It is possible to start a gesture sequence on a second window while a | |
| 82 // drag is already in progress (e.g. the user starts interacting with the | |
| 83 // window that is being revealed by the title-drag). Ignore these gesture | |
| 84 // sequences. | |
| 85 if (!tracker_.windows().empty()) | |
| 86 return; | |
| 87 aura::Window* window = static_cast<aura::Window*>(gesture->target()); | |
| 88 if (!window || !window->delegate()) | |
| 89 return; | |
| 90 int component = | |
| 91 window->delegate()->GetNonClientComponent(gesture->location()); | |
| 92 if (component != HTCAPTION) | |
| 93 return; | |
| 94 if (!delegate_->GetWindowBehind(window)) | |
| 95 return; | |
| 96 tracker_.Add(window); | |
| 97 drag_start_location_ = gesture->root_location(); | |
| 98 return; | |
| 99 } | |
| 100 | |
| 101 // If this gesture is for a different window, then ignore. | |
| 102 aura::Window* window = static_cast<aura::Window*>(gesture->target()); | |
| 103 if (!tracker_.Contains(window)) | |
| 104 return; | |
| 105 | |
| 106 if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { | |
| 107 delegate_->OnTitleDragStarted(window); | |
| 108 shadow_.reset(new wm::Shadow()); | |
| 109 shadow_->Init(wm::Shadow::STYLE_ACTIVE); | |
| 110 shadow_->SetContentBounds(gfx::Rect(window->bounds().size())); | |
| 111 window->layer()->Add(shadow_->layer()); | |
| 112 gesture->SetHandled(); | |
| 113 return; | |
| 114 } | |
| 115 | |
| 116 if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { | |
| 117 gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; | |
| 118 gfx::Transform transform; | |
| 119 transform.Translate(0, std::max(0.f, distance.y())); | |
| 120 window->SetTransform(transform); | |
| 121 gesture->SetHandled(); | |
| 122 return; | |
| 123 } | |
| 124 | |
| 125 if (gesture->type() == ui::ET_GESTURE_SCROLL_END) { | |
| 126 gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; | |
| 127 EndTransition(window, distance.y() >= kMinDragDistanceForSwitch); | |
| 128 gesture->SetHandled(); | |
| 129 return; | |
| 130 } | |
| 131 | |
| 132 if (gesture->type() == ui::ET_SCROLL_FLING_START) { | |
| 133 gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; | |
| 134 bool swipe_downwards = gesture->details().velocity_y() > 0; | |
| 135 EndTransition( | |
| 136 window, | |
| 137 swipe_downwards && | |
| 138 (distance.y() >= kMinDragDistanceForSwitch || | |
| 139 gesture->details().velocity_y() >= kMinDragVelocityForSwitch)); | |
| 140 gesture->SetHandled(); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 } // namespace athena | |
| OLD | NEW |