Make IsWidgetStyled use style system to really check whether author styled borders or backgrounds, rather than depending on default values in forms.css. b=240117 r+sr=bzbarsky a=roc

This commit is contained in:
dbaron%dbaron.org 2007-10-08 23:11:02 +00:00
Родитель 82f36a3c3f
Коммит 041b414fb6
8 изменённых файлов: 90 добавлений и 185 удалений

Просмотреть файл

@ -79,6 +79,7 @@
#include "nsIViewManager.h"
#include "nsCSSFrameConstructor.h"
#include "nsStyleChangeList.h"
#include "nsRuleNode.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
@ -1480,3 +1481,9 @@ nsPresContext::IsChrome()
return isChrome;
}
/* virtual */ PRBool
nsPresContext::HasAuthorSpecifiedBorderOrBackground(nsIFrame *aFrame) const
{
return nsRuleNode::
HasAuthorSpecifiedBorderOrBackground(aFrame->GetStyleContext());
}

Просмотреть файл

@ -729,6 +729,9 @@ public:
// Is this presentation in a chrome docshell?
PRBool IsChrome();
// Public API for native theme code to get style internals.
virtual PRBool HasAuthorSpecifiedBorderOrBackground(nsIFrame *aFrame) const;
protected:
friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal();

Просмотреть файл

@ -367,6 +367,12 @@ void nsCSSValue::SetSystemFontValue()
mUnit = eCSSUnit_System_Font;
}
void nsCSSValue::SetDummyValue()
{
Reset();
mUnit = eCSSUnit_Dummy;
}
void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
{
NS_PRECONDITION(eCSSUnit_URL == mUnit, "Not a URL value!");

Просмотреть файл

@ -63,6 +63,8 @@ enum nsCSSUnit {
eCSSUnit_None = 4, // (n/a) value is none
eCSSUnit_Normal = 5, // (n/a) value is normal (algorithmic, different than auto)
eCSSUnit_System_Font = 6, // (n/a) value is -moz-use-system-font
eCSSUnit_Dummy = 7, // (n/a) a fake but specified value, used
// only in temporary values
eCSSUnit_String = 10, // (PRUnichar*) a string value
eCSSUnit_Attr = 11, // (PRUnichar*) a attr(string) value
eCSSUnit_Array = 20, // (nsCSSValue::Array*) a list of values
@ -275,6 +277,7 @@ public:
NS_HIDDEN_(void) SetNoneValue();
NS_HIDDEN_(void) SetNormalValue();
NS_HIDDEN_(void) SetSystemFontValue();
NS_HIDDEN_(void) SetDummyValue();
NS_HIDDEN_(void) StartImageLoad(nsIDocument* aDocument)
const; // Not really const, but pretending

Просмотреть файл

@ -4917,3 +4917,63 @@ nsRuleNode::Sweep()
}
return PR_FALSE;
}
/* static */ PRBool
nsRuleNode::HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext)
{
nsRuleDataColor colorData;
nsRuleDataMargin marginData;
/* We're relying on the use of |aStyleContext| not mutating it! */
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Background) |
NS_STYLE_INHERIT_BIT(Border),
aStyleContext->PresContext(), aStyleContext);
ruleData.mColorData = &colorData;
ruleData.mMarginData = &marginData;
nsCSSValue* values[] = {
&colorData.mBackColor,
&colorData.mBackImage,
&marginData.mBorderColor.mTop,
&marginData.mBorderStyle.mTop,
&marginData.mBorderWidth.mTop,
&marginData.mBorderColor.mRight,
&marginData.mBorderStyle.mRight,
&marginData.mBorderWidth.mRight,
&marginData.mBorderColor.mBottom,
&marginData.mBorderStyle.mBottom,
&marginData.mBorderWidth.mBottom,
&marginData.mBorderColor.mLeft,
&marginData.mBorderStyle.mLeft,
&marginData.mBorderWidth.mLeft
};
// We need to be careful not to count styles covered up by
// user-important or UA-important declarations.
for (nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); ruleNode;
ruleNode = ruleNode->GetParent()) {
nsIStyleRule *rule = ruleNode->GetRule();
if (rule) {
ruleData.mLevel = ruleNode->GetLevel();
ruleData.mIsImportantRule = ruleNode->IsImportantRule();
rule->MapRuleInfoInto(&ruleData);
if (ruleData.mLevel == nsStyleSet::eAgentSheet ||
ruleData.mLevel == nsStyleSet::eUserSheet) {
// 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)
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)
if (values[i]->GetUnit() != eCSSUnit_Null &&
values[i]->GetUnit() != eCSSUnit_Dummy) // see above
return PR_TRUE;
}
}
}
return PR_FALSE;
}

