Revision: 6163
Author: [email protected]
Date: Fri Sep 18 11:17:07 2009
Log: Allows multiple GWT apps to preview native events in IE.

Patch by: jlabanca
Review by: jgw
Issue: 3892


http://code.google.com/p/google-web-toolkit/source/detail?r=6163

Added:
  /trunk/eclipse/reference/code-museum/Issue3892.launch
   
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module1.gwt.xml
   
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module2.gwt.xml
   
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module3.gwt.xml
   
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint1.java
   
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint2.java
   
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint3.java
Modified:
  /trunk/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java

=======================================
--- /dev/null
+++ /trunk/eclipse/reference/code-museum/Issue3892.launch       Fri Sep 18  
11:17:07 2009
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/code-museum"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables"  
value="true"/>
+<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot;  
javaProject=&quot;code-museum&quot; path=&quot;1&quot;  
type=&quot;4&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
internalArchive=&quot;/code-museum/src&quot; path=&quot;3&quot;  
type=&quot;2&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
internalArchive=&quot;/gwt-user/core/src&quot; path=&quot;3&quot;  
type=&quot;2&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
internalArchive=&quot;/gwt-dev-linux/core/src&quot; path=&quot;3&quot;  
type=&quot;2&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
internalArchive=&quot;/gwt-user/core/super&quot; path=&quot;3&quot;  
type=&quot;2&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
internalArchive=&quot;/gwt-dev-linux/core/super&quot; path=&quot;3&quot;  
type=&quot;2&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot;  
encoding=&quot;UTF-8&quot;  
standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry  
id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento
  
