Bug 1241275 - Change the way -moz-window-dragging works. r?dbaron, r?roc draft
authorMarkus Stange <mstange@themasta.com>
Wed, 27 Jan 2016 11:58:33 +0100
changeset 326048 61cab4e535c6c5da75fe79eb1886b6c5b7d136ea
parent 325864 16cf525a8b110701bcbb1ac02b749dc2acb956f4
child 513551 a651223bbebf74d3a084edc79ff089c03541a992
push id10094
push usermstange@themasta.com
push dateWed, 27 Jan 2016 11:39:29 +0000
reviewersdbaron, roc
bugs1241275
milestone46.0a1
Bug 1241275 - Change the way -moz-window-dragging works. r?dbaron, r?roc This adds the value -moz-window-dragging: default as the initial value of the property, and makes it a [reset] property. This allows us to change the way the window dragging region is calculated: Elements with -moz-window-dragging: no-drag will now always be undraggable, even if they are overlapped by -moz-window-dragging: drag elements. That way we can keep the region calculation simple and don't have to add code to respect z-ordering.
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1177,16 +1177,23 @@ nsDisplayListBuilder::RecomputeCurrentAn
 
 void
 nsDisplayListBuilder::AdjustWindowDraggingRegion(nsIFrame* aFrame)
 {
   if (!mWindowDraggingAllowed || !IsForPainting()) {
     return;
   }
 
+  const nsStyleUIReset* styleUI = aFrame->StyleUIReset();
+  if (styleUI->mWindowDragging == NS_STYLE_WINDOW_DRAGGING_DEFAULT) {
+    // This frame has the default value and doesn't influence the window
+    // dragging region.
+    return;
+  }
+
   LayoutDeviceToLayoutDeviceMatrix4x4 referenceFrameToRootReferenceFrame;
 
   // The const_cast is for nsLayoutUtils::GetTransformToAncestor.
   nsIFrame* referenceFrame = const_cast<nsIFrame*>(FindReferenceFrameFor(aFrame));
 
   if (IsInTransform()) {
     // Only support 2d rectilinear transforms. Transform support is needed for
     // the horizontal flip transform that's applied to the urlbar textbox in
@@ -1226,26 +1233,33 @@ nsDisplayListBuilder::AdjustWindowDraggi
   if (!borderBox.IsEmpty()) {
     LayoutDeviceRect devPixelBorderBox =
       LayoutDevicePixel::FromAppUnits(borderBox, aFrame->PresContext()->AppUnitsPerDevPixel());
     LayoutDeviceRect transformedDevPixelBorderBox =
       TransformBy(referenceFrameToRootReferenceFrame, devPixelBorderBox);
     transformedDevPixelBorderBox.Round();
     LayoutDeviceIntRect transformedDevPixelBorderBoxInt;
     if (transformedDevPixelBorderBox.ToIntRect(&transformedDevPixelBorderBoxInt)) {
-      const nsStyleUserInterface* styleUI = aFrame->StyleUserInterface();
       if (styleUI->mWindowDragging == NS_STYLE_WINDOW_DRAGGING_DRAG) {
         mWindowDraggingRegion.OrWith(transformedDevPixelBorderBoxInt);
       } else {
-        mWindowDraggingRegion.SubOut(transformedDevPixelBorderBoxInt);
+        mWindowNoDraggingRegion.OrWith(transformedDevPixelBorderBoxInt);
       }
     }
   }
 }
 
+LayoutDeviceIntRegion
+nsDisplayListBuilder::GetWindowDraggingRegion() const
+{
+  LayoutDeviceIntRegion result;
+  result.Sub(mWindowDraggingRegion, mWindowNoDraggingRegion);;
+  return result;
+}
+
 const uint32_t gWillChangeAreaMultiplier = 3;
 static uint32_t GetWillChangeCost(const nsSize& aSize) {
   // There's significant overhead for each layer created from Gecko
   // (IPC+Shared Objects) and from the backend (like an OpenGL texture).
   // Therefore we set a minimum cost threshold of a 64x64 area.
   int minBudgetCost = 64 * 64;
 
   uint32_t budgetCost =
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -614,17 +614,17 @@ public:
   /**
    * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
    * -moz-window-dragging value is |drag|, its border box is added to the
    * collected dragging region; if the value is |no-drag|, the border box is
    * subtracted from the region.
    */
   void AdjustWindowDraggingRegion(nsIFrame* aFrame);
 
-  const LayoutDeviceIntRegion& GetWindowDraggingRegion() { return mWindowDraggingRegion; }
+  LayoutDeviceIntRegion GetWindowDraggingRegion() const;
 
   /**
    * Allocate memory in our arena. It will only be freed when this display list
    * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
    * destructors are called as soon as the item is no longer used.
    */
   void* Allocate(size_t aSize);
 
@@ -1223,16 +1223,17 @@ private:
   // rects are relative to the frame's reference frame
   nsDataHashtable<nsPtrHashKey<nsIFrame>, nsRect> mDirtyRectForScrolledContents;
 
   // Relative to mCurrentFrame.
   nsRect                         mDirtyRect;
   nsRegion                       mWindowExcludeGlassRegion;
   nsRegion                       mWindowOpaqueRegion;
   LayoutDeviceIntRegion          mWindowDraggingRegion;
+  LayoutDeviceIntRegion          mWindowNoDraggingRegion;
   // The display item for the Windows window glass background, if any
   nsDisplayItem*                 mGlassDisplayItem;
   // When encountering inactive layers, we need to hoist scroll info items
   // above these layers so APZ can deliver events to content. Such scroll
   // info items are considered "committed" to the final hoisting list. If
   // no hoisting is needed immediately, it may be needed later if a blend
   // mode is introduced in a higher stacking context, so we keep all scroll
   // info items until the end of display list building.
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3669,17 +3669,17 @@ CSS_PROP_POSITION(
         CSS_PROPERTY_STORES_CALC |
         CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
         CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
     "",
     VARIANT_AHKLP | VARIANT_CALC,
     kWidthKTable,
     offsetof(nsStylePosition, mWidth),
     eStyleAnimType_Coord)
-CSS_PROP_USERINTERFACE(
+CSS_PROP_UIRESET(
     -moz-window-dragging,
     _moz_window_dragging,
     CSS_PROP_DOMPROP_PREFIXED(WindowDragging),
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kWindowDraggingKTable,
     CSS_PROP_NO_OFFSET,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -2093,16 +2093,17 @@ const KTableEntry nsCSSProps::kWidthKTab
   { eCSSKeyword__moz_max_content, NS_STYLE_WIDTH_MAX_CONTENT },
   { eCSSKeyword__moz_min_content, NS_STYLE_WIDTH_MIN_CONTENT },
   { eCSSKeyword__moz_fit_content, NS_STYLE_WIDTH_FIT_CONTENT },
   { eCSSKeyword__moz_available, NS_STYLE_WIDTH_AVAILABLE },
   { eCSSKeyword_UNKNOWN, -1 }
 };
 
 const KTableEntry nsCSSProps::kWindowDraggingKTable[] = {
+  { eCSSKeyword_default, NS_STYLE_WINDOW_DRAGGING_DEFAULT },
   { eCSSKeyword_drag, NS_STYLE_WINDOW_DRAGGING_DRAG },
   { eCSSKeyword_no_drag, NS_STYLE_WINDOW_DRAGGING_NO_DRAG },
   { eCSSKeyword_UNKNOWN, -1 }
 };
 
 const KTableEntry nsCSSProps::kWindowShadowKTable[] = {
   { eCSSKeyword_none, NS_STYLE_WINDOW_SHADOW_NONE },
   { eCSSKeyword_default, NS_STYLE_WINDOW_SHADOW_DEFAULT },
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -3820,17 +3820,17 @@ nsComputedDOMStyle::DoGetWhiteSpace()
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetWindowDragging()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
-    nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mWindowDragging,
+    nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mWindowDragging,
                                    nsCSSProps::kWindowDraggingKTable));
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetWindowShadow()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -4858,23 +4858,16 @@ nsRuleNode::ComputeUserInterfaceData(voi
 
   // user-focus: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForUserFocus(),
               ui->mUserFocus, conditions,
               SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT,
               parentUI->mUserFocus,
               NS_STYLE_USER_FOCUS_NONE, 0, 0, 0, 0);
 
-  // -moz-window-dragging: enum, inherit, initial
-  SetDiscrete(*aRuleData->ValueForWindowDragging(),
-              ui->mWindowDragging, conditions,
-              SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT,
-              parentUI->mWindowDragging,
-              NS_STYLE_WINDOW_DRAGGING_NO_DRAG, 0, 0, 0, 0);
-
   COMPUTE_END_INHERITED(UserInterface, ui)
 }
 
 const void*
 nsRuleNode::ComputeUIResetData(void* aStartStruct,
                                const nsRuleData* aRuleData,
                                nsStyleContext* aContext,
                                nsRuleNode* aHighestNode,
@@ -4900,16 +4893,23 @@ nsRuleNode::ComputeUIResetData(void* aSt
   // force-broken-image-icons: integer, inherit, initial
   SetDiscrete(*aRuleData->ValueForForceBrokenImageIcon(),
               ui->mForceBrokenImageIcon,
               conditions,
               SETDSC_INTEGER | SETDSC_UNSET_INITIAL,
               parentUI->mForceBrokenImageIcon,
               0, 0, 0, 0, 0);
 
+  // -moz-window-dragging: enum, inherit, initial
+  SetDiscrete(*aRuleData->ValueForWindowDragging(),
+              ui->mWindowDragging, conditions,
+              SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
+              parentUI->mWindowDragging,
+              NS_STYLE_WINDOW_DRAGGING_DEFAULT, 0, 0, 0, 0);
+
   // -moz-window-shadow: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForWindowShadow(),
               ui->mWindowShadow, conditions,
               SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
               parentUI->mWindowShadow,
               NS_STYLE_WINDOW_SHADOW_DEFAULT, 0, 0, 0, 0);
 
   COMPUTE_END_RESET(UIReset, ui)
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -115,18 +115,19 @@ enum class StyleBoxSizing : uint8_t {
 #define NS_STYLE_USER_INPUT_AUTO      3
 
 // user-modify
 #define NS_STYLE_USER_MODIFY_READ_ONLY   0
 #define NS_STYLE_USER_MODIFY_READ_WRITE  1
 #define NS_STYLE_USER_MODIFY_WRITE_ONLY  2
 
 // -moz-window-dragging
-#define NS_STYLE_WINDOW_DRAGGING_DRAG    0
-#define NS_STYLE_WINDOW_DRAGGING_NO_DRAG 1
+#define NS_STYLE_WINDOW_DRAGGING_DEFAULT 0
+#define NS_STYLE_WINDOW_DRAGGING_DRAG    1
+#define NS_STYLE_WINDOW_DRAGGING_NO_DRAG 2
 
 // box-align
 #define NS_STYLE_BOX_ALIGN_STRETCH     0
 #define NS_STYLE_BOX_ALIGN_START       1
 #define NS_STYLE_BOX_ALIGN_CENTER      2
 #define NS_STYLE_BOX_ALIGN_BASELINE    3
 #define NS_STYLE_BOX_ALIGN_END         4
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3681,29 +3681,27 @@ nsCursorImage::operator=(const nsCursorI
 }
 
 nsStyleUserInterface::nsStyleUserInterface(void) 
 { 
   MOZ_COUNT_CTOR(nsStyleUserInterface);
   mUserInput = NS_STYLE_USER_INPUT_AUTO;
   mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
   mUserFocus = NS_STYLE_USER_FOCUS_NONE;
-  mWindowDragging = NS_STYLE_WINDOW_DRAGGING_NO_DRAG;
 
   mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
 
   mCursorArrayLength = 0;
   mCursorArray = nullptr;
 }
 
 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
   mUserInput(aSource.mUserInput),
   mUserModify(aSource.mUserModify),
   mUserFocus(aSource.mUserFocus),
-  mWindowDragging(aSource.mWindowDragging),
   mCursor(aSource.mCursor)
 { 
   MOZ_COUNT_CTOR(nsStyleUserInterface);
   CopyCursorArrayFrom(aSource);
 }
 
 nsStyleUserInterface::~nsStyleUserInterface(void) 
 { 
@@ -3733,20 +3731,16 @@ nsChangeHint nsStyleUserInterface::CalcD
       NS_UpdateHint(hint, nsChangeHint_NeutralChange);
     }
   }
 
   if (mUserFocus != aOther.mUserFocus) {
     NS_UpdateHint(hint, nsChangeHint_NeutralChange);
   }
 
-  if (mWindowDragging != aOther.mWindowDragging) {
-    NS_UpdateHint(hint, nsChangeHint_SchedulePaint);
-  }
-
   return hint;
 }
 
 void
 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
 {
   mCursorArray = nullptr;
   mCursorArrayLength = 0;
@@ -3765,25 +3759,27 @@ nsStyleUserInterface::CopyCursorArrayFro
 //
 
 nsStyleUIReset::nsStyleUIReset(void) 
 { 
   MOZ_COUNT_CTOR(nsStyleUIReset);
   mUserSelect = NS_STYLE_USER_SELECT_AUTO;
   mForceBrokenImageIcon = 0;
   mIMEMode = NS_STYLE_IME_MODE_AUTO;
+  mWindowDragging = NS_STYLE_WINDOW_DRAGGING_DEFAULT;
   mWindowShadow = NS_STYLE_WINDOW_SHADOW_DEFAULT;
 }
 
 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) 
 {
   MOZ_COUNT_CTOR(nsStyleUIReset);
   mUserSelect = aSource.mUserSelect;
   mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
   mIMEMode = aSource.mIMEMode;
+  mWindowDragging = aSource.mWindowDragging;
   mWindowShadow = aSource.mWindowShadow;
 }
 
 nsStyleUIReset::~nsStyleUIReset(void) 
 { 
   MOZ_COUNT_DTOR(nsStyleUIReset);
 }
 
@@ -3795,16 +3791,21 @@ nsChangeHint nsStyleUIReset::CalcDiffere
   if (mWindowShadow != aOther.mWindowShadow) {
     // We really need just an nsChangeHint_SyncFrameView, except
     // on an ancestor of the frame, so we get that by doing a
     // reflow.
     return NS_STYLE_HINT_REFLOW;
   }
   if (mUserSelect != aOther.mUserSelect)
     return NS_STYLE_HINT_VISUAL;
+
+  if (mWindowDragging != aOther.mWindowDragging) {
+    return nsChangeHint_SchedulePaint;
+  }
+
   return NS_STYLE_HINT_NONE;
 }
 
 //-----------------------
 // nsStyleVariables
 //
 
 nsStyleVariables::nsStyleVariables()
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2860,16 +2860,17 @@ struct nsStyleUIReset
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
            nsChangeHint_ClearAncestorIntrinsics;
   }
 
   uint8_t   mUserSelect;      // [reset] (selection-style)
   uint8_t   mForceBrokenImageIcon; // [reset]  (0 if not forcing, otherwise forcing)
   uint8_t   mIMEMode;         // [reset]
