Merging releases/1.5 into trunk

svn merge -r3341:3372 https://google-web-toolkit.googlecode.com/svn/releases/1.5 .



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3376 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/rewrite/WriteJsoImpl.java b/dev/core/src/com/google/gwt/dev/shell/rewrite/WriteJsoImpl.java
index 8561b42..54bced6 100644
--- a/dev/core/src/com/google/gwt/dev/shell/rewrite/WriteJsoImpl.java
+++ b/dev/core/src/com/google/gwt/dev/shell/rewrite/WriteJsoImpl.java
@@ -82,11 +82,12 @@
       jsoDescList.addAll(jsoDescriptors);
       interfaces = jsoDescList.toArray(new String[jsoDescList.size()]);
     } else {
+      // Reference the old superclass's implementation class.
+      superName += '$';
       interfaces = null;
     }
 
-    super.visit(version, access, name + '$', signature, "java/lang/Object",
-        interfaces);
+    super.visit(version, access, name + '$', signature, superName, interfaces);
 
     if (isJavaScriptObject()) {
       FieldVisitor fv = visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
index 7233d75..60df7ab 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
@@ -20,10 +20,12 @@
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventPreview;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.SimplePanel;
@@ -92,7 +94,6 @@
   @Override
   public Widget createIssue() {
     // Setup the page size and cursor
-    Element bodyElement = RootPanel.getBodyElement();
     htmlElement = DOM.getParent(RootPanel.getBodyElement());
 
     // Create a crosshair to show the current position
@@ -103,6 +104,9 @@
     positioner.getElement().getStyle().setProperty("borderTop", "1px solid red");
     positioner.getElement().getStyle().setProperty("cursor", "crosshair");
 
+    // Create an area to echo position information.
+    final HTML echo = new HTML();
+
     // Create a target box to test inside
     final Label sandbox = new Label();
     sandbox.sinkEvents(Event.ONMOUSEMOVE);
@@ -123,8 +127,16 @@
 
         switch (DOM.eventGetType(event)) {
           case Event.ONMOUSEMOVE:
-            RootPanel.get().add(positioner, event.getClientX(),
-                event.getClientY());
+            int absX = event.getClientX() + Window.getScrollLeft();
+            int absY = event.getClientY() + Window.getScrollTop();
+            RootPanel.get().add(positioner, absX, absY);
+
+            echo.setHTML(
+              "event.clientX: " + event.getClientX() + "<br>" +
+              "event.clientY: " + event.getClientY() + "<br>" +
+              "absolute left: " + positioner.getAbsoluteLeft() + "<br>" +
+              "absolute top: " + positioner.getAbsoluteTop()
+            );
             break;
         }
         return true;
@@ -134,6 +146,7 @@
     // Combine the control panel and return
     VerticalPanel vPanel = new VerticalPanel();
     vPanel.add(new ControlPanel());
+    vPanel.add(echo);
     vPanel.add(sandbox);
     return vPanel;
   }
@@ -142,9 +155,9 @@
   public String getInstructions() {
     return "Move the cursor inside the blue box below and verify that the "
         + "point of the red positioner lines up directly beneath the center of "
-        + "the cursor (crosshair).  The buttons may not work on Safari 2 "
-        + "because Safari 2 has issues when you attempt to modify the HTML "
-        + "element programatically.";
+        + "the cursor (crosshair). Also confirm that event.clientX/Y == absolute "
+        + "left/top. The buttons may not work on Safari 2 because Safari 2 has "
+        + "issues when you attempt to modify the HTML element programatically.";
   }
 
   @Override
diff --git a/user/src/com/google/gwt/dom/client/DOMImpl.java b/user/src/com/google/gwt/dom/client/DOMImpl.java
index 2c0cb1e..88e4c96 100644
--- a/user/src/com/google/gwt/dom/client/DOMImpl.java
+++ b/user/src/com/google/gwt/dom/client/DOMImpl.java
@@ -71,6 +71,14 @@
     return top;
   }-*/;
 
