Revision: 7692
Author: [email protected]
Date: Wed Mar 10 05:44:28 2010
Log: Fix for KeyPressEvent.getCharCode and overall key events improvements.
http://gwt-code-reviews.appspot.com/142801/show
http://gwt-code-reviews.appspot.com/154812

Patch by: tbroyer
Review by: jlabanca

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

Modified:
 /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java
 /trunk/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
 /trunk/user/src/com/google/gwt/dom/client/DOMImplOpera.java
 /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java
 /trunk/user/src/com/google/gwt/dom/client/DOMImplStandard.java
 /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java
 /trunk/user/src/com/google/gwt/dom/client/Document.java
 /trunk/user/src/com/google/gwt/dom/client/NativeEvent.java
 /trunk/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java
 /trunk/user/test/com/google/gwt/user/client/ui/CreateEventTest.java

=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java Thu Jan 14 11:09:34 2010 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImpl.java Wed Mar 10 05:44:28 2010
@@ -35,8 +35,8 @@
     return doc.createElement(tag);
   }-*/;

- public abstract NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble,
-      boolean cancelable);
+  public abstract NativeEvent createHtmlEvent(Document doc, String type,
+      boolean canBubble, boolean cancelable);

public native InputElement createInputElement(Document doc, String type) /*-{
     var e = doc.createElement("INPUT");
@@ -46,10 +46,19 @@

public abstract InputElement createInputRadioElement(Document doc, String name);

+  public abstract NativeEvent createKeyCodeEvent(Document document,
+      String type, boolean ctrlKey, boolean altKey, boolean shiftKey,
+      boolean metaKey, int keyCode);
+
+  @Deprecated
   public abstract NativeEvent createKeyEvent(Document doc, String type,
boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
       boolean shiftKey, boolean metaKey, int keyCode, int charCode);

+  public abstract NativeEvent createKeyPressEvent(Document document,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int charCode);
+
   public abstract NativeEvent createMouseEvent(Document doc, String type,
       boolean canBubble, boolean cancelable, int detail, int screenX,
int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey,
@@ -91,6 +100,8 @@
     return evt.button || 0;
   }-*/;

+  public abstract int eventGetCharCode(NativeEvent evt);
+
   public native int eventGetClientX(NativeEvent evt) /*-{
     return evt.clientX || 0;
   }-*/;
@@ -108,10 +119,7 @@
   }-*/;

   public final native int eventGetKeyCode(NativeEvent evt) /*-{
- // 'which' gives the right key value, except when it doesn't -- in which
-    // case, keyCode gives the right value on all browsers.
-    // If all else fails, return an error code
-    return evt.which || evt.keyCode || 0;
+    return evt.keyCode || 0;
   }-*/;

   public native boolean eventGetMetaKey(NativeEvent evt) /*-{
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImplMozilla.java Tue Jun 30 08:01:08 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplMozilla.java Wed Mar 10 05:44:28 2010
@@ -30,6 +30,30 @@
       button.dispatchEvent(evt);
     }
   }-*/;
+
+  @Override
+  public NativeEvent createKeyCodeEvent(Document doc, String type,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int keyCode) {
+ return createKeyEventImpl(doc, type, true, true, ctrlKey, altKey, shiftKey,
+        metaKey, keyCode, 0);
+  }
+
+  @Override
+  @Deprecated
+  public NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode, int charCode) {
+    return createKeyEventImpl(doc, type, canBubble, cancelable, ctrlKey,
+        altKey, shiftKey, metaKey, keyCode, charCode);
+  }
+
+  @Override
+  public NativeEvent createKeyPressEvent(Document doc, boolean ctrlKey,
+      boolean altKey, boolean shiftKey, boolean metaKey, int charCode) {
+    return createKeyEventImpl(doc, "keypress", true, true, ctrlKey, altKey,
+        shiftKey, metaKey, 0, charCode);
+  }

   @Override
   public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
@@ -136,6 +160,15 @@
     return outer;
   }-*/;

+  private native NativeEvent createKeyEventImpl(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
+    var evt = doc.createEvent('KeyEvents');
+    evt.initKeyEvent(type, canBubble, cancelable, null, ctrlKey, altKey,
+      shiftKey, metaKey, keyCode, charCode);
+    return evt;
+  }-*/;
+
private native int getAbsoluteLeftImpl(Element viewport, Element elem) /*-{ // Firefox 3 is actively throwing errors when getBoxObjectFor() is called,
     // so we use getBoundingClientRect() whenever possible (but it's not
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImplOpera.java Fri Feb 6 13:06:24 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplOpera.java Wed Mar 10 05:44:28 2010
@@ -20,6 +20,40 @@
  */
 class DOMImplOpera extends DOMImplStandard {

+  @Override
+  public native NativeEvent createKeyCodeEvent(Document doc, String type,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int keyCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, true, true, ctrlKey, altKey, shiftKey, metaKey);
+    evt.keyCode = keyCode;
+    return evt;
+  }-*/;
+
+  @Override
+  @Deprecated
+  public native NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, canBubble, cancelable, ctrlKey, altKey, shiftKey, metaKey);
+    evt.keyCode = keyCode;
+    evt.which = charCode;
+    return evt;
+  }-*/;
+
+  @Override
+  public native NativeEvent createKeyPressEvent(Document doc,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int charCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, 'keypress', true, true, ctrlKey, altKey, shiftKey, metaKey);
+    evt.which = charCode;
+    return evt;
+  }-*/;
+
+  @Override
+  public native int eventGetCharCode(NativeEvent evt) /*-{
+    return evt.which || 0;
+  }-*/;
+
   @Override
   public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
     return evt.detail * 4 || 0;
