Bug 1893119: Part 21 - Separate nsIDragService and nsIDragSession implementations r=gstoll,geckoview-reviewers,rkraesig,win-reviewers,m_kato

Split the class inheritance trees for nsIDragService and nsIDragSession.
Remember that, before the start of this patch series, the inheritance
diagram was:

nsDragService -> nsBaseDragService -> nsIDragService + nsIDragSession

and the only instance was a singleton.  We switched it to:

nsDragService -> nsDragSession -> nsBaseDragService -> nsIDragService + nsBaseDragSession -> nsIDragSession

and maintained the singleton.  This allowed us to allow us to move things to
the new classes without breaking behavior.  We are done with that,
so we can now change the inheritance to its final form:

nsDragService -> nsBaseDragService -> nsIDragService

nsDragSession -> nsBaseDragSession -> nsIDragSession

Of course, we also need to properly construct and release the
nsIDragSessions (formerly part of the singleton), so that is done here as
well.  That happens in nsBaseDrag[Service|Session] for parent process drags
and in nsDrag[Service|Session]Proxy for content.  This is all fairly
straightforward, except in the case of gtk, where we need to change
some callback behavior.

Differential Revision: https://phabricator.services.mozilla.com/D211084
This commit is contained in:
David P 2024-07-04 07:48:11 +00:00
Родитель f680f60c6e
Коммит 7376694ac2
21 изменённых файлов: 765 добавлений и 447 удалений

Просмотреть файл