+  public native int getBodyOffsetLeft() /*-{
+    return 0;
+  }-*/;
+
+  public native int getBodyOffsetTop() /*-{
+    return 0;
+  }-*/;
+
   public native Element getFirstChildElement(Element elem) /*-{
     var child = elem.firstChild;
     while (child && child.nodeType != 1)
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
index fe4e816..14baeb8 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
@@ -41,16 +41,22 @@
 
   @Override
   public native int getAbsoluteLeft(Element elem) /*-{
-    return elem.getBoundingClientRect().left
-        + @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollLeft
-        - @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientLeft;
+    return elem.getBoundingClientRect().left +
+      @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollLeft;
   }-*/;
 
   @Override
   public native int getAbsoluteTop(Element elem) /*-{
-    return elem.getBoundingClientRect().top
-        + @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop
-        - @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientTop;
+    return elem.getBoundingClientRect().top +
+      @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop;
+  }-*/;
+
+  public native int getBodyOffsetLeft() /*-{
+    return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientLeft;
+  }-*/;
+
+  public native int getBodyOffsetTop() /*-{
+    return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientTop;
   }-*/;
 
   @Override
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
index 029eff9..4698069 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
@@ -27,20 +27,16 @@
     // supported on older versions). If changing this code, make sure to check
     // the museum entry for issue 1932.
     if (Element.prototype.getBoundingClientRect) {
-      // getBoundingClientRect().left is off by the document element's
-      // border-left-width.
-      var style = $wnd.getComputedStyle($doc.documentElement, '')
       return elem.getBoundingClientRect().left +
-        parseInt(style.borderLeftWidth) +
-        $doc.body.scrollLeft;
+        @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollLeft;
     } else {
       // We cannot use DOMImpl here because offsetLeft/Top return erroneous
       // values when overflow is not visible.  We have to difference screenX
       // here due to a change in getBoxObjectFor which causes inconsistencies
       // on whether the calculations are inside or outside of the element's
       // border.
-      return $doc.getBoxObjectFor(elem).screenX
-          - $doc.getBoxObjectFor($doc.documentElement).screenX;
+      return $doc.getBoxObjectFor(elem).screenX -
+        $doc.getBoxObjectFor($doc.documentElement).screenX;
     }
   }-*/;
 
@@ -51,23 +47,29 @@
     // supported on older versions). If changing this code, make sure to check
     // the museum entry for issue 1932.
     if (Element.prototype.getBoundingClientRect) {
-      // getBoundingClientRect().top is off by the document element's
-      // border-top-width.
-      var style = $wnd.getComputedStyle($doc.documentElement, '')
       return elem.getBoundingClientRect().top +
-        parseInt(style.borderTopWidth) +
-        $doc.body.scrollTop;
+        @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop;
     } else {
       // We cannot use DOMImpl here because offsetLeft/Top return erroneous
       // values when overflow is not visible.  We have to difference screenX
       // here due to a change in getBoxObjectFor which causes inconsistencies
       // on whether the calculations are inside or outside of the element's
       // border.
-      return $doc.getBoxObjectFor(elem).screenY
-          - $doc.getBoxObjectFor($doc.documentElement).screenY;
+      return $doc.getBoxObjectFor(elem).screenY -
+        $doc.getBoxObjectFor($doc.documentElement).screenY;
     }
   }-*/;
 
