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.
--- 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",