1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
ash / drag_drop / drag_drop_controller.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_
#define ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_
#include <memory>
#include <optional>
#include "ash/ash_export.h"
#include "ash/drag_drop/drag_drop_capture_delegate.h"
#include "ash/drag_drop/tab_drag_drop_delegate.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window_observer.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/display/manager/display_manager_observer.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/widget/unique_widget_ptr.h"
namespace gfx {
class LinearAnimation;
}
namespace ui {
class LocatedEvent;
}
namespace ash {
class ToplevelWindowDragDelegate;
class ASH_EXPORT DragDropController : public aura::client::DragDropClient,
public ui::EventHandler,
public gfx::AnimationDelegate,
public aura::WindowObserver,
public display::DisplayManagerObserver {
public:
DragDropController();
DragDropController(const DragDropController&) = delete;
DragDropController& operator=(const DragDropController&) = delete;
~DragDropController() override;
void set_enabled(bool enabled) { enabled_ = enabled; }
void set_toplevel_window_drag_delegate(ToplevelWindowDragDelegate* delegate) {
toplevel_window_drag_delegate_ = delegate;
}
// Returns if the drag drop operation has been fully completed. This is
// similar to IsDragDropInProgress, but returns true even after the drop_data
// is passed to the target, and keep returning true until the drag drop states
// are callbacks are called), so that the callback receive the proper
// state.
bool IsDragDropCompleted();
// Overridden from aura::client::DragDropClient:
ui::mojom::DragOperation StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
int allowed_operations,
ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override;
void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnTouchEvent(ui::TouchEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
// Overridden from aura::WindowObserver.
void OnWindowDestroying(aura::Window* window) override;
void SetDragImage(const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset);
ui::mojom::DragEventSource event_source() {
return current_drag_event_source_;
}
// Sets the `closure` that will be executed as a replacement of
// inner event loop. A test can use this closure to generate events, or
// take other actions that should happen during the drag and drop, and
// can also check the condition that should be satisfied.
// The loop closure is called with a boolean value that indicates
// that this is called from the inner loop because the same closure will
// often used to generate the event that will eventually enter the drag
// and drop inner loop. The `quit_closure` is used for a test
// to exit the outer loop in the test.
using TestLoopClosure = base::RepeatingCallback<void()>;
void SetLoopClosureForTesting(TestLoopClosure closure,
base::OnceClosure quit_closure);
void SetDisableNestedLoopForTesting(bool disable);
// Deprecated: Use `SetDisableNestedLoopForTesting`.
void set_should_block_during_drag_drop(bool should_block_during_drag_drop) {
SetDisableNestedLoopForTesting(!should_block_during_drag_drop);
}
void enable_no_image_touch_drag_for_test() {
allow_no_image_touch_drag_for_test_ = true;
}
protected:
// Helper method to create a LinearAnimation object that will run the drag
// cancel animation. Caller take ownership of the returned object. Protected
// for testing.
virtual gfx::LinearAnimation* CreateCancelAnimation(
base::TimeDelta duration,
int frame_rate,
gfx::AnimationDelegate* delegate);
// Exposed for tests to override.
virtual void DragUpdate(aura::Window* target, const ui::LocatedEvent& event);
virtual void Drop(aura::Window* target, const ui::LocatedEvent& event);
// Actual implementation of |DragCancel()|. protected for testing.
virtual void DoDragCancel(base::TimeDelta drag_cancel_animation_duration);
// Exposed for test assertions.
DragDropCaptureDelegate* get_capture_delegate() { return capture_delegate_; }
private:
friend class DragDropControllerTest;
friend class DragDropControllerTestApi;
// Overridden from gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationCanceled(const gfx::Animation* animation) override;
// display::DisplayManagerObserver
void OnWillApplyDisplayChanges() override;
// Helper method to start drag widget flying back animation.
void StartCanceledAnimation(base::TimeDelta animation_duration);
// Helper methods to forward |pending_log_tap_| event to
// |drag_source_window_|.
void ScheduleForwardPendingLongTap();
void ForwardPendingLongTap();
// Helper method to reset most of the state, except state that could be used
// during async operations of cancellation (including cancel animation and
// posting task to dispatch long tap event).
void Cleanup();
void CleanupPendingLongTap();
// Performs data drop. NOTE: this method does not run in an async drop if
// disallowed by `ui::DataTransferPolicyController`. `cancel_drag_callback`
// runs if this method does not run.
void PerformDrop(const gfx::Point drop_location_in_screen,
ui::DropTargetEvent event,
std::unique_ptr<ui::OSExchangeData> drag_data,
aura::client::DragDropDelegate::DropCallback drop_cb,
std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate,
base::ScopedClosureRunner cancel_drag_callback);
void CancelIfInProgress();
bool enabled_ = false;
bool drag_drop_completed_ = true;
std::unique_ptr<views::Widget> drag_image_widget_;
gfx::Vector2d drag_image_offset_;
std::unique_ptr<ui::OSExchangeData> drag_data_;
int allowed_operations_ = 0;
ui::mojom::DragOperation operation_ = ui::mojom::DragOperation::kNone;
aura::client::DragUpdateInfo current_drag_info_;
// Used when processing a Chrome tab drag from a WebUI tab strip.
std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate_;
// Used when processing a normal drag and drop with touch.
std::unique_ptr<DragDropCaptureDelegate> touch_drag_drop_delegate_;
// Window that is currently under the drag cursor.
raw_ptr<aura::Window> drag_window_ = nullptr;
// Starting and final bounds for the drag image for the drag cancel animation.
gfx::Rect drag_image_initial_bounds_for_cancel_animation_;
gfx::Rect drag_image_final_bounds_for_cancel_animation_;
std::unique_ptr<gfx::LinearAnimation> cancel_animation_;
std::unique_ptr<gfx::AnimationDelegate> cancel_animation_notifier_;
// Window that started the drag.
raw_ptr<aura::Window> drag_source_window_ = nullptr;
// A closure that allows a test to implement the actions within
// drag and drop event loop.
TestLoopClosure test_loop_closure_;
// True if the nested event loop is disabled.
bool nested_loop_disabled_for_testing_ = false;
// Closure for quitting nested run loop.
base::OnceClosure quit_closure_;
// If non-null, a drag is active which required a capture window.
raw_ptr<DragDropCaptureDelegate, DanglingUntriaged> capture_delegate_ =
nullptr;
ui::mojom::DragEventSource current_drag_event_source_ =
ui::mojom::DragEventSource::kMouse;
// Holds a synthetic long tap event to be sent to the |drag_source_window_|.
// See comment in OnGestureEvent() on why we need this.
std::unique_ptr<ui::Event> pending_long_tap_;
// Set to true during async operations of cancellation (including cancel
// animation and posting task to dispatch long tap event), indicating that a
// long tap event will be dispatched.
bool will_forward_long_tap_ = false;
gfx::Point start_location_;
gfx::Point current_location_;
base::ObserverList<aura::client::DragDropClientObserver>::
UncheckedAndDanglingUntriaged observers_;
raw_ptr<ToplevelWindowDragDelegate, DanglingUntriaged>
toplevel_window_drag_delegate_ = nullptr;
bool allow_no_image_touch_drag_for_test_ = false;
// Weak ptr for async callbacks to be invalidated if a new drag starts.
base::WeakPtrFactory<DragDropController> weak_factory_{this};
};
} // namespace ash
#endif // ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_