Bug 474878. Implement themed rendering of indeterminate checkboxes on Windows. r+sr=roc

This commit is contained in:
Sylvain Pasche 2009-02-05 21:17:08 +13:00
parent 31567fc527
commit 1ef7f0375b
6 changed files with 48 additions and 58 deletions

View File

@ -0,0 +1 @@
<input type="checkbox" checked>

View File

@ -0,0 +1 @@
<input type="checkbox" id="s" checked><script>document.getElementById("s").indeterminate = true;</script>

View File

@ -0,0 +1 @@
<input type="checkbox">

View File

@ -0,0 +1 @@
<input type="checkbox" id="s"><script>document.getElementById("s").indeterminate = true;</script>

View File

@ -7,3 +7,5 @@
== out-of-bounds-selectedindex.html out-of-bounds-selectedindex-ref.html # bug 471741
!= indeterminate-checked.html indeterminate-checked-notref.html
!= indeterminate-unchecked.html indeterminate-unchecked-notref.html
!= indeterminate-native-checked.html indeterminate-native-checked-notref.html
!= indeterminate-native-unchecked.html indeterminate-native-unchecked-notref.html

View File

@ -417,45 +417,30 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
aPart = isCheckbox ? BP_CHECKBOX : BP_RADIO;
// XXXdwh This check will need to be more complicated, since HTML radio groups
// use checked, but XUL radio groups use selected. There will need to be an
// IsNodeOfType test for HTML vs. XUL here.
nsIAtom* atom = isCheckbox ? nsWidgetAtoms::checked
: nsWidgetAtoms::selected;
PRBool isHTML = PR_FALSE;
PRBool isHTMLChecked = PR_FALSE;
enum InputState {
UNCHECKED = 0, CHECKED, INDETERMINATE
};
InputState inputState = UNCHECKED;
PRBool isXULCheckboxRadio = PR_FALSE;
if (!aFrame)
if (!aFrame) {
aState = TS_NORMAL;
else {
// For XUL checkboxes and radio buttons, the state of the parent
// determines our state.
nsIContent* content = aFrame->GetContent();
PRBool isXULCheckboxRadio = content->IsNodeOfType(nsINode::eXUL);
if (!isXULCheckboxRadio) {
// Attempt a QI.
nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(content));
if (inputElt) {
inputElt->GetChecked(&isHTMLChecked);
isHTML = PR_TRUE;
}
} else {
if (GetCheckedOrSelected(aFrame, !isCheckbox)) {
inputState = CHECKED;
} if (isCheckbox && GetIndeterminate(aFrame)) {
inputState = INDETERMINATE;
}
if (IsDisabled(isXULCheckboxRadio ? aFrame->GetParent(): aFrame))
if (IsDisabled(isXULCheckboxRadio ? aFrame->GetParent() : aFrame)) {
aState = TS_DISABLED;
else {
} else {
aState = StandardGetState(aFrame, aWidgetType, PR_FALSE);
}
}
if (isHTML) {
if (isHTMLChecked)
aState += 4;
}
else if (isCheckbox ? IsChecked(aFrame) : IsSelected(aFrame))
aState += 4; // 4 unchecked states, 4 checked states.
// 4 unchecked states, 4 checked states, 4 indeterminate states.
aState += inputState * 4;
return NS_OK;
}
case NS_THEME_TEXTFIELD:
@ -1994,44 +1979,43 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
}
case NS_THEME_CHECKBOX:
case NS_THEME_RADIO: {
PRInt32 contentState ;
PRInt32 contentState;
aFocused = PR_FALSE;
aPart = DFC_BUTTON;
aState = (aWidgetType == NS_THEME_CHECKBOX) ? DFCS_BUTTONCHECK : DFCS_BUTTONRADIO;
aState = 0;
nsIContent* content = aFrame->GetContent();
if (content->IsNodeOfType(nsINode::eXUL)) {
// XUL
if (aWidgetType == NS_THEME_CHECKBOX) {
if (IsChecked(aFrame))
aState |= DFCS_CHECKED;
}
else
if (IsSelected(aFrame))
aState |= DFCS_CHECKED;
contentState = GetContentState(aFrame, aWidgetType);
}
else {
// HTML
PRBool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
PRBool isChecked = GetCheckedOrSelected(aFrame, !isCheckbox);
PRBool isIndeterminate = isCheckbox && GetIndeterminate(aFrame);
nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(content));
if (inputElt) {
PRBool isChecked = PR_FALSE;
inputElt->GetChecked(&isChecked);
if (isChecked)
aState |= DFCS_CHECKED;
if (isCheckbox) {
// indeterminate state takes precedence over checkedness.
if (isIndeterminate) {
aState = DFCS_BUTTON3STATE | DFCS_CHECKED;
} else {
aState = DFCS_BUTTONCHECK;
}
contentState = GetContentState(aFrame, aWidgetType);
if (contentState & NS_EVENT_STATE_FOCUS)
aFocused = PR_TRUE;
} else {
aState = DFCS_BUTTONRADIO;
}
if (isChecked) {
aState |= DFCS_CHECKED;
}
if (IsDisabled(aFrame))
contentState = GetContentState(aFrame, aWidgetType);
if (!content->IsNodeOfType(nsINode::eXUL) &&
(contentState & NS_EVENT_STATE_FOCUS)) {
aFocused = PR_TRUE;
}
if (IsDisabled(aFrame)) {
aState |= DFCS_INACTIVE;
else if (contentState & NS_EVENT_STATE_ACTIVE && contentState & NS_EVENT_STATE_HOVER)
} else if (contentState & NS_EVENT_STATE_ACTIVE &&
contentState & NS_EVENT_STATE_HOVER) {
aState |= DFCS_PUSHED;
}
return NS_OK;
}
case NS_THEME_MENUITEM: