Bug 1942006 - Upstream a variety of Servo-specific code from Servo's downstream fork...
[gecko.git] / widget / nsBaseDragService.h
bloba735c64430f86448c9c3e96e95cfc93a3b7f981a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsBaseDragService_h__
7 #define nsBaseDragService_h__
9 #include "nsIDragService.h"
10 #include "nsIDragSession.h"
11 #include "nsCOMPtr.h"
12 #include "nsIFrame.h"
13 #include "nsRect.h"
14 #include "nsPoint.h"
15 #include "nsString.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/dom/HTMLCanvasElement.h"
18 #include "mozilla/dom/MouseEventBinding.h"
19 #include "mozilla/dom/RemoteDragStartData.h"
20 #include "mozilla/Logging.h"
21 #include "nsTArray.h"
22 #include "nsRegion.h"
23 #include "Units.h"
25 extern mozilla::LazyLogModule sWidgetDragServiceLog;
26 #define MOZ_DRAGSERVICE_LOG(...) \
27 MOZ_LOG(sWidgetDragServiceLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
28 #define MOZ_DRAGSERVICE_LOG_ENABLED() \
29 MOZ_LOG_TEST(sWidgetDragServiceLog, mozilla::LogLevel::Debug)
31 // translucency level for drag images
32 #define DRAG_TRANSLUCENCY 0.65
34 class nsIContent;
36 class nsINode;
37 class nsPresContext;
38 class nsIImageLoadingContent;
40 namespace mozilla {
41 namespace gfx {
42 class SourceSurface;
43 } // namespace gfx
45 namespace dom {
46 class BrowserParent;
47 class DataTransfer;
48 class Selection;
49 } // namespace dom
51 namespace test {
52 class MockDragServiceController;
53 } // namespace test
54 } // namespace mozilla
56 /**
57 * Platform-agnostic base for nsIDragSession.
59 class nsBaseDragSession : public nsIDragSession {
60 public:
61 NS_DECL_ISUPPORTS
62 NS_DECL_NSIDRAGSESSION
64 int32_t TakeChildProcessDragAction();
66 void SetDragEndPoint(nsIntPoint aEndDragPoint) {
67 mEndDragPoint =
68 mozilla::LayoutDeviceIntPoint::FromUnknownPoint(aEndDragPoint);
70 void SetDragEndPoint(mozilla::LayoutDeviceIntPoint aEndDragPoint) {
71 mEndDragPoint = aEndDragPoint;
74 uint16_t GetInputSource() { return mInputSource; }
76 // The nsIDragService uses this to create nsIDragSessions when dragging
77 // from a child process.
78 MOZ_CAN_RUN_SCRIPT nsresult InitWithRemoteImage(
79 nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
80 nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
81 nsIArray* aTransferableArray, uint32_t aActionType,
82 mozilla::dom::RemoteDragStartData* aDragStartData,
83 mozilla::dom::DragEvent* aDragEvent,
84 mozilla::dom::DataTransfer* aDataTransfer, bool aIsSynthesizedForTests);
86 // The nsIDragService uses this to create nsIDragSessions for dragging
87 // a selected region from a Gecko window.
88 MOZ_CAN_RUN_SCRIPT nsresult InitWithSelection(
89 nsIWidget* aWidget, mozilla::dom::Selection* aSelection,
90 nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp,
91 nsICookieJarSettings* aCookieJarSettings, nsIArray* aTransferableArray,
92 uint32_t aActionType, mozilla::dom::DragEvent* aDragEvent,
93 mozilla::dom::DataTransfer* aDataTransfer, nsINode* aTargetContent,
94 bool aIsSynthesizedForTests);
96 // The nsIDragService uses this to create nsIDragSessions when dragging
97 // from anywhere else.
98 MOZ_CAN_RUN_SCRIPT nsresult InitWithImage(
99 nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
100 nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
101 nsIArray* aTransferableArray, uint32_t aActionType, nsINode* aImage,
102 int32_t aImageX, int32_t aImageY, mozilla::dom::DragEvent* aDragEvent,
103 mozilla::dom::DataTransfer* aDataTransfer, bool aIsSynthesizedForTests);
105 protected:
106 nsBaseDragSession();
107 virtual ~nsBaseDragSession();
110 * Starts a modal drag session with an array of transaferables.
112 * @param aPrincipal - the triggering principal of the drag, or null if
113 * it's from browser chrome or OS
114 * @param aCsp - The csp of the triggering Document
115 * @param aTransferables - an array of transferables to be dragged
116 * @param aActionType - specified which of copy/move/link are allowed
117 * @param aContentPolicyType - the contentPolicyType that will be
118 * passed to the loadInfo when creating a new channel
119 * (defaults to TYPE_OTHER)
121 MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSession(
122 nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
123 nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
124 nsIArray* aTransferableArray, uint32_t aActionType,
125 nsContentPolicyType aContentPolicyType = nsIContentPolicy::TYPE_OTHER);
128 * Called to create a drag session with a Gecko source. Like all drag
129 * sessions, the resulting session needs to be eventually ended with a call
130 * to nsIDragSession::EndDragSession.
132 MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
133 nsIWidget* aWidget, nsIArray* aTransferableArray,
134 const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
135 uint32_t aActionType) = 0;
138 * Draw the drag image, if any, to a surface and return it. The drag image
139 * is constructed from mImage if specified, or aDOMNode if mImage is null.
141 * aRegion may be used to draw only a subset of the element. This region
142 * should be supplied using x and y coordinates measured in css pixels
143 * that are relative to the upper-left corner of the window.
145 * aScreenPosition should be the screen coordinates of the mouse click
146 * for the drag. These are in CSS pixels.
148 * On return, aScreenDragRect will contain the screen coordinates of the
149 * area being dragged. This is used by the platform-specific part of the
150 * drag service to determine the drag feedback. This rect will be in the
151 * device pixels of the presContext.
153 * If there is no drag image, the returned surface will be null, but
154 * aScreenDragRect will still be set to the drag area.
156 * aPresContext will be set to the nsPresContext used determined from
157 * whichever of mImage or aDOMNode is used.
159 nsresult DrawDrag(nsINode* aDOMNode,
160 const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
161 mozilla::CSSIntPoint aScreenPosition,
162 mozilla::LayoutDeviceIntRect* aScreenDragRect,
163 RefPtr<mozilla::gfx::SourceSurface>* aSurface,
164 nsPresContext** aPresContext);
167 * Draw a drag image for an image node specified by aImageLoader or aCanvas.
168 * This is called by DrawDrag.
170 nsresult DrawDragForImage(nsPresContext* aPresContext,
171 nsIImageLoadingContent* aImageLoader,
172 mozilla::dom::HTMLCanvasElement* aCanvas,
173 mozilla::LayoutDeviceIntRect* aScreenDragRect,
174 RefPtr<mozilla::gfx::SourceSurface>* aSurface);
176 MOZ_CAN_RUN_SCRIPT virtual nsresult EndDragSessionImpl(
177 bool aDoneDrag, uint32_t aKeyModifiers);
179 // Returns true if a drag event was dispatched to a child process after
180 // the previous TakeDragEventDispatchedToChildProcess() call.
181 bool TakeDragEventDispatchedToChildProcess() {
182 bool retval = mDragEventDispatchedToChildProcess;
183 mDragEventDispatchedToChildProcess = false;
184 return retval;
187 // Takes the list of PBrowsers that are engaged in the current drag session
188 // from the drag service and stores them here.
189 void TakeSessionBrowserListFromService();
192 * Free resources contained in DataTransferItems that aren't needed by JS.
194 void DiscardInternalTransferData();
197 * If the drag image is a popup, open the popup when the drag begins.
199 void OpenDragPopup();
201 // Data from a prior call to EndDragSession.
202 struct EndDragSessionData {
203 bool mDoneDrag = false;
204 uint32_t mKeyModifiers = 0;
207 // When we delay a drop event in a content process, if we subsequently need to
208 // also delay an EndDragSession call, this records the parameters to that
209 // call.
210 mozilla::Maybe<EndDragSessionData> mEndDragSessionData;
211 // When we delay a drop event in a content process, this is the dom::Element
212 // that the drop was targetted to.
213 nsWeakPtr mDelayedDropTarget;
214 // When we delay a drop event in a content process, this is the nsIFrame that
215 // would handle the drop.
216 WeakFrame mDelayedDropFrame;
218 // Parent process PBrowser with a the remote drag session that corresponds to
219 // this one and is currently delayed.
220 RefPtr<mozilla::dom::BrowserParent> mDelayedDropBrowserParent;
222 RefPtr<mozilla::dom::WindowContext> mSourceWindowContext;
223 RefPtr<mozilla::dom::WindowContext> mSourceTopWindowContext;
224 nsCOMPtr<nsINode> mSourceNode;
225 // the document at the drag source. will be null if it came from outside the
226 // app.
227 RefPtr<mozilla::dom::Document> mSourceDocument;
228 // set if a selection is being dragged
229 RefPtr<mozilla::dom::Selection> mSelection;
231 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
232 nsCOMPtr<nsIContentSecurityPolicy> mCsp;
233 RefPtr<mozilla::dom::DataTransfer> mDataTransfer;
235 // used to determine the image to appear on the cursor while dragging
236 nsCOMPtr<nsINode> mImage;
237 // offset of cursor within the image
238 mozilla::CSSIntPoint mImageOffset;
239 // set if the image in mImage is a popup. If this case, the popup will be
240 // opened and moved instead of using a drag image.
241 nsCOMPtr<mozilla::dom::Element> mDragPopup;
243 // Weak references to PBrowsers that are currently engaged in drags
244 nsTArray<nsWeakPtr> mBrowsers;
245 // remote drag data
246 RefPtr<mozilla::dom::RemoteDragStartData> mDragStartData;
248 // Sub-region for tree-selections.
249 mozilla::Maybe<mozilla::CSSIntRegion> mRegion;
251 // the screen position where drag gesture occurred, used for positioning the
252 // drag image.
253 mozilla::CSSIntPoint mScreenPosition;
255 // The position relative to the top level widget where the drag ended.
256 mozilla::LayoutDeviceIntPoint mEndDragPoint;
258 // the contentpolicy type passed to the channel when initiating the drag
259 // session
260 nsContentPolicyType mContentPolicyType = nsIContentPolicy::TYPE_OTHER;
262 uint32_t mDragAction = nsIDragService::DRAGDROP_ACTION_NONE;
263 uint32_t mDragActionFromChildProcess =
264 nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
266 // mEffectAllowedForTests stores allowed effects at invoking the drag
267 // for tests.
268 uint32_t mEffectAllowedForTests =
269 nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
271 // The input source of the drag event. Possible values are from MouseEvent.
272 uint16_t mInputSource = mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_MOUSE;
274 // false after EndDragSession has run
275 bool mDoingDrag = true;
277 bool mCanDrop = false;
278 bool mOnlyChromeDrop = false;
280 // true if the user cancelled the drag operation
281 bool mUserCancelled = false;
283 bool mDragEventDispatchedToChildProcess = false;
285 bool mIsDraggingTextInTextControl = false;
286 bool mSessionIsSynthesizedForTests = false;
288 // true if in EndDragSession
289 bool mEndingSession = false;
290 // true if mImage should be used to set a drag image
291 bool mHasImage = false;
295 * Platform-agnostic base for nsIDragService.
297 class nsBaseDragService : public nsIDragService {
298 public:
299 nsBaseDragService();
301 // nsISupports
302 NS_DECL_ISUPPORTS
304 NS_DECL_NSIDRAGSERVICE
306 using nsIDragService::GetCurrentSession;
308 uint32_t GetSuppressLevel() { return mSuppressLevel; };
310 nsTArray<nsWeakPtr> TakeSessionBrowserList() { return std::move(mBrowsers); }
312 void ClearCurrentParentDragSession() { mCurrentParentDragSession = nullptr; }
314 static nsIWidget* GetWidgetFromWidgetProvider(nsISupports* aWidgetProvider);
316 protected:
317 virtual ~nsBaseDragService();
319 virtual already_AddRefed<nsIDragSession> CreateDragSession() = 0;
321 // The drag session representing the user's current actions, if any.
322 // This value is only valid in the parent process. For child
323 // process drag sessions, see BrowserChild and PuppetWidget.
324 RefPtr<nsIDragSession> mCurrentParentDragSession;
326 // Sub-region for tree-selections.
327 mozilla::Maybe<mozilla::CSSIntRegion> mRegion;
329 RefPtr<mozilla::test::MockDragServiceController> mMockController;
331 // Weak references to PBrowsers that are currently engaged in drags.
332 // Once an nsIDragSession is created for the remote drag, these browsers
333 // will be moved to that object.
334 nsTArray<nsWeakPtr> mBrowsers;
336 uint32_t mSuppressLevel = 0;
338 // If this is set, mSessionIsSynthesizedForTests should not become true.
339 // This hack is used to bypass the "old" drag-drop test behavior.
340 // See nsIDragService.idl for details.
341 bool mNeverAllowSessionIsSynthesizedForTests = false;
344 #endif // nsBaseDragService_h__