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"
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"
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
38 class nsIImageLoadingContent
;
52 class MockDragServiceController
;
54 } // namespace mozilla
57 * Platform-agnostic base for nsIDragSession.
59 class nsBaseDragSession
: public nsIDragSession
{
62 NS_DECL_NSIDRAGSESSION
64 int32_t TakeChildProcessDragAction();
66 void SetDragEndPoint(nsIntPoint aEndDragPoint
) {
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
);
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;
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
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
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
;
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
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
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
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
{
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
);
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__