From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 2 ++ dlls/mshtml/htmlevent.h | 1 + dlls/mshtml/nsevents.c | 14 +++++++++++- dlls/mshtml/tests/documentmode.js | 17 +++++++++++++- dlls/mshtml/tests/events.c | 37 ++++++++++++++++++++++++++++++- dlls/mshtml/view.c | 10 +++++++++ 6 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 7b82d823bd9..01a385130b1 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -184,6 +184,8 @@ static const event_info_t event_info[] = { EVENT_FIXME}, {L"msthumbnailclick", EVENT_TYPE_MOUSE, DISPID_EVPROP_ONMSTHUMBNAILCLICK, EVENT_FIXME}, + {L"pagehide", EVENT_TYPE_PAGETRANSITION, DISPID_EVPROP_ONPAGEHIDE, + 0}, {L"pageshow", EVENT_TYPE_PAGETRANSITION, DISPID_EVPROP_ONPAGESHOW, 0}, {L"paste", EVENT_TYPE_CLIPBOARD, DISPID_EVMETH_ONPASTE, diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index e49c47d6988..a6d1f734a40 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -51,6 +51,7 @@ typedef enum { EVENTID_MOUSEUP, EVENTID_MOUSEWHEEL, EVENTID_MSTHUMBNAILCLICK, + EVENTID_PAGEHIDE, EVENTID_PAGESHOW, EVENTID_PASTE, EVENTID_PROGRESS, diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index f6c326b771c..e9ea8a51967 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -348,6 +348,7 @@ static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nse { nsEventListener *This = impl_from_nsIDOMEventListener(iface); HTMLDocumentNode *doc = This->This->doc; + compat_mode_t compat_mode; HTMLInnerWindow *window; DOMEvent *event; HRESULT hres; @@ -355,8 +356,19 @@ static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nse if(!doc || !(window = doc->window) || doc->unload_sent) return NS_OK; doc->unload_sent = TRUE; + compat_mode = dispex_compat_mode(&doc->node.event_target.dispex);
- hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), &event); + /* Native sends pagehide events prior to unload on the same window + before it moves on to the next window, so they're interleaved. */ + if(compat_mode >= COMPAT_MODE_IE11) { + hres = create_document_event(doc, EVENTID_PAGEHIDE, &event); + if(SUCCEEDED(hres)) { + dispatch_event(&window->event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + } + + hres = create_event_from_nsevent(nsevent, compat_mode, &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 3020cbf1b62..bb96b8b686c 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -19,12 +19,16 @@ var compat_version; var tests = [];
-var pageshow_fired = false; +var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false; window.onbeforeunload = function() { ok(false, "beforeunload fired"); }; window.onunload = function() { document.doc_unload_events_called = true; ok(document.readyState === "complete", "unload readyState = " + document.readyState); + if(document.documentMode < 11) + ok(pagehide_fired === false, "pagehide fired before unload"); + else + ok(pagehide_fired === true, "pagehide not fired before unload"); };
if(window.addEventListener) { @@ -38,6 +42,16 @@ if(window.addEventListener) { ok(document.readyState === "complete", "pageshow readyState = " + document.readyState); }, true);
+ window.addEventListener("pagehide", function(e) { + pagehide_fired = true; + ok(document.documentMode >= 11, "pagehide fired"); + + var r = Object.prototype.toString.call(e); + todo_wine. + ok(r === "[object PageTransitionEvent]", "pagehide toString = " + r); + ok("persisted" in e, "'persisted' not in pagehide event"); + }, true); + document.addEventListener("visibilitychange", function() { ok(false, "visibilitychange fired"); }); document.addEventListener("beforeunload", function() { ok(false, "beforeunload fired on document"); }); document.addEventListener("unload", function() { ok(false, "unload fired on document"); }); @@ -51,6 +65,7 @@ sync_test("page transition events", function() { ok(pageshow_fired === false, "pageshow fired"); else ok(pageshow_fired === true, "pageshow not fired"); + ok(pagehide_fired === false, "pagehide fired");
if(document.body.addEventListener) document.body.addEventListener("unload", function() { ok(false, "unload fired on document.body"); }); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 8378cd2e16a..4ea2f834827 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -101,7 +101,9 @@ DEFINE_EXPECT(visibilitychange); DEFINE_EXPECT(onbeforeunload); DEFINE_EXPECT(iframe_onbeforeunload); DEFINE_EXPECT(onunload); +DEFINE_EXPECT(pagehide); DEFINE_EXPECT(iframe_onunload); +DEFINE_EXPECT(iframe_pagehide); DEFINE_EXPECT(doc1_onstorage); DEFINE_EXPECT(doc1_onstoragecommit); DEFINE_EXPECT(window1_onstorage); @@ -1459,6 +1461,17 @@ static HRESULT WINAPI iframe_onbeforeunload(IDispatchEx *iface, DISPID id, LCID
EVENT_HANDLER_FUNC_OBJ(iframe_onbeforeunload);
+static HRESULT WINAPI pagehide(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(pagehide); + ok(!called_onunload, "unload fired before pagehide\n"); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(pagehide); + static HRESULT WINAPI onunload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -1466,18 +1479,34 @@ static HRESULT WINAPI onunload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wF if(expect_iframe_onunload) { ok(called_onbeforeunload, "beforeunload not fired before unload\n"); ok(called_iframe_onbeforeunload, "beforeunload not fired on iframe before unload\n"); - } + ok(called_pagehide, "pagehide not fired before unload\n"); + }else + ok(!called_pagehide, "pagehide fired before unload in quirks mode\n"); test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); return S_OK; }
EVENT_HANDLER_FUNC_OBJ(onunload);
+static HRESULT WINAPI iframe_pagehide(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(iframe_pagehide); + ok(called_pagehide, "pagehide not fired on parent window before iframe\n"); + ok(called_onunload, "unload not fired on parent window before pagehide on iframe\n"); + ok(!called_iframe_onunload, "unload fired before pagehide on iframe\n"); + test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(iframe_pagehide); + static HRESULT WINAPI iframe_onunload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { CHECK_EXPECT(iframe_onunload); ok(called_onunload, "unload not fired on parent window before iframe\n"); + ok(called_iframe_pagehide, "pagehide not fired before unload on iframe\n"); test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); return S_OK; } @@ -2589,6 +2618,8 @@ static void test_unload_event(IHTMLDocument2 *doc) ok(V_VT(&v) == VT_DISPATCH, "V_VT(onbeforeunload) = %d\n", V_VT(&v)); ok(V_DISPATCH(&v) == (IDispatch*)&iframe_onbeforeunload_obj, "V_DISPATCH(onbeforeunload) = %p\n", V_DISPATCH(&v));
+ add_event_listener((IUnknown*)window, L"pagehide", (IDispatch*)&pagehide_obj, VARIANT_TRUE); + add_event_listener((IUnknown*)child, L"pagehide", (IDispatch*)&iframe_pagehide_obj, VARIANT_TRUE); add_event_listener((IUnknown*)doc, L"beforeunload", (IDispatch*)&nocall_obj, VARIANT_TRUE); add_event_listener((IUnknown*)child_doc, L"beforeunload", (IDispatch*)&nocall_obj, VARIANT_TRUE); add_event_listener((IUnknown*)doc, L"unload", (IDispatch*)&nocall_obj, VARIANT_TRUE); @@ -2599,9 +2630,13 @@ static void test_unload_event(IHTMLDocument2 *doc) SET_EXPECT(onbeforeunload); SET_EXPECT(iframe_onbeforeunload); SET_EXPECT(onunload); + SET_EXPECT(pagehide); SET_EXPECT(iframe_onunload); + SET_EXPECT(iframe_pagehide); navigate(doc, L"blank.html"); + CHECK_CALLED(iframe_pagehide); CHECK_CALLED(iframe_onunload); + CHECK_CALLED(pagehide); CHECK_CALLED(onunload); CHECK_CALLED(iframe_onbeforeunload); CHECK_CALLED(onbeforeunload); diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index b54b1d6967b..72d2e3f99db 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -420,6 +420,16 @@ static void send_unload_events_impl(HTMLInnerWindow *window) if(window->doc) { window->doc->unload_sent = TRUE;
+ /* Native sends pagehide events prior to unload on the same window + before it moves on to the next window, so they're interleaved. */ + if(window->doc->document_mode >= COMPAT_MODE_IE11) { + hres = create_document_event(window->doc, EVENTID_PAGEHIDE, &event); + if(SUCCEEDED(hres)) { + dispatch_event(&window->event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + } + hres = create_document_event(window->doc, EVENTID_UNLOAD, &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event);