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
|
// 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_
|