@@ -73,4 +107,19 @@
   public native void scrollIntoView(Element elem) /*-{
     elem.scrollIntoView();
   }-*/;
-}
+
+  @SuppressWarnings("unused")
+  private native NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey) /*-{
+    // Opera fires KeyEvent instances but does not allow creating them.
+    // The best approximation is UIEvent here.
+    var evt = doc.createEvent('UIEvent');
+    evt.initUIEvent(type, canBubble, cancelable, null, 0);
+    evt.ctrlKey = ctrlKey;
+    evt.altKey = altKey;
+    evt.shiftKey = shiftKey;
+    evt.metaKey = metaKey;
+    return evt;
+  }-*/;
+}
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java Thu Feb 18 05:55:07 2010 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplSafari.java Wed Mar 10 05:44:28 2010
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 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
@@ -23,14 +23,13 @@
 class DOMImplSafari extends DOMImplStandard {

   private static class ClientRect extends JavaScriptObject {
-    @SuppressWarnings("unused")
     protected ClientRect() {
     }
-
+
     public final native int getLeft() /*-{
       return this.left;
     }-*/;
-
+
     public final native int getTop() /*-{
       return this.top;
     }-*/;
@@ -139,7 +138,7 @@
   }-*/;

   /**
- * The type property on a button element is read-only in safari, so we need to + * The type property on a button element is read-only in safari, so we need to
    * set it using setAttribute.
    */
   @Override
@@ -150,19 +149,31 @@
   }-*/;

   @Override
- public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble, - boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey,
-      boolean metaKey, int keyCode, int charCode) /*-{
- // The spec calls for KeyEvents/initKeyEvent(), but that doesn't exist on WebKit.
-    var evt = doc.createEvent('HTMLEvents');
-    evt.initEvent(type, canBubble, cancelable);
-    evt.ctrlKey = ctrlKey;
-    evt.altKey = altKey;
-    evt.shiftKey = shiftKey;
-    evt.metaKey = metaKey;
+  public native NativeEvent createKeyCodeEvent(Document doc, String type,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int keyCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, true, true, ctrlKey, altKey, shiftKey, metaKey)
     evt.keyCode = keyCode;
+    return evt;
+  }-*/;
+
+  @Override
+  @Deprecated
+  public native NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, canBubble, cancelable, ctrlKey, altKey, shiftKey, metaKey)
+    evt.keyCode = keyCode;
     evt.charCode = charCode;
-
+    return evt;
+  }-*/;
+
+  @Override
+  public native NativeEvent createKeyPressEvent(Document doc,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int charCode) /*-{
+ var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, 'keypress', true, true, ctrlKey, altKey, shiftKey, metaKey)
+    evt.charCode = charCode;
     return evt;
   }-*/;

@@ -189,26 +200,28 @@
   @Override
   public int getAbsoluteLeft(Element elem) {
     ClientRect rect = getBoundingClientRect(elem);
-    return rect != null
- ? rect.getLeft() + elem.getOwnerDocument().getBody().getScrollLeft()
+    return rect != null ? rect.getLeft()
+        + elem.getOwnerDocument().getBody().getScrollLeft()
         : getAbsoluteLeftUsingOffsets(elem);
   }

   @Override
   public int getAbsoluteTop(Element elem) {
     ClientRect rect = getBoundingClientRect(elem);
-    return rect != null
-        ? rect.getTop() + elem.getOwnerDocument().getBody().getScrollTop()
+    return rect != null ? rect.getTop()
+        + elem.getOwnerDocument().getBody().getScrollTop()
         : getAbsoluteTopUsingOffsets(elem);
   }

-  /*
+  /**
    * textContent is used over innerText for two reasons:
-   * 1 - It is consistent with DOMImplMozilla. textContent
-   *     does not convert <br>'s to new lines in WebKit.
-   * 2 - textContent is faster on retreival because WebKit
-   *     does not recalculate styles as it does for innerText.
-   */
+   *
+   * 1 - It is consistent with DOMImplMozilla. textContent does not convert
+   * <code>&lt;br&gtp;</code>'s to new lines in WebKit.
+   *
+ * 2 - textContent is faster on retreival because WebKit does not recalculate
+   * styles as it does for innerText.
+   */
   @Override
   public native String getInnerText(Element node) /*-{
     return node.textContent;
@@ -224,7 +237,8 @@
   @Override
   public int getScrollLeft(Element elem) {
     if (isRTL(elem)) {
- return super.getScrollLeft(elem) - (elem.getScrollWidth() - elem.getClientWidth());
+      return super.getScrollLeft(elem)
+          - (elem.getScrollWidth() - elem.getClientWidth());
     }
     return super.getScrollLeft(elem);
   }
@@ -287,7 +301,7 @@
   public native void setInnerText(Element elem, String text) /*-{
     elem.textContent = text || '';
   }-*/;
-
+
   @Override
   public void setScrollLeft(Document doc, int left) {
// Safari always applies document scrolling to the body element, even in
@@ -309,6 +323,22 @@
     // strict mode.
     doc.getBody().setScrollTop(top);
   }