+  public native int getBodyOffsetLeft() /*-{
+    var style = $wnd.getComputedStyle($doc.documentElement, '');
+    return parseInt(style.marginLeft) + parseInt(style.borderLeftWidth);
+  }-*/;
+
+  public native int getBodyOffsetTop() /*-{
+    var style = $wnd.getComputedStyle($doc.documentElement, '');
+    return parseInt(style.marginTop) + parseInt(style.borderTopWidth);
+  }-*/;
+
   @Override
   public native boolean isOrHasChild(Element parent, Element child) /*-{
     // For more information about compareDocumentPosition, see:
diff --git a/user/src/com/google/gwt/dom/client/Document.java b/user/src/com/google/gwt/dom/client/Document.java
index 3782e36..eb07ee3 100644
--- a/user/src/com/google/gwt/dom/client/Document.java
+++ b/user/src/com/google/gwt/dom/client/Document.java
@@ -610,6 +610,48 @@
   }-*/;
 
   /**
+   * Returns the left offset between the absolute coordinate system and the
+   * body's positioning context. This method is useful for positioning children
+   * of the body element in absolute coordinates.
+   * 
+   * <p>
+   * For example, to position an element directly under the mouse cursor
+   * (assuming you are handling a mouse event), do the following:
+   * </p>
+   * <pre>
+   * Event event;
+   * Document doc;
+   * DivElement child;  // assume absolutely-positioned child of the body
+   * 
+   * // Get the event location in absolute coordinates.
+   * int absX = event.getClientX() + Window.getScrollLeft();
+   * int absY = event.getClientY() + Window.getScrollTop();
+   * 
+   * // Position the child element, adjusting for the difference between the
+   * // absolute coordinate system and the body's positioning coordinates.
+   * child.getStyle().setPropertyPx("left", absX - doc.getBodyOffsetLeft());
+   * child.getStyle().setPropertyPx("top", absY - doc.getBodyOffsetTop());
+   * </pre>
+   * 
+   * @return the left offset of the body's positioning coordinate system
+   */
+  public final int getBodyOffsetLeft() {
+    return DOMImpl.impl.getBodyOffsetLeft();
+  }
+
+  /**
+   * Returns the top offset between the absolute coordinate system and the
+   * body's positioning context. This method is useful for positioning children
+   * of the body element in absolute coordinates.
+   * 
+   * @return the top offset of the body's positioning coordinate system
+   * @see #getBodyOffsetLeft()
+   */
+  public final int getBodyOffsetTop() {
+    return DOMImpl.impl.getBodyOffsetTop();
+  }
+
+  /**
    * The domain name of the server that served the document, or null if the
    * server cannot be identified by a domain name.
    * 
diff --git a/user/src/com/google/gwt/dom/client/TableRowElement.java b/user/src/com/google/gwt/dom/client/TableRowElement.java
index 3200227..6921f93 100644
--- a/user/src/com/google/gwt/dom/client/TableRowElement.java
+++ b/user/src/com/google/gwt/dom/client/TableRowElement.java
@@ -37,6 +37,11 @@
   protected TableRowElement() {
   }
 
+  /**
+   * Delete a cell from the current row.
+   * 
+   * @see <a href="http://www.w3.org/TR/1999/REC-html401-19991224/struct/tables.html#adef-align-TD">W3C HTML Specification</a>
+   */
   public final native void deleteCell(int index) /*-{
     this.deleteCell(index);
   }-*/;
@@ -102,6 +107,12 @@
     return this.vAlign;
   }-*/;
 
+  /**
+   * Insert an empty TD cell into this row. If index is -1 or equal to the
+   * number of cells, the new cell is appended.
+   * 
+   * @see <a href="http://www.w3.org/TR/1999/REC-html401-19991224/struct/tables.html#adef-align-TD">W3C HTML Specification</a>
+   */
   public final native TableCellElement insertCell(int index) /*-{
     return this.insertCell(index);
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/Event.java b/user/src/com/google/gwt/user/client/Event.java
index 1a4e326..94b3043 100644
--- a/user/src/com/google/gwt/user/client/Event.java
+++ b/user/src/com/google/gwt/user/client/Event.java
@@ -15,8 +15,8 @@
  */
 package com.google.gwt.user.client;
 