Просмотреть файл

@ -710,6 +710,9 @@ public:
*/
NS_HIDDEN_(void) Mark();
NS_HIDDEN_(PRBool) Sweep();
static PRBool
HasAuthorSpecifiedBorderOrBackground(nsStyleContext* aStyleContext);
};
#endif

Просмотреть файл

@ -50,34 +50,6 @@
#include "nsThemeConstants.h"
#include "nsIComponentManager.h"
nsMargin nsNativeTheme::sButtonBorderSize(2, 2, 2, 2);
PRUint8 nsNativeTheme::sButtonActiveBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
PRUint8 nsNativeTheme::sButtonInactiveBorderStyle = NS_STYLE_BORDER_STYLE_OUTSET;
nsILookAndFeel::nsColorID nsNativeTheme::sButtonBorderColorID = nsILookAndFeel::eColor_buttonface;
nsILookAndFeel::nsColorID nsNativeTheme::sButtonDisabledBorderColorID = nsILookAndFeel::eColor_buttonface;
nsILookAndFeel::nsColorID nsNativeTheme::sButtonBGColorID = nsILookAndFeel::eColor_buttonface;
nsILookAndFeel::nsColorID nsNativeTheme::sButtonDisabledBGColorID = nsILookAndFeel::eColor_buttonface;
nsMargin nsNativeTheme::sTextfieldBorderSize(2, 2, 2, 2);
PRUint8 nsNativeTheme::sTextfieldBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
nsILookAndFeel::nsColorID nsNativeTheme::sTextfieldBorderColorID = nsILookAndFeel::eColor_threedface;
PRBool nsNativeTheme::sTextfieldBGTransparent = PR_FALSE;
nsILookAndFeel::nsColorID nsNativeTheme::sTextfieldBGColorID = nsILookAndFeel::eColor__moz_field;
nsILookAndFeel::nsColorID nsNativeTheme::sTextfieldDisabledBGColorID = nsILookAndFeel::eColor_threedface;
nsMargin nsNativeTheme::sListboxBorderSize(2, 2, 2, 2);
PRUint8 nsNativeTheme::sListboxBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
nsILookAndFeel::nsColorID nsNativeTheme::sListboxBorderColorID = nsILookAndFeel::eColor_threedface;
nsILookAndFeel::nsColorID nsNativeTheme::sListboxBGColorID = nsILookAndFeel::eColor__moz_field;
nsILookAndFeel::nsColorID nsNativeTheme::sListboxDisabledBGColorID = nsILookAndFeel::eColor_threedface;
nsMargin nsNativeTheme::sComboboxBorderSize(2, 2, 2, 2);
PRUint8 nsNativeTheme::sComboboxBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
nsILookAndFeel::nsColorID nsNativeTheme::sComboboxBorderColorID = nsILookAndFeel::eColor_threedface;
PRBool nsNativeTheme::sComboboxBGTransparent = PR_FALSE;
nsILookAndFeel::nsColorID nsNativeTheme::sComboboxBGColorID = nsILookAndFeel::eColor__moz_field;
nsILookAndFeel::nsColorID nsNativeTheme::sComboboxDisabledBGColorID = nsILookAndFeel::eColor_threedface;
nsNativeTheme::nsNativeTheme()
{
}
@ -182,136 +154,19 @@ nsNativeTheme::GetCheckedOrSelected(nsIFrame* aFrame, PRBool aCheckSelected)
: nsWidgetAtoms::checked);
}
static void
ConvertBorderToAppUnits(nsPresContext* aPresContext, const nsMargin &aSource, nsMargin &aDest)
{
PRInt32 cp2a = nsPresContext::AppUnitsPerCSSPixel();
PRInt32 dp2a = aPresContext->AppUnitsPerDevPixel();
aDest.top = NS_ROUND_BORDER_TO_PIXELS(NSIntPixelsToAppUnits(aSource.top, cp2a), dp2a);
aDest.left = NS_ROUND_BORDER_TO_PIXELS(NSIntPixelsToAppUnits(aSource.left, cp2a), dp2a);
aDest.bottom = NS_ROUND_BORDER_TO_PIXELS(NSIntPixelsToAppUnits(aSource.bottom, cp2a), dp2a);
aDest.right = NS_ROUND_BORDER_TO_PIXELS(NSIntPixelsToAppUnits(aSource.right, cp2a), dp2a);;
}
PRBool
nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, nsIFrame* aFrame,
PRUint8 aWidgetType)
{
// Check for specific widgets to see if HTML has overridden the style.
if (aFrame && (aWidgetType == NS_THEME_BUTTON ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
aWidgetType == NS_THEME_LISTBOX ||
aWidgetType == NS_THEME_DROPDOWN)) {
if (aFrame->GetContent()->IsNodeOfType(nsINode::eHTML)) {
nscolor defaultBGColor;
nscolor defaultBorderColor;
PRUint8 defaultBorderStyle;
nsMargin defaultBorderSize;
PRBool defaultBGTransparent = PR_FALSE;
nsILookAndFeel *lookAndFeel = aPresContext->LookAndFeel();
switch (aWidgetType) {
case NS_THEME_BUTTON:
ConvertBorderToAppUnits(aPresContext, sButtonBorderSize,
defaultBorderSize);
if (IsDisabled(aFrame)) {
defaultBorderStyle = sButtonInactiveBorderStyle;
lookAndFeel->GetColor(sButtonDisabledBorderColorID,
defaultBorderColor);
lookAndFeel->GetColor(sButtonDisabledBGColorID,
defaultBGColor);
} else {
PRInt32 contentState = GetContentState(aFrame, aWidgetType);
if (contentState & NS_EVENT_STATE_HOVER &&
contentState & NS_EVENT_STATE_ACTIVE)
defaultBorderStyle = sButtonActiveBorderStyle;
else
defaultBorderStyle = sButtonInactiveBorderStyle;
lookAndFeel->GetColor(sButtonBorderColorID,
defaultBorderColor);
lookAndFeel->GetColor(sButtonBGColorID,
defaultBGColor);
}
break;
case NS_THEME_TEXTFIELD:
case NS_THEME_TEXTFIELD_MULTILINE:
defaultBorderStyle = sTextfieldBorderStyle;
ConvertBorderToAppUnits(aPresContext, sTextfieldBorderSize, defaultBorderSize);
lookAndFeel->GetColor(sTextfieldBorderColorID, defaultBorderColor);
defaultBGTransparent = sTextfieldBGTransparent;
if (!defaultBGTransparent) {
if (IsDisabled(aFrame))
lookAndFeel->GetColor(sTextfieldDisabledBGColorID, defaultBGColor);
else
lookAndFeel->GetColor(sTextfieldBGColorID, defaultBGColor);
}
break;
case NS_THEME_LISTBOX:
defaultBorderStyle = sListboxBorderStyle;
ConvertBorderToAppUnits(aPresContext, sListboxBorderSize, defaultBorderSize);
lookAndFeel->GetColor(sListboxBorderColorID, defaultBorderColor);
if (IsDisabled(aFrame))
lookAndFeel->GetColor(sListboxDisabledBGColorID, defaultBGColor);
else
lookAndFeel->GetColor(sListboxBGColorID, defaultBGColor);
break;
case NS_THEME_DROPDOWN:
defaultBorderStyle = sComboboxBorderStyle;
ConvertBorderToAppUnits(aPresContext, sComboboxBorderSize, defaultBorderSize);
lookAndFeel->GetColor(sComboboxBorderColorID, defaultBorderColor);
defaultBGTransparent = sComboboxBGTransparent;
if (!defaultBGTransparent) {
if (IsDisabled(aFrame))
lookAndFeel->GetColor(sComboboxDisabledBGColorID, defaultBGColor);
else
lookAndFeel->GetColor(sComboboxBGColorID, defaultBGColor);
}
break;
default:
NS_ERROR("nsNativeTheme::IsWidgetStyled widget type not handled");
return PR_FALSE;
}
// Check whether background differs from default
const nsStyleBackground* ourBG = aFrame->GetStyleBackground();
if (defaultBGTransparent) {
if (!(ourBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT))
return PR_TRUE;
} else if (ourBG->mBackgroundColor != defaultBGColor ||
ourBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)
return PR_TRUE;
if (!(ourBG->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE))
return PR_TRUE;
// Check whether border style or color differs from default
const nsStyleBorder* ourBorder = aFrame->GetStyleBorder();
for (PRInt32 i = 0; i < 4; ++i) {
if (ourBorder->GetBorderStyle(i) != defaultBorderStyle)
return PR_TRUE;
PRBool borderFG, borderClear;
nscolor borderColor;
ourBorder->GetBorderColor(i, borderColor, borderFG, borderClear);
if (borderColor != defaultBorderColor || borderClear)
return PR_TRUE;
}
// Check whether border size differs from default
if (ourBorder->GetBorder() != defaultBorderSize)
return PR_TRUE;
}
}
return PR_FALSE;
return aFrame &&
(aWidgetType == NS_THEME_BUTTON ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
aWidgetType == NS_THEME_LISTBOX ||
aWidgetType == NS_THEME_DROPDOWN) &&
aFrame->GetContent()->IsNodeOfType(nsINode::eHTML) &&
aPresContext->HasAuthorSpecifiedBorderOrBackground(aFrame);
}
// treeheadercell:

