Bug 410719 - Menu buttons, menulists, autocomplete dropdown buttons and toolbarbuttons with menupopups should appear pressed when the menupopup is open. r=neil/vlad

This commit is contained in:
Dão Gottwald 2009-03-13 13:23:26 +01:00
parent 0629f4fa0b
commit e06981f06c
4 changed files with 96 additions and 43 deletions

View File

@ -20,7 +20,7 @@
<xul:image class="menulist-icon" xbl:inherits="src=image,src"/>
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
</xul:hbox>
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled"/>
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
<children includes="menupopup"/>
</content>
@ -413,7 +413,7 @@
xbl:inherits="value=label,value,disabled,tabindex,readonly"/>
</xul:hbox>
<xul:dropmarker class="menulist-dropmarker" type="menu"
xbl:inherits="open,disabled,parentfocused=focused"/>
xbl:inherits="open,disabled,parentfocused=focused"/>
<children includes="menupopup"/>
</content>
@ -608,7 +608,7 @@
<binding id="menulist-compact" display="xul:menu"
extends="chrome://global/content/bindings/menulist.xml#menulist">
<content sizetopopup="false">
<xul:dropmarker class="menulist-dropmarker" type="menu"/>
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
<xul:image class="menulist-icon" xbl:inherits="src=image,src"/>
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
<children includes="menupopup"/>
@ -623,7 +623,7 @@
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
<xul:label class="menulist-label menulist-description" xbl:inherits="value=description" crop="right" flex="10000"/>
</xul:hbox>
<xul:dropmarker class="menulist-dropmarker" type="menu"/>
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
<children includes="menupopup"/>
</content>
</binding>

View File

@ -341,7 +341,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
if (aWidgetType == NS_THEME_TOOLBAR_BUTTON_DROPDOWN)
aFrame = aFrame->GetParent();
PRBool menuOpen = CheckBooleanAttr(aFrame, nsWidgetAtoms::open);
PRBool menuOpen = IsOpenButton(aFrame);
aState->depressed = IsCheckedButton(aFrame) || menuOpen;
// we must not highlight buttons with open drop down menus on hover.
aState->inHover = aState->inHover && !menuOpen;

View File

