xref: /reactos/dll/win32/mshtml/nsevents.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright 2007-2008 Jacek Caban for CodeWeavers
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck  *
9*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*c2c66affSColin Finck  * Lesser General Public License for more details.
13*c2c66affSColin Finck  *
14*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck #include "mshtml_private.h"
20*c2c66affSColin Finck 
21*c2c66affSColin Finck static const PRUnichar blurW[]      = {'b','l','u','r',0};
22*c2c66affSColin Finck static const PRUnichar focusW[]     = {'f','o','c','u','s',0};
23*c2c66affSColin Finck static const PRUnichar keypressW[]  = {'k','e','y','p','r','e','s','s',0};
24*c2c66affSColin Finck static const PRUnichar loadW[]      = {'l','o','a','d',0};
25*c2c66affSColin Finck 
26*c2c66affSColin Finck typedef struct {
27*c2c66affSColin Finck     nsIDOMEventListener nsIDOMEventListener_iface;
28*c2c66affSColin Finck     nsDocumentEventListener *This;
29*c2c66affSColin Finck } nsEventListener;
30*c2c66affSColin Finck 
31*c2c66affSColin Finck struct nsDocumentEventListener {
32*c2c66affSColin Finck     nsEventListener blur_listener;
33*c2c66affSColin Finck     nsEventListener focus_listener;
34*c2c66affSColin Finck     nsEventListener keypress_listener;
35*c2c66affSColin Finck     nsEventListener load_listener;
36*c2c66affSColin Finck     nsEventListener htmlevent_listener;
37*c2c66affSColin Finck 
38*c2c66affSColin Finck     LONG ref;
39*c2c66affSColin Finck 
40*c2c66affSColin Finck     HTMLDocumentNode *doc;
41*c2c66affSColin Finck };
42*c2c66affSColin Finck 
release_listener(nsDocumentEventListener * This)43*c2c66affSColin Finck static LONG release_listener(nsDocumentEventListener *This)
44*c2c66affSColin Finck {
45*c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
46*c2c66affSColin Finck 
47*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
48*c2c66affSColin Finck 
49*c2c66affSColin Finck     if(!ref)
50*c2c66affSColin Finck         heap_free(This);
51*c2c66affSColin Finck 
52*c2c66affSColin Finck     return ref;
53*c2c66affSColin Finck }
54*c2c66affSColin Finck 
impl_from_nsIDOMEventListener(nsIDOMEventListener * iface)55*c2c66affSColin Finck static inline nsEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
56*c2c66affSColin Finck {
57*c2c66affSColin Finck     return CONTAINING_RECORD(iface, nsEventListener, nsIDOMEventListener_iface);
58*c2c66affSColin Finck }
59*c2c66affSColin Finck 
nsDOMEventListener_QueryInterface(nsIDOMEventListener * iface,nsIIDRef riid,void ** result)60*c2c66affSColin Finck static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface,
61*c2c66affSColin Finck         nsIIDRef riid, void **result)
62*c2c66affSColin Finck {
63*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
64*c2c66affSColin Finck 
65*c2c66affSColin Finck     *result = NULL;
66*c2c66affSColin Finck 
67*c2c66affSColin Finck     if(IsEqualGUID(&IID_nsISupports, riid)) {
68*c2c66affSColin Finck         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
69*c2c66affSColin Finck         *result = &This->nsIDOMEventListener_iface;
70*c2c66affSColin Finck     }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
71*c2c66affSColin Finck         TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
72*c2c66affSColin Finck         *result = &This->nsIDOMEventListener_iface;
73*c2c66affSColin Finck     }
74*c2c66affSColin Finck 
75*c2c66affSColin Finck     if(*result) {
76*c2c66affSColin Finck         nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
77*c2c66affSColin Finck         return NS_OK;
78*c2c66affSColin Finck     }
79*c2c66affSColin Finck 
80*c2c66affSColin Finck     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
81*c2c66affSColin Finck     return NS_NOINTERFACE;
82*c2c66affSColin Finck }
83*c2c66affSColin Finck 
nsDOMEventListener_AddRef(nsIDOMEventListener * iface)84*c2c66affSColin Finck static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface)
85*c2c66affSColin Finck {
86*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
87*c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->This->ref);
88*c2c66affSColin Finck 
89*c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This->This, ref);
90*c2c66affSColin Finck 
91*c2c66affSColin Finck     return ref;
92*c2c66affSColin Finck }
93*c2c66affSColin Finck 
nsDOMEventListener_Release(nsIDOMEventListener * iface)94*c2c66affSColin Finck static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface)
95*c2c66affSColin Finck {
96*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
97*c2c66affSColin Finck 
98*c2c66affSColin Finck     return release_listener(This->This);
99*c2c66affSColin Finck }
100*c2c66affSColin Finck 
is_doc_child_focus(NSContainer * nscontainer)101*c2c66affSColin Finck static BOOL is_doc_child_focus(NSContainer *nscontainer)
102*c2c66affSColin Finck {
103*c2c66affSColin Finck     HWND hwnd;
104*c2c66affSColin Finck 
105*c2c66affSColin Finck     for(hwnd = GetFocus(); hwnd && hwnd != nscontainer->hwnd; hwnd = GetParent(hwnd));
106*c2c66affSColin Finck 
107*c2c66affSColin Finck     return hwnd != NULL;
108*c2c66affSColin Finck }
109*c2c66affSColin Finck 
handle_blur(nsIDOMEventListener * iface,nsIDOMEvent * event)110*c2c66affSColin Finck static nsresult NSAPI handle_blur(nsIDOMEventListener *iface, nsIDOMEvent *event)
111*c2c66affSColin Finck {
112*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
113*c2c66affSColin Finck     HTMLDocumentNode *doc = This->This->doc;
114*c2c66affSColin Finck     HTMLDocumentObj *doc_obj;
115*c2c66affSColin Finck 
116*c2c66affSColin Finck     TRACE("(%p)\n", doc);
117*c2c66affSColin Finck 
118*c2c66affSColin Finck     if(!doc || !doc->basedoc.doc_obj)
119*c2c66affSColin Finck         return NS_ERROR_FAILURE;
120*c2c66affSColin Finck     doc_obj = doc->basedoc.doc_obj;
121*c2c66affSColin Finck 
122*c2c66affSColin Finck     if(doc_obj->focus && !is_doc_child_focus(doc_obj->nscontainer)) {
123*c2c66affSColin Finck         doc_obj->focus = FALSE;
124*c2c66affSColin Finck         notif_focus(doc_obj);
125*c2c66affSColin Finck     }
126*c2c66affSColin Finck 
127*c2c66affSColin Finck     return NS_OK;
128*c2c66affSColin Finck }
129*c2c66affSColin Finck 
handle_focus(nsIDOMEventListener * iface,nsIDOMEvent * event)130*c2c66affSColin Finck static nsresult NSAPI handle_focus(nsIDOMEventListener *iface, nsIDOMEvent *event)
131*c2c66affSColin Finck {
132*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
133*c2c66affSColin Finck     HTMLDocumentNode *doc = This->This->doc;
134*c2c66affSColin Finck     HTMLDocumentObj *doc_obj;
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     TRACE("(%p)\n", doc);
137*c2c66affSColin Finck 
138*c2c66affSColin Finck     if(!doc)
139*c2c66affSColin Finck         return NS_ERROR_FAILURE;
140*c2c66affSColin Finck     doc_obj = doc->basedoc.doc_obj;
141*c2c66affSColin Finck 
142*c2c66affSColin Finck     if(!doc_obj->focus) {
143*c2c66affSColin Finck         doc_obj->focus = TRUE;
144*c2c66affSColin Finck         notif_focus(doc_obj);
145*c2c66affSColin Finck     }
146*c2c66affSColin Finck 
147*c2c66affSColin Finck     return NS_OK;
148*c2c66affSColin Finck }
149*c2c66affSColin Finck 
handle_keypress(nsIDOMEventListener * iface,nsIDOMEvent * event)150*c2c66affSColin Finck static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface,
151*c2c66affSColin Finck         nsIDOMEvent *event)
152*c2c66affSColin Finck {
153*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
154*c2c66affSColin Finck     HTMLDocumentNode *doc = This->This->doc;
155*c2c66affSColin Finck     HTMLDocumentObj *doc_obj;
156*c2c66affSColin Finck 
157*c2c66affSColin Finck     if(!doc)
158*c2c66affSColin Finck         return NS_ERROR_FAILURE;
159*c2c66affSColin Finck     doc_obj = doc->basedoc.doc_obj;
160*c2c66affSColin Finck 
161*c2c66affSColin Finck     TRACE("(%p)->(%p)\n", doc, event);
162*c2c66affSColin Finck 
163*c2c66affSColin Finck     update_doc(&doc_obj->basedoc, UPDATE_UI);
164*c2c66affSColin Finck     if(doc_obj->usermode == EDITMODE)
165*c2c66affSColin Finck         handle_edit_event(&doc_obj->basedoc, event);
166*c2c66affSColin Finck 
167*c2c66affSColin Finck     return NS_OK;
168*c2c66affSColin Finck }
169*c2c66affSColin Finck 
handle_docobj_load(HTMLDocumentObj * doc)170*c2c66affSColin Finck static void handle_docobj_load(HTMLDocumentObj *doc)
171*c2c66affSColin Finck {
172*c2c66affSColin Finck     IOleCommandTarget *olecmd = NULL;
173*c2c66affSColin Finck     HRESULT hres;
174*c2c66affSColin Finck 
175*c2c66affSColin Finck     if(doc->nscontainer->editor_controller) {
176*c2c66affSColin Finck         nsIController_Release(doc->nscontainer->editor_controller);
177*c2c66affSColin Finck         doc->nscontainer->editor_controller = NULL;
178*c2c66affSColin Finck     }
179*c2c66affSColin Finck 
180*c2c66affSColin Finck     if(doc->usermode == EDITMODE)
181*c2c66affSColin Finck         handle_edit_load(&doc->basedoc);
182*c2c66affSColin Finck 
183*c2c66affSColin Finck     if(doc->client) {
184*c2c66affSColin Finck         hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
185*c2c66affSColin Finck         if(FAILED(hres))
186*c2c66affSColin Finck             olecmd = NULL;
187*c2c66affSColin Finck     }
188*c2c66affSColin Finck 
189*c2c66affSColin Finck     if(doc->download_state) {
190*c2c66affSColin Finck         if(olecmd) {
191*c2c66affSColin Finck             VARIANT progress;
192*c2c66affSColin Finck 
193*c2c66affSColin Finck             V_VT(&progress) = VT_I4;
194*c2c66affSColin Finck             V_I4(&progress) = 0;
195*c2c66affSColin Finck             IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS,
196*c2c66affSColin Finck                     OLECMDEXECOPT_DONTPROMPTUSER, &progress, NULL);
197*c2c66affSColin Finck         }
198*c2c66affSColin Finck 
199*c2c66affSColin Finck         set_download_state(doc, 0);
200*c2c66affSColin Finck     }
201*c2c66affSColin Finck 
202*c2c66affSColin Finck     if(olecmd) {
203*c2c66affSColin Finck         IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 103, 0, NULL, NULL);
204*c2c66affSColin Finck         IOleCommandTarget_Exec(olecmd, &CGID_MSHTML, IDM_PARSECOMPLETE, 0, NULL, NULL);
205*c2c66affSColin Finck         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_HTTPEQUIV_DONE, 0, NULL, NULL);
206*c2c66affSColin Finck 
207*c2c66affSColin Finck         IOleCommandTarget_Release(olecmd);
208*c2c66affSColin Finck     }
209*c2c66affSColin Finck }
210*c2c66affSColin Finck 
handle_load(nsIDOMEventListener * iface,nsIDOMEvent * event)211*c2c66affSColin Finck static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event)
212*c2c66affSColin Finck {
213*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
214*c2c66affSColin Finck     HTMLDocumentNode *doc = This->This->doc;
215*c2c66affSColin Finck     HTMLDocumentObj *doc_obj = NULL;
216*c2c66affSColin Finck     nsresult nsres = NS_OK;
217*c2c66affSColin Finck 
218*c2c66affSColin Finck     TRACE("(%p)\n", doc);
219*c2c66affSColin Finck 
220*c2c66affSColin Finck     if(!doc || !doc->basedoc.window)
221*c2c66affSColin Finck         return NS_ERROR_FAILURE;
222*c2c66affSColin Finck     if(doc->basedoc.doc_obj && doc->basedoc.doc_obj->basedoc.doc_node == doc)
223*c2c66affSColin Finck         doc_obj = doc->basedoc.doc_obj;
224*c2c66affSColin Finck 
225*c2c66affSColin Finck     connect_scripts(doc->window);
226*c2c66affSColin Finck 
227*c2c66affSColin Finck     htmldoc_addref(&doc->basedoc);
228*c2c66affSColin Finck 
229*c2c66affSColin Finck     if(doc_obj)
230*c2c66affSColin Finck         handle_docobj_load(doc_obj);
231*c2c66affSColin Finck 
232*c2c66affSColin Finck     set_ready_state(doc->basedoc.window, READYSTATE_COMPLETE);
233*c2c66affSColin Finck 
234*c2c66affSColin Finck     if(doc_obj) {
235*c2c66affSColin Finck         if(doc_obj->view_sink)
236*c2c66affSColin Finck             IAdviseSink_OnViewChange(doc_obj->view_sink, DVASPECT_CONTENT, -1);
237*c2c66affSColin Finck 
238*c2c66affSColin Finck         set_statustext(doc_obj, IDS_STATUS_DONE, NULL);
239*c2c66affSColin Finck 
240*c2c66affSColin Finck         update_title(doc_obj);
241*c2c66affSColin Finck     }
242*c2c66affSColin Finck 
243*c2c66affSColin Finck     if(doc_obj && doc_obj->usermode!=EDITMODE && doc_obj->doc_object_service
244*c2c66affSColin Finck        && !(doc->basedoc.window->load_flags & BINDING_REFRESH))
245*c2c66affSColin Finck         IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service,
246*c2c66affSColin Finck                 &doc->basedoc.window->base.IHTMLWindow2_iface, 0);
247*c2c66affSColin Finck 
248*c2c66affSColin Finck     if(doc->nsdoc) {
249*c2c66affSColin Finck         nsIDOMHTMLElement *nsbody;
250*c2c66affSColin Finck 
251*c2c66affSColin Finck         flush_pending_tasks(doc->basedoc.task_magic);
252*c2c66affSColin Finck 
253*c2c66affSColin Finck         nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody);
254*c2c66affSColin Finck         if(NS_SUCCEEDED(nsres) && nsbody) {
255*c2c66affSColin Finck             fire_event(doc, EVENTID_LOAD, TRUE, (nsIDOMNode*)nsbody, event, (IDispatch*)&doc->window->base.IDispatchEx_iface);
256*c2c66affSColin Finck             nsIDOMHTMLElement_Release(nsbody);
257*c2c66affSColin Finck         }
258*c2c66affSColin Finck     }else {
259*c2c66affSColin Finck         ERR("NULL nsdoc\n");
260*c2c66affSColin Finck         nsres = NS_ERROR_FAILURE;
261*c2c66affSColin Finck     }
262*c2c66affSColin Finck 
263*c2c66affSColin Finck     htmldoc_release(&doc->basedoc);
264*c2c66affSColin Finck     return nsres;
265*c2c66affSColin Finck }
266*c2c66affSColin Finck 
handle_htmlevent(nsIDOMEventListener * iface,nsIDOMEvent * event)267*c2c66affSColin Finck static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event)
268*c2c66affSColin Finck {
269*c2c66affSColin Finck     nsEventListener *This = impl_from_nsIDOMEventListener(iface);
270*c2c66affSColin Finck     HTMLDocumentNode *doc = This->This->doc;
271*c2c66affSColin Finck     const PRUnichar *type;
272*c2c66affSColin Finck     nsIDOMEventTarget *event_target;
273*c2c66affSColin Finck     nsIDOMNode *nsnode;
274*c2c66affSColin Finck     nsAString type_str;
275*c2c66affSColin Finck     eventid_t eid;
276*c2c66affSColin Finck     nsresult nsres;
277*c2c66affSColin Finck 
278*c2c66affSColin Finck     TRACE("%p\n", This->This);
279*c2c66affSColin Finck 
280*c2c66affSColin Finck     if(!doc) {
281*c2c66affSColin Finck         WARN("NULL doc\n");
282*c2c66affSColin Finck         return NS_OK;
283*c2c66affSColin Finck     }
284*c2c66affSColin Finck 
285*c2c66affSColin Finck     nsAString_Init(&type_str, NULL);
286*c2c66affSColin Finck     nsIDOMEvent_GetType(event, &type_str);
287*c2c66affSColin Finck     nsAString_GetData(&type_str, &type);
288*c2c66affSColin Finck     eid = str_to_eid(type);
289*c2c66affSColin Finck     nsAString_Finish(&type_str);
290*c2c66affSColin Finck 
291*c2c66affSColin Finck     nsres = nsIDOMEvent_GetTarget(event, &event_target);
292*c2c66affSColin Finck     if(NS_FAILED(nsres) || !event_target) {
293*c2c66affSColin Finck         ERR("GetEventTarget failed: %08x\n", nsres);
294*c2c66affSColin Finck         return NS_OK;
295*c2c66affSColin Finck     }
296*c2c66affSColin Finck 
297*c2c66affSColin Finck     nsres = nsIDOMEventTarget_QueryInterface(event_target, &IID_nsIDOMNode, (void**)&nsnode);
298*c2c66affSColin Finck     nsIDOMEventTarget_Release(event_target);
299*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
300*c2c66affSColin Finck         ERR("Could not get nsIDOMNode: %08x\n", nsres);
301*c2c66affSColin Finck         return NS_OK;
302*c2c66affSColin Finck     }
303*c2c66affSColin Finck 
304*c2c66affSColin Finck     fire_event(doc, eid, TRUE, nsnode, event, NULL);
305*c2c66affSColin Finck 
306*c2c66affSColin Finck     nsIDOMNode_Release(nsnode);
307*c2c66affSColin Finck 
308*c2c66affSColin Finck     return NS_OK;
309*c2c66affSColin Finck }
310*c2c66affSColin Finck 
311*c2c66affSColin Finck #define EVENTLISTENER_VTBL(handler) \
312*c2c66affSColin Finck     { \
313*c2c66affSColin Finck         nsDOMEventListener_QueryInterface, \
314*c2c66affSColin Finck         nsDOMEventListener_AddRef, \
315*c2c66affSColin Finck         nsDOMEventListener_Release, \
316*c2c66affSColin Finck         handler, \
317*c2c66affSColin Finck     }
318*c2c66affSColin Finck 
319*c2c66affSColin Finck static const nsIDOMEventListenerVtbl blur_vtbl =      EVENTLISTENER_VTBL(handle_blur);
320*c2c66affSColin Finck static const nsIDOMEventListenerVtbl focus_vtbl =     EVENTLISTENER_VTBL(handle_focus);
321*c2c66affSColin Finck static const nsIDOMEventListenerVtbl keypress_vtbl =  EVENTLISTENER_VTBL(handle_keypress);
322*c2c66affSColin Finck static const nsIDOMEventListenerVtbl load_vtbl =      EVENTLISTENER_VTBL(handle_load);
323*c2c66affSColin Finck static const nsIDOMEventListenerVtbl htmlevent_vtbl = EVENTLISTENER_VTBL(handle_htmlevent);
324*c2c66affSColin Finck 
init_event(nsIDOMEventTarget * target,const PRUnichar * type,nsIDOMEventListener * listener,BOOL capture)325*c2c66affSColin Finck static void init_event(nsIDOMEventTarget *target, const PRUnichar *type,
326*c2c66affSColin Finck         nsIDOMEventListener *listener, BOOL capture)
327*c2c66affSColin Finck {
328*c2c66affSColin Finck     nsAString type_str;
329*c2c66affSColin Finck     nsresult nsres;
330*c2c66affSColin Finck 
331*c2c66affSColin Finck     nsAString_InitDepend(&type_str, type);
332*c2c66affSColin Finck     nsres = nsIDOMEventTarget_AddEventListener(target, &type_str, listener, capture, FALSE, 1);
333*c2c66affSColin Finck     nsAString_Finish(&type_str);
334*c2c66affSColin Finck     if(NS_FAILED(nsres))
335*c2c66affSColin Finck         ERR("AddEventTarget failed: %08x\n", nsres);
336*c2c66affSColin Finck 
337*c2c66affSColin Finck }
338*c2c66affSColin Finck 
init_listener(nsEventListener * This,nsDocumentEventListener * listener,const nsIDOMEventListenerVtbl * vtbl)339*c2c66affSColin Finck static void init_listener(nsEventListener *This, nsDocumentEventListener *listener,
340*c2c66affSColin Finck         const nsIDOMEventListenerVtbl *vtbl)
341*c2c66affSColin Finck {
342*c2c66affSColin Finck     This->nsIDOMEventListener_iface.lpVtbl = vtbl;
343*c2c66affSColin Finck     This->This = listener;
344*c2c66affSColin Finck }
345*c2c66affSColin Finck 
add_nsevent_listener(HTMLDocumentNode * doc,nsIDOMNode * nsnode,LPCWSTR type)346*c2c66affSColin Finck void add_nsevent_listener(HTMLDocumentNode *doc, nsIDOMNode *nsnode, LPCWSTR type)
347*c2c66affSColin Finck {
348*c2c66affSColin Finck     nsIDOMEventTarget *target;
349*c2c66affSColin Finck     nsresult nsres;
350*c2c66affSColin Finck 
351*c2c66affSColin Finck     if(nsnode)
352*c2c66affSColin Finck         nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMEventTarget, (void**)&target);
353*c2c66affSColin Finck     else
354*c2c66affSColin Finck         nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target);
355*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
356*c2c66affSColin Finck         ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
357*c2c66affSColin Finck         return;
358*c2c66affSColin Finck     }
359*c2c66affSColin Finck 
360*c2c66affSColin Finck     init_event(target, type, &doc->nsevent_listener->htmlevent_listener.nsIDOMEventListener_iface,
361*c2c66affSColin Finck             TRUE);
362*c2c66affSColin Finck     nsIDOMEventTarget_Release(target);
363*c2c66affSColin Finck }
364*c2c66affSColin Finck 
detach_nslistener(HTMLDocumentNode * doc,const WCHAR * type,nsEventListener * listener,cpp_bool is_capture)365*c2c66affSColin Finck static void detach_nslistener(HTMLDocumentNode *doc, const WCHAR *type, nsEventListener *listener, cpp_bool is_capture)
366*c2c66affSColin Finck {
367*c2c66affSColin Finck     nsIDOMEventTarget *target;
368*c2c66affSColin Finck     nsAString type_str;
369*c2c66affSColin Finck     nsresult nsres;
370*c2c66affSColin Finck 
371*c2c66affSColin Finck     if(!doc->basedoc.window)
372*c2c66affSColin Finck         return;
373*c2c66affSColin Finck 
374*c2c66affSColin Finck     nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target);
375*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
376*c2c66affSColin Finck         ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
377*c2c66affSColin Finck         return;
378*c2c66affSColin Finck     }
379*c2c66affSColin Finck 
380*c2c66affSColin Finck     nsAString_InitDepend(&type_str, type);
381*c2c66affSColin Finck     nsres = nsIDOMEventTarget_RemoveEventListener(target, &type_str,
382*c2c66affSColin Finck             &listener->nsIDOMEventListener_iface, is_capture);
383*c2c66affSColin Finck     nsAString_Finish(&type_str);
384*c2c66affSColin Finck     nsIDOMEventTarget_Release(target);
385*c2c66affSColin Finck     if(NS_FAILED(nsres))
386*c2c66affSColin Finck         ERR("RemoveEventTarget failed: %08x\n", nsres);
387*c2c66affSColin Finck }
388*c2c66affSColin Finck 
detach_nsevent(HTMLDocumentNode * doc,const WCHAR * type)389*c2c66affSColin Finck void detach_nsevent(HTMLDocumentNode *doc, const WCHAR *type)
390*c2c66affSColin Finck {
391*c2c66affSColin Finck     detach_nslistener(doc, type, &doc->nsevent_listener->htmlevent_listener, TRUE);
392*c2c66affSColin Finck }
393*c2c66affSColin Finck 
release_nsevents(HTMLDocumentNode * doc)394*c2c66affSColin Finck void release_nsevents(HTMLDocumentNode *doc)
395*c2c66affSColin Finck {
396*c2c66affSColin Finck     nsDocumentEventListener *listener = doc->nsevent_listener;
397*c2c66affSColin Finck 
398*c2c66affSColin Finck     TRACE("%p %p\n", doc, doc->nsevent_listener);
399*c2c66affSColin Finck 
400*c2c66affSColin Finck     if(!listener)
401*c2c66affSColin Finck         return;
402*c2c66affSColin Finck 
403*c2c66affSColin Finck     detach_nslistener(doc, blurW,     &listener->blur_listener,     TRUE);
404*c2c66affSColin Finck     detach_nslistener(doc, focusW,    &listener->focus_listener,    TRUE);
405*c2c66affSColin Finck     detach_nslistener(doc, keypressW, &listener->keypress_listener, FALSE);
406*c2c66affSColin Finck     detach_nslistener(doc, loadW,     &listener->load_listener,     TRUE);
407*c2c66affSColin Finck 
408*c2c66affSColin Finck     listener->doc = NULL;
409*c2c66affSColin Finck     release_listener(listener);
410*c2c66affSColin Finck     doc->nsevent_listener = NULL;
411*c2c66affSColin Finck }
412*c2c66affSColin Finck 
init_nsevents(HTMLDocumentNode * doc)413*c2c66affSColin Finck void init_nsevents(HTMLDocumentNode *doc)
414*c2c66affSColin Finck {
415*c2c66affSColin Finck     nsDocumentEventListener *listener;
416*c2c66affSColin Finck     nsIDOMEventTarget *target;
417*c2c66affSColin Finck     nsresult nsres;
418*c2c66affSColin Finck 
419*c2c66affSColin Finck     listener = heap_alloc(sizeof(nsDocumentEventListener));
420*c2c66affSColin Finck     if(!listener)
421*c2c66affSColin Finck         return;
422*c2c66affSColin Finck 
423*c2c66affSColin Finck     TRACE("%p %p\n", doc, listener);
424*c2c66affSColin Finck 
425*c2c66affSColin Finck     listener->ref = 1;
426*c2c66affSColin Finck     listener->doc = doc;
427*c2c66affSColin Finck 
428*c2c66affSColin Finck     init_listener(&listener->blur_listener,        listener, &blur_vtbl);
429*c2c66affSColin Finck     init_listener(&listener->focus_listener,       listener, &focus_vtbl);
430*c2c66affSColin Finck     init_listener(&listener->keypress_listener,    listener, &keypress_vtbl);
431*c2c66affSColin Finck     init_listener(&listener->load_listener,        listener, &load_vtbl);
432*c2c66affSColin Finck     init_listener(&listener->htmlevent_listener,   listener, &htmlevent_vtbl);
433*c2c66affSColin Finck 
434*c2c66affSColin Finck     doc->nsevent_listener = listener;
435*c2c66affSColin Finck 
436*c2c66affSColin Finck     nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target);
437*c2c66affSColin Finck     if(NS_FAILED(nsres)) {
438*c2c66affSColin Finck         ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
439*c2c66affSColin Finck         return;
440*c2c66affSColin Finck     }
441*c2c66affSColin Finck 
442*c2c66affSColin Finck     init_event(target, blurW,     &listener->blur_listener.nsIDOMEventListener_iface,     TRUE);
443*c2c66affSColin Finck     init_event(target, focusW,    &listener->focus_listener.nsIDOMEventListener_iface,    TRUE);
444*c2c66affSColin Finck     init_event(target, keypressW, &listener->keypress_listener.nsIDOMEventListener_iface, FALSE);
445*c2c66affSColin Finck     init_event(target, loadW,     &listener->load_listener.nsIDOMEventListener_iface,     TRUE);
446*c2c66affSColin Finck 
447*c2c66affSColin Finck     nsIDOMEventTarget_Release(target);
448*c2c66affSColin Finck }
449