+
+  @SuppressWarnings("unused")
+  private native NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey) /*-{
+ // WebKit's KeyboardEvent cannot set or even initialize charCode, keyCode, etc.
+    // And UIEvent's charCode and keyCode are read-only.
+    // So we "fake" an event using a raw Event and expandos
+    var evt = doc.createEvent('Event');
+    evt.initEvent(type, canBubble, cancelable);
+    evt.ctrlKey = ctrlKey;
+    evt.altKey = altKey;
+    evt.shiftKey = shiftKey;
+    evt.metaKey = metaKey;
+    return evt;
+  }-*/;

   private native boolean isRTL(Element elem) /*-{
return elem.ownerDocument.defaultView.getComputedStyle(elem, '').direction == 'rtl';
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImplStandard.java Wed May 13 08:32:59 2009 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplStandard.java Wed Mar 10 05:44:28 2010
@@ -23,8 +23,8 @@
 abstract class DOMImplStandard extends DOMImpl {

   @Override
- public native NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble,
-      boolean cancelable) /*-{
+  public native NativeEvent createHtmlEvent(Document doc, String type,
+      boolean canBubble, boolean cancelable) /*-{
     var evt = doc.createEvent('HTMLEvents');
     evt.initEvent(type, canBubble, cancelable);

@@ -40,22 +40,10 @@
   }-*/;

   @Override
- public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble, - boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey,
-      boolean metaKey, int keyCode, int charCode) /*-{
- // The spec calls for KeyEvents/initKeyEvent(), but that doesn't exist on WebKit.
-    var evt = doc.createEvent('KeyEvents');
-    evt.initKeyEvent(type, canBubble, cancelable, null, ctrlKey, altKey,
-      shiftKey, metaKey, keyCode, charCode);
-
-    return evt;
-  }-*/;
-
-  @Override
- public native NativeEvent createMouseEvent(Document doc, String type, boolean canBubble, - boolean cancelable, int detail, int screenX, int screenY, int clientX,
-      int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey,
-      boolean metaKey, int button, Element relatedTarget) /*-{
+  public native NativeEvent createMouseEvent(Document doc, String type,
+      boolean canBubble, boolean cancelable, int detail, int screenX,
+ int screenY, int clientX, int clientY, boolean ctrlKey, boolean altKey, + boolean shiftKey, boolean metaKey, int button, Element relatedTarget) /*-{ // Because Event.getButton() returns bitfield values [1, 4, 2] for [left,
     // middle, right], we need to translate them to the standard [0, 1, 2]
     // button constants.
@@ -74,7 +62,8 @@

     return evt;
   }-*/;
-
+
+  @Override
   public native void dispatchEvent(Element target, NativeEvent evt) /*-{
     target.dispatchEvent(evt);
   }-*/;
@@ -93,6 +82,11 @@
     return 1;
   }-*/;

+  @Override
+  public native int eventGetCharCode(NativeEvent evt) /*-{
+    return evt.charCode || 0;
+  }-*/;
+
   @Override
   public native EventTarget eventGetRelatedTarget(NativeEvent evt) /*-{
     return evt.relatedTarget;
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java Wed Jan 27 05:45:28 2010 +++ /trunk/user/src/com/google/gwt/dom/client/DOMImplTrident.java Wed Mar 10 05:44:28 2010
@@ -69,11 +69,9 @@
   }-*/;

   @Override
-  public native NativeEvent createKeyEvent(Document doc, String type,
- boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
-      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
- // NOTE: IE doesn't support changing bubbling and canceling behavior (this
-    // is documented publicly in Document.createKeyEvent()).
+  public native NativeEvent createKeyCodeEvent(Document doc, String type,
+      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
+      int keyCode) /*-{
     var evt = doc.createEventObject();
     evt.type = type;
     evt.ctrlKey = ctrlKey;
@@ -81,10 +79,29 @@
     evt.shiftKey = shiftKey;
     evt.metaKey = metaKey;
     evt.keyCode = keyCode;
-    evt.charCode = charCode;
-
+    return evt;
+  }-*/;
+
+  @Override
+  @Deprecated
+  public native NativeEvent createKeyEvent(Document doc, String type,
+ boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
+ // NOTE: IE doesn't support changing bubbling and canceling behavior (this
+    // is documented publicly in Document.createKeyEvent()).
+ var evt = [email protected]::createKeyCodeEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZI)(doc, type, ctrlKey, altKey, shiftKey, metaKey, charCode);
+    evt.charCode = charCode;
     return evt;
   }-*/;
+
+  @Override
+  public NativeEvent createKeyPressEvent(Document doc, boolean ctrlKey,
+      boolean altKey, boolean shiftKey, boolean metaKey, int charCode) {
+ // NOTE: in IE, keyCode is used in both keydown/keyup and keypress, so we
+    // delegate to createKeyCodeEvent instead of duplicating code.
+    return createKeyCodeEvent(doc, "keypress", ctrlKey, altKey, shiftKey,
+        metaKey, charCode);
+  }

   @Override
   public native NativeEvent createMouseEvent(Document doc, String type,
@@ -138,6 +155,11 @@
     target.fireEvent("on" + evt.type, evt);
   }-*/;

