b=427122, padding on select elements is ignored ; r=dbaron, a=beltzner

This commit is contained in:
vladimir@pobox.com 2008-04-25 16:12:45 -07:00
parent ff1f851a4f
commit 32bee1faae
9 changed files with 127 additions and 19 deletions

View File

@ -1499,8 +1499,8 @@ nsPresContext::IsChrome() const
}
/* virtual */ PRBool
nsPresContext::HasAuthorSpecifiedBorderOrBackground(nsIFrame *aFrame) const
nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const
{
return nsRuleNode::
HasAuthorSpecifiedBorderOrBackground(aFrame->GetStyleContext());
HasAuthorSpecifiedRules(aFrame->GetStyleContext(), ruleTypeMask);
}

View File

@ -137,6 +137,11 @@ enum nsLayoutPhase {
};
#endif
/* Used by nsPresContext::HasAuthorSpecifiedRules */
#define NS_AUTHOR_SPECIFIED_BACKGROUND (1 << 0)
#define NS_AUTHOR_SPECIFIED_BORDER (1 << 1)
#define NS_AUTHOR_SPECIFIED_PADDING (1 << 2)
// An interface for presentation contexts. Presentation contexts are
// objects that provide an outer context for a presentation shell.
@ -741,7 +746,7 @@ public:
PRBool IsChrome() const;
// Public API for native theme code to get style internals.
virtual PRBool HasAuthorSpecifiedBorderOrBackground(nsIFrame *aFrame) const;
virtual PRBool HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const;
// Is it OK to let the page specify colors and backgrounds?
PRBool UseDocumentColors() const {

View File

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<style>
div {
border: 1px solid black;
}
select {
}
</style>
<body>
<div><select><option>Hello</option></select></div>
</body>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html>
<style>
div {
border: 1px solid black;
}
select {
padding: 10px;
}
</style>
<body>
<div><select><option>Hello</option></select></div>
</body>
</html>

View File

@ -26,3 +26,7 @@
!= checkbox-native.html checkbox-nonnative.html
== checkbox-still-native-when-styled.html checkbox-still-native-when-styled-ref.html
== native-theme-disabled-cascade-levels.html native-theme-disabled-cascade-levels-ref.html
# mac ignores padding on most native widgets and has done so for a while
fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") != 427122-1.html 427122-1-ref.html

View File

@ -5159,20 +5159,35 @@ nsRuleNode::Sweep()
}
/* static */ PRBool
nsRuleNode::HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext)
nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
PRUint32 ruleTypeMask)
{
nsRuleDataColor colorData;
nsRuleDataMargin marginData;
PRUint32 nValues = 0;
PRUint32 inheritBits = 0;
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND)
inheritBits |= NS_STYLE_INHERIT_BIT(Background);
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER)
inheritBits |= NS_STYLE_INHERIT_BIT(Border);
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING)
inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
/* We're relying on the use of |aStyleContext| not mutating it! */
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Background) |
NS_STYLE_INHERIT_BIT(Border),
nsRuleData ruleData(inheritBits,
aStyleContext->PresContext(), aStyleContext);
ruleData.mColorData = &colorData;
ruleData.mMarginData = &marginData;
nsCSSValue* values[] = {
nsCSSValue* backgroundValues[] = {
&colorData.mBackColor,
&colorData.mBackImage,
&colorData.mBackImage
};
nsCSSValue* borderValues[] = {
&marginData.mBorderColor.mTop,
&marginData.mBorderStyle.mTop,
&marginData.mBorderWidth.mTop,
@ -5185,8 +5200,37 @@ nsRuleNode::HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext)
&marginData.mBorderColor.mLeft,
&marginData.mBorderStyle.mLeft,
&marginData.mBorderWidth.mLeft
// XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
};
nsCSSValue* paddingValues[] = {
&marginData.mPadding.mTop,
&marginData.mPadding.mRight,
&marginData.mPadding.mBottom,
&marginData.mPadding.mLeft,
&marginData.mPaddingStart,
&marginData.mPaddingEnd
};
nsCSSValue* values[NS_ARRAY_LENGTH(backgroundValues) +
NS_ARRAY_LENGTH(borderValues) +
NS_ARRAY_LENGTH(paddingValues)];
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
memcpy(&values[nValues], backgroundValues, NS_ARRAY_LENGTH(backgroundValues) * sizeof(nsCSSValue*));
nValues += NS_ARRAY_LENGTH(backgroundValues);
}
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
memcpy(&values[nValues], borderValues, NS_ARRAY_LENGTH(borderValues) * sizeof(nsCSSValue*));
nValues += NS_ARRAY_LENGTH(borderValues);
}
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
memcpy(&values[nValues], paddingValues, NS_ARRAY_LENGTH(paddingValues) * sizeof(nsCSSValue*));
nValues += NS_ARRAY_LENGTH(paddingValues);
}
// We need to be careful not to count styles covered up by
// user-important or UA-important declarations.
for (nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); ruleNode;
@ -5201,13 +5245,13 @@ nsRuleNode::HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext)
// This is a rule whose effect we want to ignore, so if any of
// the properties we care about were set, set them to the dummy
// value that they'll never otherwise get.
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(values); ++i)
for (PRUint32 i = 0; i < nValues; ++i)
if (values[i]->GetUnit() != eCSSUnit_Null)
values[i]->SetDummyValue();
} else {
// If any of the values we care about was set by the above rule,
// we have author style.
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(values); ++i)
for (PRUint32 i = 0; i < nValues; ++i)
if (values[i]->GetUnit() != eCSSUnit_Null &&
values[i]->GetUnit() != eCSSUnit_Dummy) // see above
return PR_TRUE;