@ -411,8 +411,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
if (IsDisabled(aFrame)) {
aState = TS_DISABLED;
return NS_OK;
} else if (CheckBooleanAttr(aFrame, nsWidgetAtoms::open) ||
CheckBooleanAttr(aFrame, nsWidgetAtoms::checked)) {
} else if (IsOpenButton(aFrame) ||
IsCheckedButton(aFrame)) {
aState = TS_ACTIVE;
return NS_OK;
}
@ -550,6 +550,10 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
aState = TS_DISABLED;
return NS_OK;
}
if (IsOpenButton(aFrame)) {
aState = TS_ACTIVE;
return NS_OK;
}
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
aState = TS_ACTIVE;
@ -781,7 +785,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
aState = TS_DISABLED;
} else if (IsReadOnly(aFrame)) {
aState = TS_NORMAL;
} else if (CheckBooleanAttr(aFrame, nsWidgetAtoms::open)) {
} else if (IsOpenButton(aFrame)) {
aState = TS_ACTIVE;
} else {
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
@ -799,10 +803,12 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
}
case NS_THEME_DROPDOWN_BUTTON: {
PRBool isHTML = IsHTMLContent(aFrame);
nsIFrame* origFrame = aFrame;
nsIFrame* parentFrame = aFrame->GetParent();
if ((parentFrame && parentFrame->GetType() == nsWidgetAtoms::menuFrame) || isHTML)
// XUL menu lists and HTML selects get state from parent
PRBool isMenulist = !isHTML && parentFrame->GetType() == nsWidgetAtoms::menuFrame;
PRBool isOpen = PR_FALSE;
// HTML select and XUL menulist dropdown buttons get state from the parent.
if (isHTML || isMenulist)
aFrame = parentFrame;
aPart = nsUXThemeData::sIsVistaOrLater ? CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
@ -818,17 +824,23 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
return NS_OK;
}
if (isHTML) {
nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
isOpen = (ccf && ccf->IsDroppedDown());
}
else
isOpen = IsOpenButton(aFrame);
if (nsUXThemeData::sIsVistaOrLater) {
if (isHTML) {
nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
if (ccf && ccf->IsDroppedDown()) {
/* Hover is propagated, but we need to know whether we're
* hovering just the combobox frame, not the dropdown frame.
* But, we can't get that information, since hover is on the
* content node, and they share the same content node. So,
* instead, we cheat -- if the dropdown is open, we always
* show the hover state. This looks fine in practice.
*/
if (isOpen) {
/* Hover is propagated, but we need to know whether we're
* hovering just the combobox frame, not the dropdown frame.
* But, we can't get that information, since hover is on the
* content node, and they share the same content node. So,
* instead, we cheat -- if the dropdown is open, we always
* show the hover state. This looks fine in practice.
*/
aState = TS_HOVER;
return NS_OK;
}
@ -838,13 +850,33 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
* isn't HTML content, we cheat and force the dropdown state
* to be normal. (Bug 430434)
*/
aState = TS_NORMAL;
return NS_OK;
aState = TS_NORMAL;
return NS_OK;
}
}
aState = StandardGetState(aFrame, aWidgetType, PR_FALSE);
aState = TS_NORMAL;
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
// Dropdown button active state doesn't need :hover.
if (eventState & NS_EVENT_STATE_ACTIVE) {
if (isOpen && (isHTML || isMenulist)) {
// XXX Button should look active until the mouse is released, but
// without making it look active when the popup is clicked.
return NS_OK;
}
aState = TS_ACTIVE;
}
else if (eventState & NS_EVENT_STATE_HOVER) {
// No hover effect for XUL menulists and autocomplete dropdown buttons
// while the dropdown menu is open.
if (isOpen) {
// XXX HTML select dropdown buttons should have the hover effect when
// hovering the combobox frame, but not the popup frame.
return NS_OK;
}
aState = TS_HOVER;
}
return NS_OK;
}
case NS_THEME_MENUPOPUP: {
@ -2009,9 +2041,9 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
contentState = GetContentState(aFrame, aWidgetType);
if (IsDisabled(aFrame))
aState |= DFCS_INACTIVE;
else if (CheckBooleanAttr(aFrame, nsWidgetAtoms::open))
else if (IsOpenButton(aFrame))
aState |= DFCS_PUSHED;
else if (CheckBooleanAttr(aFrame, nsWidgetAtoms::checked))
else if (IsCheckedButton(aFrame))
aState |= DFCS_CHECKED;
else {
if (contentState & NS_EVENT_STATE_ACTIVE && contentState & NS_EVENT_STATE_HOVER) {
@ -2164,26 +2196,43 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8
aPart = DFC_SCROLL;
aState = DFCS_SCROLLCOMBOBOX;
nsIContent* content = aFrame->GetContent();
nsIFrame* parentFrame = aFrame->GetParent();
if (parentFrame->GetType() == nsWidgetAtoms::menuFrame ||
(content && content->IsNodeOfType(nsINode::eHTML)))
// XUL menu lists and HTML selects get state from parent
aFrame = parentFrame;
// XXX the button really shouldn't depress when clicking the
// parent, but the button frame is never :active for these controls..
if (IsDisabled(aFrame))
nsIFrame* parentFrame = aFrame->GetParent();
PRBool isHTML = IsHTMLContent(aFrame);
PRBool isMenulist = !isHTML && parentFrame->GetType() == nsWidgetAtoms::menuFrame;
PRBool isOpen = PR_FALSE;
// HTML select and XUL menulist dropdown buttons get state from the parent.
if (isHTML || isMenulist)
aFrame = parentFrame;
if (IsDisabled(aFrame)) {
aState |= DFCS_INACTIVE;
else {
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
#ifndef WINCE
if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
aState |= DFCS_PUSHED | DFCS_FLAT;
#endif
return NS_OK;
}
#ifdef WINCE
return NS_OK;
#endif
if (isHTML) {
nsIComboboxControlFrame* ccf = do_QueryFrame(aFrame);
isOpen = (ccf && ccf->IsDroppedDown());
}
else
isOpen = IsOpenButton(aFrame);
// XXX Button should look active until the mouse is released, but
// without making it look active when the popup is clicked.
if (isOpen && (isHTML || isMenulist))
return NS_OK;
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
// Dropdown button active state doesn't need :hover.
if (eventState & NS_EVENT_STATE_ACTIVE)
aState |= DFCS_PUSHED | DFCS_FLAT;
return NS_OK;
}
case NS_THEME_SCROLLBAR_BUTTON_UP:

View File

@ -133,11 +133,15 @@ class nsNativeTheme
return IsFrameRTL(aFrame) ? IsBeforeSelectedTab(aFrame) : IsAfterSelectedTab(aFrame);
}
// toolbarbutton:
// button / toolbarbutton:
PRBool IsCheckedButton(nsIFrame* aFrame) {
return CheckBooleanAttr(aFrame, nsWidgetAtoms::checked);
}
PRBool IsOpenButton(nsIFrame* aFrame) {
return CheckBooleanAttr(aFrame, nsWidgetAtoms::open);
}
// treeheadercell:
TreeSortDirection GetTreeSortDirection(nsIFrame* aFrame);
PRBool IsLastTreeHeaderCell(nsIFrame* aFrame);