Bug 1362382 - Move RegisterDragDrop to be called during idle time, if possible r=jimm
authorKirk Steuber <ksteuber@mozilla.com>
Wed, 30 Aug 2017 11:18:25 -0700
changeset 379503 6aa682399e1ef4c523abff8f5447d2c10508c064
parent 379502 60cb967ca47fd6ec7e57682e2ecea5ce9123fd8d
child 379504 bb2e73cf94733b30f8af0430fec0a9edc6f2b9ce
push id32455
push userarchaeopteryx@coole-files.de
push dateThu, 07 Sep 2017 21:50:54 +0000
treeherdermozilla-central@64bf417d1bdf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1362382
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1362382 - Move RegisterDragDrop to be called during idle time, if possible r=jimm Additionally, do not call RegisterDragDrop for hidden windows. MozReview-Commit-ID: Fv8j9FntGGT
view/nsView.cpp
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/nsIWidget.h
widget/windows/nsWindow.cpp
--- 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);