-import com.google.gwt.dom.client.Element;
 import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.dom.client.Element;
 
 /**
  * <p>
@@ -184,6 +184,19 @@
   public static final int UNDEFINED = 0;
 
   /**
+   * Adds an event preview to the preview stack. As long as this preview remains
+   * on the top of the stack, it will receive all events before they are fired
+   * to their listeners. Note that the event preview will receive <u>all </u>
+   * events, including those received due to bubbling, whereas normal event
+   * handlers only receive explicitly sunk events.
+   * 
+   * @param preview the event preview to be added to the stack.
+   */
+  public static void addEventPreview(EventPreview preview) {
+    DOM.addEventPreview(preview);
+  }
+
+  /**
    * Gets the current event that is being fired. The current event is only
    * available within the lifetime of the onBrowserEvent function. Once the
    * onBrowserEvent method returns, the current event is reset to null.
@@ -217,6 +230,16 @@
   }
 
   /**
+   * Removes an element from the preview stack. This element will no longer
+   * capture events, though any preview underneath it will begin to do so.
+   * 
+   * @param preview the event preview to be removed from the stack
+   */
+  public static void removeEventPreview(EventPreview preview) {
+    DOM.removeEventPreview(preview);
+  }
+
+  /**
    * Sets mouse-capture on the given element. This element will directly receive
    * all mouse events until {@link #releaseCapture(Element)} is called on it.
    * 
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 f5df1e6..8cd05bf 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
@@ -35,18 +35,6 @@
   private static JavaScriptObject dispatchDblClickEvent;
 
   @Override
-  public native int eventGetClientX(Event evt) /*-{
-    return evt.clientX -
-        @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientLeft;
-  }-*/;
-
-  @Override
-  public native int eventGetClientY(Event evt) /*-{
-    return evt.clientY -
-        @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientTop;
-  }-*/;
-
-  @Override
   public native Element eventGetCurrentTarget(Event evt) /*-{
     return @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget;
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java b/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
index 7440b5f..20892b7 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
@@ -24,44 +24,6 @@
 class DOMImplMozilla extends DOMImplStandard {
 
   @Override
-  public native int eventGetClientX(Event evt) /*-{
-    var htmlOffset;
-    // Firefox 3 is actively throwing errors when getBoxObjectFor() is called,
-    // so we use getBoundingClientRect() whenever possible (but it's not
-    // supported on older versions). If changing this code, make sure to check
-    // the museum entry for issue 1932.
-    if (Element.prototype.getBoundingClientRect) {
-      // getBoundingClientRect().left is off by the document element's
-      // border-left-width.
-      var style = $wnd.getComputedStyle($doc.documentElement, '')
-      htmlOffset = $doc.documentElement.getBoundingClientRect().left +
-        parseInt(style.borderLeftWidth);
-    } else {
-      htmlOffset = $doc.getBoxObjectFor($doc.documentElement).x || 0;
-    }
-    return evt.clientX - htmlOffset;
-  }-*/;
-
-  @Override
-  public native int eventGetClientY(Event evt) /*-{
-    var htmlOffset;
-    // Firefox 3 is actively throwing errors when getBoxObjectFor() is called,
-    // so we use getBoundingClientRect() whenever possible (but it's not
-    // supported on older versions). If changing this code, make sure to check
-    // the museum entry for issue 1932.
-    if (Element.prototype.getBoundingClientRect) {
-      // getBoundingClientRect().top is off by the document element's
-      // border-top-width.
-      var style = $wnd.getComputedStyle($doc.documentElement, '')
-      htmlOffset = $doc.documentElement.getBoundingClientRect().top +
-        parseInt(style.borderTopWidth);
-    } else {
-      htmlOffset = $doc.getBoxObjectFor($doc.documentElement).y || 0;
-    }
-    return evt.clientY - htmlOffset;
-  }-*/;
-
-  @Override
   public native int eventGetMouseWheelVelocityY(Event evt) /*-{
     return evt.detail || 0;
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java b/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
index bdd5f10..1b7e3b55 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
@@ -25,9 +25,9 @@
   @Override
   public native int eventGetClientX(Event evt) /*-{
     // In Safari2: clientX is wrong and pageX is returned instead.
+    // $wnd.devicePixelRatio identifies Safari 3 from Safari 2
     if ($wnd.devicePixelRatio) {
-      // $wnd.devicePixelRatio identifies Safari 3 from Safari 2
-      return evt.pageX - $doc.body.scrollLeft || 0; 
+      return evt.clientX || 0;
     } else {
       // Subtract the margin and border of the HTML element in Safari 2 
       // TODO: Remove this code when we drop Safari 2 support
@@ -41,9 +41,9 @@
   @Override
   public native int eventGetClientY(Event evt) /*-{
     // In Safari2: clientY is wrong and pageY is returned instead.
+    // $wnd.devicePixelRatio identifies Safari 3 from Safari 2
     if ($wnd.devicePixelRatio) {
-      // $wnd.devicePixelRatio identifies Safari 3 from Safari 2
-      return evt.pageY - $doc.body.scrollTop || 0; 
+      return evt.clientY || 0;
     } else {
       // Subtract the margin and border of the HTML element in Safari 2 
       // TODO: Remove this code when we drop Safari 2 support
diff --git a/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java b/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
index 3200777..97dbd2e 100644
--- a/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
+++ b/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
@@ -154,14 +154,7 @@
     setWidgetPositionImpl(w, left, top);
   }
 
-  private void checkWidgetParent(Widget w) {
-    if (w.getParent() != this) {
-      throw new IllegalArgumentException(
-          "Widget must be a child of this panel.");
-    }
-  }
-
-  private void setWidgetPositionImpl(Widget w, int left, int top) {
+  protected void setWidgetPositionImpl(Widget w, int left, int top) {
     Element h = w.getElement();
     if ((left == -1) && (top == -1)) {
       changeToStaticPositioning(h);
@@ -171,4 +164,11 @@
       DOM.setStyleAttribute(h, "top", top + "px");
     }
   }
+
+  private void checkWidgetParent(Widget w) {
+    if (w.getParent() != this) {
+      throw new IllegalArgumentException(
+          "Widget must be a child of this panel.");
+    }
+  }
 }
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 9591092..ab2450a 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.animation.client.Animation;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Document;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
@@ -29,11 +30,18 @@
 
 /**
  * A panel that can "pop up" over other widgets. It overlays the browser's
- * client area (and any previously-created popups). <p/> The width and height of
- * the PopupPanel cannot be explicitly set; they are determined by the
- * PopupPanel's widget. Calls to {@link #setWidth(String)} and
+ * client area (and any previously-created popups).
+ * 
+ * <p>
+ * A PopupPanel should not generally be added to other panels; rather, it should
+ * be shown and hidden using the {@link #show()} and {@link #hide()} methods.
+ * </p>
+ * <p>
+ * The width and height of the PopupPanel cannot be explicitly set; they are
+ * determined by the PopupPanel's widget. Calls to {@link #setWidth(String)} and
  * {@link #setHeight(String)} will call these methods on the PopupPanel's
  * widget.
+ * </p>
  * <p>
  * <img class='gallery' src='PopupPanel.png'/>
  * </p>
@@ -377,7 +385,7 @@
    * @return the popup's left position
    */
   public int getPopupLeft() {
-    return DOM.getElementPropertyInt(getElement(), "offsetLeft");
+    return DOM.getAbsoluteLeft(getElement());
   }
 
   /**
@@ -386,7 +394,7 @@
    * @return the popup's top position
    */
   public int getPopupTop() {
-    return DOM.getElementPropertyInt(getElement(), "offsetTop");
+    return DOM.getAbsoluteTop(getElement());
   }
 
   @Override
