| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Google Web Toolkit
Revision: 3607
Author: jlabanca@google.com
Date: 03 Sep 2008 14:45:46
Changes: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)
| ... | ...@@ -253,12 +253,8 @@ | |
| 253 | 253 | public static void addWindowResizeListener(WindowResizeListener listener) { |
| 254 | 254 | if (resizeListeners == null) { |
| 255 | 255 | resizeListeners = new ArrayList<WindowResizeListener>(); |
| 256 | initHandler(getWindowResizeHandlerMethodString(), | |
| 257 | "__gwt_initWindowResizeHandler", new Command() { | |
| 258 | public void execute() { | |
| 259 | initWindowResizeHandler(); | |
| 260 | } | |
| 261 | }); | |
| 256 | maybeInitializeCloseHandlers(); | |
| 257 | impl.initWindowResizeHandler(); | |
| 262 | 258 | } |
| 263 | 259 | resizeListeners.add(listener); |
| 264 | 260 | } |
| ... | ...@@ -271,12 +267,8 @@ | |
| 271 | 267 | public static void addWindowScrollListener(WindowScrollListener listener) { |
| 272 | 268 | if (scrollListeners == null) { |
| 273 | 269 | scrollListeners = new ArrayList<WindowScrollListener>(); |
| 274 | initHandler(getWindowScrollHandlerMethodString(), | |
| 275 | "__gwt_initWindowScrollHandler", new Command() { | |
| 276 | public void execute() { | |
| 277 | initWindowScrollHandler(); | |
| 278 | } | |
| 279 | }); | |
| 270 | maybeInitializeCloseHandlers(); | |
| 271 | impl.initWindowScrollHandler(); | |
| 280 | 272 | } |
| 281 | 273 | scrollListeners.add(listener); |
| 282 | 274 | } |
| ... | ...@@ -577,150 +569,10 @@ | |
| 577 | 569 | } |
| 578 | 570 | } |
| 579 | 571 | |
| 580 | /** | |
| 581 | * This method defines a function that sinks an event on the Window. However, | |
| 582 | * this method returns the function as a String so it can be added to the | |
| 583 | * outer window. | |
| 584 | * | |
| 585 | * We need to declare this method on the outer window because you cannot | |
| 586 | * attach Window listeners from within an iframe on IE6. | |
| 587 | * | |
| 588 | * Per ECMAScript 262 spec 15.3.4.2, Function.prototype.toString() returns a | |
| 589 | * string representation of the function that has the syntax of the function. | |
| 590 | */ | |
| 591 | private static native String getWindowCloseHandlerMethodString() /*-{ | |
| 592 | return function(beforeunload, unload) { | |
| 593 | var wnd = window | |
| 594 | , oldOnBeforeUnload = wnd.onbeforeunload | |
| 595 | , oldOnUnload = wnd.onunload; | |
| 596 | ||
| 597 | wnd.onbeforeunload = function(evt) { | |
| 598 | var ret, oldRet; | |
| 599 | try { | |
| 600 | ret = beforeunload(); | |
| 601 | } finally { | |
| 602 | oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt); | |
| 603 | } | |
| 604 | // Avoid returning null as IE6 will coerce it into a string. | |
| 605 | // Ensure that "" gets returned properly. | |
| 606 | if (ret != null) { | |
| 607 | return ret; | |
| 608 | } | |
| 609 | if (oldRet != null) { | |
| 610 | return oldRet; | |
| 611 | } | |
| 612 | // returns undefined. | |
| 613 | }; | |
| 614 | ||
| 615 | wnd.onunload = function(evt) { | |
| 616 | try { | |
| 617 | unload(); | |
| 618 | } finally { | |
| 619 | oldOnUnload && oldOnUnload(evt); | |
| 620 | wnd.onresize = null; | |
| 621 | wnd.onscroll = null; | |
| 622 | wnd.onbeforeunload = null; | |
| 623 | wnd.onunload = null; | |
| 624 | } | |
| 625 | }; | |
| 626 | ||
| 627 | // Remove the reference once we've initialize the handler | |
| 628 | wnd.__gwt_initWindowCloseHandler = undefined; | |
| 629 | }.toString(); | |
| 630 | }-*/; | |
| 631 | ||
| 632 | /** | |
| 633 | * @see #getWindowCloseHandlerMethodString() | |
| 634 | */ | |
| 635 | private static native String getWindowResizeHandlerMethodString() /*-{ | |
| 636 | return function(resize) { | |
| 637 | var wnd = window, oldOnResize = wnd.onresize; | |
| 638 | ||
| 639 | wnd.onresize = function(evt) { | |
| 640 | try { | |
| 641 | resize(); | |
| 642 | } finally { | |
| 643 | oldOnResize && oldOnResize(evt); | |
| 644 | } | |
| 645 | }; | |
| 646 | ||
| 647 | // Remove the reference once we've initialize the handler | |
| 648 | wnd.__gwt_initWindowResizeHandler = undefined; | |
| 649 | }.toString(); | |
| 650 | }-*/; | |
| 651 | ||
| 652 | /** | |
| 653 | * @see #getWindowCloseHandlerMethodString() | |
| 654 | */ | |
| 655 | private static native String getWindowScrollHandlerMethodString() /*-{ | |
| 656 | return function(scroll) { | |
| 657 | var wnd = window, oldOnScroll = wnd.onscroll; | |
| 658 | ||
| 659 | wnd.onscroll = function(evt) { | |
| 660 | try { | |
| 661 | scroll(); | |
| 662 | } finally { | |
| 663 | oldOnScroll && oldOnScroll(evt); | |
| 664 | } | |
| 665 | }; | |
| 666 | ||
| 667 | // Remove the reference once we've initialize the handler | |
| 668 | wnd.__gwt_initWindowScrollHandler = undefined; | |
| 669 | }.toString(); | |
| 670 | }-*/; | |
| 671 | ||
| 672 | /** | |
| 673 | * Initialize an event on the outer window. | |
| 674 | * | |
| 675 | * @param initFunc the string representation of the init function | |
| 676 | * @param funcName the name to assign to the init function | |
| 677 | * @param cmd the command to execute the init function | |
| 678 | */ | |
| 679 | private static void initHandler(String initFunc, String funcName, Command cmd) { | |
| 680 | if (GWT.isClient()) { | |
| 681 | // Always initialize the close handlers first | |
| 682 | maybeInitializeCloseHandlers(); | |
| 683 | ||
| 684 | impl.initHandler(initFunc, funcName, cmd); | |
| 685 | } | |
| 686 | } | |
| 687 | ||
| 688 | private static native void initWindowCloseHandler() /*-{ | |
| 689 | $wnd.__gwt_initWindowCloseHandler( | |
| 690 | function() { | |
| 691 | return @com.google.gwt.user.client.Window::onClosing()(); | |
| 692 | }, | |
| 693 | function() { | |
| 694 | @com.google.gwt.user.client.Window::onClosed()(); | |
| 695 | } | |
| 696 | ); | |
| 697 | }-*/; | |
| 698 | ||
| 699 | private static native void initWindowResizeHandler() /*-{ | |
| 700 | $wnd.__gwt_initWindowResizeHandler( | |
| 701 | function() { | |
| 702 | @com.google.gwt.user.client.Window::onResize()(); | |
| 703 | } | |
| 704 | ); | |
| 705 | }-*/; | |
| 706 | ||
| 707 | private static native void initWindowScrollHandler() /*-{ | |
| 708 | $wnd.__gwt_initWindowScrollHandler( | |
| 709 | function() { | |
| 710 | @com.google.gwt.user.client.Window::onScroll()(); | |
| 711 | } | |
| 712 | ); | |
| 713 | }-*/; | |
| 714 | ||
| 715 | 572 | private static void maybeInitializeCloseHandlers() { |
| 716 | 573 | if (GWT.isClient() && !handlersAreInitialized) { |
| 717 | handlersAreInitialized = true; | |
| 718 | initHandler(getWindowCloseHandlerMethodString(), | |
| 719 | "__gwt_initWindowCloseHandler", new Command() { | |
| 720 | public void execute() { | |
| 721 | initWindowCloseHandler(); | |
| 722 | } | |
| 723 | }); | |
| 574 | handlersAreInitialized = true; | |
| 575 | impl.initWindowCloseHandler(); | |
| 724 | 576 | } |
| 725 | 577 | } |
| 726 | 578 |
| ... | ...@@ -15,6 +15,7 @@ | |
| 15 | 15 | */ |
| 16 | 16 | package com.google.gwt.user.client.impl; |
| 17 | 17 | |
| 18 | import com.google.gwt.core.client.GWT; | |
| 18 | 19 | import com.google.gwt.dom.client.Document; |
| 19 | 20 | import com.google.gwt.dom.client.ScriptElement; |
| 20 | 21 | import com.google.gwt.user.client.Command; |
| ... | ...@@ -51,22 +52,177 @@ | |
| 51 | 52 | return (questionLoc > 0) ? href.substring(questionLoc) : ""; |
| 52 | 53 | }-*/; |
| 53 | 54 | |
| 55 | @Override | |
| 56 | public void initWindowCloseHandler() { | |
| 57 | initHandler(getWindowCloseHandlerMethodString(), | |
| 58 | "__gwt_initWindowCloseHandler", new Command() { | |
| 59 | public void execute() { | |
| 60 | initWindowCloseHandlerImpl(); | |
| 61 | } | |
| 62 | }); | |
| 63 | } | |
| 64 | ||
| 65 | @Override | |
| 66 | public void initWindowResizeHandler() { | |
| 67 | initHandler(getWindowResizeHandlerMethodString(), | |
| 68 | "__gwt_initWindowResizeHandler", new Command() { | |
| 69 | public void execute() { | |
| 70 | initWindowResizeHandlerImpl(); | |
| 71 | } | |
| 72 | }); | |
| 73 | } | |
| 74 | ||
| 75 | @Override | |
| 76 | public void initWindowScrollHandler() { | |
| 77 | initHandler(getWindowScrollHandlerMethodString(), | |
| 78 | "__gwt_initWindowScrollHandler", new Command() { | |
| 79 | public void execute() { | |
| 80 | initWindowScrollHandlerImpl(); | |
| 81 | } | |
| 82 | }); | |
| 83 | } | |
| 84 | ||
| 85 | /** | |
| 86 | * This method defines a function that sinks an event on the Window. However, | |
| 87 | * this method returns the function as a String so it can be added to the | |
| 88 | * outer window. | |
| 89 | * | |
| 90 | * We need to declare this method on the outer window because you cannot | |
| 91 | * attach Window listeners from within an iframe on IE6. | |
| 92 | * | |
| 93 | * Per ECMAScript 262 spec 15.3.4.2, Function.prototype.toString() returns a | |
| 94 | * string representation of the function that has the syntax of the function. | |
| 95 | */ | |
| 96 | private native String getWindowCloseHandlerMethodString() /*-{ | |
| 97 | return function(beforeunload, unload) { | |
| 98 | var wnd = window | |
| 99 | , oldOnBeforeUnload = wnd.onbeforeunload | |
| 100 | , oldOnUnload = wnd.onunload; | |
| 101 | ||
| 102 | wnd.onbeforeunload = function(evt) { | |
| 103 | var ret, oldRet; | |
| 104 | try { | |
| 105 | ret = beforeunload(); | |
| 106 | } finally { | |
| 107 | oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt); | |
| 108 | } | |
| 109 | // Avoid returning null as IE6 will coerce it into a string. | |
| 110 | // Ensure that "" gets returned properly. | |
| 111 | if (ret != null) { | |
| 112 | return ret; | |
| 113 | } | |
| 114 | if (oldRet != null) { | |
| 115 | return oldRet; | |
| 116 | } | |
| 117 | // returns undefined. | |
| 118 | }; | |
| 119 | ||
| 120 | wnd.onunload = function(evt) { | |
| 121 | try { | |
| 122 | unload(); | |
| 123 | } finally { | |
| 124 | oldOnUnload && oldOnUnload(evt); | |
| 125 | wnd.onresize = null; | |
| 126 | wnd.onscroll = null; | |
| 127 | wnd.onbeforeunload = null; | |
| 128 | wnd.onunload = null; | |
| 129 | } | |
| 130 | }; | |
| 131 | ||
| 132 | // Remove the reference once we've initialize the handler | |
| 133 | wnd.__gwt_initWindowCloseHandler = undefined; | |
| 134 | }.toString(); | |
| 135 | }-*/; | |
| 136 | ||
| 137 | /** | |
| 138 | * @see #getWindowCloseHandlerMethodString() | |
| 139 | */ | |
| 140 | private native String getWindowResizeHandlerMethodString() /*-{ | |
| 141 | return function(resize) { | |
| 142 | var wnd = window, oldOnResize = wnd.onresize; | |
| 143 | ||
| 144 | wnd.onresize = function(evt) { | |
| 145 | try { | |
| 146 | resize(); | |
| 147 | } finally { | |
| 148 | oldOnResize && oldOnResize(evt); | |
| 149 | } | |
| 150 | }; | |
| 151 | ||
| 152 | // Remove the reference once we've initialize the handler | |
| 153 | wnd.__gwt_initWindowResizeHandler = undefined; | |
| 154 | }.toString(); | |
| 155 | }-*/; | |
| 156 | ||
| 157 | /** | |
| 158 | * @see #getWindowCloseHandlerMethodString() | |
| 159 | */ | |
| 160 | private native String getWindowScrollHandlerMethodString() /*-{ | |
| 161 | return function(scroll) { | |
| 162 | var wnd = window, oldOnScroll = wnd.onscroll; | |
| 163 | ||
| 164 | wnd.onscroll = function(evt) { | |
| 165 | try { | |
| 166 | scroll(); | |
| 167 | } finally { | |
| 168 | oldOnScroll && oldOnScroll(evt); | |
| 169 | } | |
| 170 | }; | |
| 171 | ||
| 172 | // Remove the reference once we've initialize the handler | |
| 173 | wnd.__gwt_initWindowScrollHandler = undefined; | |
| 174 | }.toString(); | |
| 175 | }-*/; | |
| 176 | ||
| 54 | 177 | /** |
| 55 | 178 | * IE6 does not allow direct access to event handlers on the parent window, |
| 56 | 179 | * so we must embed a script in the parent window that will set the event |
| 57 | 180 | * handlers in the correct context. |
| 181 | * | |
| 182 | * @param initFunc the string representation of the init function | |
| 183 | * @param funcName the name to assign to the init function | |
| 184 | * @param cmd the command to execute the init function | |
| 58 | 185 | */ |
| 59 | @Override | |
| 60 | public void initHandler(String initFunc, String funcName, Command cmd) { | |
| 61 | // Embed the init script on the page | |
| 62 | initFunc = initFunc.replaceFirst("function", "function " + funcName); | |
| 63 | ScriptElement scriptElem = Document.get().createScriptElement(initFunc); | |
| 64 | Document.get().getBody().appendChild(scriptElem); | |
| 186 | private void initHandler(String initFunc, String funcName, Command cmd) { | |
| 187 | if (GWT.isClient()) { | |
| 188 | // Embed the init script on the page | |
| 189 | initFunc = initFunc.replaceFirst("function", "function " + funcName); | |
| 190 | ScriptElement scriptElem = Document.get().createScriptElement(initFunc); | |
| 191 | Document.get().getBody().appendChild(scriptElem); | |
| 192 | ||
| 193 | // Initialize the handler | |
| 194 | cmd.execute(); | |
| 195 | ||
| 196 | // Remove the script element | |
| 197 | Document.get().getBody().removeChild(scriptElem); | |
| 198 | } | |
| 199 | } | |
| 65 | 200 | |
| 66 | // Initialize the handler | |
| 67 | cmd.execute(); | |
| 201 | private native void initWindowCloseHandlerImpl() /*-{ | |
| 202 | $wnd.__gwt_initWindowCloseHandler( | |
| 203 | function() { | |
| 204 | return @com.google.gwt.user.client.Window::onClosing()(); | |
| 205 | }, | |
| 206 | function() { | |
| 207 | @com.google.gwt.user.client.Window::onClosed()(); | |
| 208 | } | |
| 209 | ); | |
| 210 | }-*/; | |
| 211 | ||
| 212 | private native void initWindowResizeHandlerImpl() /*-{ | |
| 213 | $wnd.__gwt_initWindowResizeHandler( | |
| 214 | function() { | |
| 215 | @com.google.gwt.user.client.Window::onResize()(); | |
| 216 | } | |
| 217 | ); | |
| 218 | }-*/; | |
| 219 | ||
| 220 | private native void initWindowScrollHandlerImpl() /*-{ | |
| 221 | $wnd.__gwt_initWindowScrollHandler( | |
| 222 | function() { | |
| 223 | @com.google.gwt.user.client.Window::onScroll()(); | |
| 224 | } | |
| 225 | ); | |
| 226 | }-*/; | |
| 68 | 227 | |
| 69 | // Remove the script element | |
| 70 | Document.get().getBody().removeChild(scriptElem); | |
| 71 | } | |
| 72 | 228 | } |
| ... | ...@@ -15,8 +15,6 @@ | |
| 15 | 15 | */ |
| 16 | 16 | package com.google.gwt.user.client.impl; |
| 17 | 17 | |
| 18 | import com.google.gwt.user.client.Command; | |
| 19 | ||
| 20 | 18 | /** |
| 21 | 19 | * Native implementation associated with |
| 22 | 20 | * {@link com.google.gwt.user.client.Window}. |
| ... | ...@@ -51,16 +49,60 @@ | |
| 51 | 49 | return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollTop; |
| 52 | 50 | }-*/; |
| 53 | 51 | |
| 54 | public void initHandler(String initFunc, String funcName, Command cmd) { | |
| 55 | // Eval the init script | |
| 56 | initFunc = initFunc.replaceFirst("function", "function " + funcName); | |
| 57 | eval(initFunc); | |
| 58 | ||
| 59 | // Initialize the handler | |
| 60 | cmd.execute(); | |
| 61 | } | |
| 62 | ||
| 63 | private native void eval(String expr) /*-{ | |
| 64 | $wnd.eval(expr); | |
| 52 | public native void initWindowCloseHandler() /*-{ | |
| 53 | var oldOnBeforeUnload = $wnd.onbeforeunload; | |
| 54 | var oldOnUnload = $wnd.onunload; | |
| 55 | ||
| 56 | $wnd.onbeforeunload = function(evt) { | |
| 57 | var ret, oldRet; | |
| 58 | try { | |
| 59 | ret = @com.google.gwt.user.client.Window::onClosing()(); | |
| 60 | } finally { | |
| 61 | oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt); | |
| 62 | } | |
| 63 | // Avoid returning null as IE6 will coerce it into a string. | |
| 64 | // Ensure that "" gets returned properly. | |
| 65 | if (ret != null) { | |
| 66 | return ret; | |
| 67 | } | |
| 68 | if (oldRet != null) { | |
| 69 | return oldRet; | |
| 70 | } | |
| 71 | // returns undefined. | |
| 72 | }; | |
| 73 | ||
| 74 | $wnd.onunload = function(evt) { | |
| 75 | try { | |
| 76 | @com.google.gwt.user.client.Window::onClosed()(); | |
| 77 | } finally { | |
| 78 | oldOnUnload && oldOnUnload(evt); | |
| 79 | $wnd.onresize = null; | |
| 80 | $wnd.onscroll = null; | |
| 81 | $wnd.onbeforeunload = null; | |
| 82 | $wnd.onunload = null; | |
| 83 | } | |
| 84 | }; | |
| 85 | }-*/; | |
| 86 | ||
| 87 | public native void initWindowResizeHandler() /*-{ | |
| 88 | var oldOnResize = $wnd.onresize; | |
| 89 | $wnd.onresize = function(evt) { | |
| 90 | try { | |
| 91 | @com.google.gwt.user.client.Window::onResize()(); | |
| 92 | } finally { | |
| 93 | oldOnResize && oldOnResize(evt); | |
| 94 | } | |
| 95 | }; | |
| 96 | }-*/; | |
| 97 | ||
| 98 | public native void initWindowScrollHandler() /*-{ | |
| 99 | var oldOnScroll = $wnd.onscroll; | |
| 100 | $wnd.onscroll = function(evt) { | |
| 101 | try { | |
| 102 | @com.google.gwt.user.client.Window::onScroll()(); | |
| 103 | } finally { | |
| 104 | oldOnScroll && oldOnScroll(evt); | |
| 105 | } | |
| 106 | }; | |
| 65 | 107 | }-*/; |
| 66 | 108 | } |