Save and restore the state of NativePreviewEvent in case an event is fired while the current event is being previewed.

Patch by: jlabanca
Review by: jgw



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6162 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/Event.java b/user/src/com/google/gwt/user/client/Event.java
index 5cf2251..5228aa6 100644
--- a/user/src/com/google/gwt/user/client/Event.java
+++ b/user/src/com/google/gwt/user/client/Event.java
@@ -72,13 +72,27 @@
      */
     private static boolean fire(HandlerManager handlers, NativeEvent nativeEvent) {
       if (TYPE != null && handlers != null && handlers.isEventHandled(TYPE)) {
+        // Cache the current values in the singleton in case we are in the
+        // middle of handling another event.
+        boolean lastIsCanceled = singleton.isCanceled;
+        boolean lastIsConsumed = singleton.isConsumed;
+        boolean lastIsFirstHandler = singleton.isFirstHandler;
+        NativeEvent lastNativeEvent = singleton.nativeEvent;
+
         // Revive the event
         singleton.revive();
         singleton.setNativeEvent(nativeEvent);
 
         // Fire the event
         handlers.fireEvent(singleton);
-        return !(singleton.isCanceled() && !singleton.isConsumed());
+        boolean ret = !(singleton.isCanceled() && !singleton.isConsumed());
+
+        // Restore the state of the singleton.
+        singleton.isCanceled = lastIsCanceled;
+        singleton.isConsumed = lastIsConsumed;
+        singleton.isFirstHandler = lastIsFirstHandler;
+        singleton.nativeEvent = lastNativeEvent;
+        return ret;
       }
       return true;
     }
diff --git a/user/test/com/google/gwt/user/client/EventTest.java b/user/test/com/google/gwt/user/client/EventTest.java
index 6490c58..4997547 100644
--- a/user/test/com/google/gwt/user/client/EventTest.java
+++ b/user/test/com/google/gwt/user/client/EventTest.java
@@ -326,6 +326,29 @@
 
   /**
    * Test that {@link Event#fireNativePreviewEvent(NativeEvent)} returns the
+   * correct value even if another event is fired while handling the current
+   * event.
+   */
+  public void testFireNativePreviewEventWithInterupt() {
+    NativePreviewHandler handler = new NativePreviewHandler() {
+      private boolean first = true;
+
+      public void onPreviewNativeEvent(NativePreviewEvent event) {
+        if (first) {
+          event.cancel();
+          first = false;
+          assertTrue(Event.fireNativePreviewEvent(null));
+          assertTrue(event.isCanceled());
+        }
+      }
+    };
+    HandlerRegistration reg = Event.addNativePreviewHandler(handler);
+    assertFalse(Event.fireNativePreviewEvent(null));
+    reg.removeHandler();
+  }
+
+  /**
+   * Test that {@link Event#fireNativePreviewEvent(NativeEvent)} returns the
    * correct value if the native event is not canceled.
    */
   public void testFireNativePreviewEventWithoutCancel() {
@@ -524,6 +547,6 @@
   }
 
   private native boolean isInternetExplorer() /*-{
-     return navigator.userAgent.toLowerCase().indexOf("msie") != -1;
-   }-*/;
+    return navigator.userAgent.toLowerCase().indexOf("msie") != -1;
+  }-*/;
 }