View File

@ -722,7 +722,7 @@ public:
NS_HIDDEN_(PRBool) Sweep();
static PRBool
HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext);
HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, PRUint32 ruleTypeMask);
};
#endif

View File

@ -468,6 +468,15 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
if (!mThemeDLL)
return NULL;
if (!mIsVistaOrLater) {
// On XP or earlier, render dropdowns as textfields;
// doing it the right way works fine with the MS themes,
// but breaks on a lot of custom themes (presumably because MS
// apps do the textfield border business as well).
if (aWidgetType == NS_THEME_DROPDOWN)
aWidgetType = NS_THEME_TEXTFIELD;
}
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_RADIO:
@ -639,6 +648,12 @@ nsresult
nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
PRInt32& aPart, PRInt32& aState)
{
if (!mIsVistaOrLater) {
// See GetTheme
if (aWidgetType == NS_THEME_DROPDOWN)
aWidgetType = NS_THEME_TEXTFIELD;
}
switch (aWidgetType) {
case NS_THEME_BUTTON: {
aPart = BP_BUTTON;
@ -1544,6 +1559,15 @@ nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext,
}
if (mIsVistaOrLater) {
if (aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
aWidgetType == NS_THEME_DROPDOWN)
{
/* If we have author-specified padding for these elements, don't do the fixups below */
if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
return PR_FALSE;
}
/* textfields need extra pixels on all sides, otherwise they
* wrap their content too tightly. The actual border is drawn 1px
* inside the specified rectangle, so Gecko will end up making the
@ -1554,13 +1578,7 @@ nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext,
aResult->top = aResult->bottom = 2;
aResult->left = aResult->right = 2;
return PR_TRUE;
}
}
// Some things only apply to widgets in HTML content, since
// they're drawn differently
if (IsHTMLContent(aFrame)) {
if (aWidgetType == NS_THEME_DROPDOWN) {
} else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_DROPDOWN) {
/* For content menulist controls, we need an extra pixel so
* that we have room to draw our focus rectangle stuff.
* Otherwise, the focus rect might overlap the control's

View File

@ -166,7 +166,9 @@ nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, nsIFrame* aFrame,
aWidgetType == NS_THEME_LISTBOX ||
aWidgetType == NS_THEME_DROPDOWN) &&
aFrame->GetContent()->IsNodeOfType(nsINode::eHTML) &&
aPresContext->HasAuthorSpecifiedBorderOrBackground(aFrame);
aPresContext->HasAuthorSpecifiedRules(aFrame,
NS_AUTHOR_SPECIFIED_BORDER |
NS_AUTHOR_SPECIFIED_BACKGROUND);
}
// scrollbar button: