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.
5 #include "athena/wm/title_drag_controller.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"
19 // The minimum amount to drag to confirm a window switch at the end of the
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;
31 TitleDragController::TitleDragController(aura::Window
* container
,
32 TitleDragControllerDelegate
* delegate
)
33 : container_(container
),
38 container_
->AddPreTargetHandler(this);
41 TitleDragController::~TitleDragController() {
42 container_
->RemovePreTargetHandler(this);
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(),
54 gfx::Transform transform
;
55 transform
.Translate(0, complete
? window
->bounds().height() : 0);
56 window
->SetTransform(transform
);
59 void TitleDragController::OnTransitionEnd(aura::Window
* window
, bool complete
) {
60 weak_ptr_
.InvalidateWeakPtrs();
61 if (!tracker_
.Contains(window
))
65 window
->SetTransform(gfx::Transform());
66 tracker_
.Remove(window
);
68 if (complete
&& window
&& wm::IsActiveWindow(window
))
69 delegate_
->OnTitleDragCompleted(window
);
71 delegate_
->OnTitleDragCanceled(window
);
74 void TitleDragController::OnGestureEvent(ui::GestureEvent
* gesture
) {
75 // Do not process any gesture events if an animation is still in progress from
77 if (weak_ptr_
.HasWeakPtrs())
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
85 if (!tracker_
.windows().empty())
87 aura::Window
* window
= static_cast<aura::Window
*>(gesture
->target());
88 if (!window
|| !window
->delegate())
91 window
->delegate()->GetNonClientComponent(gesture
->location());
92 if (component
!= HTCAPTION
)
94 if (!delegate_
->GetWindowBehind(window
))
97 drag_start_location_
= gesture
->root_location();
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
))
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();
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();
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();
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;
138 (distance
.y() >= kMinDragDistanceForSwitch
||
139 gesture
->details().velocity_y() >= kMinDragVelocityForSwitch
));
140 gesture
->SetHandled();
144 } // namespace athena