- Fixes double-firing of clicks on CustomButton.
- Fixes DOMImpl.eventStopPropagation.
- Adds a test for the former.
Patch by: jgw
Review by: scottb (desk check)


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4595 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/DOMImpl.java b/user/src/com/google/gwt/dom/client/DOMImpl.java
index 864a1f3..2b755c6 100644
--- a/user/src/com/google/gwt/dom/client/DOMImpl.java
+++ b/user/src/com/google/gwt/dom/client/DOMImpl.java
@@ -121,7 +121,7 @@
   }-*/;
 
   public native void eventStopPropagation(NativeEvent evt) /*-{
-    evt.cancelBubble = cancel;
+    evt.stopPropagation();
   }-*/;
 
   public abstract String eventToString(NativeEvent evt);
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
index 3f062bc..fa32bdb 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
@@ -124,6 +124,11 @@
   }-*/;
 
   @Override
+  public native void eventStopPropagation(NativeEvent evt) /*-{
+    evt.cancelBubble = true;
+  }-*/;
+
+  @Override
   public native String eventToString(NativeEvent evt) /*-{
     if (evt.toString) return evt.toString();
       return "[event" + evt.type + "]";
diff --git a/user/src/com/google/gwt/user/client/ui/CustomButton.java b/user/src/com/google/gwt/user/client/ui/CustomButton.java
index 33653cf..a59978a 100644
--- a/user/src/com/google/gwt/user/client/ui/CustomButton.java
+++ b/user/src/com/google/gwt/user/client/ui/CustomButton.java
@@ -318,6 +318,12 @@
   private boolean isFocusing;
 
   /**
+   * Used to decide whether to allow clicks to propagate up to the superclass
+   * or container elements.
+   */
+  private boolean allowClick;
+
+  /**
    * Constructor for <code>CustomButton</code>.
    * 
    * @param upImage image for the default (up) face of the button
@@ -577,6 +583,14 @@
 
     int type = DOM.eventGetType(event);
     switch (type) {
+      case Event.ONCLICK:
+        // If clicks are currently disallowed, keep it from bubbling or being
+        // passed to the superclass.
+        if (!allowClick) {
+          event.stopPropagation();
+          return;
+        }
+        break;
       case Event.ONMOUSEDOWN:
         if (event.getButton() == Event.BUTTON_LEFT) {
           setFocus(true);
@@ -747,11 +761,18 @@
    * widget display.
    */
   protected void onClick() {
+    // Allow the click we're about to synthesize to pass through to the
+    // superclass and containing elements. Element.dispatchEvent() is
+    // synchronous, so we simply set and clear the flag within this method.
+    allowClick = true;
+
     // Mouse coordinates are not always available (e.g., when the click is
     // caused by a keyboard event).
     NativeEvent evt = Document.get().createClickEvent(1, 0, 0, 0, 0, false,
         false, false, false);
     getElement().dispatchEvent(evt);
+
+    allowClick = false;
   }
 
   /**
diff --git a/user/test/com/google/gwt/user/client/ui/CreateEventTest.java b/user/test/com/google/gwt/user/client/ui/CreateEventTest.java
index f6f46cc..9029f94 100644
--- a/user/test/com/google/gwt/user/client/ui/CreateEventTest.java
+++ b/user/test/com/google/gwt/user/client/ui/CreateEventTest.java
@@ -209,6 +209,29 @@
   }
 
   /**
+   * Tests NativeEvent.stopPropagation()
+   */
+  public void testStopPropagation() {
+    NonBubbleAssertingEventListener listener = new NonBubbleAssertingEventListener(
+        "click") {
+      @Override
+      public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+        if (event.getCurrentTarget() == child) {
+          event.stopPropagation();
+        }
+      }
+    };
+    Event.setEventListener(parent, listener);
+    Event.setEventListener(child, listener);
+
+    child.dispatchEvent(Document.get().createClickEvent(MOUSE_DETAIL, SCREEN_X,
+        SCREEN_Y, CLIENT_X, CLIENT_Y, true, true, true, true));
+
+    assertTrue("Expected child to receive event", listener.childReceived);
+  }
+
+  /**
    * Tests createBlurEvent().
    */
   public void testTriggerBlurEvent() {