Просмотреть файл

@ -134,36 +134,4 @@ class nsNativeTheme
PRBool CheckBooleanAttr(nsIFrame* aFrame, nsIAtom* aAtom);
PRBool GetCheckedOrSelected(nsIFrame* aFrame, PRBool aCheckSelected);
// The following should be set to appropriate platform values by the subclass,
// to match the values in forms.css. The defaults match forms.css.
// push buttons
static nsMargin sButtonBorderSize;
static PRUint8 sButtonActiveBorderStyle;
static PRUint8 sButtonInactiveBorderStyle;
static nsILookAndFeel::nsColorID sButtonBorderColorID;
static nsILookAndFeel::nsColorID sButtonDisabledBorderColorID;
static nsILookAndFeel::nsColorID sButtonBGColorID;
static nsILookAndFeel::nsColorID sButtonDisabledBGColorID;
// text fields
static nsMargin sTextfieldBorderSize;
static PRUint8 sTextfieldBorderStyle;
static nsILookAndFeel::nsColorID sTextfieldBorderColorID;
static PRBool sTextfieldBGTransparent;
static nsILookAndFeel::nsColorID sTextfieldBGColorID;
static nsILookAndFeel::nsColorID sTextfieldDisabledBGColorID;
// listboxes
static nsMargin sListboxBorderSize;
static PRUint8 sListboxBorderStyle;
static nsILookAndFeel::nsColorID sListboxBorderColorID;
static nsILookAndFeel::nsColorID sListboxBGColorID;
static nsILookAndFeel::nsColorID sListboxDisabledBGColorID;
// comboboxes
static nsMargin sComboboxBorderSize;
static PRUint8 sComboboxBorderStyle;
static nsILookAndFeel::nsColorID sComboboxBorderColorID;
static PRBool sComboboxBGTransparent;
static nsILookAndFeel::nsColorID sComboboxBGColorID;
static nsILookAndFeel::nsColorID sComboboxDisabledBGColorID;
};