blob: c0479fcd37be13b0ee9f44ea2feb4b62896632bf [file] [log] [blame]
Avi Drissman3a215d1e2022-09-07 19:43:091// Copyright 2012 The Chromium Authors
[email protected]084b6bb2011-11-17 05:18:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]2f744282011-12-23 22:40:525#ifndef ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_
6#define ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_
[email protected]084b6bb2011-11-17 05:18:167
dchenga94547472016-04-08 08:41:118#include <memory>
Arthur Sonzognia98e4432023-11-28 18:15:019#include <optional>
dchenga94547472016-04-08 08:41:1110
[email protected]b65bdda2011-12-23 23:35:3111#include "ash/ash_export.h"
Jonah55ab85e82021-12-07 17:57:4012#include "ash/drag_drop/drag_drop_capture_delegate.h"
Collin Bakerc6fae372020-05-01 23:37:4713#include "ash/drag_drop/tab_drag_drop_delegate.h"
Avi Drissman4de6dab2023-01-06 23:17:3514#include "base/functional/callback.h"
Arthur Sonzogni834e018f2023-04-22 10:20:0215#include "base/memory/raw_ptr.h"
[email protected]ffa4e4482012-11-28 12:11:4916#include "base/memory/weak_ptr.h"
Daichi Hironoe66b4152017-08-01 06:20:3317#include "base/observer_list.h"
Evan Stade55a443f2017-07-20 19:41:0218#include "base/time/time.h"
sky92d41b242016-10-27 20:10:1619#include "ui/aura/client/drag_drop_client.h"
Aya ElAttar2e554e52021-01-11 13:03:4320#include "ui/aura/client/drag_drop_delegate.h"
[email protected]341ad582012-02-03 18:31:0921#include "ui/aura/window_observer.h"
Henrique Ferreiro1748fd12020-08-04 12:51:4622#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
[email protected]084b6bb2011-11-17 05:18:1623#include "ui/base/dragdrop/os_exchange_data.h"
Vincent Chiang6b90cd4d2024-06-18 18:25:2024#include "ui/display/manager/display_manager_observer.h"
[email protected]86ccbd42013-09-18 18:11:5425#include "ui/events/event_constants.h"
26#include "ui/events/event_handler.h"
[email protected]ffb15d12013-09-15 17:29:3027#include "ui/gfx/animation/animation_delegate.h"
Avi Drissmanfefc2f82014-12-22 19:25:2928#include "ui/gfx/geometry/rect.h"
Allen Bauer35d4e722020-06-16 22:47:5629#include "ui/views/widget/unique_widget_ptr.h"
[email protected]084b6bb2011-11-17 05:18:1630
[email protected]ffb15d12013-09-15 17:29:3031namespace gfx {
[email protected]96fe25bf2012-11-27 20:30:2532class LinearAnimation;
[email protected]bb612db2012-01-09 17:31:1333}
34
sky4f4d2592016-10-28 17:14:4735namespace ui {
36class LocatedEvent;
37}
38
[email protected]55f593352011-12-24 05:42:4639namespace ash {
Nick Diego Yamanef258eb442020-10-28 04:57:1640class ToplevelWindowDragDelegate;
[email protected]084b6bb2011-11-17 05:18:1641
jamescookb8dcef522016-06-25 14:42:5542class ASH_EXPORT DragDropController : public aura::client::DragDropClient,
43 public ui::EventHandler,
44 public gfx::AnimationDelegate,
jamescook035dc062016-08-05 21:13:5245 public aura::WindowObserver,
Vincent Chiang6b90cd4d2024-06-18 18:25:2046 public display::DisplayManagerObserver {
[email protected]828a6dfa2012-05-10 20:03:0247 public:
[email protected]084b6bb2011-11-17 05:18:1648 DragDropController();
Peter Boströmec31a042021-09-16 23:37:3449
50 DragDropController(const DragDropController&) = delete;
51 DragDropController& operator=(const DragDropController&) = delete;
52
dcheng34dfcbe2014-10-29 18:58:1953 ~DragDropController() override;
[email protected]084b6bb2011-11-17 05:18:1654
James Cookeb426b52018-09-17 16:45:1255 void set_enabled(bool enabled) { enabled_ = enabled; }
56
Nick Diego Yamanef258eb442020-10-28 04:57:1657 void set_toplevel_window_drag_delegate(ToplevelWindowDragDelegate* delegate) {
58 toplevel_window_drag_delegate_ = delegate;
59 }
60
Mitsuru Oshima1feb6ad2023-02-15 04:10:0161 // Returns if the drag drop operation has been fully completed. This is
62 // similar to IsDragDropInProgress, but returns true even after the drop_data
63 // is passed to the target, and keep returning true until the drag drop states
64 // are callbacks are called), so that the callback receive the proper
65 // state.
66 bool IsDragDropCompleted();
67
[email protected]458b365c2011-12-15 05:04:0968 // Overridden from aura::client::DragDropClient:
Henrique Ferreirod7b970da2021-04-16 19:36:4469 ui::mojom::DragOperation StartDragAndDrop(
70 std::unique_ptr<ui::OSExchangeData> data,
71 aura::Window* root_window,
72 aura::Window* source_window,
73 const gfx::Point& screen_location,
74 int allowed_operations,
75 ui::mojom::DragEventSource source) override;
dcheng34dfcbe2014-10-29 18:58:1976 void DragCancel() override;
77 bool IsDragDropInProgress() override;
Daichi Hironoe66b4152017-08-01 06:20:3378 void AddObserver(aura::client::DragDropClientObserver* observer) override;
79 void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
[email protected]084b6bb2011-11-17 05:18:1680
[email protected]304594c2012-11-13 16:35:2781 // Overridden from ui::EventHandler:
dcheng34dfcbe2014-10-29 18:58:1982 void OnKeyEvent(ui::KeyEvent* event) override;
83 void OnMouseEvent(ui::MouseEvent* event) override;
84 void OnTouchEvent(ui::TouchEvent* event) override;
85 void OnGestureEvent(ui::GestureEvent* event) override;
[email protected]084b6bb2011-11-17 05:18:1686
[email protected]341ad582012-02-03 18:31:0987 // Overridden from aura::WindowObserver.
Mitsuru Oshimaf47a9382022-01-20 20:34:2188 void OnWindowDestroying(aura::Window* window) override;
[email protected]341ad582012-02-03 18:31:0989
Fergus Dalla4293852019-07-26 07:13:4790 void SetDragImage(const gfx::ImageSkia& image,
91 const gfx::Vector2d& image_offset);
92
Antonio Gomes6d6c7532022-02-09 01:25:2493 ui::mojom::DragEventSource event_source() {
94 return current_drag_event_source_;
95 }
96
Mitsuru Oshima0a710102022-01-11 21:15:5697 // Sets the `closure` that will be executed as a replacement of
98 // inner event loop. A test can use this closure to generate events, or
99 // take other actions that should happen during the drag and drop, and
100 // can also check the condition that should be satisfied.
101 // The loop closure is called with a boolean value that indicates
102 // that this is called from the inner loop because the same closure will
103 // often used to generate the event that will eventually enter the drag
104 // and drop inner loop. The `quit_closure` is used for a test
105 // to exit the outer loop in the test.
106 using TestLoopClosure = base::RepeatingCallback<void()>;
107 void SetLoopClosureForTesting(TestLoopClosure closure,
108 base::OnceClosure quit_closure);
109
110 void SetDisableNestedLoopForTesting(bool disable);
111
112 // Deprecated: Use `SetDisableNestedLoopForTesting`.
113 void set_should_block_during_drag_drop(bool should_block_during_drag_drop) {
114 SetDisableNestedLoopForTesting(!should_block_during_drag_drop);
115 }
116
Mitsuru Oshimab55be1a22024-01-17 21:25:40117 void enable_no_image_touch_drag_for_test() {
118 allow_no_image_touch_drag_for_test_ = true;
119 }
120
[email protected]ffa4e4482012-11-28 12:11:49121 protected:
[email protected]c08610452012-11-28 21:48:36122 // Helper method to create a LinearAnimation object that will run the drag
123 // cancel animation. Caller take ownership of the returned object. Protected
124 // for testing.
[email protected]ffb15d12013-09-15 17:29:30125 virtual gfx::LinearAnimation* CreateCancelAnimation(
Evan Stade55a443f2017-07-20 19:41:02126 base::TimeDelta duration,
[email protected]c08610452012-11-28 21:48:36127 int frame_rate,
[email protected]ffb15d12013-09-15 17:29:30128 gfx::AnimationDelegate* delegate);
[email protected]c08610452012-11-28 21:48:36129
sky4f4d2592016-10-28 17:14:47130 // Exposed for tests to override.
131 virtual void DragUpdate(aura::Window* target, const ui::LocatedEvent& event);
132 virtual void Drop(aura::Window* target, const ui::LocatedEvent& event);
133
[email protected]ffa4e4482012-11-28 12:11:49134 // Actual implementation of |DragCancel()|. protected for testing.
Evan Stade55a443f2017-07-20 19:41:02135 virtual void DoDragCancel(base::TimeDelta drag_cancel_animation_duration);
[email protected]ffa4e4482012-11-28 12:11:49136
Jonah55ab85e82021-12-07 17:57:40137 // Exposed for test assertions.
138 DragDropCaptureDelegate* get_capture_delegate() { return capture_delegate_; }
139
[email protected]084b6bb2011-11-17 05:18:16140 private:
James Cook317781a2017-07-18 02:08:06141 friend class DragDropControllerTest;
James Cookeb426b52018-09-17 16:45:12142 friend class DragDropControllerTestApi;
[email protected]084b6bb2011-11-17 05:18:16143
[email protected]ffb15d12013-09-15 17:29:30144 // Overridden from gfx::AnimationDelegate:
dcheng34dfcbe2014-10-29 18:58:19145 void AnimationEnded(const gfx::Animation* animation) override;
146 void AnimationProgressed(const gfx::Animation* animation) override;
147 void AnimationCanceled(const gfx::Animation* animation) override;
[email protected]bb612db2012-01-09 17:31:13148
Vincent Chiang6b90cd4d2024-06-18 18:25:20149 // display::DisplayManagerObserver
150 void OnWillApplyDisplayChanges() override;
jamescook035dc062016-08-05 21:13:52151
[email protected]bb612db2012-01-09 17:31:13152 // Helper method to start drag widget flying back animation.
Evan Stade55a443f2017-07-20 19:41:02153 void StartCanceledAnimation(base::TimeDelta animation_duration);
[email protected]ffa4e4482012-11-28 12:11:49154
Yuzhu Shene905e11a2022-08-16 22:34:53155 // Helper methods to forward |pending_log_tap_| event to
156 // |drag_source_window_|.
157 void ScheduleForwardPendingLongTap();
[email protected]ffa4e4482012-11-28 12:11:49158 void ForwardPendingLongTap();
[email protected]bb612db2012-01-09 17:31:13159
Yuzhu Shene905e11a2022-08-16 22:34:53160 // Helper method to reset most of the state, except state that could be used
161 // during async operations of cancellation (including cancel animation and
162 // posting task to dispatch long tap event).
[email protected]084b6bb2011-11-17 05:18:16163 void Cleanup();
164
Yuzhu Shene905e11a2022-08-16 22:34:53165 void CleanupPendingLongTap();
166
andrewxu754700392023-02-26 19:03:22167 // Performs data drop. NOTE: this method does not run in an async drop if
168 // disallowed by `ui::DataTransferPolicyController`. `cancel_drag_callback`
169 // runs if this method does not run.
Aya ElAttarfd5ce86f2021-09-23 18:20:00170 void PerformDrop(const gfx::Point drop_location_in_screen,
171 ui::DropTargetEvent event,
172 std::unique_ptr<ui::OSExchangeData> drag_data,
173 aura::client::DragDropDelegate::DropCallback drop_cb,
174 std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate,
andrewxu754700392023-02-26 19:03:22175 base::ScopedClosureRunner cancel_drag_callback);
Aya ElAttarfd5ce86f2021-09-23 18:20:00176
Jonah4b609892021-11-09 22:51:07177 void CancelIfInProgress();
178
James Cookeb426b52018-09-17 16:45:12179 bool enabled_ = false;
Mitsuru Oshima1feb6ad2023-02-15 04:10:01180 bool drag_drop_completed_ = true;
Ana Salazar40d497c2023-02-23 22:47:07181 std::unique_ptr<views::Widget> drag_image_widget_;
[email protected]ceb36f7d2012-10-31 18:33:24182 gfx::Vector2d drag_image_offset_;
Navid Zolghadr0beb8292019-07-08 18:54:04183 std::unique_ptr<ui::OSExchangeData> drag_data_;
Henrique Ferreirod7b970da2021-04-16 19:36:44184 int allowed_operations_ = 0;
185 ui::mojom::DragOperation operation_ = ui::mojom::DragOperation::kNone;
Aya ElAttar2e554e52021-01-11 13:03:43186 aura::client::DragUpdateInfo current_drag_info_;
[email protected]6a5fc422012-03-06 04:43:26187
Collin Bakerc6fae372020-05-01 23:37:47188 // Used when processing a Chrome tab drag from a WebUI tab strip.
Aya ElAttarfd5ce86f2021-09-23 18:20:00189 std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate_;
Collin Baker7f9a1652020-04-28 20:18:16190
Mitsuru Oshima03d96e5f2022-04-14 21:32:54191 // Used when processing a normal drag and drop with touch.
192 std::unique_ptr<DragDropCaptureDelegate> touch_drag_drop_delegate_;
193
[email protected]6a5fc422012-03-06 04:43:26194 // Window that is currently under the drag cursor.
Bartek Nowierskideb75842023-12-27 02:32:42195 raw_ptr<aura::Window> drag_window_ = nullptr;
[email protected]ffa4e4482012-11-28 12:11:49196
197 // Starting and final bounds for the drag image for the drag cancel animation.
198 gfx::Rect drag_image_initial_bounds_for_cancel_animation_;
199 gfx::Rect drag_image_final_bounds_for_cancel_animation_;
[email protected]96fe25bf2012-11-27 20:30:25200
dchenga94547472016-04-08 08:41:11201 std::unique_ptr<gfx::LinearAnimation> cancel_animation_;
sangwoo843c6cda2019-12-06 00:15:51202 std::unique_ptr<gfx::AnimationDelegate> cancel_animation_notifier_;
[email protected]084b6bb2011-11-17 05:18:16203
[email protected]ffa4e4482012-11-28 12:11:49204 // Window that started the drag.
Bartek Nowierskideb75842023-12-27 02:32:42205 raw_ptr<aura::Window> drag_source_window_ = nullptr;
[email protected]ffa4e4482012-11-28 12:11:49206
Mitsuru Oshima0a710102022-01-11 21:15:56207 // A closure that allows a test to implement the actions within
208 // drag and drop event loop.
209 TestLoopClosure test_loop_closure_;
210
211 // True if the nested event loop is disabled.
212 bool nested_loop_disabled_for_testing_ = false;
[email protected]084b6bb2011-11-17 05:18:16213
gab2998ee72017-05-05 16:23:50214 // Closure for quitting nested run loop.
Reilly Grantb6702232019-11-26 22:46:04215 base::OnceClosure quit_closure_;
[email protected]8e937c1e2012-06-28 22:57:30216
Jonah55ab85e82021-12-07 17:57:40217 // If non-null, a drag is active which required a capture window.
Bartek Nowierskideb75842023-12-27 02:32:42218 raw_ptr<DragDropCaptureDelegate, DanglingUntriaged> capture_delegate_ =
219 nullptr;
Jun Mukai14fc3002021-06-22 17:45:38220
Henrique Ferreiro1748fd12020-08-04 12:51:46221 ui::mojom::DragEventSource current_drag_event_source_ =
222 ui::mojom::DragEventSource::kMouse;
[email protected]ffa4e4482012-11-28 12:11:49223
224 // Holds a synthetic long tap event to be sent to the |drag_source_window_|.
225 // See comment in OnGestureEvent() on why we need this.
Jonah4b609892021-11-09 22:51:07226 std::unique_ptr<ui::Event> pending_long_tap_;
Yuzhu Shene905e11a2022-08-16 22:34:53227 // Set to true during async operations of cancellation (including cancel
228 // animation and posting task to dispatch long tap event), indicating that a
229 // long tap event will be dispatched.
230 bool will_forward_long_tap_ = false;
[email protected]ffa4e4482012-11-28 12:11:49231
Fergus Dalla4293852019-07-26 07:13:47232 gfx::Point start_location_;
233 gfx::Point current_location_;
234
miktbacc1fc2024-03-07 16:38:20235 base::ObserverList<aura::client::DragDropClientObserver>::
236 UncheckedAndDanglingUntriaged observers_;
Daichi Hironoe66b4152017-08-01 06:20:33237
Bartek Nowierskideb75842023-12-27 02:32:42238 raw_ptr<ToplevelWindowDragDelegate, DanglingUntriaged>
Arthur Sonzogni834e018f2023-04-22 10:20:02239 toplevel_window_drag_delegate_ = nullptr;
Nick Diego Yamanef258eb442020-10-28 04:57:16240
Mitsuru Oshimab55be1a22024-01-17 21:25:40241 bool allow_no_image_touch_drag_for_test_ = false;
242
Yuzhu Shene905e11a2022-08-16 22:34:53243 // Weak ptr for async callbacks to be invalidated if a new drag starts.
Jeremy Roman47d432e2019-08-20 14:24:00244 base::WeakPtrFactory<DragDropController> weak_factory_{this};
[email protected]084b6bb2011-11-17 05:18:16245};
246
[email protected]55f593352011-12-24 05:42:46247} // namespace ash
[email protected]084b6bb2011-11-17 05:18:16248
[email protected]2f744282011-12-23 22:40:52249#endif // ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_