Bug 1272961. r=Enn
☠☠ backed out by 760b8e6d19e4 ☠ ☠
authorFelipe Gomes <felipc@gmail.com>
Mon, 04 Jul 2016 16:33:21 -0300
changeset 303611 a7105b09ae0c18b858c33b1020bdded6a6d66c9b
parent 303610 fdffe351484e4abbd32f686424ff840ae05f0992
child 303612 760b8e6d19e41780e554573b3983aa8647bf3cbd
push id30396
push usercbook@mozilla.com
push dateTue, 05 Jul 2016 14:02:31 +0000
treeherdermozilla-central@b2e48cc9d3a0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEnn
bugs1272961
milestone50.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 1272961. r=Enn MozReview-Commit-ID: JrKnWcYylW5
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
xpfe/appshell/nsWebShellWindow.cpp
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1718,16 +1718,23 @@ public:
     mIsNeverPainting = aNeverPainting;
   }
 
   bool HasPendingReflow() const
     { return mReflowScheduled || mReflowContinueTimer; }
 
   void SyncWindowProperties(nsView* aView);
 
+  /**
+   * Prevents retargeting of mouse events to a descendant popup.
+   */
+  void SetPreventPopupRetargeting(bool aValue) {
+    mPreventPopupRetargeting = aValue;
+  }
+
 #ifdef ANDROID
   virtual nsIDocument* GetTouchEventTargetDocument() = 0;
 #endif
 
 protected:
   friend class nsRefreshDriver;
 
   // IMPORTANT: The ownership implicit in the following member variables
@@ -1851,13 +1858,16 @@ protected:
 
   // Dirty bit indicating that mFontSizeInflationEnabled needs to be recomputed.
   bool mFontSizeInflationEnabledIsDirty;
 
   // If a document belongs to an invisible DocShell, this flag must be set
   // to true, so we can avoid any paint calls for widget related to this
   // presshell.
   bool mIsNeverPainting;
+
+  // Prevents retargeting of mouse events to a descendant popup.
+  bool mPreventPopupRetargeting;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIPresShell, NS_IPRESSHELL_IID)
 
 #endif /* nsIPresShell_h___ */
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -7758,23 +7758,29 @@ PresShell::HandleEvent(nsIFrame* aFrame,
       // detect a chrome generated popup.
       if (popupFrame && capturingContent &&
           EventStateManager::IsRemoteTarget(capturingContent)) {
         capturingContent = nullptr;
       }
       // If the popupFrame is an ancestor of the 'frame', the frame should
       // handle the event, otherwise, the popup should handle it.
       if (popupFrame &&
+          !mPreventPopupRetargeting &&
           !nsContentUtils::ContentIsCrossDocDescendantOf(
              framePresContext->GetPresShell()->GetDocument(),
              popupFrame->GetContent())) {
         frame = popupFrame;
       }
     }
 
+    if (aEvent->mClass == eMouseEventClass &&
+        aEvent->mMessage == eMouseUp) {
+      mPreventPopupRetargeting = false;
+    }
+
     bool captureRetarget = false;
     if (capturingContent) {
       // If a capture is active, determine if the docshell is visible. If not,
       // clear the capture and target the mouse event normally instead. This
       // would occur if the mouse button is held down while a tab change occurs.
       // If the docshell is visible, look for a scrolling container.
       bool vis;
       nsCOMPtr<nsIBaseWindow> baseWin =
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -256,16 +256,23 @@ nsWebShellWindow::WindowMoved(nsIWidget*
 {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm) {
     nsCOMPtr<nsPIDOMWindowOuter> window =
       mDocShell ? mDocShell->GetWindow() : nullptr;
     pm->AdjustPopupsOnWindowChange(window);
   }
 
+  // If the window has moved, don't allow popup retargeting during this
+  // mousedown-mousemoves-moseup session
+  nsIPresShell* presShell = GetPresShell();
+  if (presShell) {
+    presShell->SetPreventPopupRetargeting(true);
+  }
+
   // Notify all tabs that the widget moved.
   if (mDocShell && mDocShell->GetWindow()) {
     nsCOMPtr<EventTarget> eventTarget = mDocShell->GetWindow()->GetTopWindowRoot();
     nsContentUtils::DispatchChromeEvent(mDocShell->GetDocument(),
                                         eventTarget,
                                         NS_LITERAL_STRING("MozUpdateWindowPos"),
                                         false, false, nullptr);
   }
@@ -278,16 +285,24 @@ nsWebShellWindow::WindowMoved(nsIWidget*
 
 bool
 nsWebShellWindow::WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
 {
   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
   if (shellAsWin) {
     shellAsWin->SetPositionAndSize(0, 0, aWidth, aHeight, 0);
   }
+
+  // If the window has resized, don't allow popup retargeting during this
+  // mousedown-mousemoves-moseup session
+  nsIPresShell* presShell = GetPresShell();
+  if (presShell) {
+    presShell->SetPreventPopupRetargeting(true);
+  }
+
   // Persist size, but not immediately, in case this OS is firing
   // repeated size events as the user drags the sizing handle
   if (!IsLocked())
     SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
   return true;
 }
 
 bool