@ -84,6 +84,7 @@
#include "nsDeviceContext.h"
#include "nsDocShell.h"
#include "nsDocShellLoadState.h"
#include "nsDragServiceProxy.h"
#include "nsExceptionHandler.h"
#include "nsFilePickerProxy.h"
#include "nsFocusManager.h"
@ -502,6 +503,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild)
NS_INTERFACE_MAP_ENTRY_CONCRETE(BrowserChild)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
@ -1919,6 +1921,15 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealDragEvent(
}
DispatchWidgetEventViaAPZ(localEvent);
if (aEvent.mMessage == eDragLeave ||
aEvent.mMessage == eDragExit) {
// If session is still active, remove its target.
dragSession = GetDragSession();
if (dragSession) {
static_cast<nsDragSessionProxy*>(dragSession.get())->SetDragTarget(nullptr);
}
}
return IPC_OK();
}
@ -1971,7 +1982,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvInvokeChildDragSession(
do_GetService("@mozilla.org/widget/dragservice;1")) {
nsIWidget* widget = WebWidget();
dragService->StartDragSession(widget);
if (RefPtr<nsIDragSession> session = nsContentUtils::GetDragSession(widget)) {
if (RefPtr<nsIDragSession> session = GetDragSession()) {
session->SetSourceWindowContext(aSourceWindowContext.GetMaybeDiscarded());
session->SetSourceTopWindowContext(
aSourceTopWindowContext.GetMaybeDiscarded());
@ -3889,9 +3900,11 @@ BrowserChild::ContentTransformsReceived(JSContext* aCx,
}
already_AddRefed<nsIDragSession> BrowserChild::GetDragSession() {
RefPtr<nsIDragSession> session =
nsContentUtils::GetDragSession(mPuppetWidget);
return session.forget();
return RefPtr(mDragSession).forget();
}
void BrowserChild::SetDragSession(nsIDragSession* aSession) {
mDragSession = aSession;
}
BrowserChildMessageManager::BrowserChildMessageManager(

Просмотреть файл

@ -85,6 +85,13 @@ class SessionStoreChild;
class RequestData;
class WebProgressData;
#define DOM_BROWSERCHILD_IID \
{ \
0x58a5775d, 0xba05, 0x45bf, { \
0xbd, 0xb8, 0xd7, 0x61, 0xf9, 0x01, 0x01, 0x31 \
} \
}
class BrowserChildMessageManager : public ContentFrameMessageManager,
public nsIMessageSender,
public nsSupportsWeakReference {
@ -181,6 +188,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
return mUniqueId;
}
NS_DECLARE_STATIC_IID_ACCESSOR(DOM_BROWSERCHILD_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIINTERFACEREQUESTOR
@ -658,6 +666,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
const Maybe<bool> aCanvasFingerprinterKnownText);
already_AddRefed<nsIDragSession> GetDragSession();
void SetDragSession(nsIDragSession* aSession);
mozilla::ipc::IPCResult RecvInvokeChildDragSession(
const MaybeDiscarded<WindowContext>& aSourceWindowContext,
@ -777,6 +786,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
RefPtr<ContentChild> mManager;
RefPtr<BrowsingContext> mBrowsingContext;
RefPtr<nsBrowserStatusFilter> mStatusFilter;
RefPtr<nsIDragSession> mDragSession;
Maybe<CodeNameIndex> mPreviousConsumedKeyDownCode;
uint32_t mChromeFlags;
uint32_t mMaxTouchPoints;
@ -879,6 +890,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
DISALLOW_EVIL_CONSTRUCTORS(BrowserChild);
};
NS_DEFINE_STATIC_IID_ACCESSOR(BrowserChild, DOM_BROWSERCHILD_IID)
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -17,8 +17,8 @@ namespace mozilla::test {
NS_IMPL_ISUPPORTS(MockDragServiceController, nsIMockDragServiceController)
class MockDragService : public nsBaseDragService {
public:
class MockDragSession : public nsBaseDragSession {
protected:
MOZ_CAN_RUN_SCRIPT nsresult
InvokeDragSessionImpl(nsIWidget* aWidget, nsIArray* aTransferableArray,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
@ -50,12 +50,24 @@ class MockDragService : public nsBaseDragService {
// Note that, like in non-mocked DND, we do this regardless of whether
// the source and target were the same widget -- in that case,
// EndDragSession is just called twice.
mDragAction = DRAGDROP_ACTION_MOVE;
StartDragSession(aWidget);
mDragAction = nsIDragService::DRAGDROP_ACTION_MOVE;
return NS_OK;
}
};
bool IsMockService() override { return true; }
class MockDragService : public nsBaseDragService {
public:
NS_IMETHOD GetIsMockService(bool* aRet) override {
*aRet = true;
return NS_OK;
}
uint32_t mLastModifierKeyState = 0;
protected:
already_AddRefed<nsIDragSession> CreateDragSession() override {
RefPtr<nsIDragSession> session = new MockDragSession();
return session.forget();
}
};
static void SetDragEndPointFromScreenPoint(

Просмотреть файл

@ -20,9 +20,6 @@
#include "nsViewManager.h"
#include "nsWindow.h"
NS_IMPL_ISUPPORTS_INHERITED0(nsDragSession, nsBaseDragService)
NS_IMPL_ISUPPORTS_INHERITED0(nsDragService, nsDragSession)
using namespace mozilla;
using namespace mozilla::widget;
@ -39,6 +36,11 @@ already_AddRefed<nsDragService> nsDragService::GetInstance() {
return service.forget();
}
already_AddRefed<nsIDragSession> nsDragService::CreateDragSession() {
RefPtr<nsDragSession> session = new nsDragSession();
return session.forget();
}
static nsWindow* GetWindow(dom::Document* aDocument) {
if (!aDocument) {
return nullptr;
@ -63,7 +65,7 @@ static nsWindow* GetWindow(dom::Document* aDocument) {
return window.get();
}
nsresult nsDragService::InvokeDragSessionImpl(
nsresult nsDragSession::InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aTransferableArray,
const Maybe<CSSIntRegion>& aRegion, uint32_t aActionType) {
if (jni::GetAPIVersion() < 24) {
@ -90,7 +92,6 @@ nsresult nsDragService::InvokeDragSessionImpl(
if (nsWindow* window = GetWindow(mSourceDocument)) {
mTransferable = transferable;
nsBaseDragService::StartDragSession(aWidget);
OpenDragPopup();
auto bitmap = CreateDragImage(mSourceNode, aRegion);
@ -230,18 +231,12 @@ void nsDragSession::SetData(nsITransferable* aTransferable) {
mDataTransfer = nullptr;
}
// static
void nsDragService::SetDropData(
void nsDragSession::SetDropData(
mozilla::java::GeckoDragAndDrop::DropData::Param aDropData) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
if (!dragService) {
return;
}
if (!aDropData) {
dragService->SetData(nullptr);
SetData(nullptr);
return;
}
@ -254,7 +249,7 @@ void nsDragService::SetDropData(
if (!mime.EqualsLiteral("text/plain") && !mime.EqualsLiteral("text/html")) {
// Not supported data.
dragService->SetData(nullptr);
SetData(nullptr);
return;
}
@ -263,12 +258,12 @@ void nsDragService::SetDropData(
nsPrimitiveHelpers::CreatePrimitiveForData(
mime, buffer.get(), buffer.Length() * 2, getter_AddRefs(wrapper));
if (!wrapper) {
dragService->SetData(nullptr);
SetData(nullptr);
return;
}
nsCOMPtr<nsITransferable> transferable =
do_CreateInstance("@mozilla.org/widget/transferable;1");
transferable->Init(nullptr);
transferable->SetTransferData(mime.get(), wrapper);
dragService->SetData(transferable);
SetData(transferable);
}

Просмотреть файл

@ -13,15 +13,11 @@
class nsITransferable;
// Temporary inheritance from nsBaseDragService instead of nsBaseDragSession
// (which nsBaseDragService temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragSession : public nsBaseDragService {
/**
* Android native nsIDragSession implementation
*/
class nsDragSession : public nsBaseDragSession {
public:
nsDragSession() = default;
NS_DECL_ISUPPORTS_INHERITED
// nsIDragSession
NS_IMETHOD GetData(nsITransferable* aTransferable, uint32_t anItem) override;
NS_IMETHOD GetNumDropItems(uint32_t* aNumItems) override;
@ -32,6 +28,8 @@ class nsDragSession : public nsBaseDragService {
void SetData(nsITransferable* aTransferable);
void SetDropData(mozilla::java::GeckoDragAndDrop::DropData::Param aDropData);
virtual bool MustUpdateDataTransfer(mozilla::EventMessage aMessage) override;
MOZ_CAN_RUN_SCRIPT nsresult EndDragSessionImpl(
@ -40,6 +38,12 @@ class nsDragSession : public nsBaseDragService {
protected:
virtual ~nsDragSession() = default;
// nsBaseDragSession
MOZ_CAN_RUN_SCRIPT nsresult
InvokeDragSessionImpl(nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
mozilla::java::sdk::Bitmap::LocalRef CreateDragImage(
nsINode* aNode, const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion);
@ -47,26 +51,15 @@ class nsDragSession : public nsBaseDragService {
nsCOMPtr<nsITransferable> mTransferable;
};
// Temporary inheritance from nsDragSession instead of nsBaseDragService
// (which nsDragSession temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragService final : public nsDragSession {
/**
* Android native nsIDragService implementation
*/
class nsDragService final : public nsBaseDragService {
public:
static already_AddRefed<nsDragService> GetInstance();
NS_DECL_ISUPPORTS_INHERITED
static void SetDropData(
mozilla::java::GeckoDragAndDrop::DropData::Param aDropData);
protected:
virtual ~nsDragService() = default;
// nsBaseDragService
MOZ_CAN_RUN_SCRIPT nsresult
InvokeDragSessionImpl(nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
already_AddRefed<nsIDragSession> CreateDragSession() override;
};
#endif // nsDragService_h__

Просмотреть файл

@ -2677,15 +2677,16 @@ void nsWindow::OnDragEvent(int32_t aAction, int64_t aTime, float aX, float aY,
jni::Object::Param aDropData) {
MOZ_ASSERT(NS_IsMainThread());
LayoutDeviceIntPoint point =
LayoutDeviceIntPoint(int32_t(floorf(aX)), int32_t(floorf(aY)));
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
if (!dragService) {
return;
}
LayoutDeviceIntPoint point =
LayoutDeviceIntPoint(int32_t(floorf(aX)), int32_t(floorf(aY)));
nsCOMPtr<nsIDragSession> dragSession = dragService->GetCurrentSession(this);
RefPtr<nsDragSession> dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(this));
if (dragSession && aAction == java::sdk::DragEvent::ACTION_DRAG_STARTED) {
dragSession->SetDragEndPoint(point.x, point.y);
return;
@ -2702,10 +2703,13 @@ void nsWindow::OnDragEvent(int32_t aAction, int64_t aTime, float aX, float aY,
nsIWidget* widget = this;
dragService->StartDragSession(widget);
// For compatibility, we have to set temporary data.
dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(this));
MOZ_ASSERT(dragSession);
auto dropData =
mozilla::java::GeckoDragAndDrop::DropData::Ref::From(aDropData);
nsDragService::SetDropData(dropData);
dragSession = dragService->GetCurrentSession(this);
dragSession->SetDropData(dropData);
}
if (dragSession) {
@ -2727,7 +2731,7 @@ void nsWindow::OnDragEvent(int32_t aAction, int64_t aTime, float aX, float aY,
}
auto dropData =
mozilla::java::GeckoDragAndDrop::DropData::Ref::From(aDropData);
nsDragService::SetDropData(dropData);
dragSession->SetDropData(dropData);
dragSession->SetDragEndPoint(point.x, point.y);
break;
}

Просмотреть файл

@ -11,10 +11,10 @@
#include <Cocoa/Cocoa.h>
// Temporary inheritance from nsBaseDragService instead of nsBaseDragSession
// (which nsBaseDragService temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragSession : public nsBaseDragService {
/**
* Cocoa native nsIDragSession implementation
*/
class nsDragSession : public nsBaseDragSession {
public:
// nsIDragSession
NS_IMETHOD GetData(nsITransferable* aTransferable,
@ -34,6 +34,12 @@ class nsDragSession : public nsBaseDragService {
bool aDoneDrag, uint32_t aKeyModifiers) override;
protected:
// nsBaseDragSession
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
// Creates and returns the drag image for a drag. aImagePoint will be set to
// the origin of the drag relative to mNativeDragView.
NSImage* ConstructDragImage(
@ -59,21 +65,12 @@ class nsDragSession : public nsBaseDragService {
bool mDragImageChanged = false;
};
// Temporary inheritance from nsDragSession instead of nsBaseDragService
// (which nsDragSession temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragService final : public nsDragSession {
/**
* Cocoa native nsIDragService implementation
*/
class nsDragService final : public nsBaseDragService {
public:
nsDragService();
// nsBaseDragService
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
protected:
virtual ~nsDragService();
already_AddRefed<nsIDragSession> CreateDragSession() override;
};
#endif // nsDragService_h_

Просмотреть файл

@ -44,9 +44,10 @@ extern bool gUserCancelledDrag;
// file destination callback.
mozilla::StaticRefPtr<nsIArray> gDraggedTransferables;
nsDragService::nsDragService() {}
nsDragService::~nsDragService() {}
already_AddRefed<nsIDragSession> nsDragService::CreateDragSession() {
RefPtr<nsIDragSession> sess = new nsDragSession();
return sess.forget();
}
NSImage* nsDragSession::ConstructDragImage(nsINode* aDOMNode,
const Maybe<CSSIntRegion>& aRegion,
@ -177,7 +178,7 @@ NSImage* nsDragSession::ConstructDragImage(nsINode* aDOMNode,
NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}
nsresult nsDragService::InvokeDragSessionImpl(
nsresult nsDragSession::InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aTransferableArray,
const Maybe<CSSIntRegion>& aRegion, uint32_t aActionType) {
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
@ -250,7 +251,6 @@ nsresult nsDragService::InvokeDragSessionImpl(
[pbItem release];
[dragItem setDraggingFrame:localDragRect contents:image];
nsBaseDragService::StartDragSession(aWidget);
OpenDragPopup();
mNSDraggingSession = [mNativeDragView

Просмотреть файл

@ -31,6 +31,7 @@
#include "mozilla/PresShell.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/WidgetUtils.h"
#include "mozilla/WidgetUtilsGtk.h"
#include "GRefPtr.h"
#include "nsAppShell.h"
@ -519,7 +520,7 @@ void DragData::Print() const {
/* static */ int nsDragSession::sEventLoopDepth = 0;
nsDragService::nsDragService() {
nsDragSession::nsDragSession() {
// We have to destroy the hidden widget before the event loop stops
// running.
nsCOMPtr<nsIObserverService> obsServ =
@ -580,8 +581,8 @@ nsDragService::nsDragService() {
LOGDRAGSERVICE("nsDragService::nsDragService");
}
nsDragService::~nsDragService() {
LOGDRAGSERVICE("nsDragService::~nsDragService");
nsDragSession::~nsDragSession() {
LOGDRAGSERVICE("nsDragSession::~nsDragSession");
if (mTaskSource) g_source_remove(mTaskSource);
if (mTempFileTimerID) {
g_source_remove(mTempFileTimerID);
@ -589,7 +590,7 @@ nsDragService::~nsDragService() {
}
}
NS_IMPL_ISUPPORTS_INHERITED(nsDragService, nsBaseDragService, nsIObserver)
NS_IMPL_ISUPPORTS_INHERITED(nsDragSession, nsBaseDragSession, nsIObserver)
mozilla::StaticRefPtr<nsDragService> sDragServiceInstance;
/* static */
@ -606,13 +607,18 @@ already_AddRefed<nsDragService> nsDragService::GetInstance() {
return service.forget();
}
already_AddRefed<nsIDragSession> nsDragService::CreateDragSession() {
RefPtr<nsIDragSession> session = new nsDragSession();
return session.forget();
}
// nsIObserver
NS_IMETHODIMP
nsDragService::Observe(nsISupports* aSubject, const char* aTopic,
nsDragSession::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (!nsCRT::strcmp(aTopic, "quit-application")) {
LOGDRAGSERVICE("nsDragService::Observe(\"quit-application\")");
LOGDRAGSERVICE("nsDragSession::Observe(\"quit-application\")");
if (mHiddenWidget) {
gtk_widget_destroy(mHiddenWidget);
mHiddenWidget = 0;
@ -725,15 +731,13 @@ static GtkWindow* GetGtkWindow(dom::Document* aDocument) {
return GTK_WINDOW(toplevel);
}
// nsIDragService
NS_IMETHODIMP
nsDragService::InvokeDragSession(
nsDragSession::InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aArrayTransferables, uint32_t aActionType,
nsContentPolicyType aContentPolicyType = nsIContentPolicy::TYPE_OTHER) {
LOGDRAGSERVICE("nsDragService::InvokeDragSession");
LOGDRAGSERVICE("nsDragSession::InvokeDragSession");
// If the previous source drag has not yet completed, signal handlers need
// to be removed from sGrabWidget and dragend needs to be dispatched to
@ -741,13 +745,13 @@ nsDragService::InvokeDragSession(
// know whether or not the drag succeeded.
if (mSourceNode) return NS_ERROR_NOT_AVAILABLE;
return nsBaseDragService::InvokeDragSession(
return nsBaseDragSession::InvokeDragSession(
aWidget, aDOMNode, aPrincipal, aCsp, aCookieJarSettings,
aArrayTransferables, aActionType, aContentPolicyType);
}
// nsBaseDragService
nsresult nsDragService::InvokeDragSessionImpl(
// nsBaseDragSession
nsresult nsDragSession::InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aArrayTransferables,
const Maybe<CSSIntRegion>& aRegion, uint32_t aActionType) {
// make sure that we have an array of transferables to use
@ -757,7 +761,7 @@ nsresult nsDragService::InvokeDragSessionImpl(
// length of this call
mSourceDataItems = aArrayTransferables;
LOGDRAGSERVICE("nsDragService::InvokeDragSessionImpl");
LOGDRAGSERVICE("nsDragSession::InvokeDragSessionImpl");
GdkDevice* device = widget::GdkGetPointer();
GdkWindow* originGdkWindow = nullptr;
@ -768,7 +772,7 @@ nsresult nsDragService::InvokeDragSessionImpl(
// Check we have GdkWindow drag source.
if (!originGdkWindow) {
NS_WARNING(
"nsDragService::InvokeDragSessionImpl(): Missing origin GdkWindow!");
"nsDragSession::InvokeDragSessionImpl(): Missing origin GdkWindow!");
return NS_ERROR_FAILURE;
}
}
@ -781,11 +785,11 @@ nsresult nsDragService::InvokeDragSessionImpl(
// save our action type
GdkDragAction action = GDK_ACTION_DEFAULT;
if (aActionType & DRAGDROP_ACTION_COPY)
if (aActionType & nsIDragService::DRAGDROP_ACTION_COPY)
action = (GdkDragAction)(action | GDK_ACTION_COPY);
if (aActionType & DRAGDROP_ACTION_MOVE)
if (aActionType & nsIDragService::DRAGDROP_ACTION_MOVE)
action = (GdkDragAction)(action | GDK_ACTION_MOVE);
if (aActionType & DRAGDROP_ACTION_LINK)
if (aActionType & nsIDragService::DRAGDROP_ACTION_LINK)
action = (GdkDragAction)(action | GDK_ACTION_LINK);
GdkEvent* existingEvent = widget::GetLastMousePressEvent();
@ -826,8 +830,6 @@ nsresult nsDragService::InvokeDragSessionImpl(
nsresult rv;
if (context) {
StartDragSession(aWidget);
// GTK uses another hidden window for receiving mouse events.
sGrabWidget = gtk_window_group_get_current_grab(window_group);
if (sGrabWidget) {
@ -849,7 +851,7 @@ nsresult nsDragService::InvokeDragSessionImpl(
return rv;
}
bool nsDragService::SetAlphaPixmap(SourceSurface* aSurface,
bool nsDragSession::SetAlphaPixmap(SourceSurface* aSurface,
GdkDragContext* aContext, int32_t aXOffset,
int32_t aYOffset,
const LayoutDeviceIntRect& dragRect) {
@ -902,7 +904,6 @@ bool nsDragService::SetAlphaPixmap(SourceSurface* aSurface,
NS_IMETHODIMP
nsDragService::StartDragSession(nsISupports* aWidgetProvider) {
LOGDRAGSERVICE("nsDragService::StartDragSession");
mTempFileUrls.Clear();
return nsBaseDragService::StartDragSession(aWidgetProvider);
}
@ -943,7 +944,6 @@ gboolean nsDragSession::TaskRemoveTempFiles(gpointer data) {
// We manually deref it here.
RefPtr<nsDragSession> session = static_cast<nsDragSession*>(data);
session.get()->Release();
RefPtr<nsDragService> dragService = static_cast<nsDragService*>(data);
return session->RemoveTempFiles();
}
@ -968,7 +968,7 @@ nsresult nsDragSession::EndDragSessionImpl(bool aDoneDrag,
}
// unset our drag action
SetDragAction(DRAGDROP_ACTION_NONE);
SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE);
// start timer to remove temporary files
if (mTemporaryFiles.Count() > 0 && !mTempFileTimerID) {
@ -1297,15 +1297,15 @@ void nsDragSession::ReplyToDragMotion(GdkDragContext* aDragContext,
if (mCanDrop) {
// notify the dragger if we can drop
switch (mDragAction) {
case DRAGDROP_ACTION_COPY:
case nsIDragService::DRAGDROP_ACTION_COPY:
LOGDRAGSERVICE(" set explicit action copy");
action = GDK_ACTION_COPY;
break;
case DRAGDROP_ACTION_LINK:
case nsIDragService::DRAGDROP_ACTION_LINK:
LOGDRAGSERVICE(" set explicit action link");
action = GDK_ACTION_LINK;
break;
case DRAGDROP_ACTION_NONE:
case nsIDragService::DRAGDROP_ACTION_NONE:
LOGDRAGSERVICE(" set explicit action none");
action = (GdkDragAction)0;
break;
@ -1345,7 +1345,7 @@ void nsDragSession::ReplyToDragMotion(GdkDragContext* aDragContext,
gdk_drag_status(aDragContext, action, aTime);
}
void nsDragService::SetCachedDragContext(GdkDragContext* aDragContext) {
void nsDragSession::SetCachedDragContext(GdkDragContext* aDragContext) {
LOGDRAGSERVICE("nsDragService::SetCachedDragContext(): [drag %p / cached %p]",
aDragContext, (void*)mCachedDragContext);
// Clear cache data if we're going to D&D with different drag context.
@ -1371,7 +1371,7 @@ bool nsDragSession::IsTargetContextList(void) {
return IsDragFlavorAvailable(sMimeListTypeAtom);
}
bool nsDragService::IsDragFlavorAvailable(GdkAtom aRequestedFlavor) {
bool nsDragSession::IsDragFlavorAvailable(GdkAtom aRequestedFlavor) {
if (mCachedDragFlavors.IsEmpty()) {
for (GList* tmp = gdk_drag_context_list_targets(mTargetDragContext); tmp;
tmp = tmp->next) {
@ -1388,7 +1388,7 @@ bool nsDragService::IsDragFlavorAvailable(GdkAtom aRequestedFlavor) {
// Spins event loop, called from eDragTaskMotion handler by
// DispatchMotionEvents().
// Can lead to another round of drag_motion events.
RefPtr<DragData> nsDragService::GetDragData(GdkAtom aRequestedFlavor) {
RefPtr<DragData> nsDragSession::GetDragData(GdkAtom aRequestedFlavor) {
LOGDRAGSERVICE("nsDragService::GetDragData(%p) requested '%s'\n",
mTargetDragContext.get(),
GUniquePtr<gchar>(gdk_atom_name(aRequestedFlavor)).get());
@ -1455,7 +1455,7 @@ RefPtr<DragData> nsDragService::GetDragData(GdkAtom aRequestedFlavor) {
return nullptr;
}
void nsDragService::TargetDataReceived(GtkWidget* aWidget,
void nsDragSession::TargetDataReceived(GtkWidget* aWidget,
GdkDragContext* aContext, gint aX,
gint aY,
GtkSelectionData* aSelectionData,
@ -1558,7 +1558,7 @@ static bool CanExportAsURLTarget(const char16_t* aURLData, uint32_t aURLLen) {
return true;
}
GtkTargetList* nsDragService::GetSourceList(void) {
GtkTargetList* nsDragSession::GetSourceList(void) {
if (!mSourceDataItems) {
return nullptr;
}
@ -1691,7 +1691,7 @@ GtkTargetList* nsDragService::GetSourceList(void) {
return targetList;
}
void nsDragService::SourceEndDragSession(GdkDragContext* aContext,
void nsDragSession::SourceEndDragSession(GdkDragContext* aContext,
gint aResult) {
LOGDRAGSERVICE("SourceEndDragSession(%p) result %s\n", aContext,
kGtkDragResults[aResult]);
@ -1722,10 +1722,7 @@ void nsDragService::SourceEndDragSession(GdkDragContext* aContext,
gdk_window_get_device_position(
gdkWindow, gdk_drag_context_get_device(aContext), &x, &y, nullptr);
gint scale = gdk_window_get_scale_factor(gdkWindow);
nsCOMPtr<nsIDragSession> session = GetCurrentSession(mSourceWindow);
if (session) {
session->SetDragEndPoint(x * scale, y * scale);
}
SetDragEndPoint(x * scale, y * scale);
LOGDRAGSERVICE(" guess drag end point %d %d\n", x * scale, y * scale);
}
@ -1750,23 +1747,23 @@ void nsDragService::SourceEndDragSession(GdkDragContext* aContext,
// unusual action combinations as NONE.
if (!action) {
LOGDRAGSERVICE(" drop action is none");
dropEffect = DRAGDROP_ACTION_NONE;
dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
} else if (action & GDK_ACTION_COPY) {
LOGDRAGSERVICE(" drop action is copy");
dropEffect = DRAGDROP_ACTION_COPY;
dropEffect = nsIDragService::DRAGDROP_ACTION_COPY;
} else if (action & GDK_ACTION_LINK) {
LOGDRAGSERVICE(" drop action is link");
dropEffect = DRAGDROP_ACTION_LINK;
dropEffect = nsIDragService::DRAGDROP_ACTION_LINK;
} else if (action & GDK_ACTION_MOVE) {
LOGDRAGSERVICE(" drop action is move");
dropEffect = DRAGDROP_ACTION_MOVE;
dropEffect = nsIDragService::DRAGDROP_ACTION_MOVE;
} else {
LOGDRAGSERVICE(" drop action is copy");
dropEffect = DRAGDROP_ACTION_COPY;
dropEffect = nsIDragService::DRAGDROP_ACTION_COPY;
}
} else {
LOGDRAGSERVICE(" drop action is none");
dropEffect = DRAGDROP_ACTION_NONE;
dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
if (aResult != GTK_DRAG_RESULT_NO_TARGET) {
LOGDRAGSERVICE(" drop is user chancelled\n");
mUserCancelled = true;
@ -1778,7 +1775,8 @@ void nsDragService::SourceEndDragSession(GdkDragContext* aContext,
}
// Schedule the appropriate drag end dom events.
Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0);
Schedule(eDragTaskSourceEnd, mTargetWindow, nullptr, LayoutDeviceIntPoint(),
0);
}
static nsresult GetDownloadDetails(nsITransferable* aTransferable,
@ -1837,9 +1835,9 @@ static nsresult GetDownloadDetails(nsITransferable* aTransferable,
}
// See nsContentAreaDragDropDataProvider::GetFlavorData() for reference.
nsresult nsDragService::CreateTempFile(nsITransferable* aItem,
nsresult nsDragSession::CreateTempFile(nsITransferable* aItem,
nsACString& aURI) {
LOGDRAGSERVICE("nsDragService::CreateTempFile()");
LOGDRAGSERVICE("nsDragSession::CreateTempFile()");
nsCOMPtr<nsIFile> tmpDir;
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
@ -1973,7 +1971,7 @@ nsresult nsDragService::CreateTempFile(nsITransferable* aItem,
return NS_OK;
}
bool nsDragService::SourceDataAppendURLFileItem(nsACString& aURI,
bool nsDragSession::SourceDataAppendURLFileItem(nsACString& aURI,
nsITransferable* aItem) {
// If there is a file available, create a URI from the file.
nsCOMPtr<nsISupports> data;
@ -1990,7 +1988,7 @@ bool nsDragService::SourceDataAppendURLFileItem(nsACString& aURI,
return false;
}
bool nsDragService::SourceDataAppendURLItem(nsITransferable* aItem,
bool nsDragSession::SourceDataAppendURLItem(nsITransferable* aItem,
bool aExternalDrop,
nsACString& aURI) {
nsCOMPtr<nsISupports> data;
@ -2035,7 +2033,7 @@ bool nsDragService::SourceDataAppendURLItem(nsITransferable* aItem,
return NS_SUCCEEDED(CreateTempFile(aItem, aURI));
}
void nsDragService::SourceDataGetUriList(GdkDragContext* aContext,
void nsDragSession::SourceDataGetUriList(GdkDragContext* aContext,
GtkSelectionData* aSelectionData,
uint32_t aDragItems) {
// Check if we're transfering data to another application.
@ -2047,7 +2045,7 @@ void nsDragService::SourceDataGetUriList(GdkDragContext* aContext,
? !nsWindow::GetWindow(gdk_drag_context_get_dest_window(aContext))
: !gdk_drag_context_get_dest_window(aContext);
LOGDRAGSERVICE("nsDragService::SourceDataGetUriLists() len %d external %d",
LOGDRAGSERVICE("nsDragSession::SourceDataGetUriLists() len %d external %d",
aDragItems, isExternalDrop);
// Disable processing of native events until we store all files to /tmp.
@ -2081,9 +2079,9 @@ void nsDragService::SourceDataGetUriList(GdkDragContext* aContext,
uriList.Length());
}
void nsDragService::SourceDataGetImage(nsITransferable* aItem,
void nsDragSession::SourceDataGetImage(nsITransferable* aItem,
GtkSelectionData* aSelectionData) {
LOGDRAGSERVICE("nsDragService::SourceDataGetImage()");
LOGDRAGSERVICE("nsDragSession::SourceDataGetImage()");
nsresult rv;
nsCOMPtr<nsISupports> data;
@ -2106,10 +2104,10 @@ void nsDragService::SourceDataGetImage(nsITransferable* aItem,
return;
}
void nsDragService::SourceDataGetXDND(nsITransferable* aItem,
void nsDragSession::SourceDataGetXDND(nsITransferable* aItem,
GdkDragContext* aContext,
GtkSelectionData* aSelectionData) {
LOGDRAGSERVICE("nsDragService::SourceDataGetXDND");
LOGDRAGSERVICE("nsDragSession::SourceDataGetXDND");
// Indicate failure by default.
GdkAtom target = gtk_selection_data_get_target(aSelectionData);
@ -2200,11 +2198,11 @@ void nsDragService::SourceDataGetXDND(nsITransferable* aItem,
return;
}
bool nsDragService::SourceDataGetText(nsITransferable* aItem,
bool nsDragSession::SourceDataGetText(nsITransferable* aItem,
const nsACString& aMIMEType,
bool aNeedToDoConversionToPlainText,
GtkSelectionData* aSelectionData) {
LOGDRAGSERVICE("nsDragService::SourceDataGetPlain()");
LOGDRAGSERVICE("nsDragSession::SourceDataGetPlain()");
nsresult rv;
nsCOMPtr<nsISupports> data;
@ -2248,11 +2246,11 @@ bool nsDragService::SourceDataGetText(nsITransferable* aItem,
// GtkSelectionData (Gtk D&D interface).
// We need to check mSourceDataItems data type and try to convert it
// to data type accepted by Gtk.
void nsDragService::SourceDataGet(GtkWidget* aWidget, GdkDragContext* aContext,
void nsDragSession::SourceDataGet(GtkWidget* aWidget, GdkDragContext* aContext,
GtkSelectionData* aSelectionData,
guint32 aTime) {
GdkAtom requestedFlavor = gtk_selection_data_get_target(aSelectionData);
LOGDRAGSERVICE("nsDragService::SourceDataGet(%p) MIME %s", aContext,
LOGDRAGSERVICE("nsDragSession::SourceDataGet(%p) MIME %s", aContext,
GUniquePtr<gchar>(gdk_atom_name(requestedFlavor)).get());
// check to make sure that we have data items to return.
@ -2321,8 +2319,8 @@ void nsDragService::SourceDataGet(GtkWidget* aWidget, GdkDragContext* aContext,
/* aNeedToDoConversionToPlainText */ false, aSelectionData);
}
void nsDragService::SourceBeginDrag(GdkDragContext* aContext) {
LOGDRAGSERVICE("nsDragService::SourceBeginDrag(%p)\n", aContext);
void nsDragSession::SourceBeginDrag(GdkDragContext* aContext) {
LOGDRAGSERVICE("nsDragSession::SourceBeginDrag(%p)\n", aContext);
nsCOMPtr<nsITransferable> transferable =
do_QueryElementAt(mSourceDataItems, 0);
@ -2364,10 +2362,10 @@ void nsDragService::SourceBeginDrag(GdkDragContext* aContext) {
}
}
void nsDragService::SetDragIcon(GdkDragContext* aContext) {
void nsDragSession::SetDragIcon(GdkDragContext* aContext) {
if (!mHasImage && !mSelection) return;
LOGDRAGSERVICE("nsDragService::SetDragIcon(%p)", aContext);
LOGDRAGSERVICE("nsDragSession::SetDragIcon(%p)", aContext);
LayoutDeviceIntRect dragRect;
nsPresContext* pc;
@ -2445,10 +2443,10 @@ void nsDragService::SetDragIcon(GdkDragContext* aContext) {
static void invisibleSourceDragBegin(GtkWidget* aWidget,
GdkDragContext* aContext, gpointer aData) {
LOGDRAGSERVICESTATIC("invisibleSourceDragBegin (%p)", aContext);
nsDragService* dragService = (nsDragService*)aData;
nsDragSession* dragSession = (nsDragSession*)aData;
dragService->SourceBeginDrag(aContext);
dragService->SetDragIcon(aContext);
dragSession->SourceBeginDrag(aContext);
dragSession->SetDragIcon(aContext);
}
static void invisibleSourceDragDataGet(GtkWidget* aWidget,
@ -2457,15 +2455,13 @@ static void invisibleSourceDragDataGet(GtkWidget* aWidget,
guint aInfo, guint32 aTime,
gpointer aData) {
LOGDRAGSERVICESTATIC("invisibleSourceDragDataGet (%p)", aContext);
nsDragService* dragService = (nsDragService*)aData;
dragService->SourceDataGet(aWidget, aContext, aSelectionData, aTime);
nsDragSession* dragSession = (nsDragSession*)aData;
dragSession->SourceDataGet(aWidget, aContext, aSelectionData, aTime);
}
static gboolean invisibleSourceDragFailed(GtkWidget* aWidget,
GdkDragContext* aContext,
gint aResult, gpointer aData) {
nsDragService* dragService = (nsDragService*)aData;
// Wayland and X11 uses different drag results here. When drag target is
// missing X11 passes GDK_DRAG_CANCEL_NO_TARGET
// (from gdk_dnd_handle_button_event()/gdkdnd-x11.c)
@ -2482,10 +2478,11 @@ static gboolean invisibleSourceDragFailed(GtkWidget* aWidget,
LOGDRAGSERVICESTATIC("invisibleSourceDragFailed(%p) %s", aContext,
kGtkDragResults[aResult]);
nsDragSession* dragSession = (nsDragSession*)aData;
// End the drag session now (rather than waiting for the drag-end signal)
// so that operations performed on dropEffect == none can start immediately
// rather than waiting for the drag-failed animation to finish.
dragService->SourceEndDragSession(aContext, aResult);
dragSession->SourceEndDragSession(aContext, aResult);
// We should return TRUE to disable the drag-failed animation iff the
// source performed an operation when dropEffect was none, but the handler
@ -2496,10 +2493,10 @@ static gboolean invisibleSourceDragFailed(GtkWidget* aWidget,
static void invisibleSourceDragEnd(GtkWidget* aWidget, GdkDragContext* aContext,
gpointer aData) {
LOGDRAGSERVICESTATIC("invisibleSourceDragEnd(%p)", aContext);
nsDragService* dragService = (nsDragService*)aData;
nsDragSession* dragSession = (nsDragSession*)aData;
// The drag has ended. Release the hostages!
dragService->SourceEndDragSession(aContext, GTK_DRAG_RESULT_SUCCESS);
dragSession->SourceEndDragSession(aContext, GTK_DRAG_RESULT_SUCCESS);
}
// The following methods handle responding to GTK drag signals and
@ -2543,7 +2540,7 @@ static void invisibleSourceDragEnd(GtkWidget* aWidget, GdkDragContext* aContext,
// Gecko drag events are in flight. This helps event handlers that may not
// expect nested events, while accessing an event's dataTransfer for example.
gboolean nsDragService::ScheduleMotionEvent(nsWindow* aWindow,
gboolean nsDragSession::ScheduleMotionEvent(nsWindow* aWindow,
GdkDragContext* aDragContext,
LayoutDeviceIntPoint aWindowPoint,
guint aTime) {
@ -2561,7 +2558,7 @@ gboolean nsDragService::ScheduleMotionEvent(nsWindow* aWindow,
return Schedule(eDragTaskMotion, aWindow, aDragContext, aWindowPoint, aTime);
}
void nsDragService::ScheduleLeaveEvent() {
void nsDragSession::ScheduleLeaveEvent() {
// We don't know at this stage whether a drop signal will immediately
// follow. If the drop signal gets sent it will happen before we return
// to the main loop and the scheduled leave task will be replaced.
@ -2570,7 +2567,7 @@ void nsDragService::ScheduleLeaveEvent() {
}
}
gboolean nsDragService::ScheduleDropEvent(nsWindow* aWindow,
gboolean nsDragSession::ScheduleDropEvent(nsWindow* aWindow,
GdkDragContext* aDragContext,
LayoutDeviceIntPoint aWindowPoint,
guint aTime) {
@ -2579,17 +2576,14 @@ gboolean nsDragService::ScheduleDropEvent(nsWindow* aWindow,
return FALSE;
}
nsCOMPtr<nsIDragSession> session = GetCurrentSession(aWindow);
if (session) {
session->SetDragEndPoint(aWindowPoint.x, aWindowPoint.y);
}
SetDragEndPoint(aWindowPoint.x, aWindowPoint.y);
// We'll reply with gtk_drag_finish().
return TRUE;
}
#ifdef MOZ_LOGGING
const char* nsDragService::GetDragServiceTaskName(DragTask aTask) {
const char* nsDragSession::GetDragServiceTaskName(DragTask aTask) {
static const char* taskNames[] = {"eDragTaskNone", "eDragTaskMotion",
"eDragTaskLeave", "eDragTaskDrop",
"eDragTaskSourceEnd"};
@ -2598,7 +2592,7 @@ const char* nsDragService::GetDragServiceTaskName(DragTask aTask) {
}
#endif
gboolean nsDragService::Schedule(DragTask aTask, nsWindow* aWindow,
gboolean nsDragSession::Schedule(DragTask aTask, nsWindow* aWindow,
GdkDragContext* aDragContext,
LayoutDeviceIntPoint aWindowPoint,
guint aTime) {
@ -2611,7 +2605,7 @@ gboolean nsDragService::Schedule(DragTask aTask, nsWindow* aWindow,
// within the allowed time). Otherwise, if we haven't yet run a scheduled
// drop or end task, just say that we are not ready to receive another
// drop.
LOGDRAGSERVICE("nsDragService::Schedule(%p) task %s window %p\n",
LOGDRAGSERVICE("nsDragSession::Schedule(%p) task %s window %p\n",
aDragContext, GetDragServiceTaskName(aTask), aWindow);
if (mScheduledTask == eDragTaskSourceEnd ||
@ -2632,7 +2626,7 @@ gboolean nsDragService::Schedule(DragTask aTask, nsWindow* aWindow,
// right after drag_motion event handler which is called by Gtk.
// An ideal scenario is to call TaskDispatchCallback() directly here
// but we can't do that. TaskDispatchCallback() spins gtk event loop
// while nsDragService::Schedule() is already called from event loop
// while nsDragSession::Schedule() is already called from event loop
// (by drag_motion* gtk_widget events) so that direct call will cause
// nested recursion.
mTaskSource = g_timeout_add_full(G_PRIORITY_HIGH, 0, TaskDispatchCallback,
@ -2649,15 +2643,17 @@ gboolean nsDragService::Schedule(DragTask aTask, nsWindow* aWindow,
return TRUE;
}
gboolean nsDragService::TaskDispatchCallback(gpointer data) {
RefPtr<nsDragService> dragService = static_cast<nsDragService*>(data);
AutoEventLoop loop(dragService);
return dragService->RunScheduledTask();
gboolean nsDragSession::TaskDispatchCallback(gpointer data) {
// Make sure we hold a strong reference to the session while we process
// the task.
RefPtr<nsDragSession> dragSession = static_cast<nsDragSession*>(data);
AutoEventLoop loop(dragSession);
return dragSession->RunScheduledTask();
}
gboolean nsDragService::RunScheduledTask() {
gboolean nsDragSession::RunScheduledTask() {
LOGDRAGSERVICE(
"nsDragService::RunScheduledTask() task %s mTargetWindow %p "
"nsDragSession::RunScheduledTask() task %s mTargetWindow %p "
"mPendingWindow %p\n",
GetDragServiceTaskName(mScheduledTask), mTargetWindow.get(),
mPendingWindow.get());
@ -2679,10 +2675,7 @@ gboolean nsDragService::RunScheduledTask() {
// The drag that was initiated in a different app. End the drag
// session, since we're done with it for now (until the user drags
// back into this app).
RefPtr<nsIDragSession> session = GetCurrentSession(mTargetWindow);
if (session) {
session->EndDragSession(false, GetCurrentModifiers());
}
EndDragSession(false, GetCurrentModifiers());
}
}
@ -2704,10 +2697,7 @@ gboolean nsDragService::RunScheduledTask() {
LOGDRAGSERVICE(" quit, selected task %s\n", GetDragServiceTaskName(task));
if (task == eDragTaskSourceEnd) {
// Dispatch drag end events.
RefPtr<nsIDragSession> session = GetCurrentSession(mTargetWindow);
if (session) {
session->EndDragSession(true, GetCurrentModifiers());
}
EndDragSession(true, GetCurrentModifiers());
}
// Nothing more to do
@ -2716,10 +2706,6 @@ gboolean nsDragService::RunScheduledTask() {
return FALSE;
}
// This may be the start of a destination drag session.
nsIWidget* targetWidget = mTargetWindow;
StartDragSession(targetWidget);
// mTargetWidget may be nullptr if the window has been destroyed.
// (The leave event is not scheduled if a drop task is still scheduled.)
// We still reply appropriately to indicate that the drop will or didn't
@ -2786,10 +2772,7 @@ gboolean nsDragService::RunScheduledTask() {
}
// Make sure to end the drag session. If this drag started in a
// different app, we won't get a drag_end signal to end it from.
RefPtr<nsIDragSession> session = GetCurrentSession(mTargetWindow);
if (session) {
session->EndDragSession(true, GetCurrentModifiers());
}
EndDragSession(true, GetCurrentModifiers());
}
// We're done with the drag context.
@ -2813,14 +2796,14 @@ gboolean nsDragService::RunScheduledTask() {
// drag context. Gtk gets this from a combination of the key settings
// and what the source is offering.
void nsDragService::UpdateDragAction(GdkDragContext* aDragContext) {
void nsDragSession::UpdateDragAction(GdkDragContext* aDragContext) {
// This doesn't look right. dragSession.dragAction is used by
// nsContentUtils::SetDataTransferInEvent() to set the initial
// dataTransfer.dropEffect, so GdkDragContext::suggested_action would be
// more appropriate. GdkDragContext::actions should be used to set
// dataTransfer.effectAllowed, which doesn't currently happen with
// external sources.
LOGDRAGSERVICE("nsDragService::UpdateDragAction(%p)", aDragContext);
LOGDRAGSERVICE("nsDragSession::UpdateDragAction(%p)", aDragContext);
// default is to do nothing
int action = nsIDragService::DRAGDROP_ACTION_NONE;
@ -2836,7 +2819,7 @@ void nsDragService::UpdateDragAction(GdkDragContext* aDragContext) {
// So we need to call gdk_drag_context_get_selected_action() on Wayland
// to get potential D&D modifier.
// gdk_drag_context_get_selected_action() is also affected by
// gdk_drag_status(), see nsDragService::ReplyToDragMotion().
// gdk_drag_status(), see nsDragSession::ReplyToDragMotion().
if (widget::GdkIsWaylandDisplay()) {
GdkDragAction gdkActionSelected =
gdk_drag_context_get_selected_action(aDragContext);
@ -2871,7 +2854,7 @@ void nsDragService::UpdateDragAction(GdkDragContext* aDragContext) {
SetDragAction(action);
}
void nsDragService::UpdateDragAction() { UpdateDragAction(mTargetDragContext); }
void nsDragSession::UpdateDragAction() { UpdateDragAction(mTargetDragContext); }
NS_IMETHODIMP
nsDragSession::UpdateDragEffect() {
@ -2889,12 +2872,9 @@ void nsDragSession::ReplyToDragMotion() {
}
}
void nsDragService::DispatchMotionEvents() {
void nsDragSession::DispatchMotionEvents() {
if (mSourceWindow) {
RefPtr<nsIDragSession> session = GetCurrentSession(mSourceWindow);
if (session) {
session->FireDragEventAtSource(eDrag, GetCurrentModifiers());
}
FireDragEventAtSource(eDrag, GetCurrentModifiers());
}
if (mTargetWindow) {
mTargetWindow->DispatchDragEvent(eDragOver, mTargetWindowPoint,
@ -2903,7 +2883,7 @@ void nsDragService::DispatchMotionEvents() {
}
// Returns true if the drop was successful
gboolean nsDragService::DispatchDropEvent() {
gboolean nsDragSession::DispatchDropEvent() {
// We need to check IsDestroyed here because the nsRefPtr
// only protects this from being deleted, it does NOT protect
// against nsView::~nsView() calling Destroy() on it, bug 378273.
@ -2919,7 +2899,7 @@ gboolean nsDragService::DispatchDropEvent() {
}
/* static */
uint32_t nsDragService::GetCurrentModifiers() {
uint32_t nsDragSession::GetCurrentModifiers() {
return mozilla::widget::KeymapWrapper::ComputeCurrentKeyModifiers();
}

Просмотреть файл

@ -87,11 +87,14 @@ class DragData final {
nsTArray<nsString> mUris;
};
// Temporary inheritance from nsBaseDragService instead of nsBaseDragSession
// (which nsBaseDragService temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragSession : public nsBaseDragService {
/**
* GTK native nsIDragSession implementation
*/
class nsDragSession : public nsBaseDragSession, public nsIObserver {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
// nsIDragSession
NS_IMETHOD SetCanDrop(bool aCanDrop) override;
NS_IMETHOD GetCanDrop(bool* aCanDrop) override;
@ -109,6 +112,7 @@ class nsDragSession : public nsBaseDragService {
MOZ_CAN_RUN_SCRIPT nsresult EndDragSessionImpl(
bool aDoneDrag, uint32_t aKeyModifiers) override;
class AutoEventLoop {
RefPtr<nsDragSession> mSession;
@ -123,8 +127,6 @@ class nsDragSession : public nsBaseDragService {
static int GetLoopDepth() { return sEventLoopDepth; };
protected:
virtual ~nsDragSession() = default;
// mScheduledTask indicates what signal has been received from GTK and
// so what needs to be dispatched when the scheduled task is run. It is
// eDragTaskNone when there is no task scheduled (but the
@ -259,37 +261,25 @@ class nsDragSession : public nsBaseDragService {
static GdkAtom sFilePromiseURLMimeAtom;
static GdkAtom sFilePromiseMimeAtom;
static GdkAtom sNativeImageMimeAtom;
};
// Temporary inheritance from nsDragSession instead of nsBaseDragService
// (which nsDragSession temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragService final : public nsDragSession, public nsIObserver {
public:
nsDragService();
nsDragSession();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
// nsBaseDragService
// nsBaseDragSession
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
// nsIDragService
// nsIDragSession
MOZ_CAN_RUN_SCRIPT NS_IMETHOD InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* anArrayTransferables, uint32_t aActionType,
nsContentPolicyType aContentPolicyType) override;
NS_IMETHOD StartDragSession(nsISupports* aWidgetProvider) override;
// Methods called from nsWindow to handle responding to GTK drag
// destination signals
static already_AddRefed<nsDragService> GetInstance();
void TargetDataReceived(GtkWidget* aWidget, GdkDragContext* aContext, gint aX,
gint aY, GtkSelectionData* aSelection_data,
guint aInfo, guint32 aTime);
@ -334,7 +324,7 @@ class nsDragService final : public nsDragSession, public nsIObserver {
void SetDragIcon(GdkDragContext* aContext);
protected:
virtual ~nsDragService();
virtual ~nsDragSession();
private:
// target/destination side vars
@ -370,8 +360,9 @@ class nsDragService final : public nsDragSession, public nsIObserver {
// attempts to create a semi-transparent drag image. Returns TRUE if
// successful, FALSE if not
bool SetAlphaPixmap(SourceSurface* aPixbuf, GdkDragContext* aContext,
int32_t aXOffset, int32_t aYOffset,
bool SetAlphaPixmap(mozilla::gfx::SourceSurface* aPixbuf,
GdkDragContext* aContext, int32_t aXOffset,
int32_t aYOffset,
const mozilla::LayoutDeviceIntRect& dragRect);
gboolean Schedule(DragTask aTask, nsWindow* aWindow,
@ -386,7 +377,7 @@ class nsDragService final : public nsDragSession, public nsIObserver {
void UpdateDragAction();
#ifdef MOZ_LOGGING
const char* GetDragServiceTaskName(nsDragService::DragTask aTask);
const char* GetDragServiceTaskName(DragTask aTask);
#endif
gboolean DispatchDropEvent();
static uint32_t GetCurrentModifiers();
@ -394,4 +385,16 @@ class nsDragService final : public nsDragSession, public nsIObserver {
nsresult CreateTempFile(nsITransferable* aItem, nsACString& aURI);
};
/**
* Native GTK nsIDragService implementation
*/
class nsDragService : public nsBaseDragService {
public:
static already_AddRefed<nsDragService> GetInstance();
NS_IMETHOD StartDragSession(nsISupports* aWidgetProvider) override;
protected:
already_AddRefed<nsIDragSession> CreateDragSession() override;
};
#endif // nsDragService_h__

Просмотреть файл

@ -591,10 +591,14 @@ void nsWindow::Destroy() {
UnlockNativePointer();
#endif
// dragService will be null after shutdown of the service manager.
// Cancel (dragleave) the current drag session, if any.
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
if (dragService && this == dragService->GetMostRecentDestWindow()) {
dragService->ScheduleLeaveEvent();
if (dragService) {
nsDragSession* dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(this));
if (dragSession && this == dragSession->GetMostRecentDestWindow()) {
dragSession->ScheduleLeaveEvent();
}
}
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
@ -5465,9 +5469,13 @@ void nsWindow::OnDragDataReceivedEvent(GtkWidget* aWidget,
LOGDRAG("nsWindow::OnDragDataReceived");
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
nsDragService::AutoEventLoop loop(dragService);
dragService->TargetDataReceived(aWidget, aDragContext, aX, aY, aSelectionData,
aInfo, aTime);
nsDragSession* dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(this));
if (dragSession) {
nsDragSession::AutoEventLoop loop(dragSession);
dragSession->TargetDataReceived(aWidget, aDragContext, aX, aY, aSelectionData,
aInfo, aTime);
}
}
nsWindow* nsWindow::GetTransientForWindowIfPopup() {
@ -8704,8 +8712,20 @@ gboolean WindowDragMotionHandler(GtkWidget* aWidget,
LOGDRAG("WindowDragMotionHandler target nsWindow [%p]", window.get());
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
nsDragService::AutoEventLoop loop(dragService);
if (!dragService->ScheduleMotionEvent(
NS_ENSURE_TRUE(dragService, FALSE);
nsDragSession* dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(window));
if (!dragSession) {
// This may be the start of an external drag session.
nsIWidget* widget = window;
static_cast<nsDragSession*>(dragService->StartDragSession(widget));
dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(window));
}
NS_ENSURE_TRUE(dragSession, FALSE);
nsDragSession::AutoEventLoop loop(dragSession);
if (!dragSession->ScheduleMotionEvent(
window, aDragContext, GetWindowDropPosition(window, aX, aY), aTime)) {
return FALSE;
}
@ -8728,9 +8748,17 @@ void WindowDragLeaveHandler(GtkWidget* aWidget) {
}
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
nsDragService::AutoEventLoop loop(dragService);
nsIWidget* widget = window;
nsDragSession* dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(widget));
if (!dragSession) {
LOGDRAG(" Received dragleave after drag had ended.\n");
return;
}
nsWindow* mostRecentDragWindow = dragService->GetMostRecentDestWindow();
nsDragSession::AutoEventLoop loop(dragSession);
nsWindow* mostRecentDragWindow = dragSession->GetMostRecentDestWindow();
if (!mostRecentDragWindow) {
// This can happen when the target will not accept a drop. A GTK drag
// source sends the leave message to the destination before the
@ -8750,7 +8778,7 @@ void WindowDragLeaveHandler(GtkWidget* aWidget) {
}
LOGDRAG("WindowDragLeaveHandler nsWindow %p\n", (void*)mostRecentDragWindow);
dragService->ScheduleLeaveEvent();
dragSession->ScheduleLeaveEvent();
}
static void drag_leave_event_cb(GtkWidget* aWidget,
@ -8778,8 +8806,10 @@ gboolean WindowDragDropHandler(GtkWidget* aWidget, GdkDragContext* aDragContext,
LOGDRAG("WindowDragDropHandler nsWindow [%p]", window.get());
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
nsDragService::AutoEventLoop loop(dragService);
return dragService->ScheduleDropEvent(
nsDragSession* dragSession =
static_cast<nsDragSession*>(dragService->GetCurrentSession(window));
nsDragSession::AutoEventLoop loop(dragSession);
return dragSession->ScheduleDropEvent(
window, aDragContext, GetWindowDropPosition(window, aX, aY), aTime);
}

Просмотреть файл

@ -153,6 +153,7 @@ EXPORTS += [
"nsBaseDragService.h",
"nsBaseFilePicker.h",
"nsBaseWidget.h",
"nsDragServiceProxy.h",
"nsIDeviceContextSpec.h",
"nsIRollupListener.h",
"nsIWidget.h",

Просмотреть файл

@ -72,20 +72,22 @@ uint32_t GetSuppressLevel() {
return static_cast<nsBaseDragService*>(svc.get())->GetSuppressLevel();
}
nsBaseDragService::nsBaseDragService()
: mContentPolicyType(nsIContentPolicy::TYPE_OTHER),
mSuppressLevel(0) {}
nsBaseDragService::nsBaseDragService() = default;
nsBaseDragService::~nsBaseDragService() = default;
NS_IMPL_ISUPPORTS(nsBaseDragService, nsIDragService, nsIDragSession)
nsBaseDragSession::nsBaseDragSession() {
TakeSessionBrowserListFromService();
}
nsBaseDragSession::~nsBaseDragSession() = default;
NS_IMPL_ISUPPORTS(nsBaseDragService, nsIDragService)
NS_IMPL_ISUPPORTS(nsBaseDragSession, nsIDragSession)
NS_IMETHODIMP nsBaseDragService::GetIsMockService(bool* aRet) {
*aRet = false;
return NS_OK;
}
//---------------------------------------------------------
NS_IMETHODIMP
nsBaseDragSession::SetCanDrop(bool aCanDrop) {
@ -309,7 +311,7 @@ NS_IMETHODIMP nsBaseDragSession::SetDragEndPointForTests(int32_t aScreenX,
}
//-------------------------------------------------------------------------
nsresult nsBaseDragService::InvokeDragSession(
nsresult nsBaseDragSession::InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
@ -317,7 +319,6 @@ nsresult nsBaseDragService::InvokeDragSession(
AUTO_PROFILER_LABEL("nsBaseDragService::InvokeDragSession", OTHER);
NS_ENSURE_TRUE(aDOMNode, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
// stash the document of the dom node
mSourceDocument = aDOMNode->OwnerDoc();
@ -353,8 +354,11 @@ nsresult nsBaseDragService::InvokeDragSession(
//
// The best way to avoid this is to use the mock service in tests. See
// synthesizeMockDragAndDrop.
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
MOZ_ASSERT(dragService);
MOZ_ASSERT(
!xpc::IsInAutomation() || IsMockService(),
!xpc::IsInAutomation() || dragService->IsMockService(),
"About to start drag-drop native loop on which will prevent later "
"tests from running properly.");
}
@ -395,10 +399,7 @@ nsresult nsBaseDragService::InvokeDragSession(
// Set mDoingDrag so that EndDragSession cleans up and sends the dragend
// event after the aborted drag.
mDoingDrag = true;
RefPtr<nsIDragSession> session = GetCurrentSession(aWidget);
if (session) {
session->EndDragSession(true, 0);
}
EndDragSession(true, 0);
}
return rv;
@ -418,9 +419,27 @@ nsBaseDragService::InvokeDragSessionWithImage(
NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
mSessionIsSynthesizedForTests =
RefPtr<nsBaseDragSession> session =
CreateDragSession().downcast<nsBaseDragSession>();
if (XRE_IsParentProcess()) {
mCurrentParentDragSession = session;
}
bool isSynthesized =
aDragEvent->WidgetEventPtr()->mFlags.mIsSynthesizedForTests &&
!GetNeverAllowSessionIsSynthesizedForTests();
return session->InitWithImage(widget, aDOMNode, aPrincipal, aCsp,
aCookieJarSettings, aTransferableArray,
aActionType, aImage, aImageX, aImageY,
aDragEvent, aDataTransfer, isSynthesized);
}
nsresult nsBaseDragSession::InitWithImage(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType, nsINode* aImage,
int32_t aImageX, int32_t aImageY, DragEvent* aDragEvent,
DataTransfer* aDataTransfer, bool aIsSynthesizedForTests) {
mSessionIsSynthesizedForTests = aIsSynthesizedForTests;
mDataTransfer = aDataTransfer;
mSelection = nullptr;
mHasImage = true;
@ -454,7 +473,7 @@ nsBaseDragService::InvokeDragSessionWithImage(
}
nsresult rv = InvokeDragSession(
widget, aDOMNode, aPrincipal, aCsp, aCookieJarSettings,
aWidget, aDOMNode, aPrincipal, aCsp, aCookieJarSettings,
aTransferableArray, aActionType, nsIContentPolicy::TYPE_INTERNAL_IMAGE);
mRegion = Nothing();
return rv;
@ -474,9 +493,27 @@ nsBaseDragService::InvokeDragSessionWithRemoteImage(
NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
mSessionIsSynthesizedForTests =
RefPtr<nsBaseDragSession> session =
CreateDragSession().downcast<nsBaseDragSession>();
if (XRE_IsParentProcess()) {
mCurrentParentDragSession = session;
}
bool isSynthesized =
aDragEvent->WidgetEventPtr()->mFlags.mIsSynthesizedForTests &&
!GetNeverAllowSessionIsSynthesizedForTests();
return session->InitWithRemoteImage(widget, aDOMNode, aPrincipal, aCsp,
aCookieJarSettings, aTransferableArray,
aActionType, aDragStartData, aDragEvent,
aDataTransfer, isSynthesized);
}
nsresult nsBaseDragSession::InitWithRemoteImage(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
RemoteDragStartData* aDragStartData, DragEvent* aDragEvent,
DataTransfer* aDataTransfer, bool aIsSynthesizedForTests) {
mSessionIsSynthesizedForTests = aIsSynthesizedForTests;
mDataTransfer = aDataTransfer;
mSelection = nullptr;
mHasImage = true;
@ -491,7 +528,7 @@ nsBaseDragService::InvokeDragSessionWithRemoteImage(
mInputSource = aDragEvent->InputSource(CallerType::System);
nsresult rv = InvokeDragSession(
widget, aDOMNode, aPrincipal, aCsp, aCookieJarSettings,
aWidget, aDOMNode, aPrincipal, aCsp, aCookieJarSettings,
aTransferableArray, aActionType, nsIContentPolicy::TYPE_INTERNAL_IMAGE);
mRegion = Nothing();
return rv;
@ -511,9 +548,26 @@ nsBaseDragService::InvokeDragSessionWithSelection(
NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
mSessionIsSynthesizedForTests =
RefPtr<nsBaseDragSession> session =
CreateDragSession().downcast<nsBaseDragSession>();
if (XRE_IsParentProcess()) {
mCurrentParentDragSession = session;
}
bool isSynthesized =
aDragEvent->WidgetEventPtr()->mFlags.mIsSynthesizedForTests &&
!GetNeverAllowSessionIsSynthesizedForTests();
return session->InitWithSelection(widget, aSelection, aPrincipal, aCsp,
aCookieJarSettings, aTransferableArray,
aActionType, aDragEvent, aDataTransfer,
isSynthesized);
}
nsresult nsBaseDragSession::InitWithSelection(
nsIWidget* aWidget, Selection* aSelection, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType, DragEvent* aDragEvent,
DataTransfer* aDataTransfer, bool aIsSynthesizedForTests) {
mSessionIsSynthesizedForTests = aIsSynthesizedForTests;
mDataTransfer = aDataTransfer;
mSelection = aSelection;
mHasImage = true;
@ -535,7 +589,7 @@ nsBaseDragService::InvokeDragSessionWithSelection(
mSourceTopWindowContext =
mSourceWindowContext ? mSourceWindowContext->TopWindowContext() : nullptr;
return InvokeDragSession(widget, node, aPrincipal, aCsp, aCookieJarSettings,
return InvokeDragSession(aWidget, node, aPrincipal, aCsp, aCookieJarSettings,
aTransferableArray, aActionType,
nsIContentPolicy::TYPE_OTHER);
}
@ -544,15 +598,17 @@ nsBaseDragService::InvokeDragSessionWithSelection(
NS_IMETHODIMP
nsBaseDragService::GetCurrentSession(nsISupports* aWidgetProvider,
nsIDragSession** aSession) {
if (!aSession) return NS_ERROR_INVALID_ARG;
MOZ_ASSERT(XRE_IsParentProcess());
if (!aSession) {
return NS_ERROR_INVALID_ARG;
}
// "this" also implements a drag session, so say we are one but only
// if there is currently a drag going on.
if (!mSuppressLevel && mDoingDrag) {
*aSession = this;
NS_ADDREF(*aSession); // addRef because we're a "getter"
} else
if (!mSuppressLevel && mCurrentParentDragSession) {
RefPtr<nsIDragSession> session = mCurrentParentDragSession;
session.forget(aSession);
} else {
*aSession = nullptr;
}
return NS_OK;
}
@ -560,16 +616,26 @@ nsBaseDragService::GetCurrentSession(nsISupports* aWidgetProvider,
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsBaseDragService::StartDragSession(nsISupports* aWidgetProvider) {
MOZ_ASSERT(XRE_IsParentProcess());
if (!aWidgetProvider) {
return NS_ERROR_NULL_POINTER;
}
if (mDoingDrag) {
return NS_ERROR_FAILURE;
if (mCurrentParentDragSession) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mDoingDrag = true;
// By default dispatch drop also to content.
mOnlyChromeDrop = false;
RefPtr<nsIDragSession> session = CreateDragSession();
if (XRE_IsParentProcess()) {
mCurrentParentDragSession = session;
}
return NS_OK;
}
NS_IMETHODIMP
nsBaseDragSession::InitForTests(uint32_t aAllowedEffect) {
mDragAction = aAllowedEffect;
mEffectAllowedForTests = aAllowedEffect;
mSessionIsSynthesizedForTests = true;
return NS_OK;
}
@ -578,12 +644,13 @@ NS_IMETHODIMP nsBaseDragService::StartDragSessionForTests(
// This method must set mSessionIsSynthesizedForTests
MOZ_ASSERT(!mNeverAllowSessionIsSynthesizedForTests);
if (NS_WARN_IF(NS_FAILED(StartDragSession(aWidgetProvider)))) {
return NS_ERROR_FAILURE;
}
mDragAction = aAllowedEffect;
mEffectAllowedForTests = aAllowedEffect;
mSessionIsSynthesizedForTests = true;
nsresult rv = StartDragSession(aWidgetProvider);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDragSession> session;
GetCurrentSession(aWidgetProvider, getter_AddRefs(session));
MOZ_ASSERT(session);
session->InitForTests(aAllowedEffect);
return NS_OK;
}
@ -660,6 +727,11 @@ nsresult nsBaseDragSession::EndDragSessionImpl(bool aDoneDrag,
// CC to reclaim the memory.
if (XRE_IsParentProcess()) {
DiscardInternalTransferData();
nsCOMPtr<nsIDragService> svc =
do_GetService("@mozilla.org/widget/dragservice;1");
if (svc) {
static_cast<nsBaseDragService*>(svc.get())->ClearCurrentParentDragSession();
}
}
mDoingDrag = false;
@ -788,7 +860,7 @@ static PresShell* GetPresShellForContent(nsINode* aDOMNode) {
return nullptr;
}
nsresult nsBaseDragService::DrawDrag(nsINode* aDOMNode,
nsresult nsBaseDragSession::DrawDrag(nsINode* aDOMNode,
const Maybe<CSSIntRegion>& aRegion,
CSSIntPoint aScreenPosition,
LayoutDeviceIntRect* aScreenDragRect,
@ -940,7 +1012,7 @@ nsresult nsBaseDragService::DrawDrag(nsINode* aDOMNode,
return NS_OK;
}
nsresult nsBaseDragService::DrawDragForImage(
nsresult nsBaseDragSession::DrawDragForImage(
nsPresContext* aPresContext, nsIImageLoadingContent* aImageLoader,
HTMLCanvasElement* aCanvas, LayoutDeviceIntRect* aScreenDragRect,
RefPtr<SourceSurface>* aSurface) {
@ -1005,7 +1077,10 @@ nsresult nsBaseDragService::DrawDragForImage(
NS_IMETHODIMP
nsBaseDragService::Suppress() {
EndDragSession(false, 0);
RefPtr<nsIDragSession> session = mCurrentParentDragSession;
if (session) {
session->EndDragSession(false, 0);
}
++mSuppressLevel;
return NS_OK;
}
@ -1075,28 +1150,20 @@ static bool RemoveAllBrowsers(nsTArray<nsWeakPtr>& aBrowsers) {
}
bool nsBaseDragService::MaybeAddBrowser(BrowserParent* aBP) {
/*
// TODO: until nsBaseDragService and nsBaseDragSession separate
// (part 21), they automatically share mBrowsers, so skip this.
nsCOMPtr<nsIDragSession> session;
GetCurrentSession(nullptr, getter_AddRefs(session));
if (session) {
return session->MaybeAddBrowser(aBP);
}
*/
return ::MaybeAddBrowser(mBrowsers, aBP);
}
bool nsBaseDragService::RemoveAllBrowsers() {
/*
// TODO: until nsBaseDragService and nsBaseDragSession separate
// (part 21), they automatically share mBrowsers, so skip this.
nsCOMPtr<nsIDragSession> session;
GetCurrentSession(nullptr, getter_AddRefs(session));
if (session) {
return session->RemoveAllBrowsers();
}
*/
return ::RemoveAllBrowsers(mBrowsers);
}
@ -1172,3 +1239,33 @@ void nsBaseDragSession::TakeSessionBrowserListFromService() {
NS_ENSURE_TRUE_VOID(svc);
mBrowsers = static_cast<nsBaseDragService*>(svc.get())->TakeSessionBrowserList();
}
/* static */
nsIWidget* nsBaseDragService::GetWidgetFromWidgetProvider(nsISupports* aWidgetProvider) {
nsCOMPtr<nsIWidget> widget = do_QueryObject(aWidgetProvider);
if (widget) {
return widget;
}
nsPIDOMWindowOuter* outer;
if (aWidgetProvider) {
nsCOMPtr<mozIDOMWindow> window = do_GetInterface(aWidgetProvider);
NS_ENSURE_TRUE(window, nullptr);
RefPtr<nsPIDOMWindowInner> innerWin = nsGlobalWindowInner::Cast(window);
NS_ENSURE_TRUE(innerWin, nullptr);
outer = innerWin->GetOuterWindow();
} else {
nsCOMPtr<nsPIDOMWindowInner> winInner;
winInner = do_QueryInterface(GetEntryGlobal());
NS_ENSURE_TRUE(winInner, nullptr);
outer = winInner->GetOuterWindow();
}
NS_ENSURE_TRUE(outer, nullptr);
nsIDocShell* docShell = outer->GetDocShell();
NS_ENSURE_TRUE(docShell, nullptr);
PresShell* presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, nullptr);
nsViewManager* vm = presShell->GetViewManager();
NS_ENSURE_TRUE(vm, nullptr);
return vm->GetRootWidget();
}

Просмотреть файл

@ -56,6 +56,7 @@ class MockDragServiceController;
*/
class nsBaseDragSession : public nsIDragSession {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDRAGSESSION
int32_t TakeChildProcessDragAction();
@ -68,9 +69,106 @@ class nsBaseDragSession : public nsIDragSession {
mEndDragPoint = aEndDragPoint;
}
uint16_t GetInputSource() { return mInputSource; }
// The nsIDragService uses this to create nsIDragSessions when dragging
// from a child process.
MOZ_CAN_RUN_SCRIPT nsresult InitWithRemoteImage(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
mozilla::dom::RemoteDragStartData* aDragStartData,
mozilla::dom::DragEvent* aDragEvent,
mozilla::dom::DataTransfer* aDataTransfer, bool aIsSynthesizedForTests);
// The nsIDragService uses this to create nsIDragSessions for dragging
// a selected region from a Gecko window.
MOZ_CAN_RUN_SCRIPT nsresult InitWithSelection(
nsIWidget* aWidget, mozilla::dom::Selection* aSelection,
nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCsp,
nsICookieJarSettings* aCookieJarSettings, nsIArray* aTransferableArray,
uint32_t aActionType, mozilla::dom::DragEvent* aDragEvent,
mozilla::dom::DataTransfer* aDataTransfer, bool aIsSynthesizedForTests);
// The nsIDragService uses this to create nsIDragSessions when dragging
// from anywhere else.
MOZ_CAN_RUN_SCRIPT nsresult InitWithImage(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType, nsINode* aImage,
int32_t aImageX, int32_t aImageY, mozilla::dom::DragEvent* aDragEvent,
mozilla::dom::DataTransfer* aDataTransfer, bool aIsSynthesizedForTests);
protected:
nsBaseDragSession();
~nsBaseDragSession();
virtual ~nsBaseDragSession();
/**
* Starts a modal drag session with an array of transaferables.
*
* @param aPrincipal - the triggering principal of the drag, or null if
* it's from browser chrome or OS
* @param aCsp - The csp of the triggering Document
* @param aTransferables - an array of transferables to be dragged
* @param aActionType - specified which of copy/move/link are allowed
* @param aContentPolicyType - the contentPolicyType that will be
* passed to the loadInfo when creating a new channel
* (defaults to TYPE_OTHER)
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
nsContentPolicyType aContentPolicyType = nsIContentPolicy::TYPE_OTHER);
/**
* Called to create a drag session with a Gecko source. Like all drag
* sessions, the resulting session needs to be eventually ended with a call
* to nsIDragSession::EndDragSession.
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aTransferableArray,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) = 0;
/**
* Draw the drag image, if any, to a surface and return it. The drag image
* is constructed from mImage if specified, or aDOMNode if mImage is null.
*
* aRegion may be used to draw only a subset of the element. This region
* should be supplied using x and y coordinates measured in css pixels
* that are relative to the upper-left corner of the window.
*
* aScreenPosition should be the screen coordinates of the mouse click
* for the drag. These are in CSS pixels.
*
* On return, aScreenDragRect will contain the screen coordinates of the
* area being dragged. This is used by the platform-specific part of the
* drag service to determine the drag feedback. This rect will be in the
* device pixels of the presContext.
*
* If there is no drag image, the returned surface will be null, but
* aScreenDragRect will still be set to the drag area.
*
* aPresContext will be set to the nsPresContext used determined from
* whichever of mImage or aDOMNode is used.
*/
nsresult DrawDrag(nsINode* aDOMNode,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
mozilla::CSSIntPoint aScreenPosition,
mozilla::LayoutDeviceIntRect* aScreenDragRect,
RefPtr<mozilla::gfx::SourceSurface>* aSurface,
nsPresContext** aPresContext);
/**
* Draw a drag image for an image node specified by aImageLoader or aCanvas.
* This is called by DrawDrag.
*/
nsresult DrawDragForImage(nsPresContext* aPresContext,
nsIImageLoadingContent* aImageLoader,
mozilla::dom::HTMLCanvasElement* aCanvas,
mozilla::LayoutDeviceIntRect* aScreenDragRect,
RefPtr<mozilla::gfx::SourceSurface>* aSurface);
MOZ_CAN_RUN_SCRIPT virtual nsresult EndDragSessionImpl(
bool aDoneDrag, uint32_t aKeyModifiers);
@ -133,6 +231,10 @@ class nsBaseDragSession : public nsIDragSession {
// The position relative to the top level widget where the drag ended.
mozilla::LayoutDeviceIntPoint mEndDragPoint;
// the contentpolicy type passed to the channel when initiating the drag
// session
nsContentPolicyType mContentPolicyType = nsIContentPolicy::TYPE_OTHER;
uint32_t mDragAction = nsIDragService::DRAGDROP_ACTION_NONE;
uint32_t mDragActionFromChildProcess =
nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
@ -145,7 +247,8 @@ class nsBaseDragSession : public nsIDragSession {
// The input source of the drag event. Possible values are from MouseEvent.
uint16_t mInputSource = mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_MOUSE;
bool mDoingDrag = false;
// false after EndDragSession has run
bool mDoingDrag = true;
bool mCanDrop = false;
bool mOnlyChromeDrop = false;
@ -166,14 +269,9 @@ class nsBaseDragSession : public nsIDragSession {
/**
* Platform-agnostic base for nsIDragService.
* NB: This class temporarily subclasses nsBaseDragSession while we move
* methods from it to nsBaseDragSession. The inheritance relationship
* will be severed by the end of this patch series.
*/
class nsBaseDragService : public nsIDragService, public nsBaseDragSession {
class nsBaseDragService : public nsIDragService {
public:
typedef mozilla::gfx::SourceSurface SourceSurface;
nsBaseDragService();
// nsISupports
@ -181,8 +279,6 @@ class nsBaseDragService : public nsIDragService, public nsBaseDragSession {
NS_DECL_NSIDRAGSERVICE
uint16_t GetInputSource() { return mInputSource; }
using nsIDragService::GetCurrentSession;
uint32_t GetSuppressLevel() { return mSuppressLevel; };
@ -191,89 +287,34 @@ class nsBaseDragService : public nsIDragService, public nsBaseDragSession {
return std::move(mBrowsers);
}
void ClearCurrentParentDragSession() {
mCurrentParentDragSession = nullptr;
}
static nsIWidget* GetWidgetFromWidgetProvider(nsISupports* aWidgetProvider);
protected:
virtual ~nsBaseDragService();
/**
* Starts a modal drag session with an array of transaferables.
*
* @param aPrincipal - the triggering principal of the drag, or null if
* it's from browser chrome or OS
* @param aCsp - The csp of the triggering Document
* @param aTransferables - an array of transferables to be dragged
* @param aActionType - specified which of copy/move/link are allowed
* @param aContentPolicyType - the contentPolicyType that will be
* passed to the loadInfo when creating a new channel
* (defaults to TYPE_OTHER)
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
nsContentPolicyType aContentPolicyType = nsIContentPolicy::TYPE_OTHER);
virtual already_AddRefed<nsIDragSession> CreateDragSession() = 0;
/**
* Called from nsBaseDragService to initiate a platform drag from a source
* in this process. This is expected to ensure that StartDragSession() and
* EndDragSession() get called if the platform drag is successfully invoked.
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aTransferableArray,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) = 0;
/**
* Draw the drag image, if any, to a surface and return it. The drag image
* is constructed from mImage if specified, or aDOMNode if mImage is null.
*
* aRegion may be used to draw only a subset of the element. This region
* should be supplied using x and y coordinates measured in css pixels
* that are relative to the upper-left corner of the window.
*
* aScreenPosition should be the screen coordinates of the mouse click
* for the drag. These are in CSS pixels.
*
* On return, aScreenDragRect will contain the screen coordinates of the
* area being dragged. This is used by the platform-specific part of the
* drag service to determine the drag feedback. This rect will be in the
* device pixels of the presContext.
*
* If there is no drag image, the returned surface will be null, but
* aScreenDragRect will still be set to the drag area.
*
* aPresContext will be set to the nsPresContext used determined from
* whichever of mImage or aDOMNode is used.
*/
nsresult DrawDrag(nsINode* aDOMNode,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
mozilla::CSSIntPoint aScreenPosition,
mozilla::LayoutDeviceIntRect* aScreenDragRect,
RefPtr<SourceSurface>* aSurface,
nsPresContext** aPresContext);
/**
* Draw a drag image for an image node specified by aImageLoader or aCanvas.
* This is called by DrawDrag.
*/
nsresult DrawDragForImage(nsPresContext* aPresContext,
nsIImageLoadingContent* aImageLoader,
mozilla::dom::HTMLCanvasElement* aCanvas,
mozilla::LayoutDeviceIntRect* aScreenDragRect,
RefPtr<SourceSurface>* aSurface);
virtual bool IsMockService() { return false; }
// the contentpolicy type passed to the channel when initiating the drag
// session
nsContentPolicyType mContentPolicyType;
uint32_t mSuppressLevel;
// The drag session representing the user's current actions, if any.
// This value is only valid in the parent process. For child
// process drag sessions, see BrowserChild and PuppetWidget.
RefPtr<nsIDragSession> mCurrentParentDragSession;
// Sub-region for tree-selections.
mozilla::Maybe<mozilla::CSSIntRegion> mRegion;
RefPtr<mozilla::test::MockDragServiceController> mMockController;
// Weak references to PBrowsers that are currently engaged in drags.
// Once an nsIDragSession is created for the remote drag, these browsers
// will be moved to that object.
nsTArray<nsWeakPtr> mBrowsers;
uint32_t mSuppressLevel = 0;
// If this is set, mSessionIsSynthesizedForTests should not become true.
// This hack is used to bypass the "old" drag-drop test behavior.
// See nsIDragService.idl for details.

Просмотреть файл

@ -24,11 +24,36 @@ using mozilla::gfx::SourceSurface;
using mozilla::gfx::SurfaceFormat;
using mozilla::ipc::Shmem;
nsDragServiceProxy::nsDragServiceProxy() = default;
nsDragServiceProxy::~nsDragServiceProxy() = default;
nsresult nsDragServiceProxy::InvokeDragSessionImpl(
nsDragSessionProxy::~nsDragSessionProxy() = default;
already_AddRefed<nsIDragSession> nsDragServiceProxy::CreateDragSession() {
RefPtr<nsIDragSession> session = new nsDragSessionProxy();
return session.forget();
}
nsresult nsDragSessionProxy::InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
nsContentPolicyType aContentPolicyType) {
BrowserChild* sourceBrowser = aWidget->GetOwningBrowserChild();
NS_ENSURE_TRUE(sourceBrowser, NS_ERROR_INVALID_ARG);
[[maybe_unused]] RefPtr<nsIDragSession> sourceSession =
sourceBrowser->GetDragSession();
MOZ_ASSERT(!sourceSession);
nsresult rv = nsBaseDragSession::InvokeDragSession(aWidget, aDOMNode,
aPrincipal, aCsp, aCookieJarSettings, aTransferableArray, aActionType,
aContentPolicyType);
if (NS_SUCCEEDED(rv)) {
MOZ_ALWAYS_SUCCEEDS(sourceBrowser->GetWeakReference(getter_AddRefs(mSourceBrowser)));
sourceBrowser->SetDragSession(this);
}
return rv;
}
nsresult nsDragSessionProxy::InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* aArrayTransferables,
const Maybe<CSSIntRegion>& aRegion, uint32_t aActionType) {
NS_ENSURE_STATE(mSourceDocument->GetDocShell());
@ -81,7 +106,6 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
std::move(transferables), aActionType, std::move(surfaceData),
stride, dataSurface->GetFormat(), dragRect, principal, csp, csArgs,
mSourceWindowContext, mSourceTopWindowContext);
StartDragSession(aWidget);
return NS_OK;
}
}
@ -91,6 +115,88 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
std::move(transferables), aActionType, Nothing(), 0,
static_cast<SurfaceFormat>(0), dragRect, principal, csp, csArgs,
mSourceWindowContext, mSourceTopWindowContext);
StartDragSession(aWidget);
return NS_OK;
}
NS_IMETHODIMP
nsDragServiceProxy::StartDragSession(nsISupports* aWidgetProvider) {
nsIWidget* widget = GetWidgetFromWidgetProvider(aWidgetProvider);
NS_ENSURE_TRUE(widget, NS_ERROR_INVALID_ARG);
BrowserChild* targetBrowser = widget->GetOwningBrowserChild();
NS_ENSURE_TRUE(targetBrowser, NS_ERROR_INVALID_ARG);
RefPtr<nsIDragSession> session = targetBrowser->GetDragSession();
if (session) {
// session already exists on the browser
return NS_OK;
}
session = CreateDragSession();
MOZ_ASSERT(session);
static_cast<nsDragSessionProxy*>(session.get())->SetDragTarget(targetBrowser);
targetBrowser->SetDragSession(session);
return NS_OK;
}
NS_IMETHODIMP
nsDragServiceProxy::GetCurrentSession(nsISupports* aWidgetProvider,
nsIDragSession** aSession) {
if (!aSession) {
return NS_ERROR_INVALID_ARG;
}
*aSession = nullptr;
nsIWidget* widget = GetWidgetFromWidgetProvider(aWidgetProvider);
NS_ENSURE_TRUE(widget, NS_ERROR_INVALID_ARG);
BrowserChild* browser = widget->GetOwningBrowserChild();
NS_ENSURE_TRUE(browser, NS_ERROR_INVALID_ARG);
RefPtr<nsIDragSession> session = browser->GetDragSession();
if (!mSuppressLevel && session) {
session.forget(aSession);
}
return NS_OK;
}
void nsDragSessionProxy::SetDragTarget(BrowserChild* aTarget) {
if (!aTarget) {
if (mTargetBrowser) {
nsCOMPtr<BrowserChild> targetBC = do_QueryReferent(mTargetBrowser);
MOZ_ASSERT(targetBC);
if (targetBC) {
targetBC->SetDragSession(nullptr);
}
mTargetBrowser = nullptr;
}
return;
}
[[maybe_unused]] RefPtr<nsIDragSession> session =
aTarget->GetDragSession();
MOZ_ASSERT(!session);
MOZ_ALWAYS_SUCCEEDS(aTarget->GetWeakReference(getter_AddRefs(mTargetBrowser)));
}
nsresult nsDragSessionProxy::EndDragSessionImpl(bool aDoneDrag,
uint32_t aKeyModifiers) {
if (mSourceBrowser) {
nsCOMPtr<BrowserChild> sourceBC = do_QueryReferent(mSourceBrowser);
MOZ_ASSERT(sourceBC);
[[maybe_unused]] RefPtr<nsIDragSession> session =
sourceBC->GetDragSession();
MOZ_ASSERT(session == this);
sourceBC->SetDragSession(nullptr);
mSourceBrowser = nullptr;
}
if (mTargetBrowser) {
nsCOMPtr<BrowserChild> targetBC = do_QueryReferent(mTargetBrowser);
MOZ_ASSERT(targetBC);
[[maybe_unused]] RefPtr<nsIDragSession> session =
targetBC->GetDragSession();
MOZ_ASSERT(session == this);
targetBC->SetDragSession(nullptr);
mTargetBrowser = nullptr;
}
return nsBaseDragSession::EndDragSessionImpl(aDoneDrag, aKeyModifiers);
}

Просмотреть файл

@ -8,26 +8,48 @@
#include "nsBaseDragService.h"
// Temporary inheritance from nsBaseDragService instead of nsBaseDragSession
// (which nsBaseDragService temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragSessionProxy : public nsBaseDragService {};
// Temporary inheritance from nsDragSessionProxy instead of nsBaseDragService
// (which nsDragSession temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragServiceProxy final : public nsDragSessionProxy {
class nsDragSessionProxy : public nsBaseDragSession {
public:
nsDragServiceProxy();
NS_INLINE_DECL_REFCOUNTING_INHERITED(nsDragSessionProxy, nsBaseDragSession)
NS_INLINE_DECL_REFCOUNTING_INHERITED(nsDragServiceProxy, nsDragSessionProxy)
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSession(
nsIWidget* aWidget, nsINode* aDOMNode, nsIPrincipal* aPrincipal,
nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings,
nsIArray* aTransferableArray, uint32_t aActionType,
nsContentPolicyType aContentPolicyType) override;
// nsBaseDragService
virtual nsresult InvokeDragSessionImpl(
nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType) override;
void SetDragTarget(mozilla::dom::BrowserChild* aTarget);
MOZ_CAN_RUN_SCRIPT
nsresult EndDragSessionImpl(bool aDoneDrag, uint32_t aKeyModifiers) override;
private:
~nsDragSessionProxy();
// The source for this drag. This is null if the source is a different
// application or drag session.
nsWeakPtr mSourceBrowser;
// The target for this drag. This is null if the target is a different
// application or drag session.
nsWeakPtr mTargetBrowser;
};
class nsDragServiceProxy : public nsBaseDragService {
public:
NS_INLINE_DECL_REFCOUNTING_INHERITED(nsDragServiceProxy, nsBaseDragService)
already_AddRefed<nsIDragSession> CreateDragSession() override;
NS_IMETHOD StartDragSession(nsISupports* aWidgetProvider) override;
NS_IMETHOD GetCurrentSession(nsISupports* aWidgetProvider,
nsIDragSession** aSession) override;
private:
virtual ~nsDragServiceProxy();
};

Просмотреть файл

@ -128,15 +128,7 @@ interface nsIDragService : nsISupports
*/
nsIDragSession getCurrentSession([optional] in nsISupports aWidgetProvider);
/**
* TODO: Temporary proxy for old C++ callers, for whom [optional] is
* insufficient. This method is removed at the end of this patch series.
*/
%{ C++
nsresult GetCurrentSession(nsIDragSession** aSession) {
return GetCurrentSession(nullptr, aSession);
}
nsIDragSession* GetCurrentSession(nsIWidget* aWidget) {
nsCOMPtr<nsIDragSession> session;
GetCurrentSession(aWidget, getter_AddRefs(session));
@ -195,6 +187,20 @@ interface nsIDragService : nsISupports
*/
nsIMockDragServiceController getMockDragController();
/**
* True if this is a mock nsIDragService, created with
* createMockDragController().
*/
readonly attribute boolean isMockService;
%{ C++
bool IsMockService() {
bool ret = false;
MOZ_ALWAYS_SUCCEEDS(GetIsMockService(&ret));
return ret;
}
%}
/**
* If this is true, mSessionIsSynthesizedForTests should not become true.
* This hack is used to bypass the "old" drag-drop test behavior, which needed

Просмотреть файл

@ -137,6 +137,12 @@ interface nsIDragSession : nsISupports
// nsIDragService::InvokeDragSessionWithImage.
void updateDragImage(in Node aImage, in long aImageX, in long aImageY);
/**
* Tell Gecko that this session is generated for automated testing.
* This should be called immediately after StartDragSession when testing.
*/
[noscript] void InitForTests(in uint32_t aAllowedEffect);
/**
* Returns effects allowed at starting the session for tests.
*/

Просмотреть файл

@ -46,13 +46,13 @@ using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
//-------------------------------------------------------------------------
//
// DragService destructor
//
//-------------------------------------------------------------------------
nsDragSession::~nsDragSession() { NS_IF_RELEASE(mDataObject); }
already_AddRefed<nsIDragSession> nsDragService::CreateDragSession() {
RefPtr<nsIDragSession> session = new nsDragSession();
return session.forget();
}
bool nsDragSession::CreateDragImage(nsINode* aDOMNode,
const Maybe<CSSIntRegion>& aRegion,
SHDRAGIMAGE* psdi) {
@ -140,7 +140,7 @@ bool nsDragSession::CreateDragImage(nsINode* aDOMNode,
}
//-------------------------------------------------------------------------
nsresult nsDragService::InvokeDragSessionImpl(
nsresult nsDragSession::InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const Maybe<CSSIntRegion>& aRegion, uint32_t aActionType) {
// Try and get source URI of the items that are being dragged
@ -229,7 +229,7 @@ static HWND GetSourceWindow(dom::Document* aSourceDocument) {
}
//-------------------------------------------------------------------------
nsresult nsDragService::StartInvokingDragSession(nsIWidget* aWidget,
nsresult nsDragSession::StartInvokingDragSession(nsIWidget* aWidget,
IDataObject* aDataObj,
uint32_t aActionType) {
// To do the drag we need to create an object that
@ -240,13 +240,13 @@ nsresult nsDragService::StartInvokingDragSession(nsIWidget* aWidget,
// Now figure out what the native drag effect should be
DWORD winDropRes;
DWORD effects = DROPEFFECT_SCROLL;
if (aActionType & DRAGDROP_ACTION_COPY) {
if (aActionType & nsIDragService::DRAGDROP_ACTION_COPY) {
effects |= DROPEFFECT_COPY;
}
if (aActionType & DRAGDROP_ACTION_MOVE) {
if (aActionType & nsIDragService::DRAGDROP_ACTION_MOVE) {
effects |= DROPEFFECT_MOVE;
}
if (aActionType & DRAGDROP_ACTION_LINK) {
if (aActionType & nsIDragService::DRAGDROP_ACTION_LINK) {
effects |= DROPEFFECT_LINK;
}
@ -256,7 +256,6 @@ nsresult nsDragService::StartInvokingDragSession(nsIWidget* aWidget,
mSentLocalDropEvent = false;
// Start dragging
StartDragSession(aWidget);
OpenDragPopup();
RefPtr<IDataObjectAsyncCapability> pAsyncOp;
@ -277,19 +276,19 @@ nsresult nsDragService::StartInvokingDragSession(nsIWidget* aWidget,
uint32_t dropResult;
// Order is important, since multiple flags can be returned.
if (winDropRes & DROPEFFECT_COPY)
dropResult = DRAGDROP_ACTION_COPY;
dropResult = nsIDragService::DRAGDROP_ACTION_COPY;
else if (winDropRes & DROPEFFECT_LINK)
dropResult = DRAGDROP_ACTION_LINK;
dropResult = nsIDragService::DRAGDROP_ACTION_LINK;
else if (winDropRes & DROPEFFECT_MOVE)
dropResult = DRAGDROP_ACTION_MOVE;
dropResult = nsIDragService::DRAGDROP_ACTION_MOVE;
else
dropResult = DRAGDROP_ACTION_NONE;
dropResult = nsIDragService::DRAGDROP_ACTION_NONE;
if (mDataTransfer) {
if (res == DRAGDROP_S_DROP) // Success
mDataTransfer->SetDropEffectInt(dropResult);
else
mDataTransfer->SetDropEffectInt(DRAGDROP_ACTION_NONE);
mDataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE);
}
}
@ -310,11 +309,8 @@ nsresult nsDragService::StartInvokingDragSession(nsIWidget* aWidget,
}
SetDragEndPoint(LayoutDeviceIntPoint(cpos.x, cpos.y));
RefPtr<nsIDragSession> session = GetCurrentSession(aWidget);
if (session) {
ModifierKeyState modifierKeyState;
session->EndDragSession(true, modifierKeyState.GetModifiers());
}
ModifierKeyState modifierKeyState;
EndDragSession(true, modifierKeyState.GetModifiers());
mDoingDrag = false;
@ -471,7 +467,7 @@ void nsDragSession::SetIDataObject(IDataObject* aDataObj) {
}
//---------------------------------------------------------
void nsDragService::SetDroppedLocal() {
void nsDragSession::SetDroppedLocal() {
// Sent from the native drag handler, letting us know
// a drop occurred within the application vs. outside of it.
mSentLocalDropEvent = true;

Просмотреть файл

@ -13,10 +13,10 @@
struct IDataObject;
class nsDataObjCollection;
// Temporary inheritance from nsBaseDragService instead of nsBaseDragSession
// (which nsBaseDragService temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragSession : public nsBaseDragService {
/**
* Windows native nsIDragSession implementation
*/
class nsDragSession : public nsBaseDragSession {
public:
virtual ~nsDragSession();
@ -30,9 +30,21 @@ class nsDragSession : public nsBaseDragService {
void SetIDataObject(IDataObject* aDataObj);
IDataObject* GetDataObject() { return mDataObject; }
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType);
MOZ_CAN_RUN_SCRIPT nsresult EndDragSessionImpl(
bool aDoneDrag, uint32_t aKeyModifiers) override;
MOZ_CAN_RUN_SCRIPT nsresult StartInvokingDragSession(nsIWidget* aWidget,
IDataObject* aDataObj,
uint32_t aActionType);
// A drop occurred within the application vs. outside of it.
void SetDroppedLocal();
protected:
// determine if we have a single data object or one of our private
// collections
@ -45,29 +57,16 @@ class nsDragSession : public nsBaseDragService {
SHDRAGIMAGE* psdi);
IDataObject* mDataObject = nullptr;
};
// Temporary inheritance from nsDragSession instead of nsBaseDragService
// (which nsDragSession temporarily inherits).
// This will be undone at the end of this patch series.
class nsDragService final : public nsDragSession {
public:
// nsBaseDragService
MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
nsIWidget* aWidget, nsIArray* anArrayTransferables,
const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
uint32_t aActionType);
// native impl.
MOZ_CAN_RUN_SCRIPT nsresult StartInvokingDragSession(nsIWidget* aWidget,
IDataObject* aDataObj,
uint32_t aActionType);
// A drop occurred within the application vs. outside of it.
void SetDroppedLocal();
protected:
bool mSentLocalDropEvent = false;
};
/**
* Windows native nsIDragService implementation
*/
class nsDragService final : public nsBaseDragService {
public:
already_AddRefed<nsIDragSession> CreateDragSession() override;
};
#endif // nsDragService_h__

Просмотреть файл

@ -16,6 +16,7 @@
#include "nsClipboard.h"
#include "KeyboardLayout.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/MouseEvents.h"
using namespace mozilla;
@ -152,8 +153,13 @@ void nsNativeDragTarget::DispatchDragDropEvent(EventMessage aEventMessage,
ModifierKeyState modifierKeyState;
modifierKeyState.InitInputEvent(event);
event.mInputSource =
static_cast<nsBaseDragService*>(mDragService.get())->GetInputSource();
nsDragSession* currSession =
static_cast<nsDragSession*>(mDragService->GetCurrentSession(mWidget));
if (currSession) {
event.mInputSource = currSession->GetInputSource();
} else {
event.mInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_MOUSE;
}
mWidget->DispatchInputEvent(&event);
}
@ -426,14 +432,12 @@ nsNativeDragTarget::Drop(LPDATAOBJECT pData, DWORD grfKeyState, POINTL aPT,
return S_OK; // DragCancel() was called.
}
// Let the win drag service know whether this session experienced
// Let the win drag session know whether it experienced
// a drop event within the application. Drop will not oocur if the
// drop landed outside the app. (used in tab tear off, bug 455884)
RefPtr<nsDragService> winDragService =
static_cast<nsDragService*>(mDragService.get());
winDragService->SetDroppedLocal();
currentDragSession->SetDroppedLocal();
// tell the drag service we're done with the session
// Tell the drag session we're done with it.
// Use GetMessagePos to get the position of the mouse at the last message
// seen by the event loop. (Bug 489729)
DWORD pos = ::GetMessagePos();