Bug 1373739 - Make headless widgets hidden by default, matching other platforms. r?bdahl draft
authorMichael Smith <michael@spinda.net>
Tue, 11 Jul 2017 13:57:25 -0700
changeset 620651 8f79ebade2806c33356432d83eea977a34a5ae7a
parent 620650 1334eb5fc3c4d818de9338e24036c9bf1e40d161
child 620652 9bc768274c517cd727f361f2e678ba436a0193a8
push id72121
push userbmo:lists@spinda.net
push dateThu, 03 Aug 2017 18:54:01 +0000
reviewersbdahl
bugs1373739
milestone56.0a1
Bug 1373739 - Make headless widgets hidden by default, matching other platforms. r?bdahl It seems that my reworking of how the z-index events are sent in the patch pertaining to active window tracking made it so that we can have headless widgets default to being invisible again, which matches the behavior on all other platforms. This then allows us to avoid applying size mode change side effects while a window/widget is invisible, matching the behavior on Windows and allowing the relevant web platform tests to pass despite the low screen resolution with which we run Windows VMs in testing (eg. open-features-non-integer-height.html). MozReview-Commit-ID: 3xnaEn7RImP
widget/headless/HeadlessWidget.cpp
widget/headless/HeadlessWidget.h
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -50,17 +50,17 @@ HeadlessWidget::Create(nsIWidget* aParen
                        nsWidgetInitData* aInitData)
 {
   MOZ_ASSERT(!aNativeParent, "No native parents for headless widgets.");
 
   BaseCreate(nullptr, aInitData);
 
   mBounds = aRect;
   mRestoreBounds = aRect;
-  mVisible = true;
+  mVisible = false;
   mEnabled = true;
 
   if (aParent) {
     mTopLevel = aParent->GetTopLevelWidget();
   } else {
     mTopLevel = this;
   }
 
@@ -126,16 +126,18 @@ HeadlessWidget::RaiseWindow()
 void
 HeadlessWidget::Show(bool aState)
 {
   mVisible = aState;
 
   // Top-level windows are activated/raised when shown.
   if (aState && mTopLevel == this)
     RaiseWindow();
+
+  ApplySizeModeSideEffects();
 }
 
 bool
 HeadlessWidget::IsVisible() const
 {
   return mVisible;
 }
 
@@ -241,28 +243,39 @@ HeadlessWidget::Resize(double aX,
 }
 
 void
 HeadlessWidget::SetSizeMode(nsSizeMode aMode)
 {
   if (aMode == mSizeMode) {
     return;
   }
-  if (mSizeMode == nsSizeMode_Normal) {
-    // Store the last normal size bounds so it can be restored when entering
-    // normal mode again.
-    mRestoreBounds = mBounds;
-  }
 
   nsBaseWidget::SetSizeMode(aMode);
 
   // Normally in real widget backends a window event would be triggered that
   // would cause the window manager to handle resizing the window. In headless
   // the window must manually be resized.
-  switch(aMode) {
+  ApplySizeModeSideEffects();
+}
+
+void
+HeadlessWidget::ApplySizeModeSideEffects()
+{
+  if (!mVisible || mEffectiveSizeMode == mSizeMode) {
+    return;
+  }
+
+  if (mEffectiveSizeMode == nsSizeMode_Normal) {
+    // Store the last normal size bounds so it can be restored when entering
+    // normal mode again.
+    mRestoreBounds = mBounds;
+  }
+
+  switch(mSizeMode) {
   case nsSizeMode_Normal: {
     Resize(mRestoreBounds.x, mRestoreBounds.y, mRestoreBounds.width, mRestoreBounds.height, false);
     break;
   }
   case nsSizeMode_Minimized:
     break;
   case nsSizeMode_Maximized: {
     nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
@@ -276,16 +289,18 @@ HeadlessWidget::SetSizeMode(nsSizeMode a
   }
   case nsSizeMode_Fullscreen:
     // This will take care of resizing the window.
     nsBaseWidget::InfallibleMakeFullScreen(true);
     break;
   default:
     break;
   }
+
+  mEffectiveSizeMode = mSizeMode;
 }
 
 nsresult
 HeadlessWidget::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
 {
   // Directly update the size mode here so a later call SetSizeMode does
   // nothing.
   if (aFullScreen) {
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -11,17 +11,17 @@
 #include "nsBaseWidget.h"
 
 namespace mozilla {
 namespace widget {
 
 class HeadlessWidget : public nsBaseWidget
 {
 public:
-  HeadlessWidget() {}
+  HeadlessWidget() : mEffectiveSizeMode(nsSizeMode_Normal) {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
   void* GetNativeData(uint32_t aDataType) override
   {
     // Headless widgets have no native data.
     return nullptr;
   }
@@ -90,20 +90,23 @@ public:
 
 private:
   ~HeadlessWidget();
   bool mEnabled;
   bool mVisible;
   nsIWidget* mTopLevel;
   // The size mode before entering fullscreen mode.
   nsSizeMode mLastSizeMode;
+  // The last size mode set while the window was visible.
+  nsSizeMode mEffectiveSizeMode;
   InputContext mInputContext;
   // In headless there is no window manager to track window bounds
   // across size mode changes, so we must track it to emulate.
   LayoutDeviceIntRect mRestoreBounds;
+  void ApplySizeModeSideEffects();
   // Similarly, we must track the active window ourselves in order
   // to dispatch (de)activation events properly.
   void RaiseWindow();
   static HeadlessWidget* sActiveWindow;
 };
 
 } // namespace widget
 } // namespace mozilla