One more fix to address Window level events. This time, all browsers except IE sink the events directly on the outer window. IE still embeds a script element on the outer window in order to sink events in the correct context.
Patch by: jlabanca
Review by: ajr (desk)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3607 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/Window.java b/user/src/com/google/gwt/user/client/Window.java
index 4e3b2a6..7667fd9 100644
--- a/user/src/com/google/gwt/user/client/Window.java
+++ b/user/src/com/google/gwt/user/client/Window.java
@@ -253,12 +253,8 @@
public static void addWindowResizeListener(WindowResizeListener listener) {
if (resizeListeners == null) {
resizeListeners = new ArrayList<WindowResizeListener>();
- initHandler(getWindowResizeHandlerMethodString(),
- "__gwt_initWindowResizeHandler", new Command() {
- public void execute() {
- initWindowResizeHandler();
- }
- });
+ maybeInitializeCloseHandlers();
+ impl.initWindowResizeHandler();
}
resizeListeners.add(listener);
}
@@ -271,12 +267,8 @@
public static void addWindowScrollListener(WindowScrollListener listener) {
if (scrollListeners == null) {
scrollListeners = new ArrayList<WindowScrollListener>();
- initHandler(getWindowScrollHandlerMethodString(),
- "__gwt_initWindowScrollHandler", new Command() {
- public void execute() {
- initWindowScrollHandler();
- }
- });
+ maybeInitializeCloseHandlers();
+ impl.initWindowScrollHandler();
}
scrollListeners.add(listener);
}
@@ -577,150 +569,10 @@
}
}
- /**
- * This method defines a function that sinks an event on the Window. However,
- * this method returns the function as a String so it can be added to the
- * outer window.
- *
- * We need to declare this method on the outer window because you cannot
- * attach Window listeners from within an iframe on IE6.
- *
- * Per ECMAScript 262 spec 15.3.4.2, Function.prototype.toString() returns a
- * string representation of the function that has the syntax of the function.
- */
- private static native String getWindowCloseHandlerMethodString() /*-{
- return function(beforeunload, unload) {
- var wnd = window
- , oldOnBeforeUnload = wnd.onbeforeunload
- , oldOnUnload = wnd.onunload;
-
- wnd.onbeforeunload = function(evt) {
- var ret, oldRet;
- try {
- ret = beforeunload();
- } finally {
- oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt);
- }
- // Avoid returning null as IE6 will coerce it into a string.
- // Ensure that "" gets returned properly.
- if (ret != null) {
- return ret;
- }
- if (oldRet != null) {
- return oldRet;
- }
- // returns undefined.
- };
-
- wnd.onunload = function(evt) {
- try {
- unload();
- } finally {
- oldOnUnload && oldOnUnload(evt);
- wnd.onresize = null;
- wnd.onscroll = null;
- wnd.onbeforeunload = null;
- wnd.onunload = null;
- }
- };
-
- // Remove the reference once we've initialize the handler
- wnd.__gwt_initWindowCloseHandler = undefined;
- }.toString();
- }-*/;
-
- /**
- * @see #getWindowCloseHandlerMethodString()
- */
- private static native String getWindowResizeHandlerMethodString() /*-{
- return function(resize) {
- var wnd = window, oldOnResize = wnd.onresize;
-
- wnd.onresize = function(evt) {
- try {
- resize();
- } finally {
- oldOnResize && oldOnResize(evt);
- }
- };
-
- // Remove the reference once we've initialize the handler
- wnd.__gwt_initWindowResizeHandler = undefined;
- }.toString();
- }-*/;
-
- /**
- * @see #getWindowCloseHandlerMethodString()
- */
- private static native String getWindowScrollHandlerMethodString() /*-{
- return function(scroll) {
- var wnd = window, oldOnScroll = wnd.onscroll;
-
- wnd.onscroll = function(evt) {
- try {
- scroll();
- } finally {
- oldOnScroll && oldOnScroll(evt);
- }
- };
-
- // Remove the reference once we've initialize the handler
- wnd.__gwt_initWindowScrollHandler = undefined;
- }.toString();
- }-*/;
-
- /**
- * Initialize an event on the outer window.
- *
- * @param initFunc the string representation of the init function
- * @param funcName the name to assign to the init function
- * @param cmd the command to execute the init function
- */
- private static void initHandler(String initFunc, String funcName, Command cmd) {
- if (GWT.isClient()) {
- // Always initialize the close handlers first
- maybeInitializeCloseHandlers();
-
- impl.initHandler(initFunc, funcName, cmd);
- }
- }
-
- private static native void initWindowCloseHandler() /*-{
- $wnd.__gwt_initWindowCloseHandler(
- function() {
- return @com.google.gwt.user.client.Window::onClosing()();
- },
- function() {
- @com.google.gwt.user.client.Window::onClosed()();
- }
- );
- }-*/;
-
- private static native void initWindowResizeHandler() /*-{
- $wnd.__gwt_initWindowResizeHandler(
- function() {
- @com.google.gwt.user.client.Window::onResize()();
- }
- );
- }-*/;
-
- private static native void initWindowScrollHandler() /*-{
- $wnd.__gwt_initWindowScrollHandler(
- function() {
- @com.google.gwt.user.client.Window::onScroll()();
- }
- );
- }-*/;
-
private static void maybeInitializeCloseHandlers() {
if (GWT.isClient() && !handlersAreInitialized) {
- handlersAreInitialized = true;
- initHandler(getWindowCloseHandlerMethodString(),
- "__gwt_initWindowCloseHandler", new Command() {
- public void execute() {
- initWindowCloseHandler();
- }
- });
+ handlersAreInitialized = true;
+ impl.initWindowCloseHandler();
}
}
diff --git a/user/src/com/google/gwt/user/client/impl/WindowImpl.java b/user/src/com/google/gwt/user/client/impl/WindowImpl.java
index 3eaeca2..9bb6333 100644
--- a/user/src/com/google/gwt/user/client/impl/WindowImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/WindowImpl.java
@@ -15,8 +15,6 @@
*/
package com.google.gwt.user.client.impl;
-import com.google.gwt.user.client.Command;
-
/**
* Native implementation associated with
* {@link com.google.gwt.user.client.Window}.
@@ -51,16 +49,60 @@
return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop;
}-*/;
- public void initHandler(String initFunc, String funcName, Command cmd) {
- // Eval the init script
- initFunc = initFunc.replaceFirst("function", "function " + funcName);
- eval(initFunc);
+ public native void initWindowCloseHandler() /*-{
+ var oldOnBeforeUnload = $wnd.onbeforeunload;
+ var oldOnUnload = $wnd.onunload;
+
+ $wnd.onbeforeunload = function(evt) {
+ var ret, oldRet;
+ try {
+ ret = @com.google.gwt.user.client.Window::onClosing()();
+ } finally {
+ oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt);
+ }
+ // Avoid returning null as IE6 will coerce it into a string.
+ // Ensure that "" gets returned properly.
+ if (ret != null) {
+ return ret;
+ }
+ if (oldRet != null) {
+ return oldRet;
+ }
+ // returns undefined.
+ };
+
+ $wnd.onunload = function(evt) {
+ try {
+ @com.google.gwt.user.client.Window::onClosed()();
+ } finally {
+ oldOnUnload && oldOnUnload(evt);
+ $wnd.onresize = null;
+ $wnd.onscroll = null;
+ $wnd.onbeforeunload = null;
+ $wnd.onunload = null;
+ }
+ };
+ }-*/;
- // Initialize the handler
- cmd.execute();
- }
+ public native void initWindowResizeHandler() /*-{
+ var oldOnResize = $wnd.onresize;
+ $wnd.onresize = function(evt) {
+ try {
+ @com.google.gwt.user.client.Window::onResize()();
+ } finally {
+ oldOnResize && oldOnResize(evt);
+ }
+ };
+ }-*/;
- private native void eval(String expr) /*-{
- $wnd.eval(expr);
+ public native void initWindowScrollHandler() /*-{
+ var oldOnScroll = $wnd.onscroll;
+ $wnd.onscroll = function(evt) {
+ try {
+ @com.google.gwt.user.client.Window::onScroll()();
+ } finally {
+ oldOnScroll && oldOnScroll(evt);
+ }
+ };
}-*/;
}
diff --git a/user/src/com/google/gwt/user/client/impl/WindowImplIE.java b/user/src/com/google/gwt/user/client/impl/WindowImplIE.java
index 6e2d70c..46ec347 100644
--- a/user/src/com/google/gwt/user/client/impl/WindowImplIE.java
+++ b/user/src/com/google/gwt/user/client/impl/WindowImplIE.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.user.client.impl;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.ScriptElement;
import com.google.gwt.user.client.Command;
@@ -51,22 +52,177 @@
return (questionLoc > 0) ? href.substring(questionLoc) : "";
}-*/;
+ @Override
+ public void initWindowCloseHandler() {
+ initHandler(getWindowCloseHandlerMethodString(),
+ "__gwt_initWindowCloseHandler", new Command() {
+ public void execute() {
+ initWindowCloseHandlerImpl();
+ }
+ });
+ }
+
+ @Override
+ public void initWindowResizeHandler() {
+ initHandler(getWindowResizeHandlerMethodString(),
+ "__gwt_initWindowResizeHandler", new Command() {
+ public void execute() {
+ initWindowResizeHandlerImpl();
+ }
+ });
+ }
+
+ @Override
+ public void initWindowScrollHandler() {
+ initHandler(getWindowScrollHandlerMethodString(),
+ "__gwt_initWindowScrollHandler", new Command() {
+ public void execute() {
+ initWindowScrollHandlerImpl();
+ }
+ });
+ }
+
+ /**
+ * This method defines a function that sinks an event on the Window. However,
+ * this method returns the function as a String so it can be added to the
+ * outer window.
+ *
+ * We need to declare this method on the outer window because you cannot
+ * attach Window listeners from within an iframe on IE6.
+ *
+ * Per ECMAScript 262 spec 15.3.4.2, Function.prototype.toString() returns a
+ * string representation of the function that has the syntax of the function.
+ */
+ private native String getWindowCloseHandlerMethodString() /*-{
+ return function(beforeunload, unload) {
+ var wnd = window
+ , oldOnBeforeUnload = wnd.onbeforeunload
+ , oldOnUnload = wnd.onunload;
+
+ wnd.onbeforeunload = function(evt) {
+ var ret, oldRet;
+ try {
+ ret = beforeunload();
+ } finally {
+ oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt);
+ }
+ // Avoid returning null as IE6 will coerce it into a string.
+ // Ensure that "" gets returned properly.
+ if (ret != null) {
+ return ret;
+ }
+ if (oldRet != null) {
+ return oldRet;
+ }
+ // returns undefined.
+ };
+
+ wnd.onunload = function(evt) {
+ try {
+ unload();
+ } finally {
+ oldOnUnload && oldOnUnload(evt);
+ wnd.onresize = null;
+ wnd.onscroll = null;
+ wnd.onbeforeunload = null;
+ wnd.onunload = null;
+ }
+ };
+
+ // Remove the reference once we've initialize the handler
+ wnd.__gwt_initWindowCloseHandler = undefined;
+ }.toString();
+ }-*/;
+
+ /**
+ * @see #getWindowCloseHandlerMethodString()
+ */
+ private native String getWindowResizeHandlerMethodString() /*-{
+ return function(resize) {
+ var wnd = window, oldOnResize = wnd.onresize;
+
+ wnd.onresize = function(evt) {
+ try {
+ resize();
+ } finally {
+ oldOnResize && oldOnResize(evt);
+ }
+ };
+
+ // Remove the reference once we've initialize the handler
+ wnd.__gwt_initWindowResizeHandler = undefined;
+ }.toString();
+ }-*/;
+
+ /**
+ * @see #getWindowCloseHandlerMethodString()
+ */
+ private native String getWindowScrollHandlerMethodString() /*-{
+ return function(scroll) {
+ var wnd = window, oldOnScroll = wnd.onscroll;
+
+ wnd.onscroll = function(evt) {
+ try {
+ scroll();
+ } finally {
+ oldOnScroll && oldOnScroll(evt);
+ }
+ };
+
+ // Remove the reference once we've initialize the handler
+ wnd.__gwt_initWindowScrollHandler = undefined;
+ }.toString();
+ }-*/;
+
/**
* IE6 does not allow direct access to event handlers on the parent window,
* so we must embed a script in the parent window that will set the event
* handlers in the correct context.
+ *
+ * @param initFunc the string representation of the init function
+ * @param funcName the name to assign to the init function
+ * @param cmd the command to execute the init function
*/
- @Override
- public void initHandler(String initFunc, String funcName, Command cmd) {
- // Embed the init script on the page
- initFunc = initFunc.replaceFirst("function", "function " + funcName);
- ScriptElement scriptElem = Document.get().createScriptElement(initFunc);
- Document.get().getBody().appendChild(scriptElem);
-
- // Initialize the handler
- cmd.execute();
-
- // Remove the script element
- Document.get().getBody().removeChild(scriptElem);
+ private void initHandler(String initFunc, String funcName, Command cmd) {
+ if (GWT.isClient()) {
+ // Embed the init script on the page
+ initFunc = initFunc.replaceFirst("function", "function " + funcName);
+ ScriptElement scriptElem = Document.get().createScriptElement(initFunc);
+ Document.get().getBody().appendChild(scriptElem);
+
+ // Initialize the handler
+ cmd.execute();
+
+ // Remove the script element
+ Document.get().getBody().removeChild(scriptElem);
+ }
}
+
+ private native void initWindowCloseHandlerImpl() /*-{
+ $wnd.__gwt_initWindowCloseHandler(
+ function() {
+ return @com.google.gwt.user.client.Window::onClosing()();
+ },
+ function() {
+ @com.google.gwt.user.client.Window::onClosed()();
+ }
+ );
+ }-*/;
+
+ private native void initWindowResizeHandlerImpl() /*-{
+ $wnd.__gwt_initWindowResizeHandler(
+ function() {
+ @com.google.gwt.user.client.Window::onResize()();
+ }
+ );
+ }-*/;
+
+ private native void initWindowScrollHandlerImpl() /*-{
+ $wnd.__gwt_initWindowScrollHandler(
+ function() {
+ @com.google.gwt.user.client.Window::onScroll()();
+ }
+ );
+ }-*/;
+
}