+  uint8_t   mWindowDragging;  // [reset]
   uint8_t   mWindowShadow;    // [reset]
 };
 
 struct nsCursorImage
 {
   bool mHaveHotspot;
   float mHotspotX, mHotspotY;
 
@@ -2926,17 +2927,16 @@ struct nsStyleUserInterface
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
            nsChangeHint_ClearAncestorIntrinsics;
   }
 
   uint8_t   mUserInput;       // [inherited]
   uint8_t   mUserModify;      // [inherited] (modify-content)
   uint8_t   mUserFocus;       // [inherited] (auto-select)
-  uint8_t   mWindowDragging;  // [inherited]
 
   uint8_t   mCursor;          // [inherited] See nsStyleConsts.h
 
   uint32_t mCursorArrayLength;
   nsCursorImage *mCursorArray;// [inherited] The specified URL values
                               //   and coordinates.  Takes precedence over
                               //   mCursor.  Zero-length array is represented
                               //   by null pointer.
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -4229,20 +4229,20 @@ var gCSSProperties = {
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
     other_values: [ "non-scaling-stroke" ],
     invalid_values: []
   },
   "-moz-window-dragging": {
     domProp: "MozWindowDragging",
-    inherited: true,
-    type: CSS_TYPE_LONGHAND,
-    initial_values: [ "no-drag" ],
-    other_values: [ "drag" ],
+    inherited: false,
+    type: CSS_TYPE_LONGHAND,
+    initial_values: [ "default" ],
+    other_values: [ "drag", "no-drag" ],
     invalid_values: [ "none" ]
   },
   "align-content": {
     domProp: "alignContent",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "normal" ],
     other_values: [ "start", "end", "flex-start", "flex-end", "center", "left",