Bug 1089005, add a third consume option that never consumes even over the anchor. This allows clicks on the location field to adjust the caret position, r=dao
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -968,17 +968,17 @@
</implementation>
</binding>
<!-- Note: this binding is applied to the autocomplete popup used in the Search bar -->
<binding id="browser-search-autocomplete-result-popup" extends="chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup">
<resources>
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
- <content ignorekeys="true" level="top">
+ <content ignorekeys="true" level="top" consumeoutsideclicks="never">
<xul:hbox xbl:inherits="collapsed=showonlysettings" anonid="searchbar-engine"
class="search-panel-header search-panel-current-engine">
<xul:image class="searchbar-engine-image" xbl:inherits="src"/>
<xul:label anonid="searchbar-engine-name" flex="1" crop="end"
role="presentation"/>
</xul:hbox>
<xul:tree anonid="tree" flex="1"
class="autocomplete-tree plain search-panel-tree"
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -896,20 +896,16 @@
// in browser.xul) is hidden to avoid impacting startup / new
// window performance. The base binding's openPopup would normally
// call the overriden openAutocompletePopup in urlbarBindings.xml's
// browser-autocomplete-result-popup binding to unhide the popup,
// but since we're overriding openPopup we need to unhide the panel
// ourselves.
popup.hidden = false;
- // showHistoryPopup sets consumeoutsideclicks to true so reset it
- // here
- popup.setAttribute("consumeoutsideclicks", "false");
-
popup.mInput = this;
popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
popup.invalidate();
popup.showCommentColumn = this.showCommentColumn;
popup.showImageColumn = this.showImageColumn;
document.popupNode = null;
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -1502,62 +1502,67 @@ void nsMenuPopupFrame::CanAdjustEdges(in
}
else if (aVerticalSide == (mVFlip ? NS_SIDE_TOP : NS_SIDE_BOTTOM)) {
if (popupAlign == POPUPALIGNMENT_BOTTOMLEFT || popupAlign == POPUPALIGNMENT_BOTTOMRIGHT) {
aChange.y = 0;
}
}
}
-bool nsMenuPopupFrame::ConsumeOutsideClicks()
+ConsumeOutsideClicksResult nsMenuPopupFrame::ConsumeOutsideClicks()
{
// If the popup has explicitly set a consume mode, honor that.
if (mConsumeRollupEvent != PopupBoxObject::ROLLUP_DEFAULT) {
- return (mConsumeRollupEvent == PopupBoxObject::ROLLUP_CONSUME);
+ return (mConsumeRollupEvent == PopupBoxObject::ROLLUP_CONSUME) ?
+ ConsumeOutsideClicks_True : ConsumeOutsideClicks_ParentOnly;
}
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
nsGkAtoms::_true, eCaseMatters)) {
- return true;
+ return ConsumeOutsideClicks_True;
}
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
nsGkAtoms::_false, eCaseMatters)) {
- return false;
+ return ConsumeOutsideClicks_ParentOnly;
+ }
+ if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::consumeoutsideclicks,
+ nsGkAtoms::never, eCaseMatters)) {
+ return ConsumeOutsideClicks_Never;
}
nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
if (parentContent) {
dom::NodeInfo *ni = parentContent->NodeInfo();
if (ni->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL)) {
- return true; // Consume outside clicks for combo boxes on all platforms
+ return ConsumeOutsideClicks_True; // Consume outside clicks for combo boxes on all platforms
}
#if defined(XP_WIN)
// Don't consume outside clicks for menus in Windows
if (ni->Equals(nsGkAtoms::menu, kNameSpaceID_XUL) ||
ni->Equals(nsGkAtoms::splitmenu, kNameSpaceID_XUL) ||
ni->Equals(nsGkAtoms::popupset, kNameSpaceID_XUL) ||
((ni->Equals(nsGkAtoms::button, kNameSpaceID_XUL) ||
ni->Equals(nsGkAtoms::toolbarbutton, kNameSpaceID_XUL)) &&
(parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::menu, eCaseMatters) ||
parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::menuButton, eCaseMatters)))) {
- return false;
+ return ConsumeOutsideClicks_Never;
}
#endif
if (ni->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL)) {
// Don't consume outside clicks for autocomplete widget
if (parentContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::autocomplete, eCaseMatters)) {
- return false;
+ return ConsumeOutsideClicks_Never;
}
}
}
- return true;
+ return ConsumeOutsideClicks_True;
}
// XXXroc this is megalame. Fossicking around for a frame of the right
// type is a recipe for disaster in the long term.
nsIScrollableFrame* nsMenuPopupFrame::GetScrollFrame(nsIFrame* aStart)
{
if (!aStart)
return nullptr;
--- a/layout/xul/nsMenuPopupFrame.h
+++ b/layout/xul/nsMenuPopupFrame.h
@@ -58,16 +58,22 @@ enum nsPopupState {
// popuphiding or popuphidden events. It is used when executing a menu
// command because the menu needs to be hidden before the command event
// fires, yet the popuphiding and popuphidden events are fired after. This
// state can also occur when the popup is removed because the document is
// unloaded.
ePopupInvisible
};
+enum ConsumeOutsideClicksResult {
+ ConsumeOutsideClicks_ParentOnly = 0, // Only consume clicks on the parent anchor
+ ConsumeOutsideClicks_True = 1, // Always consume clicks
+ ConsumeOutsideClicks_Never = 2 // Never consume clicks
+};
+
// How a popup may be flipped. Flipping to the outside edge is like how
// a submenu would work. The entire popup is flipped to the opposite side
// of the anchor.
enum FlipStyle {
FlipStyle_None = 0,
FlipStyle_Outside = 1,
FlipStyle_Inside = 2
};
@@ -183,17 +189,17 @@ public:
* Should clicks outside of a popup be eaten?
*
* Menus Autocomplete Comboboxes
* Mac Eat No Eat
* Win No No Eat
* Unix Eat No Eat
*
*/
- bool ConsumeOutsideClicks();
+ ConsumeOutsideClicksResult ConsumeOutsideClicks();
virtual bool IsContextMenu() MOZ_OVERRIDE { return mIsContextMenu; }
virtual bool MenuClosed() MOZ_OVERRIDE { return true; }
virtual void LockMenuUntilClosed(bool aLock) MOZ_OVERRIDE;
virtual bool IsMenuLocked() MOZ_OVERRIDE { return mIsMenuLocked; }
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -197,20 +197,23 @@ nsXULPopupManager::Rollup(uint32_t aCoun
// that case we don't need to deal with the menu reopening as it will
// already still be open.
nsMenuChainItem* first = item;
while (first->GetParent())
first = first->GetParent();
*aLastRolledUp = first->Content();
}
- consume = item->Frame()->ConsumeOutsideClicks();
- // If the click was over the anchor, always consume the click. This way,
- // clicking on a menu doesn't reopen the menu.
- if (!consume && pos) {
+ ConsumeOutsideClicksResult consumeResult = item->Frame()->ConsumeOutsideClicks();
+ consume = (consumeResult == ConsumeOutsideClicks_True);
+
+ // If ConsumeOutsideClicks_ParentOnly was returned, then only consume the
+ // click is it was over the anchor. This way, clicking on a menu doesn't
+ // reopen the menu.
+ if (consumeResult == ConsumeOutsideClicks_ParentOnly && pos) {
nsCOMPtr<nsIContent> anchor = item->Frame()->GetAnchor();
// Check if the anchor has indicated another node to use for checking
// for roll-up. That way, we can anchor a popup on anonymous content or
// an individual icon, while clicking elsewhere within a button or other
// container doesn't result in us re-opening the popup.
if (anchor) {
nsAutoString consumeAnchor;
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -350,34 +350,32 @@
<method name="openPopup">
<body><![CDATA[
this.popup.openAutocompletePopup(this, this);
]]></body>
</method>
<method name="closePopup">
<body><![CDATA[
- this.popup.setAttribute("consumeoutsideclicks", "false");
this.popup.closePopup();
]]></body>
</method>
<method name="showHistoryPopup">
<body><![CDATA[
// history dropmarker pushed state
function cleanup(popup) {
popup.removeEventListener("popupshowing", onShow, false);
}
function onShow(event) {
var popup = event.target, input = popup.input;
cleanup(popup);
input.setAttribute("open", "true");
function onHide() {
input.removeAttribute("open");
- popup.setAttribute("consumeoutsideclicks", "false");
popup.removeEventListener("popuphiding", onHide, false);
}
popup.addEventListener("popuphiding", onHide, false);
}
this.popup.addEventListener("popupshowing", onShow, false);
setTimeout(cleanup, 1000, this.popup);
// Store our "normal" maxRows on the popup, so that it can reset the
@@ -387,17 +385,16 @@
// Increase our maxRows temporarily, since we want the dropdown to
// be bigger in this case. The popup's popupshowing/popuphiding
// handlers will take care of resetting this.
this.maxRows = this.maxDropMarkerRows;
// Ensure that we have focus.
if (!this.focused)
this.focus();
- this.popup.setAttribute("consumeoutsideclicks", "true");
this.attachController();
this.mController.startSearch("");
]]></body>
</method>
<method name="toggleHistoryPopup">
<body><![CDATA[
if (!this.popup.popupOpen)
@@ -608,17 +605,17 @@
<binding id="autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-base-popup">
<resources>
<stylesheet src="chrome://global/content/autocomplete.css"/>
<stylesheet src="chrome://global/skin/tree.css"/>
<stylesheet src="chrome://global/skin/autocomplete.css"/>
</resources>
- <content ignorekeys="true" level="top" consumeoutsideclicks="false">
+ <content ignorekeys="true" level="top" consumeoutsideclicks="never">
<xul:tree anonid="tree" class="autocomplete-tree plain" hidecolumnpicker="true" flex="1" seltype="single">
<xul:treecols anonid="treecols">
<xul:treecol id="treecolAutoCompleteValue" class="autocomplete-treecol" flex="1" overflow="true"/>
</xul:treecols>
<xul:treechildren class="autocomplete-treebody"/>
</xul:tree>
</content>
@@ -961,17 +958,17 @@ extends="chrome://global/content/binding
</binding>
<binding id="autocomplete-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-base-popup">
<resources>
<stylesheet src="chrome://global/content/autocomplete.css"/>
<stylesheet src="chrome://global/skin/autocomplete.css"/>
</resources>
- <content ignorekeys="true" level="top" consumeoutsideclicks="false">
+ <content ignorekeys="true" level="top" consumeoutsideclicks="never">
<xul:richlistbox anonid="richlistbox" class="autocomplete-richlistbox" flex="1"/>
<xul:hbox>
<children/>
</xul:hbox>
</content>
<implementation implements="nsIAutoCompletePopup">
<field name="_currentIndex">0</field>