Bug 1362382 - Move RegisterDragDrop to be called during idle time, if possible
Additionally, do not call RegisterDragDrop for hidden windows.
MozReview-Commit-ID: Fv8j9FntGGT
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -711,17 +711,20 @@ nsresult nsView::AttachToTopLevelWidget(
// Note, the previous device context will be released. Detaching
// will not restore the old one.
aWidget->AttachViewToTopLevel(!nsIWidget::UsePuppetWidgets());
mWindow = aWidget;
mWindow->SetAttachedWidgetListener(this);
- mWindow->EnableDragDrop(true);
+ if (mWindow->WindowType() != eWindowType_invisible) {
+ nsresult rv = mWindow->AsyncEnableDragDrop(true);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
mWidgetIsTopLevel = true;
// Refresh the view bounds
CalcWidgetBounds(mWindow->WindowType());
return NS_OK;
}
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -120,16 +120,21 @@ bool gDisableNativeTheme
#define TOUCH_INJECT_PUMP_TIMER_MSEC 50
#define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500
int32_t nsIWidget::sPointerIdCounter = 0;
// Some statics from nsIWidget.h
/*static*/ uint64_t AutoObserverNotifier::sObserverId = 0;
/*static*/ nsDataHashtable<nsUint64HashKey, nsCOMPtr<nsIObserver>> AutoObserverNotifier::sSavedObservers;
+// The maximum amount of time to let the EnableDragDrop runnable wait in the
+// idle queue before timing out and moving it to the regular queue. Value is in
+// milliseconds.
+const uint32_t kAsyncDragDropTimeout = 1000;
+
namespace mozilla {
namespace widget {
void
IMENotification::SelectionChangeDataBase::SetWritingMode(
const WritingMode& aWritingMode)
{
mWritingMode = aWritingMode.mWritingMode;
@@ -2224,16 +2229,28 @@ nsBaseWidget::UnregisterPluginWindowForR
NS_WARNING("This is not a valid native widget!");
return;
}
MOZ_ASSERT(sPluginWidgetList);
sPluginWidgetList->Remove(id);
#endif
}
+nsresult
+nsBaseWidget::AsyncEnableDragDrop(bool aEnable)
+{
+ RefPtr<nsBaseWidget> kungFuDeathGrip = this;
+ return NS_IdleDispatchToCurrentThread(
+ NS_NewRunnableFunction("AsyncEnableDragDropFn",
+ [this, aEnable, kungFuDeathGrip]() {
+ EnableDragDrop(aEnable);
+ }),
+ kAsyncDragDropTimeout);
+}
+
// static
nsIWidget*
nsIWidget::LookupRegisteredPluginWindow(uintptr_t aWindowID)
{
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
NS_NOTREACHED("nsBaseWidget::LookupRegisteredPluginWindow not implemented!");
return nullptr;
#else
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -245,16 +245,17 @@ public:
virtual void ResizeClient(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
virtual LayoutDeviceIntRect GetBounds() override;
virtual LayoutDeviceIntRect GetClientBounds() override;
virtual LayoutDeviceIntRect GetScreenBounds() override;
virtual MOZ_MUST_USE nsresult GetRestoredBounds(LayoutDeviceIntRect& aRect) override;
virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
virtual LayoutDeviceIntPoint GetClientOffset() override;
virtual void EnableDragDrop(bool aEnable) override {};
+ virtual nsresult AsyncEnableDragDrop(bool aEnable) override;
virtual MOZ_MUST_USE nsresult
GetAttention(int32_t aCycleCount) override
{ return NS_OK; }
virtual bool HasPendingInputEvent() override;
virtual void SetIcon(const nsAString &aIconSpec) override {}
virtual void SetWindowTitlebarColor(nscolor aColor, bool aActive)
override {}
virtual void SetDrawsInTitlebar(bool aState) override {}
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1410,16 +1410,17 @@ class nsIWidget : public nsISupports
* Returns true if APZ is in use, false otherwise.
*/
virtual bool AsyncPanZoomEnabled() const = 0;
/**
* Enables the dropping of files to a widget.
*/
virtual void EnableDragDrop(bool aEnable) = 0;
+ virtual nsresult AsyncEnableDragDrop(bool aEnable) = 0;
/**
* Enables/Disables system mouse capture.
* @param aCapture true enables mouse capture, false disables mouse capture
*
*/
virtual void CaptureMouse(bool aCapture) = 0;
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3767,17 +3767,20 @@ nsWindow::ClientToWindowSize(const Layou
*
* Enables/Disables drag and drop of files on this widget.
*
**************************************************************/
void
nsWindow::EnableDragDrop(bool aEnable)
{
- NS_ASSERTION(mWnd, "nsWindow::EnableDragDrop() called after Destroy()");
+ if (!mWnd) {
+ // Return early if the window already closed
+ return;
+ }
if (aEnable) {
if (!mNativeDragTarget) {
mNativeDragTarget = new nsNativeDragTarget(this);
mNativeDragTarget->AddRef();
if (SUCCEEDED(::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget,
TRUE, FALSE))) {
::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget);