Fixes the unfortunate situation with MouseEvent coordinates.
Review by: bruce (desk check)
Review thread: http://gwt-code-reviews.appspot.com/11803


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@5014 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 dd0c07c..1d7e39b 100644
--- a/user/src/com/google/gwt/dom/client/DOMImpl.java
+++ b/user/src/com/google/gwt/dom/client/DOMImpl.java
@@ -85,6 +85,10 @@
     return !!evt.ctrlKey;
   }-*/;
 
+  public native EventTarget eventGetCurrentTarget(NativeEvent event) /*-{
+    return event.currentTarget;
+  }-*/;
+
   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.
@@ -98,7 +102,7 @@
 
   public abstract int eventGetMouseWheelVelocityY(NativeEvent evt);
 
-  public abstract Element eventGetRelatedTarget(NativeEvent nativeEvent);
+  public abstract EventTarget eventGetRelatedTarget(NativeEvent nativeEvent);
 
   public native int eventGetScreenX(NativeEvent evt) /*-{
     return evt.screenX || 0;
@@ -112,7 +116,7 @@
     return !!evt.shiftKey;
   }-*/;
 
-  public abstract Element eventGetTarget(NativeEvent evt);
+  public abstract EventTarget eventGetTarget(NativeEvent evt);
 
   public final native String eventGetType(NativeEvent evt) /*-{
     return evt.type;
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
index d0c2f21..04c205a 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
@@ -21,6 +21,15 @@
  */
 class DOMImplIE6 extends DOMImpl {
 
+  /**
+   * This field *must* be filled in from JSNI code before dispatching an event
+   * on IE. It should be set to the 'this' context of the handler that receives
+   * the event, then restored to its initial value when the dispatcher is done.
+   * See {@link com.google.gwt.user.client.impl.DOMImplIE6#initEventSystem()}
+   * for an example of how this should be done.
+   */
+  private static EventTarget currentEventTarget;
+
   @Override
   public native NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble,
       boolean cancelable) /*-{
@@ -34,7 +43,7 @@
   @Override
   public native InputElement createInputRadioElement(Document doc, String name) /*-{
     return doc.createElement("<INPUT type='RADIO' name='" + name + "'>");
-  }-*/; 
+  }-*/;
 
   @Override
   public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble,
@@ -101,12 +110,17 @@
   }-*/;
 
   @Override
+  public EventTarget eventGetCurrentTarget(NativeEvent event) {
+    return currentEventTarget;
+  }
+
+  @Override
   public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
     return Math.round(-evt.wheelDelta / 40) || 0;
   }-*/;
 
   @Override
-  public native Element eventGetRelatedTarget(NativeEvent evt) /*-{
+  public native EventTarget eventGetRelatedTarget(NativeEvent evt) /*-{
     // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
     // explicitly sets relatedTarget when synthesizing mouse events).
     return evt.relatedTarget ||
@@ -114,7 +128,7 @@
   }-*/;
 
   @Override
-  public native Element eventGetTarget(NativeEvent evt) /*-{
+  public native EventTarget eventGetTarget(NativeEvent evt) /*-{
     return evt.srcElement;
   }-*/;
 
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozillaOld.java b/user/src/com/google/gwt/dom/client/DOMImplMozillaOld.java
index 64184a9..c40400c 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozillaOld.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozillaOld.java
@@ -25,7 +25,47 @@
  class DOMImplMozillaOld extends DOMImplMozilla {
 
   @Override
-  public native int getAbsoluteLeft(Element elem) /*-{
+  public int getAbsoluteLeft(Element elem) {
+    return getAbsoluteLeftImpl(elem.getOwnerDocument().getViewportElement(),
+        elem);
+  }
+
+  @Override
+  public int getAbsoluteTop(Element elem) {
+    return getAbsoluteTopImpl(elem.getOwnerDocument().getViewportElement(),
+        elem);
+  }
+
+  @Override
+  public native String getInnerText(Element node) /*-{
+    // To mimic IE's 'innerText' property in the W3C DOM, we need to recursively
+    // concatenate all child text nodes (depth first).
+    var text = '', child = node.firstChild;
+    while (child) {
+      // 1 == Element node
+      if (child.nodeType == 1) {
+        text += this.@com.google.gwt.dom.client.DOMImpl::getInnerText(Lcom/google/gwt/dom/client/Element;)(child);
+      } else if (child.nodeValue) {
+        text += child.nodeValue;
+      }
+      child = child.nextSibling;
+    }
+    return text;
+  }-*/;
+
+  @Override
+  public native void setInnerText(Element elem, String text) /*-{
+    // Remove all children first.
+    while (elem.firstChild) {
+      elem.removeChild(elem.firstChild);
+    }
+    // Add a new text node.
+    if (text != null) {
+      elem.appendChild(elem.ownerDocument.createTextNode(text));
+    }
+  }-*/;
+  
+  private native int getAbsoluteLeftImpl(Element viewport, Element elem) /*-{
     var doc = elem.ownerDocument;
     var style = doc.defaultView.getComputedStyle(elem, null);
     var left = doc.getBoxObjectFor(elem).x - Math.round(
@@ -41,12 +81,10 @@
       parent = parent.parentNode;
     }
 
-    return left +
-      @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollLeft;
+    return left + viewport.scrollLeft;
   }-*/;
-
-  @Override
-  public native int getAbsoluteTop(Element elem) /*-{
+  
+  private native int getAbsoluteTopImpl(Element viewport, Element elem) /*-{
     var doc = elem.ownerDocument;
     var style = doc.defaultView.getComputedStyle(elem, null);
     var top = doc.getBoxObjectFor(elem).y - Math.round(
@@ -65,33 +103,4 @@
     return top +
       @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop;
   }-*/;
-  
-  @Override
-  public native String getInnerText(Element node) /*-{
-    // To mimic IE's 'innerText' property in the W3C DOM, we need to recursively
-    // concatenate all child text nodes (depth first).
-    var text = '', child = node.firstChild;
-    while (child) {
-      // 1 == Element node
-      if (child.nodeType == 1) {
-        text += this.@com.google.gwt.dom.client.DOMImpl::getInnerText(Lcom/google/gwt/dom/client/Element;)(child);
-      } else if (child.nodeValue) {
-        text += child.nodeValue;
-      }
-      child = child.nextSibling;
-    }
-    return text;
-  }-*/;
-  
-  @Override
-  public native void setInnerText(Element elem, String text) /*-{
-    // Remove all children first.
-    while (elem.firstChild) {
-      elem.removeChild(elem.firstChild);
-    }
-    // Add a new text node.
-    if (text != null) {
-      elem.appendChild(elem.ownerDocument.createTextNode(text));
-    }
-  }-*/;
 }
diff --git a/user/src/com/google/gwt/dom/client/DOMImplStandard.java b/user/src/com/google/gwt/dom/client/DOMImplStandard.java
index c1cd284..90d2e89 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplStandard.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplStandard.java
@@ -94,12 +94,12 @@
   }-*/;
 
   @Override
-  public native Element eventGetRelatedTarget(NativeEvent evt) /*-{
+  public native EventTarget eventGetRelatedTarget(NativeEvent evt) /*-{
     return evt.relatedTarget;
   }-*/;
 
   @Override
-  public native Element eventGetTarget(NativeEvent evt) /*-{
+  public native EventTarget eventGetTarget(NativeEvent evt) /*-{
     return evt.target;
   }-*/;
 
diff --git a/user/src/com/google/gwt/dom/client/Element.java b/user/src/com/google/gwt/dom/client/Element.java
index f5c9aed..a0bf9f2 100644
--- a/user/src/com/google/gwt/dom/client/Element.java
+++ b/user/src/com/google/gwt/dom/client/Element.java
@@ -15,20 +15,49 @@
  */
 package com.google.gwt.dom.client;
 
+import com.google.gwt.core.client.JavaScriptObject;
+
 /**
  * All HTML element interfaces derive from this class.
  */
 public class Element extends Node {
 
   /**
-   * Assert that the given {@link Node} is of type {@link Node#ELEMENT_NODE} and
-   * automatically typecast it.
+   * Assert that the given {@link Node} is an {@link Element} and automatically
+   * typecast it.
+   */
+  public static Element as(JavaScriptObject o) {
+    assert is(o);
+    return (Element)o;
+  }
+
+  /**
+   * Assert that the given {@link Node} is an {@link Element} and automatically
+   * typecast it.
    */
   public static Element as(Node node) {
-    assert node.getNodeType() == Node.ELEMENT_NODE;
+    assert is(node);
     return (Element) node;
   }
 
+  /**
+   * Determines whether the given {@link JavaScriptObject} can be cast to an
+   * {@link Element}.
+   */
+  public static boolean is(JavaScriptObject o) {
+    if (Node.is(o)) {
+      return is((Node)o);
+    }
+    return false;
+  }
+
+  /**
+   * Determine whether the given {@link Node} can be cast to an {@link Element}.
+   */
+  public static boolean is(Node node) {
+    return node.getNodeType() == Node.ELEMENT_NODE;
+  }
+
   protected Element() {
   }
 
diff --git a/user/src/com/google/gwt/dom/client/EventTarget.java b/user/src/com/google/gwt/dom/client/EventTarget.java
new file mode 100644
index 0000000..77c32fe
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/EventTarget.java
@@ -0,0 +1,39 @@
+/*
+ * 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.dom.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * Represents the target of a JavaScript event.
+ * 
+ * <p>
+ * This type is returned from methods such as
+ * {@link NativeEvent#getEventTarget()}, and must usually be cast to another
+ * type using methods such as {@link Element#is(JavaScriptObject)} and
+ * {@link Element#as(JavaScriptObject)}.
+ * </p>
+ * 
+ * <p>
+ * This class intentionally does <em>not</em> specify the methods from the DOM
+ * IDL (dispatchEvent, addEventListener, and removeEventListener).
+ * </p>
+ */
+public class EventTarget extends JavaScriptObject {
+
+  protected EventTarget() {
+  }
+}
diff --git a/user/src/com/google/gwt/dom/client/NativeEvent.java b/user/src/com/google/gwt/dom/client/NativeEvent.java
index 8109652..9dceb85 100644
--- a/user/src/com/google/gwt/dom/client/NativeEvent.java
+++ b/user/src/com/google/gwt/dom/client/NativeEvent.java
@@ -91,6 +91,16 @@
   }

 

   /**

+   * Gets the current target element of this event. This is the element whose

+   * listener fired last, not the element which fired the event initially.

+   * 

+   * @return the event's current target element

+   */

+  public final EventTarget getCurrentEventTarget() {

+    return DOMImpl.impl.eventGetCurrentTarget(this);

+  }

+

+  /**

    * Gets the key code associated with this event.

    * 

    * <p>

@@ -138,7 +148,7 @@
    * 

    * @return the related target

    */

-  public final Element getRelatedTarget() {

+  public final EventTarget getRelatedEventTarget() {

     return DOMImpl.impl.eventGetRelatedTarget(this);

   }

 

@@ -186,7 +196,7 @@
    * 

    * @return the target element

    */

-  public final Element getTarget() {

+  public final EventTarget getEventTarget() {

     return DOMImpl.impl.eventGetTarget(this);

   }

 

diff --git a/user/src/com/google/gwt/dom/client/Node.java b/user/src/com/google/gwt/dom/client/Node.java
index cf7c211..fa3e35c 100644
--- a/user/src/com/google/gwt/dom/client/Node.java
+++ b/user/src/com/google/gwt/dom/client/Node.java
@@ -40,6 +40,22 @@
    */
   public static final short DOCUMENT_NODE = 9;
 
+  /**
+   * Assert that the given {@link JavaScriptObject} is a DOM node and
+   * automatically typecast it.
+   */
+  public static Node as(JavaScriptObject o) {
+    assert is(o);
+    return (Node)o;
+  }
+
+  /**
+   * Determines whether the given {@link JavaScriptObject} is a DOM node.
+   */
+  public static native boolean is(JavaScriptObject o) /*-{
+    return !!o.nodeType;
+  }-*/;
+
   protected Node() {
   }
 
diff --git a/user/src/com/google/gwt/event/dom/client/MouseEvent.java b/user/src/com/google/gwt/event/dom/client/MouseEvent.java
index e86407e..6b2eb40 100644
--- a/user/src/com/google/gwt/event/dom/client/MouseEvent.java
+++ b/user/src/com/google/gwt/event/dom/client/MouseEvent.java
@@ -16,6 +16,7 @@
 package com.google.gwt.event.dom.client;
 
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.event.shared.EventHandler;
 
@@ -102,21 +103,29 @@
   }
 
   /**
-   * Gets the mouse x-position relative to the event's target element.
+   * Gets the mouse x-position relative to the event's current target element.
    * 
    * @return the relative x-position
    */
-  public int getTargetX() {
-    return getRelativeX(getNativeEvent().getTarget());
+  public int getX() {
+    EventTarget currentTarget = getNativeEvent().getCurrentEventTarget();
+    if (Element.is(currentTarget)) {
+      return getRelativeX(Element.as(currentTarget));
+    }
+    return getClientX();
   }
 
   /**
-   * Gets the mouse y-position relative to the event's target element.
+   * Gets the mouse y-position relative to the event's current target element.
    * 
    * @return the relative y-position
    */
-  public int getTargetY() {
-    return getRelativeY(getNativeEvent().getTarget());
+  public int getY() {
+    EventTarget currentTarget = getNativeEvent().getCurrentEventTarget();
+    if (Element.is(currentTarget)) {
+      return getRelativeY(Element.as(currentTarget));
+    }
+    return getClientY();
   }
 
   /**
diff --git a/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java b/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java
index 9b89c91..7611621 100644
--- a/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java
+++ b/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java
@@ -15,7 +15,7 @@
  */

 package com.google.gwt.event.dom.client;

 

-import com.google.gwt.dom.client.Element;

+import com.google.gwt.dom.client.EventTarget;

 

 /**

  * Represents a native mouse out event.

@@ -52,27 +52,16 @@
   }

 

   /**

-   * Gets the element from which the mouse pointer was moved.

+   * Gets the target to which the mouse pointer was moved.

    * 

-   * @return the element from which the mouse pointer was moved

+   * @return the target to which the mouse pointer was moved

    */

-  public Element getFromElement() {

-    return getNativeEvent().getTarget();

-  }

-

-  /**

-   * Gets the element to which the mouse pointer was moved.

-   * 

-   * @return the element to which the mouse pointer was moved

-   */

-  public Element getToElement() {

-    // Use a deferred binding instead of DOMImpl's inefficient switch statement

-    return getNativeEvent().getRelatedTarget();

+  public EventTarget getRelatedTarget() {

+    return getNativeEvent().getRelatedEventTarget();

   }

 

   @Override

   protected void dispatch(MouseOutHandler handler) {

     handler.onMouseOut(this);

   }

-

 }

diff --git a/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java b/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java
index 3306151..0518b82 100644
--- a/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java
+++ b/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java
@@ -15,7 +15,7 @@
  */

 package com.google.gwt.event.dom.client;

 

-import com.google.gwt.dom.client.Element;

+import com.google.gwt.dom.client.EventTarget;

 

 /**

  * Represents a native mouse over event.

@@ -52,26 +52,16 @@
   }

 

   /**

-   * Gets the element from which the mouse pointer was moved.

+   * Gets the target from which the mouse pointer was moved.

    * 

-   * @return the element from which the mouse pointer was moved

+   * @return the target from which the mouse pointer was moved

    */

-  public Element getFromElement() {

-    return getNativeEvent().getRelatedTarget();

-  }

-

-  /**

-   * Gets the element to which the mouse pointer was moved.

-   * 

-   * @return the element to which the mouse pointer was moved

-   */

-  public Element getToElement() {

-    return getNativeEvent().getTarget();

+  public EventTarget getRelatedTarget() {

+    return getNativeEvent().getRelatedEventTarget();

   }

 

   @Override

   protected void dispatch(MouseOverHandler handler) {

     handler.onMouseOver(this);

   }

-

 }

diff --git a/user/src/com/google/gwt/user/client/DOM.java b/user/src/com/google/gwt/user/client/DOM.java
index 8ba36b5..03721b8 100644
--- a/user/src/com/google/gwt/user/client/DOM.java
+++ b/user/src/com/google/gwt/user/client/DOM.java
@@ -457,7 +457,7 @@
    * @see DOM#eventGetTarget(Event)
    */
   public static Element eventGetCurrentTarget(Event evt) {
-    return impl.eventGetCurrentTarget(evt);
+    return evt.getCurrentTarget().cast();
   }
 
   /**
diff --git a/user/src/com/google/gwt/user/client/Event.java b/user/src/com/google/gwt/user/client/Event.java
index a7e466a..76b3c7c 100644
--- a/user/src/com/google/gwt/user/client/Event.java
+++ b/user/src/com/google/gwt/user/client/Event.java
@@ -446,30 +446,6 @@
   }
 
   /**
-   * Gets the x coordinate relative to the given element.
-   * 
-   * @param nativeEvent the native event
-   * @param relativeTo the relative element
-   * @return the relative x
-   */
-  public static int getRelativeX(NativeEvent nativeEvent, Element relativeTo) {
-    return nativeEvent.getClientX() - relativeTo.getAbsoluteLeft()
-        + relativeTo.getScrollLeft() + Window.getScrollLeft();
-  }
-
-  /**
-   * Gets the y coordinate relative to the given element.
-   * 
-   * @param nativeEvent the native event
-   * @param relativeTo the relative element
-   * @return the relative y
-   */
-  public static int getRelativeY(NativeEvent nativeEvent, Element relativeTo) {
-    return nativeEvent.getClientY() - relativeTo.getAbsoluteTop()
-        + relativeTo.getScrollTop() + Window.getScrollTop();
-  }
-
-  /**
    * Gets the enumerated type of this event given a valid event type name.
    * 
    * @param typeName the typeName to be tested
@@ -549,7 +525,9 @@
    * propagated to parent elements.
    * 
    * @param cancel <code>true</code> to cancel bubbling
+   * @deprecated use {@link NativeEvent#stopPropagation()} instead
    */
+  @Deprecated
   public final void cancelBubble(boolean cancel) {
     DOM.eventCancelBubble(this, cancel);
   }
@@ -559,9 +537,11 @@
    * listener fired last, not the element which fired the event initially.
    * 
    * @return the event's current target element
+   * @deprecated use {@link NativeEvent#getCurrentEventTarget()} instead
    */
+  @Deprecated
   public final Element getCurrentTarget() {
-    return DOM.eventGetCurrentTarget(this);
+    return getCurrentEventTarget().cast();
   }
 
   /**
@@ -577,6 +557,17 @@
   }
 
   /**
+   * Gets the related target for this event.
+   * 
+   * @return the related target
+   * @deprecated use {@link NativeEvent#getRelatedEventTarget()} instead
+   */
+  @Deprecated
+  public final Element getRelatedTarget() {
+    return getRelatedEventTarget().cast();
+  }
+
+  /**
    * Gets the key-repeat state of this event.
    * 
    * @return <code>true</code> if this key event was an auto-repeat
@@ -588,6 +579,17 @@
   }
 
   /**
+   * Returns the element that was the actual target of the given event.
+   * 
+   * @return the target element
+   * @deprecated use {@link NativeEvent#getEventTarget()} instead
+   */
+  @Deprecated
+  public final Element getTarget() {
+    return getEventTarget().cast();
+  }
+
+  /**
    * Gets the element to which the mouse pointer was moved (only valid for
    * {@link Event#ONMOUSEOUT}).
    * 
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImpl.java b/user/src/com/google/gwt/user/client/impl/DOMImpl.java
index 2b31054..11f9ef6 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImpl.java
@@ -48,10 +48,6 @@
   public native void eventCancelBubble(Event evt, boolean cancel) /*-{
     evt.cancelBubble = cancel;
   }-*/;
-  
-  public native Element eventGetCurrentTarget(Event evt) /*-{
-    return evt.currentTarget;
-  }-*/;
 
   public abstract Element eventGetFromElement(Event evt);
   
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
index 03e937c..3ce49bd 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
@@ -26,20 +26,12 @@
 class DOMImplIE6 extends DOMImpl {
 
   @SuppressWarnings("unused")
-  private static Element currentEventTarget;
-
-  @SuppressWarnings("unused")
   private static JavaScriptObject dispatchEvent;
 
   @SuppressWarnings("unused")
   private static JavaScriptObject dispatchDblClickEvent;
 
   @Override
-  public native Element eventGetCurrentTarget(Event evt) /*-{
-    return @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget;
-  }-*/;
-
-  @Override
   public native Element eventGetFromElement(Event evt) /*-{
     // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
     // explicitly sets relatedTarget when synthesizing mouse events).
@@ -81,13 +73,13 @@
       // also seems that IE won't allow you to add expandos to the event object,
       // so we have to store it in a global. This is ok because only one event
       // can actually be dispatched at a time.
-      var oldEventTarget = @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget;
-      @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = this;
+      var oldEventTarget = @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget;
+      @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = this;
 
       if ($wnd.event.returnValue == null) {
         $wnd.event.returnValue = true;
         if (!@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event)) {
-          @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = oldEventTarget;
+          @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = oldEventTarget;
           return;
         }
       }
@@ -103,7 +95,7 @@
         }
       }
 
-      @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = oldEventTarget;
+      @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = oldEventTarget;
     };
 
     @com.google.gwt.user.client.impl.DOMImplIE6::dispatchDblClickEvent = function() {
diff --git a/user/src/com/google/gwt/user/client/ui/DialogBox.java b/user/src/com/google/gwt/user/client/ui/DialogBox.java
index a5bde38..363692e 100644
--- a/user/src/com/google/gwt/user/client/ui/DialogBox.java
+++ b/user/src/com/google/gwt/user/client/ui/DialogBox.java
@@ -16,6 +16,7 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.event.dom.client.HasAllMouseHandlers;
 import com.google.gwt.event.dom.client.MouseDownEvent;
@@ -329,8 +330,7 @@
    * @param event the mouse down event that triggered dragging
    */
   protected void beginDragging(MouseDownEvent event) {
-    onMouseDown(caption, Event.getRelativeX(event.getNativeEvent(),
-        getElement()), Event.getRelativeY(event.getNativeEvent(), getElement()));
+    onMouseDown(caption, event.getX(), event.getY());
   }
 
   /**
@@ -342,8 +342,7 @@
    * @param event the mouse move event that continues dragging
    */
   protected void continueDragging(MouseMoveEvent event) {
-    onMouseMove(caption, Event.getRelativeX(event.getNativeEvent(),
-        getElement()), Event.getRelativeY(event.getNativeEvent(), getElement()));
+    onMouseMove(caption, event.getX(), event.getY());
   }
 
   @Override
@@ -376,9 +375,7 @@
    * @see #endDragging
    */
   protected void endDragging(MouseUpEvent event) {
-    onMouseUp(caption,
-        Event.getRelativeX(event.getNativeEvent(), getElement()),
-        Event.getRelativeY(event.getNativeEvent(), getElement()));
+    onMouseUp(caption, event.getX(), event.getY());
   }
 
   /**
@@ -414,7 +411,11 @@
   }
 
   private boolean isCaptionEvent(NativeEvent event) {
-    return getCellElement(0, 1).getParentElement().isOrHasChild(
-        event.getTarget());
+    EventTarget target = event.getEventTarget();
+    if (Element.is(target)) {
+      return getCellElement(0, 1).getParentElement().isOrHasChild(
+          Element.as(target));
+    }
+    return false;
   }
 }
diff --git a/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
index a3a5435..24e4e40 100644
--- a/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
+++ b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
@@ -463,18 +463,12 @@
 

     public void onMouseDown(MouseDownEvent event) {

       Widget source = getSource(event);

-      Element elem = source.getElement();

-      getListener().onMouseDown(source,

-          Event.getRelativeX(event.getNativeEvent(), elem),

-          Event.getRelativeY(event.getNativeEvent(), elem));

+      getListener().onMouseDown(source, event.getX(), event.getY());

     }

 

     public void onMouseMove(MouseMoveEvent event) {

       Widget source = getSource(event);

-      Element elem = source.getElement();

-      getListener().onMouseMove(source,

-          Event.getRelativeX(event.getNativeEvent(), elem),

-          Event.getRelativeY(event.getNativeEvent(), elem));

+      getListener().onMouseMove(source, event.getX(), event.getY());

     }

 

     public void onMouseOut(MouseOutEvent event) {

@@ -487,10 +481,7 @@
 

     public void onMouseUp(MouseUpEvent event) {

       Widget source = getSource(event);

-      Element elem = source.getElement();

-      getListener().onMouseUp(source,

-          Event.getRelativeX(event.getNativeEvent(), elem),

-          Event.getRelativeY(event.getNativeEvent(), elem));

+      getListener().onMouseUp(source, event.getX(), event.getY());

     }

   }

   /**

diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index a9fa5b3..135056c 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -16,6 +16,7 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
@@ -1006,9 +1007,9 @@
             case Event.ONMOUSEDOWN:
               // If the event target is part of the parent menu, suppress the
               // event altogether.
-              com.google.gwt.dom.client.Element target = event.getNativeEvent().getTarget();
+              EventTarget target = event.getNativeEvent().getEventTarget();
               Element parentMenuElement = item.getParentMenu().getElement();
-              if (parentMenuElement.isOrHasChild(target)) {
+              if (parentMenuElement.isOrHasChild(Element.as(target))) {
                 event.cancel();
                 return;
               }
diff --git a/user/src/com/google/gwt/user/client/ui/PopupPanel.java b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
index 08fd2b8..07f85e5 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -19,6 +19,7 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
@@ -902,10 +903,12 @@
       return false;
     }
 
-    Element target = event.getTarget();
-    for (Element elem : autoHidePartners) {
-      if (elem.isOrHasChild(target)) {
-        return true;
+    EventTarget target = event.getEventTarget();
+    if (Element.is(target)) {
+      for (Element elem : autoHidePartners) {
+        if (elem.isOrHasChild(Element.as(target))) {
+          return true;
+        }
       }
     }
     return false;
@@ -918,7 +921,11 @@
    * @return true if the event targets the popup
    */
   private boolean eventTargetsPopup(NativeEvent event) {
-    return getElement().isOrHasChild(event.getTarget());
+    EventTarget target = event.getEventTarget();
+    if (Element.is(target)) {
+      return getElement().isOrHasChild(Element.as(target));
+    }
+    return false;
   }
 
   /**
diff --git a/user/test/com/google/gwt/event/dom/client/DomEventTest.java b/user/test/com/google/gwt/event/dom/client/DomEventTest.java
index 5655c59..e7c211c 100644
--- a/user/test/com/google/gwt/event/dom/client/DomEventTest.java
+++ b/user/test/com/google/gwt/event/dom/client/DomEventTest.java
@@ -15,9 +15,13 @@
  */
 package com.google.gwt.event.dom.client;
 
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.event.shared.HandlerManager;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.event.shared.HandlerTestBase;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.RootPanel;
 
 /**
  * Events test.
@@ -59,7 +63,6 @@
   }
 
   public void testMouseEvents() {
-
     final Flag flag = new Flag();
     manager = new HandlerManager(flag);
 
@@ -128,6 +131,28 @@
         "onDoubleClick");
   }
 
+  public void testMouseEventCoordinates() {
+    Button b = new Button();
+    RootPanel.get().add(b);
+
+    final Flag flag = new Flag();
+    b.addMouseDownHandler(new MouseDownHandler() {
+      public void onMouseDown(MouseDownEvent event) {
+        assertEquals("", 16, event.getX());
+        assertEquals("", 8, event.getY());
+        flag.flag = true;
+      }
+    });
+
+    int x = b.getAbsoluteLeft() + 16;
+    int y = b.getAbsoluteTop() + 8;
+    NativeEvent event = Document.get().createMouseDownEvent(0, x, y, x, y,
+        false, false, false, false, 1);
+    b.getElement().dispatchEvent(event);
+
+    assertTrue("Never received expected mouse-down event", flag.flag);
+  }
+
   private void checkFire(DomEvent<?> event, HandlerRegistration registration,
       Flag flag, String eventName) {
 
diff --git a/user/test/com/google/gwt/user/client/ui/ButtonTest.java b/user/test/com/google/gwt/user/client/ui/ButtonTest.java
index 83777e7..9ba6cef 100644
--- a/user/test/com/google/gwt/user/client/ui/ButtonTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ButtonTest.java
@@ -15,7 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
-import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.junit.client.GWTTestCase;
@@ -31,10 +31,10 @@
 
   private class H implements ClickHandler {
     boolean clicked;
-    Element target;
+    EventTarget target;
 
     public void onClick(ClickEvent event) {
-      target = event.getNativeEvent().getTarget();
+      target = event.getNativeEvent().getEventTarget();
       clicked = true;
     }
   }
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 9029f94..09a06f9 100644
--- a/user/test/com/google/gwt/user/client/ui/CreateEventTest.java
+++ b/user/test/com/google/gwt/user/client/ui/CreateEventTest.java
@@ -18,6 +18,7 @@
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+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.junit.client.GWTTestCase;
@@ -75,21 +76,23 @@
     public void onBrowserEvent(Event event) {
       assertEquals(eventType, event.getType());
 
-      Element target = event.getCurrentTarget();
-      if (target == child) {
-        assertFalse("Expecting child to receive the event only once",
-            childReceived);
-        assertFalse("Expecting child to receive the event before parent",
-            parentReceived);
+      EventTarget target = event.getCurrentEventTarget();
+      if (Element.is(target)) {
+        if (Element.as(target) == child) {
+          assertFalse("Expecting child to receive the event only once",
+              childReceived);
+          assertFalse("Expecting child to receive the event before parent",
+              parentReceived);
 
-        childReceived = true;
-      } else if (target == parent) {
-        assertFalse("Expecting parent to receive the event only once",
-            parentReceived);
-        assertTrue("Expecting parent to receive the event after the child",
-            childReceived);
+          childReceived = true;
+        } else if (Element.as(target) == parent) {
+          assertFalse("Expecting parent to receive the event only once",
+              parentReceived);
+          assertTrue("Expecting parent to receive the event after the child",
+              childReceived);
 
-        parentReceived = true;
+          parentReceived = true;
+        }
       }
     }
   }