Bug 1498973: Don't show a popup that should be hidden. r=jmathies a=lizzard
authorAdam Gashlin <agashlin@mozilla.com>
Tue, 26 Mar 2019 10:49:50 -0700
changeset 516422 4400ca694ade
parent 516421 bc2c55e0de10
child 516423 7f4781ff8f7d
push id1999
push userarchaeopteryx@coole-files.de
push dateFri, 05 Apr 2019 18:44:18 +0000
treeherdermozilla-release@70bc92ce18e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies, lizzard
bugs1498973, 1534935
milestone66.0.3
Bug 1498973: Don't show a popup that should be hidden. r=jmathies a=lizzard This includes the fix for the bug 1534935 regression.
view/nsView.cpp
view/nsView.h
widget/nsIWidgetListener.cpp
widget/nsIWidgetListener.h
widget/windows/nsWindow.cpp
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -1036,16 +1036,25 @@ void nsView::DidCompositeWindow(mozilla:
 
 void nsView::RequestRepaint() {
   nsIPresShell* presShell = mViewManager->GetPresShell();
   if (presShell) {
     presShell->ScheduleViewManagerFlush();
   }
 }
 
+bool nsView::ShouldNotBeVisible() {
+  if (mFrame && mFrame->IsMenuPopupFrame()) {
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    return !pm || !pm->IsPopupOpen(mFrame->GetContent());
+  }
+
+  return false;
+}
+
 nsEventStatus nsView::HandleEvent(WidgetGUIEvent* aEvent,
                                   bool aUseAttachedEvents) {
   MOZ_ASSERT(nullptr != aEvent->mWidget, "null widget ptr");
 
   nsEventStatus result = nsEventStatus_eIgnore;
   nsView* view;
   if (aUseAttachedEvents) {
     nsIWidgetListener* listener = aEvent->mWidget->GetAttachedWidgetListener();
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -388,16 +388,17 @@ class nsView final : public nsIWidgetLis
   virtual bool PaintWindow(nsIWidget* aWidget,
                            LayoutDeviceIntRegion aRegion) override;
   virtual void DidPaintWindow() override;
   virtual void DidCompositeWindow(
       mozilla::layers::TransactionId aTransactionId,
       const mozilla::TimeStamp& aCompositeStart,
       const mozilla::TimeStamp& aCompositeEnd) override;
   virtual void RequestRepaint() override;
+  virtual bool ShouldNotBeVisible() override;
   virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
                                     bool aUseAttachedEvents) override;
 
   virtual ~nsView();
 
   nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const;
   nsIWidget* GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const;
 
--- a/widget/nsIWidgetListener.cpp
+++ b/widget/nsIWidgetListener.cpp
@@ -65,12 +65,17 @@ bool nsIWidgetListener::PaintWindow(nsIW
 void nsIWidgetListener::DidPaintWindow() {}
 
 void nsIWidgetListener::DidCompositeWindow(
     mozilla::layers::TransactionId aTransactionId,
     const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd) {}
 
 void nsIWidgetListener::RequestRepaint() {}
 
+bool nsIWidgetListener::ShouldNotBeVisible() {
+  // Returns false to assume that nothing should happen in most cases.
+  return false;
+}
+
 nsEventStatus nsIWidgetListener::HandleEvent(WidgetGUIEvent* aEvent,
                                              bool aUseAttachedEvents) {
   return nsEventStatus_eIgnore;
 }
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -158,15 +158,22 @@ class nsIWidgetListener {
                                   const mozilla::TimeStamp& aCompositeEnd);
 
   /**
    * Request that layout schedules a repaint on the next refresh driver tick.
    */
   virtual void RequestRepaint();
 
   /**
+   * Returns true if this is a popup that should not be visible. If this
+   * is a popup that is visible, not a popup or this state is unknown,
+   * returns false.
+   */
+  virtual bool ShouldNotBeVisible();
+
+  /**
    * Handle an event.
    */
   virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
                                     bool aUseAttachedEvents);
 };
 
 #endif
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6536,16 +6536,26 @@ void nsWindow::OnWindowPosChanging(LPWIN
           info->hwndInsertAfter =
               (HWND)actualBelow->GetNativeData(NS_NATIVE_WINDOW);
         }
       }
     }
   }
   // prevent rude external programs from making hidden window visible
   if (mWindowType == eWindowType_invisible) info->flags &= ~SWP_SHOWWINDOW;
+
+  // When waking from sleep or switching out of tablet mode, Windows 10
+  // Version 1809 will reopen popup windows that should be hidden. Detect
+  // this case and refuse to show the window.
+  static bool sDWMUnhidesPopups = IsWin10Sep2018UpdateOrLater();
+  if (sDWMUnhidesPopups && (info->flags & SWP_SHOWWINDOW) &&
+      mWindowType == eWindowType_popup && mWidgetListener &&
+      mWidgetListener->ShouldNotBeVisible()) {
+    info->flags &= ~SWP_SHOWWINDOW;
+  }
 }
 
 void nsWindow::UserActivity() {
   // Check if we have the idle service, if not we try to get it.
   if (!mIdleService) {
     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
   }