exportedEntriesOnly=&quot;false&quot;  
project=&quot;code-museum&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH"  
value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE"  
value="com.google.gwt.dev.HostedMode"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS"  
value="-startupUrl  
Issue3892.html&#10;com.google.gwt.museum.Issue3892Module1&#10;com.google.gwt.museum.Issue3892Module2&#10;com.google.gwt.museum.Issue3892Module3"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR"  
value="code-museum"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS"  
value="-ea&#13;&#10;-Xmx256M&#10;-Dgwt.devjar=${gwt_devjar}&quot;"/>
+</launchConfiguration>
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module1.gwt.xml 
 
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,28 @@
+<!--                                                                         
-->
+<!-- Copyright 2009 Google  
Inc.                                             -->
+<!-- Licensed under the Apache License, Version 2.0 (the "License");  
you    -->
+<!-- may not use this file except in compliance with the License. You  
may   -->
+<!-- may obtain a copy of the License  
at                                    -->
+<!--                                                                         
-->
+<!--  
http://www.apache.org/licenses/LICENSE-2.0                             -->
+<!--                                                                         
-->
+<!-- Unless required by applicable law or agreed to in writing,  
software    -->
+<!-- distributed under the License is distributed on an "AS IS"  
BASIS,      -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express  
or        -->
+<!-- implied. License for the specific language governing permissions  
and   -->
+<!-- limitations under the  
License.                                         -->
+<module rename-to="issue3892Module1">
+
+  <!-- Inherit the core Web Toolkit stuff.                  -->
+  <inherits name='com.google.gwt.user.User' />
+  <inherits name='com.google.gwt.museum.Museum' />
+  <inherits name="com.google.gwt.user.theme.standard.StandardResources" />
+  <inherits name="com.google.gwt.user.theme.chrome.ChromeResources" />
+  <inherits name="com.google.gwt.user.theme.dark.DarkResources" />
+
+  <!-- Specify the app entry point class.                   -->
+  <entry-point  
class='com.google.gwt.museum.client.defaultmuseum.Issue3892EntryPoint1' />
+  <source path="client/common" />
+  <source path="client/defaultmuseum" />
+  <source path="client/viewer" />
+</module>
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module2.gwt.xml 
 
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,28 @@
+<!--                                                                         
-->
+<!-- Copyright 2009 Google  
Inc.                                             -->
+<!-- Licensed under the Apache License, Version 2.0 (the "License");  
you    -->
+<!-- may not use this file except in compliance with the License. You  
may   -->
+<!-- may obtain a copy of the License  
at                                    -->
+<!--                                                                         
-->
+<!--  
http://www.apache.org/licenses/LICENSE-2.0                             -->
+<!--                                                                         
-->
+<!-- Unless required by applicable law or agreed to in writing,  
software    -->
+<!-- distributed under the License is distributed on an "AS IS"  
BASIS,      -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express  
or        -->
+<!-- implied. License for the specific language governing permissions  
and   -->
+<!-- limitations under the  
License.                                         -->
+<module rename-to="issue3892Module2">
+
+  <!-- Inherit the core Web Toolkit stuff.                  -->
+  <inherits name='com.google.gwt.user.User' />
+  <inherits name='com.google.gwt.museum.Museum' />
+  <inherits name="com.google.gwt.user.theme.standard.StandardResources" />
+  <inherits name="com.google.gwt.user.theme.chrome.ChromeResources" />
+  <inherits name="com.google.gwt.user.theme.dark.DarkResources" />
+
+  <!-- Specify the app entry point class.                   -->
+  <entry-point  
class="com.google.gwt.museum.client.defaultmuseum.Issue3892EntryPoint2" />
+  <source path="client/common" />
+  <source path="client/defaultmuseum" />
+  <source path="client/viewer" />
+</module>
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/Issue3892Module3.gwt.xml 
 
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,28 @@
+<!--                                                                         
-->
+<!-- Copyright 2009 Google  
Inc.                                             -->
+<!-- Licensed under the Apache License, Version 2.0 (the "License");  
you    -->
+<!-- may not use this file except in compliance with the License. You  
may   -->
+<!-- may obtain a copy of the License  
at                                    -->
+<!--                                                                         
-->
+<!--  
http://www.apache.org/licenses/LICENSE-2.0                             -->
+<!--                                                                         
-->
+<!-- Unless required by applicable law or agreed to in writing,  
software    -->
+<!-- distributed under the License is distributed on an "AS IS"  
BASIS,      -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express  
or        -->
+<!-- implied. License for the specific language governing permissions  
and   -->
+<!-- limitations under the  
License.                                         -->
+<module rename-to="issue3892Module3">
+
+  <!-- Inherit the core Web Toolkit stuff.                  -->
+  <inherits name='com.google.gwt.user.User' />
+  <inherits name='com.google.gwt.museum.Museum' />
+  <inherits name="com.google.gwt.user.theme.standard.StandardResources" />
+  <inherits name="com.google.gwt.user.theme.chrome.ChromeResources" />
+  <inherits name="com.google.gwt.user.theme.dark.DarkResources" />
+
+  <!-- Specify the app entry point class.                   -->
+  <entry-point  
class="com.google.gwt.museum.client.defaultmuseum.Issue3892EntryPoint3" />
+  <source path="client/common" />
+  <source path="client/defaultmuseum" />
+  <source path="client/viewer" />
+</module>
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint1.java
    
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Only a single GWT application can preview native events.
+ */
+public class Issue3892EntryPoint1 extends AbstractIssue {
+
+  public static final String BUTTON_1_ID = "Issue3892Button1";
+  public static final String BUTTON_2_ID = "Issue3892Button2";
+  public static final String BUTTON_3_ID = "Issue3892Button3";
+
+  /**
+   * The main grid used for layout.
+   */
+  private Grid grid = new Grid(1, 3);
+
+  @Override
+  public Widget createIssue() {
+    Window.alert("Module 1 loaded");
+
+    // Setup the grid.
+    grid.setHTML(0, 0, "<b>Test<b>");
+    grid.setHTML(0, 1, "<b>Description<b>");
+    grid.setHTML(0, 2, "<b>Expected Results<b>");
+    addTest(BUTTON_1_ID, "Event is not cancelled by any module.",
+        "The event will fire in the button.", false);
+    addTest(BUTTON_2_ID, "Module 1 cancels event.",
+        "The event will not fire in the button.", true);
+    addTest(BUTTON_3_ID, "Module 2 cancels event.",
+        "The event will not fire in the button.", true);
+
+    // Add the event preview.
+    Event.addNativePreviewHandler(new NativePreviewHandler() {
+      public void onPreviewNativeEvent(NativePreviewEvent event) {
+        if (event.getTypeInt() == Event.ONCLICK) {
+          Element target = event.getNativeEvent().getEventTarget().cast();
+          if (BUTTON_2_ID.equals(target.getId())) {
+            event.cancel();
+            Window.alert("Click handled by module 1 and cancelled");
+          } else {
+            Window.alert("Click handled by module 1");
+          }
+        }
+      }
+    });
+
+    return grid;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "After all three modules have loaded (indicated by alert  
boxes), "
+        + "click the buttons and verify that you see the expected  
results. "
+        + "For each test, all three modules should preview the event (even  
if "
+        + "one of the modules cancels the event).";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Only a single GWT application can preview native events";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  /**
+   * Add a test button to the grid.
+   *
+   * @param buttonId the ID of the button
+   * @param description the test description
+   * @param results the expected result of the test
+   * @param isCancelled true if one of the modules will cancel the event
+   */
+  private void addTest(String buttonId, String description, String results,
+      final boolean isCancelled) {
+    int row = grid.getRowCount();
+    grid.resizeRows(row + 1);
+
+    // Add the test button.
+    Button button = new Button("Run Test", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        if (isCancelled) {
+          Window.alert("[Error] Event should have been cancelled");
+        } else {
+          Window.alert("[Success] Event successfully fired");
+        }
+      }
+    });
+    button.getElement().setId(buttonId);
+    grid.setWidget(row, 0, button);
+
+    // Add the description and expected results.
+    grid.setText(row, 1, description);
+    grid.setText(row, 2, results);
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint2.java
    
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+
+/**
+ * Only a single GWT application can preview native events.
+ */
+public class Issue3892EntryPoint2 implements EntryPoint {
+  public void onModuleLoad() {
+    Window.alert("Module 2 loaded");
+    Event.addNativePreviewHandler(new NativePreviewHandler() {
+      public void onPreviewNativeEvent(NativePreviewEvent event) {
+        if (event.getTypeInt() == Event.ONCLICK) {
+          Element target = event.getNativeEvent().getEventTarget().cast();
+          if (Issue3892EntryPoint1.BUTTON_3_ID.equals(target.getId())) {
+            event.cancel();
+            Window.alert("Click handled by module 2 and cancelled");
+          } else {
+            Window.alert("Click handled by module 2");
+          }
+        }
+      }
+    });
+  }
+}
=======================================
--- /dev/null
+++  
/trunk/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3892EntryPoint3.java
    
