[email protected] | bb612db | 2012-01-09 17:31:13 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 2f74428 | 2011-12-23 22:40:52 | [diff] [blame] | 5 | #ifndef ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_ |
| 6 | #define ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_ |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 7 | |
dcheng | a9454747 | 2016-04-08 08:41:11 | [diff] [blame] | 8 | #include <memory> |
| 9 | |
[email protected] | b65bdda | 2011-12-23 23:35:31 | [diff] [blame] | 10 | #include "ash/ash_export.h" |
Scott Violet | 9838c93 | 2017-06-19 20:54:51 | [diff] [blame] | 11 | #include "ash/display/window_tree_host_manager.h" |
Jonah | 55ab85e8 | 2021-12-07 17:57:40 | [diff] [blame] | 12 | #include "ash/drag_drop/drag_drop_capture_delegate.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 13 | #include "ash/drag_drop/tab_drag_drop_delegate.h" |
[email protected] | 8e937c1e | 2012-06-28 22:57:30 | [diff] [blame] | 14 | #include "base/callback.h" |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 15 | #include "base/memory/weak_ptr.h" |
Daichi Hirono | e66b415 | 2017-08-01 06:20:33 | [diff] [blame] | 16 | #include "base/observer_list.h" |
Evan Stade | 55a443f | 2017-07-20 19:41:02 | [diff] [blame] | 17 | #include "base/time/time.h" |
Anton Bikineev | 43cee28e | 2021-05-14 23:35:33 | [diff] [blame] | 18 | #include "third_party/abseil-cpp/absl/types/optional.h" |
sky | 92d41b24 | 2016-10-27 20:10:16 | [diff] [blame] | 19 | #include "ui/aura/client/drag_drop_client.h" |
Aya ElAttar | 2e554e5 | 2021-01-11 13:03:43 | [diff] [blame] | 20 | #include "ui/aura/client/drag_drop_delegate.h" |
[email protected] | 341ad58 | 2012-02-03 18:31:09 | [diff] [blame] | 21 | #include "ui/aura/window_observer.h" |
Henrique Ferreiro | 1748fd1 | 2020-08-04 12:51:46 | [diff] [blame] | 22 | #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 23 | #include "ui/base/dragdrop/os_exchange_data.h" |
[email protected] | 86ccbd4 | 2013-09-18 18:11:54 | [diff] [blame] | 24 | #include "ui/events/event_constants.h" |
| 25 | #include "ui/events/event_handler.h" |
[email protected] | ffb15d1 | 2013-09-15 17:29:30 | [diff] [blame] | 26 | #include "ui/gfx/animation/animation_delegate.h" |
Avi Drissman | fefc2f8 | 2014-12-22 19:25:29 | [diff] [blame] | 27 | #include "ui/gfx/geometry/rect.h" |
Allen Bauer | 35d4e72 | 2020-06-16 22:47:56 | [diff] [blame] | 28 | #include "ui/views/widget/unique_widget_ptr.h" |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 29 | |
[email protected] | ffb15d1 | 2013-09-15 17:29:30 | [diff] [blame] | 30 | namespace gfx { |
[email protected] | 96fe25bf | 2012-11-27 20:30:25 | [diff] [blame] | 31 | class LinearAnimation; |
[email protected] | bb612db | 2012-01-09 17:31:13 | [diff] [blame] | 32 | } |
| 33 | |
sky | 4f4d259 | 2016-10-28 17:14:47 | [diff] [blame] | 34 | namespace ui { |
| 35 | class LocatedEvent; |
| 36 | } |
| 37 | |
[email protected] | 55f59335 | 2011-12-24 05:42:46 | [diff] [blame] | 38 | namespace ash { |
Nick Diego Yamane | f258eb44 | 2020-10-28 04:57:16 | [diff] [blame] | 39 | class ToplevelWindowDragDelegate; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 40 | |
jamescook | b8dcef52 | 2016-06-25 14:42:55 | [diff] [blame] | 41 | class ASH_EXPORT DragDropController : public aura::client::DragDropClient, |
| 42 | public ui::EventHandler, |
| 43 | public gfx::AnimationDelegate, |
jamescook | 035dc06 | 2016-08-05 21:13:52 | [diff] [blame] | 44 | public aura::WindowObserver, |
Scott Violet | 9838c93 | 2017-06-19 20:54:51 | [diff] [blame] | 45 | public WindowTreeHostManager::Observer { |
[email protected] | 828a6dfa | 2012-05-10 20:03:02 | [diff] [blame] | 46 | public: |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 47 | DragDropController(); |
Peter Boström | ec31a04 | 2021-09-16 23:37:34 | [diff] [blame] | 48 | |
| 49 | DragDropController(const DragDropController&) = delete; |
| 50 | DragDropController& operator=(const DragDropController&) = delete; |
| 51 | |
dcheng | 34dfcbe | 2014-10-29 18:58:19 | [diff] [blame] | 52 | ~DragDropController() override; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 53 | |
James Cook | eb426b5 | 2018-09-17 16:45:12 | [diff] [blame] | 54 | void set_enabled(bool enabled) { enabled_ = enabled; } |
| 55 | |
Nick Diego Yamane | f258eb44 | 2020-10-28 04:57:16 | [diff] [blame] | 56 | void set_toplevel_window_drag_delegate(ToplevelWindowDragDelegate* delegate) { |
| 57 | toplevel_window_drag_delegate_ = delegate; |
| 58 | } |
| 59 | |
[email protected] | 458b365c | 2011-12-15 05:04:09 | [diff] [blame] | 60 | // Overridden from aura::client::DragDropClient: |
Henrique Ferreiro | d7b970da | 2021-04-16 19:36:44 | [diff] [blame] | 61 | ui::mojom::DragOperation StartDragAndDrop( |
| 62 | std::unique_ptr<ui::OSExchangeData> data, |
| 63 | aura::Window* root_window, |
| 64 | aura::Window* source_window, |
| 65 | const gfx::Point& screen_location, |
| 66 | int allowed_operations, |
| 67 | ui::mojom::DragEventSource source) override; |
dcheng | 34dfcbe | 2014-10-29 18:58:19 | [diff] [blame] | 68 | void DragCancel() override; |
| 69 | bool IsDragDropInProgress() override; |
Daichi Hirono | e66b415 | 2017-08-01 06:20:33 | [diff] [blame] | 70 | void AddObserver(aura::client::DragDropClientObserver* observer) override; |
| 71 | void RemoveObserver(aura::client::DragDropClientObserver* observer) override; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 72 | |
[email protected] | 304594c | 2012-11-13 16:35:27 | [diff] [blame] | 73 | // Overridden from ui::EventHandler: |
dcheng | 34dfcbe | 2014-10-29 18:58:19 | [diff] [blame] | 74 | void OnKeyEvent(ui::KeyEvent* event) override; |
| 75 | void OnMouseEvent(ui::MouseEvent* event) override; |
| 76 | void OnTouchEvent(ui::TouchEvent* event) override; |
| 77 | void OnGestureEvent(ui::GestureEvent* event) override; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 78 | |
[email protected] | 341ad58 | 2012-02-03 18:31:09 | [diff] [blame] | 79 | // Overridden from aura::WindowObserver. |
Mitsuru Oshima | f47a938 | 2022-01-20 20:34:21 | [diff] [blame^] | 80 | void OnWindowDestroying(aura::Window* window) override; |
[email protected] | 341ad58 | 2012-02-03 18:31:09 | [diff] [blame] | 81 | |
Fergus Dall | a429385 | 2019-07-26 07:13:47 | [diff] [blame] | 82 | void SetDragImage(const gfx::ImageSkia& image, |
| 83 | const gfx::Vector2d& image_offset); |
| 84 | |
Mitsuru Oshima | 0a71010 | 2022-01-11 21:15:56 | [diff] [blame] | 85 | // Sets the `closure` that will be executed as a replacement of |
| 86 | // inner event loop. A test can use this closure to generate events, or |
| 87 | // take other actions that should happen during the drag and drop, and |
| 88 | // can also check the condition that should be satisfied. |
| 89 | // The loop closure is called with a boolean value that indicates |
| 90 | // that this is called from the inner loop because the same closure will |
| 91 | // often used to generate the event that will eventually enter the drag |
| 92 | // and drop inner loop. The `quit_closure` is used for a test |
| 93 | // to exit the outer loop in the test. |
| 94 | using TestLoopClosure = base::RepeatingCallback<void()>; |
| 95 | void SetLoopClosureForTesting(TestLoopClosure closure, |
| 96 | base::OnceClosure quit_closure); |
| 97 | |
| 98 | void SetDisableNestedLoopForTesting(bool disable); |
| 99 | |
| 100 | // Deprecated: Use `SetDisableNestedLoopForTesting`. |
| 101 | void set_should_block_during_drag_drop(bool should_block_during_drag_drop) { |
| 102 | SetDisableNestedLoopForTesting(!should_block_during_drag_drop); |
| 103 | } |
| 104 | |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 105 | protected: |
[email protected] | c0861045 | 2012-11-28 21:48:36 | [diff] [blame] | 106 | // Helper method to create a LinearAnimation object that will run the drag |
| 107 | // cancel animation. Caller take ownership of the returned object. Protected |
| 108 | // for testing. |
[email protected] | ffb15d1 | 2013-09-15 17:29:30 | [diff] [blame] | 109 | virtual gfx::LinearAnimation* CreateCancelAnimation( |
Evan Stade | 55a443f | 2017-07-20 19:41:02 | [diff] [blame] | 110 | base::TimeDelta duration, |
[email protected] | c0861045 | 2012-11-28 21:48:36 | [diff] [blame] | 111 | int frame_rate, |
[email protected] | ffb15d1 | 2013-09-15 17:29:30 | [diff] [blame] | 112 | gfx::AnimationDelegate* delegate); |
[email protected] | c0861045 | 2012-11-28 21:48:36 | [diff] [blame] | 113 | |
sky | 4f4d259 | 2016-10-28 17:14:47 | [diff] [blame] | 114 | // Exposed for tests to override. |
| 115 | virtual void DragUpdate(aura::Window* target, const ui::LocatedEvent& event); |
| 116 | virtual void Drop(aura::Window* target, const ui::LocatedEvent& event); |
| 117 | |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 118 | // Actual implementation of |DragCancel()|. protected for testing. |
Evan Stade | 55a443f | 2017-07-20 19:41:02 | [diff] [blame] | 119 | virtual void DoDragCancel(base::TimeDelta drag_cancel_animation_duration); |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 120 | |
Jonah | 55ab85e8 | 2021-12-07 17:57:40 | [diff] [blame] | 121 | // Exposed for test assertions. |
| 122 | DragDropCaptureDelegate* get_capture_delegate() { return capture_delegate_; } |
| 123 | |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 124 | private: |
James Cook | 317781a | 2017-07-18 02:08:06 | [diff] [blame] | 125 | friend class DragDropControllerTest; |
James Cook | eb426b5 | 2018-09-17 16:45:12 | [diff] [blame] | 126 | friend class DragDropControllerTestApi; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 127 | |
[email protected] | ffb15d1 | 2013-09-15 17:29:30 | [diff] [blame] | 128 | // Overridden from gfx::AnimationDelegate: |
dcheng | 34dfcbe | 2014-10-29 18:58:19 | [diff] [blame] | 129 | void AnimationEnded(const gfx::Animation* animation) override; |
| 130 | void AnimationProgressed(const gfx::Animation* animation) override; |
| 131 | void AnimationCanceled(const gfx::Animation* animation) override; |
[email protected] | bb612db | 2012-01-09 17:31:13 | [diff] [blame] | 132 | |
Scott Violet | 9838c93 | 2017-06-19 20:54:51 | [diff] [blame] | 133 | // WindowTreeHostManager::Observer: |
jamescook | 035dc06 | 2016-08-05 21:13:52 | [diff] [blame] | 134 | void OnDisplayConfigurationChanging() override; |
| 135 | |
[email protected] | bb612db | 2012-01-09 17:31:13 | [diff] [blame] | 136 | // Helper method to start drag widget flying back animation. |
Evan Stade | 55a443f | 2017-07-20 19:41:02 | [diff] [blame] | 137 | void StartCanceledAnimation(base::TimeDelta animation_duration); |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 138 | |
| 139 | // Helper method to forward |pending_log_tap_| event to |drag_source_window_|. |
| 140 | void ForwardPendingLongTap(); |
[email protected] | bb612db | 2012-01-09 17:31:13 | [diff] [blame] | 141 | |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 142 | // Helper method to reset everything. |
| 143 | void Cleanup(); |
| 144 | |
Aya ElAttar | fd5ce86f | 2021-09-23 18:20:00 | [diff] [blame] | 145 | // Helper method to perform the drop if allowed by |
| 146 | // DataTransferPolicyController. If it's run, `drag_cancel` will be replaced. |
| 147 | // Otherwise `drag_cancel` will run to cancel the drag. |
| 148 | void PerformDrop(const gfx::Point drop_location_in_screen, |
| 149 | ui::DropTargetEvent event, |
| 150 | std::unique_ptr<ui::OSExchangeData> drag_data, |
| 151 | aura::client::DragDropDelegate::DropCallback drop_cb, |
| 152 | std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate, |
| 153 | base::ScopedClosureRunner drag_cancel); |
| 154 | |
Jonah | 4b60989 | 2021-11-09 22:51:07 | [diff] [blame] | 155 | void CancelIfInProgress(); |
| 156 | |
James Cook | eb426b5 | 2018-09-17 16:45:12 | [diff] [blame] | 157 | bool enabled_ = false; |
Allen Bauer | 35d4e72 | 2020-06-16 22:47:56 | [diff] [blame] | 158 | views::UniqueWidgetPtr drag_image_widget_; |
[email protected] | ceb36f7d | 2012-10-31 18:33:24 | [diff] [blame] | 159 | gfx::Vector2d drag_image_offset_; |
Navid Zolghadr | 0beb829 | 2019-07-08 18:54:04 | [diff] [blame] | 160 | std::unique_ptr<ui::OSExchangeData> drag_data_; |
Henrique Ferreiro | d7b970da | 2021-04-16 19:36:44 | [diff] [blame] | 161 | int allowed_operations_ = 0; |
| 162 | ui::mojom::DragOperation operation_ = ui::mojom::DragOperation::kNone; |
Aya ElAttar | 2e554e5 | 2021-01-11 13:03:43 | [diff] [blame] | 163 | aura::client::DragUpdateInfo current_drag_info_; |
[email protected] | 6a5fc42 | 2012-03-06 04:43:26 | [diff] [blame] | 164 | |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 165 | // Used when processing a Chrome tab drag from a WebUI tab strip. |
Aya ElAttar | fd5ce86f | 2021-09-23 18:20:00 | [diff] [blame] | 166 | std::unique_ptr<TabDragDropDelegate> tab_drag_drop_delegate_; |
Collin Baker | 7f9a165 | 2020-04-28 20:18:16 | [diff] [blame] | 167 | |
[email protected] | 6a5fc42 | 2012-03-06 04:43:26 | [diff] [blame] | 168 | // Window that is currently under the drag cursor. |
Allen Bauer | 35d4e72 | 2020-06-16 22:47:56 | [diff] [blame] | 169 | aura::Window* drag_window_ = nullptr; |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 170 | |
| 171 | // Starting and final bounds for the drag image for the drag cancel animation. |
| 172 | gfx::Rect drag_image_initial_bounds_for_cancel_animation_; |
| 173 | gfx::Rect drag_image_final_bounds_for_cancel_animation_; |
[email protected] | 96fe25bf | 2012-11-27 20:30:25 | [diff] [blame] | 174 | |
dcheng | a9454747 | 2016-04-08 08:41:11 | [diff] [blame] | 175 | std::unique_ptr<gfx::LinearAnimation> cancel_animation_; |
sangwoo | 843c6cda | 2019-12-06 00:15:51 | [diff] [blame] | 176 | std::unique_ptr<gfx::AnimationDelegate> cancel_animation_notifier_; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 177 | |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 178 | // Window that started the drag. |
Allen Bauer | 35d4e72 | 2020-06-16 22:47:56 | [diff] [blame] | 179 | aura::Window* drag_source_window_ = nullptr; |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 180 | |
Mitsuru Oshima | 0a71010 | 2022-01-11 21:15:56 | [diff] [blame] | 181 | // A closure that allows a test to implement the actions within |
| 182 | // drag and drop event loop. |
| 183 | TestLoopClosure test_loop_closure_; |
| 184 | |
| 185 | // True if the nested event loop is disabled. |
| 186 | bool nested_loop_disabled_for_testing_ = false; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 187 | |
gab | 2998ee7 | 2017-05-05 16:23:50 | [diff] [blame] | 188 | // Closure for quitting nested run loop. |
Reilly Grant | b670223 | 2019-11-26 22:46:04 | [diff] [blame] | 189 | base::OnceClosure quit_closure_; |
[email protected] | 8e937c1e | 2012-06-28 22:57:30 | [diff] [blame] | 190 | |
Jonah | 55ab85e8 | 2021-12-07 17:57:40 | [diff] [blame] | 191 | // If non-null, a drag is active which required a capture window. |
| 192 | DragDropCaptureDelegate* capture_delegate_; |
Jun Mukai | 14fc300 | 2021-06-22 17:45:38 | [diff] [blame] | 193 | |
Henrique Ferreiro | 1748fd1 | 2020-08-04 12:51:46 | [diff] [blame] | 194 | ui::mojom::DragEventSource current_drag_event_source_ = |
| 195 | ui::mojom::DragEventSource::kMouse; |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 196 | |
| 197 | // Holds a synthetic long tap event to be sent to the |drag_source_window_|. |
| 198 | // See comment in OnGestureEvent() on why we need this. |
Jonah | 4b60989 | 2021-11-09 22:51:07 | [diff] [blame] | 199 | std::unique_ptr<ui::Event> pending_long_tap_; |
[email protected] | ffa4e448 | 2012-11-28 12:11:49 | [diff] [blame] | 200 | |
Fergus Dall | a429385 | 2019-07-26 07:13:47 | [diff] [blame] | 201 | gfx::Point start_location_; |
| 202 | gfx::Point current_location_; |
| 203 | |
Trent Apted | a250ec3ab | 2018-08-19 08:52:19 | [diff] [blame] | 204 | base::ObserverList<aura::client::DragDropClientObserver>::Unchecked |
| 205 | observers_; |
Daichi Hirono | e66b415 | 2017-08-01 06:20:33 | [diff] [blame] | 206 | |
Nick Diego Yamane | f258eb44 | 2020-10-28 04:57:16 | [diff] [blame] | 207 | ToplevelWindowDragDelegate* toplevel_window_drag_delegate_ = nullptr; |
| 208 | |
Aya ElAttar | fd5ce86f | 2021-09-23 18:20:00 | [diff] [blame] | 209 | // Weak ptr for async drop callbacks to be invalidated if a new drag starts. |
| 210 | base::WeakPtrFactory<DragDropController> drop_weak_factory_{this}; |
| 211 | |
Jeremy Roman | 47d432e | 2019-08-20 14:24:00 | [diff] [blame] | 212 | base::WeakPtrFactory<DragDropController> weak_factory_{this}; |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 213 | }; |
| 214 | |
[email protected] | 55f59335 | 2011-12-24 05:42:46 | [diff] [blame] | 215 | } // namespace ash |
[email protected] | 084b6bb | 2011-11-17 05:18:16 | [diff] [blame] | 216 | |
[email protected] | 2f74428 | 2011-12-23 22:40:52 | [diff] [blame] | 217 | #endif // ASH_DRAG_DROP_DRAG_DROP_CONTROLLER_H_ |