From d52f41ba4153ce7976d75fb38e1213e66200c9f2 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 27 Oct 2009 21:09:25 +0100 Subject: [PATCH] mshtml: Moved nsIDOMEventListener implementations to HTMLDocumentNode. --- dlls/mshtml/htmldoc.c | 7 +- dlls/mshtml/mshtml_private.h | 20 ++-- dlls/mshtml/navigate.c | 4 - dlls/mshtml/nsembed.c | 2 - dlls/mshtml/nsevents.c | 179 +++++++++++++++++++++++------------ 5 files changed, 131 insertions(+), 81 deletions(-) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index c1eca663a86..a5422f23649 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -1763,6 +1763,8 @@ static void HTMLDocumentNode_destructor(HTMLDOMNode *iface) { HTMLDocumentNode *This = HTMLDOCNODE_NODE_THIS(iface); + if(This->nsevent_listener) + release_nsevents(This); if(This->secmgr) IInternetSecurityManager_Release(This->secmgr); @@ -1819,11 +1821,12 @@ HRESULT create_doc_from_nsdoc(nsIDOMHTMLDocument *nsdoc, HTMLDocumentObj *doc_ob HTMLDocumentNode_SecMgr_Init(doc); doc->ref = 1; + doc->basedoc.window = window; + nsIDOMHTMLDocument_AddRef(nsdoc); doc->nsdoc = nsdoc; init_mutation(doc); - - doc->basedoc.window = window; + init_nsevents(doc); list_init(&doc->bindings); list_init(&doc->selection_list); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index eb4b34f123c..e3a12b24d87 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -365,11 +365,6 @@ struct HTMLDocumentObj { DWORD update; }; -typedef struct { - const nsIDOMEventListenerVtbl *lpDOMEventListenerVtbl; - NSContainer *This; -} nsEventListener; - struct NSContainer { const nsIWebBrowserChromeVtbl *lpWebBrowserChromeVtbl; const nsIContextMenuListenerVtbl *lpContextMenuListenerVtbl; @@ -380,12 +375,6 @@ struct NSContainer { const nsIWeakReferenceVtbl *lpWeakReferenceVtbl; const nsISupportsWeakReferenceVtbl *lpSupportsWeakReferenceVtbl; - nsEventListener blur_listener; - nsEventListener focus_listener; - nsEventListener keypress_listener; - nsEventListener load_listener; - nsEventListener htmlevent_listener; - nsIWebBrowser *webbrowser; nsIWebNavigation *navigation; nsIBaseWindow *window; @@ -479,6 +468,8 @@ typedef struct _mutation_queue_t { struct _mutation_queue_t *next; } mutation_queue_t; +typedef struct nsDocumentEventListener nsDocumentEventListener; + struct HTMLDocumentNode { HTMLDOMNode node; HTMLDocument basedoc; @@ -495,6 +486,7 @@ struct HTMLDocumentNode { BOOL content_ready; IInternetSecurityManager *secmgr; + nsDocumentEventListener *nsevent_listener; mutation_queue_t *mutation_queue; mutation_queue_t *mutation_queue_tail; @@ -656,10 +648,12 @@ void nsAString_Finish(nsAString*); nsICommandParams *create_nscommand_params(void); HRESULT nsnode_to_nsstring(nsIDOMNode*,nsAString*); void get_editor_controller(NSContainer*); -void init_nsevents(NSContainer*); -void add_nsevent_listener(HTMLWindow*,LPCWSTR); nsresult get_nsinterface(nsISupports*,REFIID,void**); +void init_nsevents(HTMLDocumentNode*); +void release_nsevents(HTMLDocumentNode*); +void add_nsevent_listener(HTMLWindow*,LPCWSTR); + void set_window_bscallback(HTMLWindow*,nsChannelBSC*); void set_current_mon(HTMLWindow*,IMoniker*); HRESULT start_binding(HTMLWindow*,HTMLDocumentNode*,BSCallback*,IBindCtx*); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index d5fea3af886..3a1644c3d6e 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -955,10 +955,6 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) if(This->window) update_window_doc(This->window); - - /* events are reset when a new document URI is loaded, so re-initialise them here */ - if(This->window && This->window->doc_obj->basedoc.window == This->window) - init_nsevents(This->window->doc_obj->nscontainer); } This->bsc.readed += This->nsstream->buf_size; diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index f6efd263e87..6207c13a608 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -1697,8 +1697,6 @@ NSContainer *NSContainer_Create(HTMLDocumentObj *doc, NSContainer *parent) if(NS_FAILED(nsres)) ERR("SetParentURIContentListener failed: %08x\n", nsres); - init_nsevents(ret); - nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIScrollable, (void**)&scrollable); if(NS_SUCCEEDED(nsres)) { nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index e2758ce2986..3aef7384de3 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -35,6 +35,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); +typedef struct { + const nsIDOMEventListenerVtbl *lpDOMEventListenerVtbl; + nsDocumentEventListener *This; +} nsEventListener; + +struct nsDocumentEventListener { + nsEventListener blur_listener; + nsEventListener focus_listener; + nsEventListener keypress_listener; + nsEventListener load_listener; + nsEventListener htmlevent_listener; + + LONG ref; + + HTMLDocumentNode *doc; +}; + +static LONG release_listener(nsDocumentEventListener *This) +{ + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) + heap_free(This); + + return ref; +} + #define NSEVENTLIST_THIS(iface) DEFINE_THIS(nsEventListener, DOMEventListener, iface) static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface, @@ -63,37 +92,44 @@ static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *ifa static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; - return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); + nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This; + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; } static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; - return nsIWebBrowserChrome_Release(NSWBCHROME(This)); + nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This; + + return release_listener(This); } -static BOOL is_doc_child_focus(NSContainer *This) +static BOOL is_doc_child_focus(HTMLDocumentObj *doc) { HWND hwnd; - if(!This->doc) - return FALSE; - - for(hwnd = GetFocus(); hwnd && hwnd != This->doc->basedoc.doc_obj->hwnd; hwnd = GetParent(hwnd)); + for(hwnd = GetFocus(); hwnd && hwnd != doc->hwnd; hwnd = GetParent(hwnd)); return hwnd != NULL; } static nsresult NSAPI handle_blur(nsIDOMEventListener *iface, nsIDOMEvent *event) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; + HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; + HTMLDocumentObj *doc_obj; - TRACE("(%p)\n", This); + TRACE("(%p)\n", doc); - if(!This->reset_focus && This->doc && This->doc->basedoc.doc_obj->focus && !is_doc_child_focus(This)) { - This->doc->basedoc.doc_obj->focus = FALSE; - notif_focus(This->doc); + if(!doc) + return NS_ERROR_FAILURE; + doc_obj = doc->basedoc.doc_obj; + + if(!doc_obj->nscontainer->reset_focus && doc_obj->focus && !is_doc_child_focus(doc_obj)) { + doc_obj->focus = FALSE; + notif_focus(doc_obj); } return NS_OK; @@ -101,13 +137,18 @@ static nsresult NSAPI handle_blur(nsIDOMEventListener *iface, nsIDOMEvent *event static nsresult NSAPI handle_focus(nsIDOMEventListener *iface, nsIDOMEvent *event) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; + HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; + HTMLDocumentObj *doc_obj; - TRACE("(%p)\n", This); + TRACE("(%p)\n", doc); - if(!This->reset_focus && This->doc && !This->doc->focus) { - This->doc->focus = TRUE; - notif_focus(This->doc); + if(!doc) + return NS_ERROR_FAILURE; + doc_obj = doc->basedoc.doc_obj; + + if(!doc_obj->nscontainer->reset_focus && !doc_obj->focus) { + doc_obj->focus = TRUE; + notif_focus(doc_obj); } return NS_OK; @@ -116,45 +157,52 @@ static nsresult NSAPI handle_focus(nsIDOMEventListener *iface, nsIDOMEvent *even static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface, nsIDOMEvent *event) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; + HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; + HTMLDocumentObj *doc_obj; - TRACE("(%p)->(%p)\n", This, event); + if(!doc) + return NS_ERROR_FAILURE; + doc_obj = doc->basedoc.doc_obj; - update_doc(&This->doc->basedoc, UPDATE_UI); - if(This->doc->usermode == EDITMODE) - handle_edit_event(&This->doc->basedoc, event); + TRACE("(%p)->(%p)\n", doc, event); + + update_doc(&doc_obj->basedoc, UPDATE_UI); + if(doc_obj->usermode == EDITMODE) + handle_edit_event(&doc_obj->basedoc, event); return NS_OK; } static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; + HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; + HTMLDocumentObj *doc_obj; nsIDOMHTMLElement *nsbody = NULL; - TRACE("(%p)\n", This); + TRACE("(%p)\n", doc); - if(!This->doc) - return NS_OK; + if(!doc) + return NS_ERROR_FAILURE; + doc_obj = doc->basedoc.doc_obj; - connect_scripts(This->doc->basedoc.window); + connect_scripts(doc->basedoc.window); - if(This->editor_controller) { - nsIController_Release(This->editor_controller); - This->editor_controller = NULL; + if(doc_obj->nscontainer->editor_controller) { + nsIController_Release(doc_obj->nscontainer->editor_controller); + doc_obj->nscontainer->editor_controller = NULL; } - if(This->doc->usermode == EDITMODE) - handle_edit_load(&This->doc->basedoc); + if(doc_obj->usermode == EDITMODE) + handle_edit_load(&doc_obj->basedoc); - if(!This->doc->basedoc.doc_node->nsdoc) { + if(!doc->nsdoc) { ERR("NULL nsdoc\n"); return NS_ERROR_FAILURE; } - nsIDOMHTMLDocument_GetBody(This->doc->basedoc.doc_node->nsdoc, &nsbody); + nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); if(nsbody) { - fire_event(This->doc->basedoc.doc_node, EVENTID_LOAD, (nsIDOMNode*)nsbody, event); + fire_event(doc, EVENTID_LOAD, (nsIDOMNode*)nsbody, event); nsIDOMHTMLElement_Release(nsbody); } @@ -163,7 +211,7 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event) { - NSContainer *This = NSEVENTLIST_THIS(iface)->This; + HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; const PRUnichar *type; nsIDOMEventTarget *event_target; nsIDOMNode *nsnode; @@ -190,7 +238,7 @@ static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent * return NS_OK; } - fire_event(This->doc->basedoc.doc_node, eid, nsnode, event); + fire_event(doc, eid, nsnode, event); nsIDOMNode_Release(nsnode); @@ -227,11 +275,11 @@ static void init_event(nsIDOMEventTarget *target, const PRUnichar *type, } -static void init_listener(nsEventListener *This, NSContainer *container, +static void init_listener(nsEventListener *This, nsDocumentEventListener *listener, const nsIDOMEventListenerVtbl *vtbl) { This->lpDOMEventListenerVtbl = vtbl; - This->This = container; + This->This = listener; } void add_nsevent_listener(HTMLWindow *window, LPCWSTR type) @@ -245,13 +293,22 @@ void add_nsevent_listener(HTMLWindow *window, LPCWSTR type) return; } - init_event(target, type, NSEVENTLIST(&window->doc_obj->nscontainer->htmlevent_listener), TRUE); + init_event(target, type, NSEVENTLIST(&window->doc->nsevent_listener->htmlevent_listener), TRUE); nsIDOMEventTarget_Release(target); } -void init_nsevents(NSContainer *This) +void release_nsevents(HTMLDocumentNode *doc) { - nsIDOMWindow *dom_window; + if(doc->nsevent_listener) { + doc->nsevent_listener->doc = NULL; + release_listener(doc->nsevent_listener); + doc->nsevent_listener = NULL; + } +} + +void init_nsevents(HTMLDocumentNode *doc) +{ + nsDocumentEventListener *listener; nsIDOMEventTarget *target; nsresult nsres; @@ -260,29 +317,31 @@ void init_nsevents(NSContainer *This) static const PRUnichar wsz_keypress[] = {'k','e','y','p','r','e','s','s',0}; static const PRUnichar wsz_load[] = {'l','o','a','d',0}; - init_listener(&This->blur_listener, This, &blur_vtbl); - init_listener(&This->focus_listener, This, &focus_vtbl); - init_listener(&This->keypress_listener, This, &keypress_vtbl); - init_listener(&This->load_listener, This, &load_vtbl); - init_listener(&This->htmlevent_listener, This, &htmlevent_vtbl); - - nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window); - if(NS_FAILED(nsres)) { - ERR("GetContentDOMWindow failed: %08x\n", nsres); + listener = heap_alloc(sizeof(nsDocumentEventListener)); + if(!listener) return; - } - nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target); - nsIDOMWindow_Release(dom_window); + listener->ref = 1; + listener->doc = doc; + + init_listener(&listener->blur_listener, listener, &blur_vtbl); + init_listener(&listener->focus_listener, listener, &focus_vtbl); + init_listener(&listener->keypress_listener, listener, &keypress_vtbl); + init_listener(&listener->load_listener, listener, &load_vtbl); + init_listener(&listener->htmlevent_listener, listener, &htmlevent_vtbl); + + doc->nsevent_listener = listener; + + nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target); if(NS_FAILED(nsres)) { ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres); return; } - init_event(target, wsz_blur, NSEVENTLIST(&This->blur_listener), TRUE); - init_event(target, wsz_focus, NSEVENTLIST(&This->focus_listener), TRUE); - init_event(target, wsz_keypress, NSEVENTLIST(&This->keypress_listener), FALSE); - init_event(target, wsz_load, NSEVENTLIST(&This->load_listener), TRUE); + init_event(target, wsz_blur, NSEVENTLIST(&listener->blur_listener), TRUE); + init_event(target, wsz_focus, NSEVENTLIST(&listener->focus_listener), TRUE); + init_event(target, wsz_keypress, NSEVENTLIST(&listener->keypress_listener), FALSE); + init_event(target, wsz_load, NSEVENTLIST(&listener->load_listener), TRUE); nsIDOMEventTarget_Release(target); }