Bug 562554 - "Toolbar buttons with drop-down menus are still busted in SeaMonkey Modern Theme" [r=roc] [a=Mossop] SEAMONKEY_2_1a1_BUILD1 SEAMONKEY_2_1a1_RELEASE
authorFelipe Gomes <felipc@gmail.com>
Sat, 01 May 2010 12:39:00 -0400
changeset 42016 3a26cbe20cd2
parent 42015 0459345d8026
child 42017 2bdb71ccde71
child 42109 58d9ba779e5e
push idunknown
push userunknown
push dateunknown
reviewersroc, Mossop
bugs562554
milestone1.9.3a5pre
Bug 562554 - "Toolbar buttons with drop-down menus are still busted in SeaMonkey Modern Theme" [r=roc] [a=Mossop]
layout/xul/base/src/nsBoxFrame.cpp
toolkit/content/tests/widgets/Makefile.in
toolkit/content/tests/widgets/test_bug562554.xul
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -2145,34 +2145,42 @@ private:
 };
 
 void nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder* aBuilder,
     const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
 {
   nsTArray<nsIFrame*> outFrames;
   mList.HitTest(aBuilder, aRect, aState, &outFrames);
 
-  PRUint32 originalLength = aOutFrames->Length();
+  PRBool topMostAdded = PR_FALSE;
   PRUint32 localLength = outFrames.Length();
 
   for (PRUint32 i = 0; i < localLength; i++) {
 
     for (nsIContent* content = outFrames.ElementAt(i)->GetContent();
          content && content != mTargetFrame->GetContent();
          content = content->GetParent()) {
       if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
                                nsGkAtoms::_true, eCaseMatters)) {
         // Events are allowed on 'frame', so let it go.
         aOutFrames->AppendElement(outFrames.ElementAt(i));
+        topMostAdded = PR_TRUE;
       }
     }
 
+    // If there was no hit on the topmost frame or its ancestors,
+    // add the target frame itself as the first candidate (see bug 562554).
+    if (!topMostAdded) {
+      topMostAdded = PR_TRUE;
+      aOutFrames->AppendElement(mTargetFrame);
+    }
+
   }
-  // If no hits were found, treat it as a hit on the target frame itself
-  if (aOutFrames->Length() == originalLength) {
+  // If no hits were found, treat it as a hit on the target frame itself.
+  if (localLength == 0) {
     aOutFrames->AppendElement(mTargetFrame);
   }
 }
 
 class nsXULEventRedirectorWrapper : public nsDisplayWrapper
 {
 public:
   nsXULEventRedirectorWrapper(nsIFrame* aTargetFrame)
--- a/toolkit/content/tests/widgets/Makefile.in
+++ b/toolkit/content/tests/widgets/Makefile.in
@@ -47,16 +47,17 @@ include $(topsrcdir)/config/rules.mk
 _TEST_FILES = 	test_bug360220.xul \
 		test_bug359754.xul \
 		test_bug365773.xul \
 		test_bug382990.xul \
 		test_bug457632.xul \
 		test_bug460942.xul \
 		test_bug509732.xul \
 		test_bug557987.xul\
+		test_bug562554.xul \
 		test_button.xul \
 		test_closemenu_attribute.xul \
 		test_colorpicker_popup.xul \
 		test_deck.xul \
 		test_menuitem_blink.xul \
 		test_menulist_keynav.xul \
 		test_menulist_null_value.xul \
 		test_popup_coords.xul \
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/widgets/test_bug562554.xul
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+  XUL Widget Test for bug 562554
+  -->
+<window title="Bug 557987" width="400" height="400"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+
+  <toolbarbutton type="menu" id="toolbarmenu" height="200px">
+    <menupopup id="menupopup" onpopupshowing="eventReceived('popupshowing'); return false;"/>
+    <stack>
+       <button width="100px" left="0px" height="30px" id="button1"
+        allowevents="true" onclick="eventReceived('clickbutton1'); return false;"/>
+
+       <button width="100px" left="70px" id="button2"
+        onclick="eventReceived('clickbutton2'); return false;"/>
+    </stack>
+  </toolbarbutton>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
+
+<script type="application/javascript">
+<![CDATA[
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(test);
+
+// Tests that mouse events are correctly dispatched to <toolbarbutton type="menu"/>
+function test() {
+  disableNonTestMouseEvents(true);
+  nextTest();
+}
+
+let tests = [
+  // Click on the toolbarbutton itself - should call popupshowing
+  function() synthesizeMouse($("toolbarmenu"), 10, 50, {}, window),
+
+  // Click on button1 which has allowevents="true" - should call clickbutton1
+  function() synthesizeMouse($("button1"), 10, 15, {}, window),
+
+  // Click on button2 where it intersects with button1 - should call popupshowing
+  function() synthesizeMouse($("button2"), 5, 15, {}, window),
+
+  // Click on button2 outside of intersection - should call popupshowing
+  function() synthesizeMouse($("button2"), 50, 15, {}, window)
+];
+
+function nextTest() {
+  if (tests.length) {
+    let func = tests.shift();
+    func();
+    SimpleTest.executeSoon(nextTest);
+  } else {
+    disableNonTestMouseEvents(false);
+    SimpleTest.executeSoon(finishTest);
+  }
+}
+
+function finishTest() {
+  is(eventCount.clickbutton1, 1, "Correct number of clicks on button 1");
+  is(eventCount.clickbutton2, 0, "Correct number of clicks on button 2");
+  is(eventCount.popupshowing, 3, "Correct number of popupshowing events received");
+
+  SimpleTest.finish();
+}
+
+let eventCount = {
+  popupshowing: 0,
+  clickbutton1: 0,
+  clickbutton2: 0
+};
+
+function eventReceived(eventName) {
+  eventCount[eventName]++;
+}
+
+]]>
+</script>
+</window>