@@ -580,6 +588,11 @@
     leftPosition = left;
     topPosition = top;
 
+    // Account for the difference between absolute position and the
+    // body's positioning context.
+    left -= Document.get().getBodyOffsetLeft();
+    top -= Document.get().getBodyOffsetTop();
+
     // Set the popup's position manually, allowing setPopupPosition() to be
     // called before show() is called (so a popup can be positioned without it
     // 'jumping' on the screen).
diff --git a/user/src/com/google/gwt/user/client/ui/RootPanel.java b/user/src/com/google/gwt/user/client/ui/RootPanel.java
index 9509744..cabdc9c 100644
--- a/user/src/com/google/gwt/user/client/ui/RootPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/RootPanel.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.dom.client.Document;
 import com.google.gwt.i18n.client.BidiUtils;
 import com.google.gwt.i18n.client.HasDirection;
 import com.google.gwt.i18n.client.LocaleInfo;
@@ -39,6 +40,26 @@
  */
 public class RootPanel extends AbsolutePanel {
 
+  /**
+   * A default RootPanel implementation that wraps the body element.
+   */
+  private static class DefaultRootPanel extends RootPanel {
+
+    public DefaultRootPanel() {
+      super(getBodyElement());
+    }
+
+    @Override
+    protected void setWidgetPositionImpl(Widget w, int left, int top) {
+      // Account for the difference between absolute position and the
+      // body's positioning context.
+      left -= Document.get().getBodyOffsetLeft();
+      top -= Document.get().getBodyOffsetTop();
+
+      super.setWidgetPositionImpl(w, left, top);
+    }
+  }
+
   private static Map<String, RootPanel> rootPanels = new HashMap<String, RootPanel>();
   private static Set<Widget> widgetsToDetach = new HashSet<Widget>();
 
@@ -143,9 +164,13 @@
     // Create the panel and put it in the map.
     if (elem == null) {
       // 'null' means use document's body element.
-      elem = getBodyElement();
+      rp = new DefaultRootPanel();
+    } else {
+      // Otherwise, wrap the existing element.
+      rp = new RootPanel(elem);
     }
-    rootPanels.put(id, rp = new RootPanel(elem));
+
+    rootPanels.put(id, rp);
     detachOnWindowClose(rp);
     return rp;
   }