Fri Sep 18 11:17:07 2009
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+
+/**
+ * Only a single GWT application can preview native events.
+ */
+public class Issue3892EntryPoint3 implements EntryPoint {
+  public void onModuleLoad() {
+    Window.alert("Module 3 loaded");
+    Event.addNativePreviewHandler(new NativePreviewHandler() {
+      public void onPreviewNativeEvent(NativePreviewEvent event) {
+        if (event.getTypeInt() == Event.ONCLICK) {
+          Window.alert("Click handled by module 3");
+        }
+      }
+    });
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java Tue  
Jul 21 07:10:53 2009
+++ /trunk/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java Fri  
Sep 18 11:17:07 2009
@@ -31,6 +31,23 @@
    @SuppressWarnings("unused")
    private static JavaScriptObject dispatchDblClickEvent;

+  /**
+   * Let every GWT app on the page preview the current event. If any app  
cancels
+   * the event, the event will be canceled for all apps.
+   *
+   * @return <code>false</code> to cancel the event
+   */
+  @SuppressWarnings("unused")
+  private static native boolean previewEventImpl() /*-{
+    var isCancelled = false;
+    for (var i = 0; i < $wnd.__gwt_globalEventArray.length; i++) {
+      if (!$wnd.__gwt_globalEventArray[i]()) {
+        isCancelled = true;
+      }
+    }
+    return !isCancelled;
+  }-*/;
+
    @Override
    public native Element eventGetFromElement(Event evt) /*-{
      // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
@@ -68,6 +85,24 @@

    @Override
    public native void initEventSystem() /*-{
+    // All GWT apps on the page register themselves with the  
globelEventArray
+    // so that the first app to handle an event can allow all apps on the  
page
+    // to preview it. See issue 3892 for more details.
+    //
+    // Apps cannot just mark the event as they visit it for a few reasons.
+    // First, window level event handlers fire last in IE, so the first  
app to
+    // cancel the event will be the last to see it. Second, window events  
do
+    // not support arbitrary attributes, and the only writable field is the
+    // returnValue, which has another use. Finally, window events are not
+    // comparable (ex. a=event; b=event; a!=b), so we cannot keep a list of
+    // events that have already been previewed by the current app.
+    if ($wnd.__gwt_globalEventArray == null) {
+      $wnd.__gwt_globalEventArray = new Array();
+    }
+    $wnd.__gwt_globalEventArray[$wnd.__gwt_globalEventArray.length] =  
function() {
+      return  
@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event);
+    }
+
      @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent =  
function() {
        // IE doesn't define event.currentTarget, so we squirrel it away  
here. It
        // also seems that IE won't allow you to add expandos to the event  
object,
@@ -76,9 +111,12 @@
        var oldEventTarget =  
@com.google.gwt.dom.client.DOMImplTrident::currentEventTarget;
        @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = this;

+      // The first GWT app on the page to handle the event allows all apps  
to
+      // preview it before continuing or cancelling, which is consistent  
with
+      // other browsers.
        if ($wnd.event.returnValue == null) {
          $wnd.event.returnValue = true;
-        if  
([email protected]::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event))
  
{
+        if  
([email protected]::previewEventImpl()()) {
            @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget =  
oldEventTarget;
            return;
          }
@@ -109,7 +147,7 @@
        } else if ($wnd.event.returnValue == null) {
          // Ensure that we preview the event even if we aren't handling it.
          $wnd.event.returnValue = true;
-         
@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event);
+         
@com.google.gwt.user.client.impl.DOMImplTrident::previewEventImpl()();
        }
      };


--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to