+  @Override
+  public native int eventGetCharCode(NativeEvent evt) /*-{
+    return evt.keyCode || 0;
+  }-*/;
+
   @Override
   public EventTarget eventGetCurrentTarget(NativeEvent event) {
     return currentEventTarget;
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/Document.java Mon Nov 2 10:54:13 2009 +++ /trunk/user/src/com/google/gwt/dom/client/Document.java Wed Mar 10 05:44:28 2010
@@ -434,6 +434,46 @@
   public final ModElement createInsElement() {
return (ModElement) DOMImpl.impl.createElement(this, ModElement.TAG_INS);
   }
+
+  /**
+   * Creates a key-code event ('keydown' or 'keyup').
+   *
+   * <p>
+ * While this method may be used to create events directly, it is generally
+   * preferable to use existing helper methods such as
+ * {...@link #createKeyDownEvent(boolean, boolean, boolean, boolean, int)} or
+   * {...@link #createKeyUpEvent(boolean, boolean, boolean, boolean, int)}.
+   * </p>
+   *
+   * @param type the type of event (e.g., "keydown", "keypress", etc)
+   * @param ctrlKey <code>true</code> if the ctrl key is depressed
+   * @param altKey <code>true</code> if the alt key is depressed
+   * @param shiftKey <code>true</code> if the shift key is depressed
+   * @param metaKey <code>true</code> if the meta key is depressed
+   * @param keyCode the key-code to be set on the event
+   * @return the event object
+   */
+  public final NativeEvent createKeyCodeEvent(String type, boolean ctrlKey,
+      boolean altKey, boolean shiftKey, boolean metaKey, int keyCode) {
+    return DOMImpl.impl.createKeyCodeEvent(this, type, ctrlKey, altKey,
+        shiftKey, metaKey, keyCode);
+  }
+
+  /**
+   * Creates a 'keydown' event.
+   *
+   * @param ctrlKey <code>true</code> if the ctrl key is depressed
+   * @param altKey <code>true</code> if the alt key is depressed
+   * @param shiftKey <code>true</code> if the shift key is depressed
+   * @param metaKey <code>true</code> if the meta key is depressed
+   * @param keyCode the key-code to be set on the event
+   * @return the event object
+   */
+ public final NativeEvent createKeyDownEvent(boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode) {
+ return createKeyCodeEvent("keydown", ctrlKey, altKey, shiftKey, metaKey,
+        keyCode);
+  }

   /**
    * Creates a 'keydown' event.
@@ -445,7 +485,11 @@
    * @param keyCode the key-code to be set on the event
    * @param charCode the char-code to be set on the event
    * @return the event object
+   *
+   * @deprecated as of GWT2.1 (keydown events don't have a charCode), use
+ * {...@link #createKeyDownEvent(boolean, boolean, boolean, boolean, int)}
    */
+  @Deprecated
public final NativeEvent createKeyDownEvent(boolean ctrlKey, boolean altKey,
       boolean shiftKey, boolean metaKey, int keyCode, int charCode) {
     return createKeyEvent("keydown", true, true, ctrlKey, altKey, shiftKey,
@@ -468,7 +512,7 @@
    * based upon its type).
    * </p>
    *
-   * @param type the type of event (e.g., "focus", "load", etc)
+   * @param type the type of event (e.g., "keydown", "keypress", etc)
    * @param canBubble <code>true</code> if the event should bubble
    * @param cancelable <code>true</code> if the event should be cancelable
    * @param ctrlKey <code>true</code> if the ctrl key is depressed
@@ -478,13 +522,35 @@
    * @param keyCode the key-code to be set on the event
    * @param charCode the char-code to be set on the event
    * @return the event object
+   *
+   * @deprecated use
+ * {...@link #createKeyCodeEvent(String, boolean, boolean, boolean, boolean, int)}
+   *             or
+ * {...@link #createKeyPressEvent(boolean, boolean, boolean, boolean, int)}
    */
+  @Deprecated
   public final NativeEvent createKeyEvent(String type, boolean canBubble,
boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey,
       boolean metaKey, int keyCode, int charCode) {
     return DOMImpl.impl.createKeyEvent(this, type, canBubble, cancelable,
         ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode);
   }
+
+  /**
+   * Creates a 'keypress' event.
+   *
+   * @param ctrlKey <code>true</code> if the ctrl key is depressed
+   * @param altKey <code>true</code> if the alt key is depressed
+   * @param shiftKey <code>true</code> if the shift key is depressed
+   * @param metaKey <code>true</code> if the meta key is depressed
+   * @param charCode the char-code to be set on the event
+   * @return the event object
+   */
+ public final NativeEvent createKeyPressEvent(boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int charCode) {
+ return DOMImpl.impl.createKeyPressEvent(this, ctrlKey, altKey, shiftKey,
+        metaKey, charCode);
+  }

   /**
    * Creates a 'keypress' event.
@@ -496,12 +562,32 @@
    * @param keyCode the key-code to be set on the event
    * @param charCode the char-code to be set on the event
    * @return the event object
+   *
+   * @deprecated as of GWT 2.1 (keypress events don't have a keyCode), use
+ * {...@link #createKeyPressEvent(boolean, boolean, boolean, boolean, int)}
    */
+  @Deprecated
public final NativeEvent createKeyPressEvent(boolean ctrlKey, boolean altKey,
       boolean shiftKey, boolean metaKey, int keyCode, int charCode) {
return createKeyEvent("keypress", true, true, ctrlKey, altKey, shiftKey,
         metaKey, keyCode, charCode);
   }
+
+  /**
+   * Creates a 'keyup' event.
+   *
+   * @param ctrlKey <code>true</code> if the ctrl key is depressed
+   * @param altKey <code>true</code> if the alt key is depressed
+   * @param shiftKey <code>true</code> if the shift key is depressed
+   * @param metaKey <code>true</code> if the meta key is depressed
+   * @param keyCode the key-code to be set on the event
+   * @return the event object
+   */
+ public final NativeEvent createKeyUpEvent(boolean ctrlKey, boolean altKey,
+      boolean shiftKey, boolean metaKey, int keyCode) {
+    return createKeyCodeEvent("keyup", ctrlKey, altKey, shiftKey, metaKey,
+        keyCode);
+  }

   /**
    * Creates a 'keyup' event.
@@ -513,7 +599,11 @@
    * @param keyCode the key-code to be set on the event
    * @param charCode the char-code to be set on the event
    * @return the event object
+   *
+   * @deprecated as of GWT 2.1 (keyup events don't have a charCode), use
+ * {...@link #createKeyUpEvent(boolean, boolean, boolean, boolean, int)}
    */
+  @Deprecated
public final NativeEvent createKeyUpEvent(boolean ctrlKey, boolean altKey,
       boolean shiftKey, boolean metaKey, int keyCode, int charCode) {
     return createKeyEvent("keyup", true, true, ctrlKey, altKey, shiftKey,
=======================================
--- /trunk/user/src/com/google/gwt/dom/client/NativeEvent.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/dom/client/NativeEvent.java Wed Mar 10 05:44:28 2010
@@ -62,6 +62,15 @@
   public final int getButton() {
     return DOMImpl.impl.eventGetButton(this);
   }
+
+  /**
+ * Gets the Unicode codepoint of the character generated by this key event.
+   *
+   * @return the Unicode codepoint.
+   */
+  public final int getCharCode() {
+    return DOMImpl.impl.eventGetCharCode(this);
+  }

   /**
    * Gets the mouse x-position within the browser window's client area.
@@ -110,15 +119,10 @@
   }

   /**
-   * Gets the key code associated with this event.
+ * Gets the key code (code associated with the physical key) associated with
+   * this event.
    *
-   * <p>
-   * For key press events, this method returns the Unicode value of the
- * character generated. For key down and key up events, it returns the code
-   * associated with the physical key.
-   * </p>
-   *
-   * @return the Unicode character or key code.
+   * @return the key code
    * @see com.google.gwt.event.dom.client.KeyCodes
    */
   public final int getKeyCode() {
=======================================
--- /trunk/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java Wed Mar 10 05:44:28 2010
@@ -15,8 +15,6 @@
  */
 package com.google.gwt.event.dom.client;

-import com.google.gwt.dom.client.NativeEvent;
-
 /**
  * Represents a native key press event.
  */
@@ -57,7 +55,16 @@
    * @return the char code
    */
   public char getCharCode() {
-    return getCharCode(getNativeEvent());
+    return (char) getUnicodeCharCode();
+  }
+
+  /**
+   * Gets the Unicode char code (code point) for this event.
+   *
+   * @return the Unicode char code
+   */
+  public int getUnicodeCharCode() {
+    return getNativeEvent().getCharCode();
   }

   @Override
@@ -69,9 +76,4 @@
   protected void dispatch(KeyPressHandler handler) {
     handler.onKeyPress(this);
   }
-
-  private native char getCharCode(NativeEvent e)/*-{
-    return e.charCode || e.keyCode;
-  }-*/;
-
-}
+}
=======================================
--- /trunk/user/test/com/google/gwt/user/client/ui/CreateEventTest.java Thu Feb 25 06:57:14 2010 +++ /trunk/user/test/com/google/gwt/user/client/ui/CreateEventTest.java Wed Mar 10 05:44:28 2010
@@ -21,6 +21,7 @@
 import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.ImageElement;
 import com.google.gwt.dom.client.InputElement;
+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
@@ -35,30 +36,50 @@
   /**
    * Listener for use with key[down up press].
    */
-  private class KeyEventListener extends BubbleAssertingEventListener {
-    public KeyEventListener(String eventType) {
-      super(eventType);
+  private class KeyCodeEventListener extends BubbleAssertingEventListener {
+
+    public KeyCodeEventListener(String eventType) {
+      super(eventType, true);
     }

+    @Override
     public void onBrowserEvent(Event event) {
       super.onBrowserEvent(event);
-      assertAllShiftKeysOn(event);
       assertEquals(KEY_CODE, event.getKeyCode());
+      // shouldn't throw:
+      event.getCharCode();
     }
   }
+
+  /**
+   * Listener for use with key[down up press].
+   */
+ private class KeyPressEventListener extends BubbleAssertingEventListener {
+    public KeyPressEventListener() {
+      super("keypress", true);
+    }
+
+    @Override
+    public void onBrowserEvent(Event event) {
+      super.onBrowserEvent(event);
+      assertEquals(KEY_CODE, event.getCharCode());
+      // shouldn't throw:
+      event.getKeyCode();
+    }
+  }

   /**
    * Listener for use with mouse[down up move over out].
    */
   private class MouseEventListener extends BubbleAssertingEventListener {
     public MouseEventListener(String eventType) {
-      super(eventType);
+      super(eventType, true);
     }

+    @Override
     public void onBrowserEvent(Event event) {
       super.onBrowserEvent(event);
       assertMouseCoordinates(event);
-      assertAllShiftKeysOn(event);
       assertEquals(Event.BUTTON_LEFT, event.getButton());
     }
   }
@@ -68,15 +89,32 @@
    * parent.
    */
   private class BubbleAssertingEventListener implements EventListener {
-    public boolean parentReceived, childReceived;
+    private boolean parentReceived, childReceived;
     private final String eventType;
-
-    public BubbleAssertingEventListener(String eventType) {
+    private boolean supportsShiftKeys;
+    private boolean expectedCtrl = true;
+    private boolean expectedAlt = true;
+    private boolean expectedShift = true;
+    private boolean expectedMeta = true;
+
+ public BubbleAssertingEventListener(String eventType, boolean supportsShiftKeys) {
       this.eventType = eventType;
+      this.supportsShiftKeys = supportsShiftKeys;
+    }
+
+    public void assertReceived() {
+      assertTrue("Expected child to receive event", childReceived);
+      assertTrue("Expected parent to receive event", parentReceived);
+      childReceived = false;
+      parentReceived = false;
     }

     public void onBrowserEvent(Event event) {
       assertEquals(eventType, event.getType());
+      if (supportsShiftKeys) {
+        assertAllShiftKeys(event, expectedCtrl, expectedAlt, expectedShift,
+            expectedMeta);
+      }

       EventTarget target = event.getCurrentEventTarget();
       if (Element.is(target)) {
@@ -97,6 +135,17 @@
         }
       }
     }
+
+    /**
+     * Set the expected shift keys that should be on during the next event.
+     */
+ public void setExpectedShiftKeys(boolean expectedCtrl, boolean expectedAlt,
+        boolean expectedShift, boolean expectedMeta) {
+      this.expectedCtrl = expectedCtrl;
+      this.expectedAlt = expectedAlt;
+      this.expectedShift = expectedShift;
+      this.expectedMeta = expectedMeta;
+    }
   }

   /**
@@ -173,6 +222,14 @@
       }
     }
   }
+
+  /**
+   * Interface to create a new event for testing.
+   */
+  private static interface EventCreator {
+ NativeEvent createEvent(boolean ctrlKey, boolean altKey, boolean shiftKey,
+        boolean metaKey);
+  }

   private static final int MOUSE_DETAIL = 1;
   private static final int CLIENT_X = 2;
@@ -242,6 +299,7 @@
   public void testTriggerBlurEvent() {
NonBubbleAssertingEventListener listener = new NonBubbleAssertingEventListener(
         "blur") {
+      @Override
       public void onBrowserEvent(Event event) {
         super.onBrowserEvent(event);
         assertEquals("blur", event.getType());
@@ -260,7 +318,7 @@
    */
   public void testTriggerChangeEvent() {
BubbleAssertingEventListener listener = new BubbleAssertingEventListener(
-        "change");
+        "change", false);
     Event.setEventListener(parent, listener);
     Event.setEventListener(child, listener);

@@ -274,11 +332,11 @@
    */
   public void testTriggerClickEvent() {
BubbleAssertingEventListener listener = new BubbleAssertingEventListener(
-        "click") {
+        "click", true) {
+      @Override
       public void onBrowserEvent(Event event) {
         super.onBrowserEvent(event);
         assertMouseCoordinates(event);
-        assertAllShiftKeysOn(event);
       }
     };
     Event.setEventListener(parent, listener);
@@ -293,27 +351,26 @@

   /**
    * Tests createContextMenuEvent().
- * TODO: Re-enable this test when we no longer support Firefox2 and earlier
-   * (which doesn't appear to dispatch contextmenu events properly).
    */
-//  public void testTriggerContextMenuEvent() {
-// BubbleAssertingEventListener listener = new BubbleAssertingEventListener(
-//        "contextmenu");
-//    Event.setEventListener(parent, listener);
-//    Event.setEventListener(child, listener);
-//
-//    child.dispatchEvent(Document.get().createContextMenuEvent());
-//
-// assertTrue("Expected child to receive event", listener.childReceived); -// assertTrue("Expected parent to receive event", listener.parentReceived);
-//  }
+  public void testTriggerContextMenuEvent() {
+ BubbleAssertingEventListener listener = new BubbleAssertingEventListener(
+        "contextmenu", false);
+    Event.setEventListener(parent, listener);
+    Event.setEventListener(child, listener);
+
+    child.dispatchEvent(Document.get().createContextMenuEvent());
+
+    assertTrue("Expected child to receive event", listener.childReceived);
+ assertTrue("Expected parent to receive event", listener.parentReceived);
+  }

   /**
    * Tests createDblClickEvent().
    */
   public void testTriggerDblClickEvent() {
BubbleAssertingEventListener listener = new BubbleAssertingEventListener(
-        "dblclick") {
+        "dblclick", true) {
+      @Override
       public void onBrowserEvent(Event event) {
         if (event.getTypeInt() == Event.ONCLICK) {
// Some browsers (IE, I'm looking at you) synthesize an extra click
@@ -325,7 +382,6 @@

         super.onBrowserEvent(event);
         assertMouseCoordinates(event);
-        assertAllShiftKeysOn(event);
       }
     };
     Event.setEventListener(parent, listener);
@@ -340,6 +396,7 @@

   /**
    * Tests createErrorEvent().
+   *
    * Failed in all modes due to HtmlUnit bug:
* https://sourceforge.net/tracker/?func=detail&aid=2888342&group_id=47038&atid=448266
    */
@@ -360,6 +417,7 @@
   public void testTriggerFocusEvent() {
NonBubbleAssertingEventListener listener = new NonBubbleAssertingEventListener(
         "focus") {
+      @Override
       public void onBrowserEvent(Event event) {
         super.onBrowserEvent(event);
         assertEquals("focus", event.getType());
@@ -377,45 +435,45 @@
    * Tests createKeyDownEvent().
    */
   public void testTriggerKeyDownEvent() {
-    KeyEventListener listener = new KeyEventListener("keydown");
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
-    child.dispatchEvent(Document.get().createKeyDownEvent(true, true, true,
-        true, KEY_CODE, KEY_CODE));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    KeyCodeEventListener listener = new KeyCodeEventListener("keydown");
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createKeyDownEvent(ctrlKey, altKey, shiftKey,
+            metaKey, KEY_CODE);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
    * Tests createKeyPressEvent().
    */
   public void testTriggerKeyPressEvent() {
-    KeyEventListener listener = new KeyEventListener("keypress");
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
- child.dispatchEvent(Document.get().createKeyPressEvent(true, true, true,
-        true, KEY_CODE, KEY_CODE));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    KeyPressEventListener listener = new KeyPressEventListener();
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+ return Document.get().createKeyPressEvent(ctrlKey, altKey, shiftKey,
+            metaKey, KEY_CODE);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
    * Tests createKeyUpEvent().
    */
   public void testTriggerKeyUpEvent() {
-    KeyEventListener listener = new KeyEventListener("keyup");
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
- child.dispatchEvent(Document.get().createKeyUpEvent(true, true, true, true,
-        KEY_CODE, KEY_CODE));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    KeyCodeEventListener listener = new KeyCodeEventListener("keyup");
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createKeyUpEvent(ctrlKey, altKey, shiftKey,
+            metaKey, KEY_CODE);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
@@ -436,15 +494,15 @@
    */
   public void testTriggerMouseDownEvent() {
     MouseEventListener listener = new MouseEventListener("mousedown");
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
-    child.dispatchEvent(Document.get().createMouseDownEvent(MOUSE_DETAIL,
-        SCREEN_X, SCREEN_Y, CLIENT_X, CLIENT_Y, true, true, true, true,
-        Event.BUTTON_LEFT));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createMouseDownEvent(MOUSE_DETAIL, SCREEN_X,
+ SCREEN_Y, CLIENT_X, CLIENT_Y, ctrlKey, altKey, shiftKey, metaKey,
+            Event.BUTTON_LEFT);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
@@ -452,15 +510,15 @@
    */
   public void testTriggerMouseMoveEvent() {
     MouseEventListener listener = new MouseEventListener("mousemove");
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
-    child.dispatchEvent(Document.get().createMouseMoveEvent(MOUSE_DETAIL,
-        SCREEN_X, SCREEN_Y, CLIENT_X, CLIENT_Y, true, true, true, true,
-        Event.BUTTON_LEFT));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createMouseMoveEvent(MOUSE_DETAIL, SCREEN_X,
+ SCREEN_Y, CLIENT_X, CLIENT_Y, ctrlKey, altKey, shiftKey, metaKey,
+            Event.BUTTON_LEFT);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
@@ -468,24 +526,22 @@
    */
   public void testTriggerMouseOutEvent() {
     MouseEventListener listener = new MouseEventListener("mouseout") {
+      @Override
       public void onBrowserEvent(Event event) {
         super.onBrowserEvent(event);
-
-// TODO: Re-enable this assertion when we no longer support Firefox2 and earlier. -// Old Firefoxen throw away the relatedTarget parameter of initMouseEvent().
-//        Element relatedTarget = event.getRelatedTarget();
-// assertEquals("Expected relatedElement to be img", img, relatedTarget);
+        Element relatedTarget = event.getRelatedEventTarget().cast();
+ assertEquals("Expected relatedElement to be img", img, relatedTarget);
       }
     };
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
-    child.dispatchEvent(Document.get().createMouseOutEvent(MOUSE_DETAIL,
-        SCREEN_X, SCREEN_Y, CLIENT_X, CLIENT_Y, true, true, true, true,
-        Event.BUTTON_LEFT, img));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createMouseOutEvent(MOUSE_DETAIL, SCREEN_X,
+ SCREEN_Y, CLIENT_X, CLIENT_Y, ctrlKey, altKey, shiftKey, metaKey,
+            Event.BUTTON_LEFT, img);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
@@ -493,23 +549,22 @@
    */
   public void testTriggerMouseOverEvent() {
     MouseEventListener listener = new MouseEventListener("mouseover") {
+      @Override
       public void onBrowserEvent(Event event) {
         super.onBrowserEvent(event);
-
-// TODO: Re-enable this assertion when we no longer support Firefox2 and earlier. -// Old Firefoxen throw away the relatedTarget parameter of initMouseEvent().
-//        Element relatedTarget = event.getRelatedTarget();
-// assertEquals("Expected relatedElement to be img", img, relatedTarget);
+        Element relatedTarget = event.getRelatedEventTarget().cast();
+ assertEquals("Expected relatedElement to be img", img, relatedTarget);
       }
     };
-    Event.setEventListener(parent, listener);
-    Event.setEventListener(child, listener);
-
- child.dispatchEvent(Document.get().createMouseOverEvent(MOUSE_DETAIL, SCREEN_X, SCREEN_Y, - CLIENT_X, CLIENT_Y, true, true, true, true, Event.BUTTON_LEFT, img));
-
-    assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createMouseOverEvent(MOUSE_DETAIL, SCREEN_X,
+ SCREEN_Y, CLIENT_X, CLIENT_Y, ctrlKey, altKey, shiftKey, metaKey,
+            Event.BUTTON_LEFT, img);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
   }

   /**
@@ -517,37 +572,33 @@
    */
   public void testTriggerMouseUpEvent() {
     MouseEventListener listener = new MouseEventListener("mouseup");
+    EventCreator creator = new EventCreator() {
+      public NativeEvent createEvent(boolean ctrlKey, boolean altKey,
+          boolean shiftKey, boolean metaKey) {
+        return Document.get().createMouseUpEvent(MOUSE_DETAIL, SCREEN_X,
+ SCREEN_Y, CLIENT_X, CLIENT_Y, ctrlKey, altKey, shiftKey, metaKey,
+            Event.BUTTON_LEFT);
+      }
+    };
+    testTriggerEventWithShiftKeys(listener, creator);
+  }
+
+  public void testTriggerScrollEvent() {
+ NonBubbleAssertingEventListener listener = new NonBubbleAssertingEventListener(
+        "scroll") {
+      @Override
+      public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+        assertEquals("scroll", event.getType());
+      }
+    };
     Event.setEventListener(parent, listener);
     Event.setEventListener(child, listener);

-    child.dispatchEvent(Document.get().createMouseUpEvent(MOUSE_DETAIL,
-        SCREEN_X, SCREEN_Y, CLIENT_X, CLIENT_Y, true, true, true, true,
-        Event.BUTTON_LEFT));
+    child.dispatchEvent(Document.get().createScrollEvent());

     assertTrue("Expected child to receive event", listener.childReceived);
- assertTrue("Expected parent to receive event", listener.parentReceived);
-  }
-
-  /**
-   * Tests createScrollEvent().
- * TODO: Re-enable this test when we no longer support Firefox2 and earlier
-   * (which doesn't appear to dispatch contextmenu events properly).
-   */
-//  public void testTriggerScrollEvent() {
-// NonBubbleAssertingEventListener listener = new NonBubbleAssertingEventListener(
-//        "scroll") {
-//      public void onBrowserEvent(Event event) {
-//        super.onBrowserEvent(event);
-//        assertEquals("scroll", event.getType());
-//      }
-//    };
-//    Event.setEventListener(parent, listener);
-//    Event.setEventListener(child, listener);
-//
-//    child.dispatchEvent(Document.get().createScrollEvent());
-//
-// assertTrue("Expected child to receive event", listener.childReceived);
-//  }
+  }

   @Override
   protected void gwtSetUp() throws Exception {
@@ -564,11 +615,21 @@
     Event.sinkEvents(img, ALL_EVENTS);
   }

-  private void assertAllShiftKeysOn(Event event) {
-    assertEquals("Expecting ctrl on", true, event.getCtrlKey());
-    assertEquals("Expecting alt on", true, event.getAltKey());
-    assertEquals("Expecting shift on", true, event.getShiftKey());
-    assertEquals("Expecting meta on", true, event.getMetaKey());
+  /**
+   * Assert that all shift keys are in the expected state.
+   *
+   * @param event the event that was triggered
+   */
+  private void assertAllShiftKeys(Event event, boolean expectedCtrl,
+      boolean expectedAlt, boolean expectedShift, boolean expectedMeta) {
+    assertEquals("Expecting ctrl = " + expectedCtrl, expectedCtrl,
+        event.getCtrlKey());
+    assertEquals("Expecting alt = " + expectedAlt, expectedAlt,
+        event.getAltKey());
+    assertEquals("Expecting shift = " + expectedShift, expectedShift,
+        event.getShiftKey());
+    assertEquals("Expecting meta = " + expectedMeta, expectedMeta,
+        event.getMetaKey());
   }

   private void assertMouseCoordinates(Event event) {
@@ -577,4 +638,34 @@
     assertEquals("screenX", SCREEN_X, event.getScreenX());
     assertEquals("screenY", SCREEN_Y, event.getScreenY());
   }
-}
+
+  /**
+   * Test an event that supports shift keys by testing each shift key
+   * individually.
+   */
+  private void testTriggerEventWithShiftKeys(
+      BubbleAssertingEventListener listener, EventCreator creator) {
+    Event.setEventListener(parent, listener);
+    Event.setEventListener(child, listener);
+
+    listener.setExpectedShiftKeys(true, true, true, true);
+    child.dispatchEvent(creator.createEvent(true, true, true, true));
+    listener.assertReceived();
+
+    listener.setExpectedShiftKeys(true, false, false, false);
+    child.dispatchEvent(creator.createEvent(true, false, false, false));
+    listener.assertReceived();
+
+    listener.setExpectedShiftKeys(false, true, false, false);
+    child.dispatchEvent(creator.createEvent(false, true, false, false));
+    listener.assertReceived();
+
+    listener.setExpectedShiftKeys(false, false, true, false);
+    child.dispatchEvent(creator.createEvent(false, false, true, false));
+    listener.assertReceived();
+
+    listener.setExpectedShiftKeys(false, false, false, true);
+    child.dispatchEvent(creator.createEvent(false, false, false, true));
+    listener.assertReceived();
+  }
+}

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

Reply via email to