diff --git a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
index 43e68ce..c5a4a1b 100644
--- a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
@@ -23,9 +23,9 @@
  */
 public class JsoTest extends GWTTestCase {
 
-  private static class Bar extends JavaScriptObject {
+  static class Bar extends JavaScriptObject {
     public static int field;
-    
+
     public static native String staticNative() /*-{
       return "nativeBar";
     }-*/;
@@ -36,7 +36,7 @@
 
     protected Bar() {
     }
-    
+
     public final native String getBar() /*-{
       return this.bar;
     }-*/;
@@ -46,7 +46,7 @@
     }
   }
 
-  private static class Foo extends JavaScriptObject {
+  static class Foo extends JavaScriptObject {
     public static int field;
 
     public static native String staticNative() /*-{
@@ -69,7 +69,7 @@
     }
   }
 
-  private static class FooSub extends Foo {
+  static class FooSub extends Foo {
     protected FooSub() {
     }
 
@@ -82,7 +82,7 @@
     }
   }
 
-  private static class JsArray<T> extends JavaScriptObject {
+  static class JsArray<T> extends JavaScriptObject {
     public static native <T> JsArray<T> create() /*-{
       return [];
     }-*/;
@@ -103,7 +103,7 @@
     }-*/;
   }
 
-  private static class MethodMangleClash {
+  static class MethodMangleClash {
     @SuppressWarnings("unused")
     public static String func(JavaScriptObject this_) {
       return "funcJavaScriptObject";
@@ -120,26 +120,26 @@
     }
   }
 
-  private static class Overloads {
+  static class Overloads {
     private static volatile boolean FALSE = false;
 
     @SuppressWarnings("unused")
-    private static String sFunc(Bar b) {
+    static String sFunc(Bar b) {
       return "sFunc Bar";
     }
 
     @SuppressWarnings("unused")
-    private static String sFunc(Bar[][] b) {
+    static String sFunc(Bar[][] b) {
       return "sFunc Bar[][]";
     }
 
     @SuppressWarnings("unused")
-    private static String sFunc(Foo f) {
+    static String sFunc(Foo f) {
       return "sFunc Foo";
     }
 
     @SuppressWarnings("unused")
-    private static String sFunc(Foo[][] f) {
+    static String sFunc(Foo[][] f) {
       return "sFunc Foo[][]";
     }
 
@@ -160,7 +160,7 @@
     }
 
     @SuppressWarnings("unused")
-    private String func(Bar b) {
+    String func(Bar b) {
       if (FALSE) {
         // prevent inlining
         return func(b);
@@ -169,7 +169,7 @@
     }
 
     @SuppressWarnings("unused")
-    private String func(Bar[][] b) {
+    String func(Bar[][] b) {
       if (FALSE) {
         // prevent inlining
         return func(b);
@@ -178,7 +178,7 @@
     }
 
     @SuppressWarnings("unused")
-    private String func(Foo f) {
+    String func(Foo f) {
       if (FALSE) {
         // prevent inlining
         return func(f);
@@ -187,7 +187,7 @@
     }
 
     @SuppressWarnings("unused")
-    private String func(Foo[][] f) {
+    String func(Foo[][] f) {
       if (FALSE) {
         // prevent inlining
         return func(f);
@@ -443,7 +443,7 @@
     assertEquals("[[Lcom.google.gwt.core.client.JavaScriptObject$;",
         JavaScriptObject[][].class.getName());
   }
-  
+
   public void testEquality() {
     JavaScriptObject jso = makeJSO();
     assertEquals(jso, jso);
@@ -626,4 +626,11 @@
     @junit.framework.Assert::assertEquals(Ljava/lang/Object;Ljava/lang/Object;)("Bar11", @com.google.gwt.dev.jjs.test.JsoTest.Bar::staticValue()());
     @junit.framework.Assert::assertEquals(Ljava/lang/Object;Ljava/lang/Object;)("nativeBar", @com.google.gwt.dev.jjs.test.JsoTest.Bar::staticNative()());
   }-*/;
+
+  public void testStaticAccessSubclass() {
+    FooSub.field = 3;
+    assertEquals(3, FooSub.field--);
+    assertEquals("Foo2", FooSub.staticValue());
+    assertEquals("nativeFoo", FooSub.staticNative());
+  }
 }
diff --git a/user/test/com/google/gwt/dom/client/ElementTest.java b/user/test/com/google/gwt/dom/client/ElementTest.java
index f218d39..9fb4657 100644
--- a/user/test/com/google/gwt/dom/client/ElementTest.java
+++ b/user/test/com/google/gwt/dom/client/ElementTest.java
@@ -62,8 +62,8 @@
     elem.getStyle().setProperty("padding", padding + "px");
     elem.getStyle().setProperty("margin", margin + "px");
 
-    elem.getStyle().setProperty("top", top + "px");
-    elem.getStyle().setProperty("left", left + "px");
+    elem.getStyle().setPropertyPx("top", top - doc.getBodyOffsetLeft());
+    elem.getStyle().setPropertyPx("left", left - doc.getBodyOffsetTop());
 
     delayTestFinish(1000);
     DeferredCommand.addCommand(new Command() {
diff --git a/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java b/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
index 155b845..c38ea16 100644
--- a/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.dom.client.Document;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.Window;
 
@@ -32,13 +33,13 @@
   }
 
   public void testPositioning() {
-    // Make an absolute panel with a label at (42, 43).
+    // Make an absolute panel with a label at (3, 7).
     AbsolutePanel abs = new AbsolutePanel();
     abs.setSize("128px", "128px");
     Label lbl = new Label("foo");
     abs.add(lbl, 3, 7);
 
-    // Put the panel in a grid that will place it at (32, 32) within the grid.
+    // Put the panel in a grid that will place it at (100, 200) within the grid.
     Grid g = new Grid(2, 2);
     g.setBorderWidth(0);
     g.setCellPadding(0);
@@ -57,11 +58,11 @@
     // wacky positioning of its children.
     int x = abs.getWidgetLeft(lbl);
     int y = abs.getWidgetTop(lbl);
-    int absX = lbl.getAbsoluteLeft();
-    int absY = lbl.getAbsoluteTop();
-    assertEquals(x, 3);
-    assertEquals(y, 7);
-    assertEquals(absX, 3 + 100);
-    assertEquals(absY, 7 + 200);
+    int absX = lbl.getAbsoluteLeft() - Document.get().getBodyOffsetLeft();
+    int absY = lbl.getAbsoluteTop() - Document.get().getBodyOffsetTop();
+    assertEquals(3, x);
+    assertEquals(7, y);
+    assertEquals(3 + 100, absX);
+    assertEquals(7 + 200, absY);
   }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/DOMTest.java b/user/test/com/google/gwt/user/client/ui/DOMTest.java
index 7d61e56..071a164 100644
--- a/user/test/com/google/gwt/user/client/ui/DOMTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DOMTest.java
@@ -86,8 +86,9 @@
     DOM.setStyleAttribute(elem, "padding", padding + "px");
     DOM.setStyleAttribute(elem, "margin", margin + "px");
 
-    DOM.setStyleAttribute(elem, "top", top + "px");
-    DOM.setStyleAttribute(elem, "left", left + "px");
+    Document doc = Document.get();
+    DOM.setStyleAttribute(elem, "top", (top - doc.getBodyOffsetLeft()) + "px");
+    DOM.setStyleAttribute(elem, "left", (left - doc.getBodyOffsetTop()) + "px");
 
     delayTestFinish(1000);
     DeferredCommand.addCommand(new Command() {
@@ -128,8 +129,9 @@
     assertTrue(DOM.getElementPropertyInt(outer, "scrollTop") > 0);
     assertTrue(DOM.getElementPropertyInt(outer, "scrollLeft") > 0);
 
-    assertEquals(0, DOM.getAbsoluteTop(outer));
-    assertEquals(0, DOM.getAbsoluteLeft(outer));
+    Document doc = Document.get();
+    assertEquals(doc.getBodyOffsetLeft(), DOM.getAbsoluteTop(outer));
+    assertEquals(doc.getBodyOffsetTop(), DOM.getAbsoluteLeft(outer));
   }
 
   /**