2 * Copyright 2008-2009 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
32 #include "htmlscript.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
39 LISTENER_TYPE_CAPTURE
,
41 LISTENER_TYPE_ONEVENT
,
42 LISTENER_TYPE_ATTACHED
52 struct wine_rb_entry entry
;
54 struct list listeners
;
55 } listener_container_t
;
57 static const WCHAR abortW
[] = {'a','b','o','r','t',0};
58 static const WCHAR beforeactivateW
[] = {'b','e','f','o','r','e','a','c','t','i','v','a','t','e',0};
59 static const WCHAR beforeunloadW
[] = {'b','e','f','o','r','e','u','n','l','o','a','d',0};
60 static const WCHAR blurW
[] = {'b','l','u','r',0};
61 static const WCHAR changeW
[] = {'c','h','a','n','g','e',0};
62 static const WCHAR clickW
[] = {'c','l','i','c','k',0};
63 static const WCHAR contextmenuW
[] = {'c','o','n','t','e','x','t','m','e','n','u',0};
64 static const WCHAR dataavailableW
[] = {'d','a','t','a','a','v','a','i','l','a','b','l','e',0};
65 static const WCHAR dblclickW
[] = {'d','b','l','c','l','i','c','k',0};
66 static const WCHAR dragW
[] = {'d','r','a','g',0};
67 static const WCHAR dragstartW
[] = {'d','r','a','g','s','t','a','r','t',0};
68 static const WCHAR errorW
[] = {'e','r','r','o','r',0};
69 static const WCHAR focusW
[] = {'f','o','c','u','s',0};
70 static const WCHAR focusinW
[] = {'f','o','c','u','s','i','n',0};
71 static const WCHAR focusoutW
[] = {'f','o','c','u','s','o','u','t',0};
72 static const WCHAR helpW
[] = {'h','e','l','p',0};
73 static const WCHAR keydownW
[] = {'k','e','y','d','o','w','n',0};
74 static const WCHAR keypressW
[] = {'k','e','y','p','r','e','s','s',0};
75 static const WCHAR keyupW
[] = {'k','e','y','u','p',0};
76 static const WCHAR loadW
[] = {'l','o','a','d',0};
77 static const WCHAR messageW
[] = {'m','e','s','s','a','g','e',0};
78 static const WCHAR mousedownW
[] = {'m','o','u','s','e','d','o','w','n',0};
79 static const WCHAR mousemoveW
[] = {'m','o','u','s','e','m','o','v','e',0};
80 static const WCHAR mouseoutW
[] = {'m','o','u','s','e','o','u','t',0};
81 static const WCHAR mouseoverW
[] = {'m','o','u','s','e','o','v','e','r',0};
82 static const WCHAR mouseupW
[] = {'m','o','u','s','e','u','p',0};
83 static const WCHAR mousewheelW
[] = {'m','o','u','s','e','w','h','e','e','l',0};
84 static const WCHAR pasteW
[] = {'p','a','s','t','e',0};
85 static const WCHAR readystatechangeW
[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
86 static const WCHAR resizeW
[] = {'r','e','s','i','z','e',0};
87 static const WCHAR scrollW
[] = {'s','c','r','o','l','l',0};
88 static const WCHAR selectstartW
[] = {'s','e','l','e','c','t','s','t','a','r','t',0};
89 static const WCHAR selectionchangeW
[] = {'s','e','l','e','c','t','i','o','n','c','h','a','n','g','e',0};
90 static const WCHAR submitW
[] = {'s','u','b','m','i','t',0};
91 static const WCHAR unloadW
[] = {'u','n','l','o','a','d',0};
93 static const WCHAR EventW
[] = {'E','v','e','n','t',0};
94 static const WCHAR UIEventW
[] = {'U','I','E','v','e','n','t',0};
95 static const WCHAR KeyboardEventW
[] = {'K','e','y','b','o','a','r','d','E','v','e','n','t',0};
96 static const WCHAR MouseEventW
[] = {'M','o','u','s','e','E','v','e','n','t',0};
109 static const WCHAR
*event_types
[] = {
127 #define EVENT_DEFAULTLISTENER 0x0001
128 #define EVENT_BUBBLES 0x0002
129 #define EVENT_BIND_TO_BODY 0x0008
130 #define EVENT_CANCELABLE 0x0010
131 #define EVENT_HASDEFAULTHANDLERS 0x0020
132 #define EVENT_FIXME 0x0040
134 static const event_info_t event_info
[] = {
135 {abortW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONABORT
,
137 {beforeactivateW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREACTIVATE
,
138 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
139 {beforeunloadW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREUNLOAD
,
140 EVENT_DEFAULTLISTENER
| EVENT_CANCELABLE
},
141 {blurW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONBLUR
,
142 EVENT_DEFAULTLISTENER
},
143 {changeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONCHANGE
,
144 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
},
145 {clickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCLICK
,
146 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
147 {contextmenuW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCONTEXTMENU
,
148 EVENT_BUBBLES
| EVENT_CANCELABLE
},
149 {dataavailableW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONDATAAVAILABLE
,
150 EVENT_FIXME
| EVENT_BUBBLES
},
151 {dblclickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONDBLCLICK
,
152 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
153 {dragW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAG
,
154 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
155 {dragstartW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAGSTART
,
156 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
157 {errorW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONERROR
,
159 {focusW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUS
,
160 EVENT_DEFAULTLISTENER
},
161 {focusinW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSIN
,
163 {focusoutW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSOUT
,
165 {helpW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONHELP
,
166 EVENT_BUBBLES
| EVENT_CANCELABLE
},
167 {keydownW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYDOWN
,
168 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
169 {keypressW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYPRESS
,
170 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
171 {keyupW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYUP
,
172 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
173 {loadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONLOAD
,
175 {messageW
, EVENT_TYPE_MESSAGE
, DISPID_EVMETH_ONMESSAGE
,
177 {mousedownW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEDOWN
,
178 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
179 {mousemoveW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEMOVE
,
180 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
181 {mouseoutW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOUT
,
182 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
183 {mouseoverW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOVER
,
184 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
185 {mouseupW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEUP
,
186 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
187 {mousewheelW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEWHEEL
,
189 {pasteW
, EVENT_TYPE_CLIPBOARD
, DISPID_EVMETH_ONPASTE
,
190 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
191 {readystatechangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONREADYSTATECHANGE
,
193 {resizeW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONRESIZE
,
194 EVENT_DEFAULTLISTENER
},
195 {scrollW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONSCROLL
,
196 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
/* FIXME: not for elements */},
197 {selectionchangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTIONCHANGE
,
199 {selectstartW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTSTART
,
200 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
201 {submitW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSUBMIT
,
202 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
203 {unloadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONUNLOAD
,
207 static BOOL
use_event_quirks(EventTarget
*);
209 static eventid_t
str_to_eid(const WCHAR
*str
)
213 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
214 if(!strcmpW(event_info
[i
].name
, str
))
218 ERR("unknown type %s\n", debugstr_w(str
));
222 static eventid_t
attr_to_eid(const WCHAR
*str
)
226 if((str
[0] != 'o' && str
[0] != 'O') || (str
[1] != 'n' && str
[1] != 'N'))
229 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
230 if(!strcmpW(event_info
[i
].name
, str
+2))
237 static listener_container_t
*get_listener_container(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
)
239 const event_target_vtbl_t
*vtbl
;
240 listener_container_t
*container
;
241 struct wine_rb_entry
*entry
;
243 entry
= wine_rb_get(&event_target
->handler_map
, (const void*)eid
);
245 return WINE_RB_ENTRY_VALUE(entry
, listener_container_t
, entry
);
249 if(event_info
[eid
].flags
& EVENT_FIXME
)
250 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
252 container
= heap_alloc(sizeof(*container
));
256 container
->event_id
= eid
;
257 list_init(&container
->listeners
);
258 vtbl
= dispex_get_vtbl(&event_target
->dispex
);
260 vtbl
->bind_event(&event_target
->dispex
, eid
);
262 FIXME("Unsupported event binding on target %p\n", event_target
);
264 wine_rb_put(&event_target
->handler_map
, (const void*)eid
, &container
->entry
);
268 static void remove_event_listener(EventTarget
*event_target
, eventid_t eid
, listener_type_t type
, IDispatch
*function
)
270 listener_container_t
*container
;
271 event_listener_t
*listener
;
273 container
= get_listener_container(event_target
, eid
, FALSE
);
277 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
278 if(listener
->function
== function
&& listener
->type
== type
) {
279 IDispatch_Release(listener
->function
);
280 list_remove(&listener
->entry
);
289 IHTMLEventObj IHTMLEventObj_iface
;
293 const event_info_t
*type
;
295 VARIANT return_value
;
298 static inline HTMLEventObj
*impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
300 return CONTAINING_RECORD(iface
, HTMLEventObj
, IHTMLEventObj_iface
);
303 static HRESULT WINAPI
HTMLEventObj_QueryInterface(IHTMLEventObj
*iface
, REFIID riid
, void **ppv
)
305 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
307 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
309 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
310 *ppv
= &This
->IHTMLEventObj_iface
;
311 }else if(IsEqualGUID(&IID_IHTMLEventObj
, riid
)) {
312 *ppv
= &This
->IHTMLEventObj_iface
;
313 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
314 return *ppv
? S_OK
: E_NOINTERFACE
;
317 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
318 return E_NOINTERFACE
;
321 IUnknown_AddRef((IUnknown
*)*ppv
);
325 static ULONG WINAPI
HTMLEventObj_AddRef(IHTMLEventObj
*iface
)
327 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
328 LONG ref
= InterlockedIncrement(&This
->ref
);
330 TRACE("(%p) ref=%d\n", This
, ref
);
335 static ULONG WINAPI
HTMLEventObj_Release(IHTMLEventObj
*iface
)
337 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
338 LONG ref
= InterlockedDecrement(&This
->ref
);
340 TRACE("(%p) ref=%d\n", This
, ref
);
344 IDOMEvent_Release(&This
->event
->IDOMEvent_iface
);
345 release_dispex(&This
->dispex
);
352 static HRESULT WINAPI
HTMLEventObj_GetTypeInfoCount(IHTMLEventObj
*iface
, UINT
*pctinfo
)
354 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
355 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
358 static HRESULT WINAPI
HTMLEventObj_GetTypeInfo(IHTMLEventObj
*iface
, UINT iTInfo
,
359 LCID lcid
, ITypeInfo
**ppTInfo
)
361 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
362 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
365 static HRESULT WINAPI
HTMLEventObj_GetIDsOfNames(IHTMLEventObj
*iface
, REFIID riid
,
366 LPOLESTR
*rgszNames
, UINT cNames
,
367 LCID lcid
, DISPID
*rgDispId
)
369 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
370 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
374 static HRESULT WINAPI
HTMLEventObj_Invoke(IHTMLEventObj
*iface
, DISPID dispIdMember
,
375 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
376 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
378 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
379 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
380 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
383 static HRESULT WINAPI
HTMLEventObj_get_srcElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
385 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
387 TRACE("(%p)->(%p)\n", This
, p
);
390 if(This
->event
&& This
->event
->target
)
391 IDispatchEx_QueryInterface(&This
->event
->target
->dispex
.IDispatchEx_iface
, &IID_IHTMLElement
, (void**)p
);
395 static HRESULT WINAPI
HTMLEventObj_get_altKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
397 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
398 cpp_bool ret
= FALSE
;
400 TRACE("(%p)->(%p)\n", This
, p
);
403 nsIDOMKeyEvent
*key_event
;
406 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
407 if(NS_SUCCEEDED(nsres
)) {
408 nsIDOMKeyEvent_GetAltKey(key_event
, &ret
);
409 nsIDOMKeyEvent_Release(key_event
);
411 nsIDOMMouseEvent
*mouse_event
;
413 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
414 if(NS_SUCCEEDED(nsres
)) {
415 nsIDOMMouseEvent_GetAltKey(mouse_event
, &ret
);
416 nsIDOMMouseEvent_Release(mouse_event
);
421 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
425 static HRESULT WINAPI
HTMLEventObj_get_ctrlKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
427 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
428 cpp_bool ret
= FALSE
;
430 TRACE("(%p)->(%p)\n", This
, p
);
433 nsIDOMKeyEvent
*key_event
;
436 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
437 if(NS_SUCCEEDED(nsres
)) {
438 nsIDOMKeyEvent_GetCtrlKey(key_event
, &ret
);
439 nsIDOMKeyEvent_Release(key_event
);
441 nsIDOMMouseEvent
*mouse_event
;
443 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
444 if(NS_SUCCEEDED(nsres
)) {
445 nsIDOMMouseEvent_GetCtrlKey(mouse_event
, &ret
);
446 nsIDOMMouseEvent_Release(mouse_event
);
451 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
455 static HRESULT WINAPI
HTMLEventObj_get_shiftKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
457 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
458 cpp_bool ret
= FALSE
;
460 TRACE("(%p)->(%p)\n", This
, p
);
463 nsIDOMKeyEvent
*key_event
;
466 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
467 if(NS_SUCCEEDED(nsres
)) {
468 nsIDOMKeyEvent_GetShiftKey(key_event
, &ret
);
469 nsIDOMKeyEvent_Release(key_event
);
471 nsIDOMMouseEvent
*mouse_event
;
473 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
474 if(NS_SUCCEEDED(nsres
)) {
475 nsIDOMMouseEvent_GetShiftKey(mouse_event
, &ret
);
476 nsIDOMMouseEvent_Release(mouse_event
);
481 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
485 static HRESULT WINAPI
HTMLEventObj_put_returnValue(IHTMLEventObj
*iface
, VARIANT v
)
487 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
489 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&v
));
491 if(V_VT(&v
) != VT_BOOL
) {
492 FIXME("unsupported value %s\n", debugstr_variant(&v
));
493 return DISP_E_BADVARTYPE
;
496 This
->return_value
= v
;
497 if(!V_BOOL(&v
) && This
->event
)
498 IDOMEvent_preventDefault(&This
->event
->IDOMEvent_iface
);
502 static HRESULT WINAPI
HTMLEventObj_get_returnValue(IHTMLEventObj
*iface
, VARIANT
*p
)
504 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
506 TRACE("(%p)->(%p)\n", This
, p
);
509 return VariantCopy(p
, &This
->return_value
);
512 static HRESULT WINAPI
HTMLEventObj_put_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL v
)
514 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
516 TRACE("(%p)->(%x)\n", This
, v
);
519 IDOMEvent_stopPropagation(&This
->event
->IDOMEvent_iface
);
523 static HRESULT WINAPI
HTMLEventObj_get_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
525 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
527 TRACE("(%p)->(%p)\n", This
, p
);
529 *p
= This
->event
&& This
->event
->stop_propagation
? VARIANT_TRUE
: VARIANT_FALSE
;
533 static HRESULT WINAPI
HTMLEventObj_get_fromElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
535 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
537 FIXME("(%p)->(%p)\n", This
, p
);
543 static HRESULT WINAPI
HTMLEventObj_get_toElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
545 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
547 FIXME("(%p)->(%p)\n", This
, p
);
553 static HRESULT WINAPI
HTMLEventObj_put_keyCode(IHTMLEventObj
*iface
, LONG v
)
555 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
556 FIXME("(%p)->(%d)\n", This
, v
);
560 static HRESULT WINAPI
HTMLEventObj_get_keyCode(IHTMLEventObj
*iface
, LONG
*p
)
562 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
565 TRACE("(%p)->(%p)\n", This
, p
);
568 nsIDOMKeyEvent
*key_event
;
571 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
572 if(NS_SUCCEEDED(nsres
)) {
573 nsIDOMKeyEvent_GetKeyCode(key_event
, &key_code
);
574 nsIDOMKeyEvent_Release(key_event
);
582 static HRESULT WINAPI
HTMLEventObj_get_button(IHTMLEventObj
*iface
, LONG
*p
)
584 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
587 TRACE("(%p)->(%p)\n", This
, p
);
590 nsIDOMMouseEvent
*mouse_event
;
593 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
594 if(NS_SUCCEEDED(nsres
)) {
595 nsIDOMMouseEvent_GetButton(mouse_event
, &button
);
596 nsIDOMMouseEvent_Release(mouse_event
);
604 static HRESULT WINAPI
HTMLEventObj_get_type(IHTMLEventObj
*iface
, BSTR
*p
)
606 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
608 TRACE("(%p)->(%p)\n", This
, p
);
615 *p
= SysAllocString(This
->type
->name
);
616 return *p
? S_OK
: E_OUTOFMEMORY
;
619 static HRESULT WINAPI
HTMLEventObj_get_qualifier(IHTMLEventObj
*iface
, BSTR
*p
)
621 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
623 FIXME("(%p)->(%p)\n", This
, p
);
629 static HRESULT WINAPI
HTMLEventObj_get_reason(IHTMLEventObj
*iface
, LONG
*p
)
631 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
633 FIXME("(%p)->(%p)\n", This
, p
);
639 static HRESULT WINAPI
HTMLEventObj_get_x(IHTMLEventObj
*iface
, LONG
*p
)
641 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
644 TRACE("(%p)->(%p)\n", This
, p
);
647 nsIDOMUIEvent
*ui_event
;
650 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMUIEvent
, (void**)&ui_event
);
651 if(NS_SUCCEEDED(nsres
)) {
652 /* NOTE: pageX is not exactly right here. */
653 nsres
= nsIDOMUIEvent_GetPageX(ui_event
, &x
);
654 assert(nsres
== NS_OK
);
655 nsIDOMUIEvent_Release(ui_event
);
663 static HRESULT WINAPI
HTMLEventObj_get_y(IHTMLEventObj
*iface
, LONG
*p
)
665 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
668 TRACE("(%p)->(%p)\n", This
, p
);
671 nsIDOMUIEvent
*ui_event
;
674 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMUIEvent
, (void**)&ui_event
);
675 if(NS_SUCCEEDED(nsres
)) {
676 /* NOTE: pageY is not exactly right here. */
677 nsres
= nsIDOMUIEvent_GetPageY(ui_event
, &y
);
678 assert(nsres
== NS_OK
);
679 nsIDOMUIEvent_Release(ui_event
);
687 static HRESULT WINAPI
HTMLEventObj_get_clientX(IHTMLEventObj
*iface
, LONG
*p
)
689 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
692 TRACE("(%p)->(%p)\n", This
, p
);
695 nsIDOMMouseEvent
*mouse_event
;
698 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
699 if(NS_SUCCEEDED(nsres
)) {
700 nsIDOMMouseEvent_GetClientX(mouse_event
, &x
);
701 nsIDOMMouseEvent_Release(mouse_event
);
709 static HRESULT WINAPI
HTMLEventObj_get_clientY(IHTMLEventObj
*iface
, LONG
*p
)
711 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
714 TRACE("(%p)->(%p)\n", This
, p
);
717 nsIDOMMouseEvent
*mouse_event
;
720 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
721 if(NS_SUCCEEDED(nsres
)) {
722 nsIDOMMouseEvent_GetClientY(mouse_event
, &y
);
723 nsIDOMMouseEvent_Release(mouse_event
);
731 static HRESULT WINAPI
HTMLEventObj_get_offsetX(IHTMLEventObj
*iface
, LONG
*p
)
733 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
735 FIXME("(%p)->(%p)\n", This
, p
);
741 static HRESULT WINAPI
HTMLEventObj_get_offsetY(IHTMLEventObj
*iface
, LONG
*p
)
743 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
745 FIXME("(%p)->(%p)\n", This
, p
);
751 static HRESULT WINAPI
HTMLEventObj_get_screenX(IHTMLEventObj
*iface
, LONG
*p
)
753 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
756 TRACE("(%p)->(%p)\n", This
, p
);
759 nsIDOMMouseEvent
*mouse_event
;
762 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
763 if(NS_SUCCEEDED(nsres
)) {
764 nsIDOMMouseEvent_GetScreenX(mouse_event
, &x
);
765 nsIDOMMouseEvent_Release(mouse_event
);
773 static HRESULT WINAPI
HTMLEventObj_get_screenY(IHTMLEventObj
*iface
, LONG
*p
)
775 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
778 TRACE("(%p)->(%p)\n", This
, p
);
781 nsIDOMMouseEvent
*mouse_event
;
784 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
785 if(NS_SUCCEEDED(nsres
)) {
786 nsIDOMMouseEvent_GetScreenY(mouse_event
, &y
);
787 nsIDOMMouseEvent_Release(mouse_event
);
795 static HRESULT WINAPI
HTMLEventObj_get_srcFilter(IHTMLEventObj
*iface
, IDispatch
**p
)
797 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
799 FIXME("(%p)->(%p)\n", This
, p
);
805 static const IHTMLEventObjVtbl HTMLEventObjVtbl
= {
806 HTMLEventObj_QueryInterface
,
808 HTMLEventObj_Release
,
809 HTMLEventObj_GetTypeInfoCount
,
810 HTMLEventObj_GetTypeInfo
,
811 HTMLEventObj_GetIDsOfNames
,
813 HTMLEventObj_get_srcElement
,
814 HTMLEventObj_get_altKey
,
815 HTMLEventObj_get_ctrlKey
,
816 HTMLEventObj_get_shiftKey
,
817 HTMLEventObj_put_returnValue
,
818 HTMLEventObj_get_returnValue
,
819 HTMLEventObj_put_cancelBubble
,
820 HTMLEventObj_get_cancelBubble
,
821 HTMLEventObj_get_fromElement
,
822 HTMLEventObj_get_toElement
,
823 HTMLEventObj_put_keyCode
,
824 HTMLEventObj_get_keyCode
,
825 HTMLEventObj_get_button
,
826 HTMLEventObj_get_type
,
827 HTMLEventObj_get_qualifier
,
828 HTMLEventObj_get_reason
,
831 HTMLEventObj_get_clientX
,
832 HTMLEventObj_get_clientY
,
833 HTMLEventObj_get_offsetX
,
834 HTMLEventObj_get_offsetY
,
835 HTMLEventObj_get_screenX
,
836 HTMLEventObj_get_screenY
,
837 HTMLEventObj_get_srcFilter
840 static inline HTMLEventObj
*unsafe_impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
842 return iface
->lpVtbl
== &HTMLEventObjVtbl
? impl_from_IHTMLEventObj(iface
) : NULL
;
845 static const tid_t HTMLEventObj_iface_tids
[] = {
850 static dispex_static_data_t HTMLEventObj_dispex
= {
853 HTMLEventObj_iface_tids
856 static HTMLEventObj
*alloc_event_obj(DOMEvent
*event
)
858 HTMLEventObj
*event_obj
;
860 event_obj
= heap_alloc_zero(sizeof(*event_obj
));
864 event_obj
->IHTMLEventObj_iface
.lpVtbl
= &HTMLEventObjVtbl
;
866 event_obj
->event
= event
;
868 IDOMEvent_AddRef(&event
->IDOMEvent_iface
);
870 init_dispex(&event_obj
->dispex
, (IUnknown
*)&event_obj
->IHTMLEventObj_iface
, &HTMLEventObj_dispex
);
874 HRESULT
create_event_obj(IHTMLEventObj
**ret
)
876 HTMLEventObj
*event_obj
;
878 event_obj
= alloc_event_obj(NULL
);
880 return E_OUTOFMEMORY
;
882 *ret
= &event_obj
->IHTMLEventObj_iface
;
886 static inline DOMEvent
*impl_from_IDOMEvent(IDOMEvent
*iface
)
888 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMEvent_iface
);
891 static HRESULT WINAPI
DOMEvent_QueryInterface(IDOMEvent
*iface
, REFIID riid
, void **ppv
)
893 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
895 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
897 if(IsEqualGUID(&IID_IUnknown
, riid
))
898 *ppv
= &This
->IDOMEvent_iface
;
899 else if(IsEqualGUID(&IID_IDOMEvent
, riid
))
900 *ppv
= &This
->IDOMEvent_iface
;
901 else if(dispex_query_interface(&This
->dispex
, riid
, ppv
))
902 return *ppv
? S_OK
: E_NOINTERFACE
;
905 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
906 return E_NOINTERFACE
;
909 IUnknown_AddRef((IUnknown
*)*ppv
);
913 static ULONG WINAPI
DOMEvent_AddRef(IDOMEvent
*iface
)
915 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
916 LONG ref
= InterlockedIncrement(&This
->ref
);
918 TRACE("(%p) ref=%u\n", This
, ref
);
923 static ULONG WINAPI
DOMEvent_Release(IDOMEvent
*iface
)
925 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
926 LONG ref
= InterlockedDecrement(&This
->ref
);
928 TRACE("(%p) ref=%u\n", This
, ref
);
932 IDispatchEx_Release(&This
->target
->dispex
.IDispatchEx_iface
);
933 nsIDOMEvent_Release(This
->nsevent
);
934 release_dispex(&This
->dispex
);
941 static HRESULT WINAPI
DOMEvent_GetTypeInfoCount(IDOMEvent
*iface
, UINT
*pctinfo
)
943 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
944 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
947 static HRESULT WINAPI
DOMEvent_GetTypeInfo(IDOMEvent
*iface
, UINT iTInfo
,
948 LCID lcid
, ITypeInfo
**ppTInfo
)
950 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
951 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
954 static HRESULT WINAPI
DOMEvent_GetIDsOfNames(IDOMEvent
*iface
, REFIID riid
,
955 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
957 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
958 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
962 static HRESULT WINAPI
DOMEvent_Invoke(IDOMEvent
*iface
, DISPID dispIdMember
,
963 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
964 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
966 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
967 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
968 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
971 static HRESULT WINAPI
DOMEvent_get_bubbles(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
973 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
974 FIXME("(%p)->(%p)\n", This
, p
);
978 static HRESULT WINAPI
DOMEvent_get_cancelable(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
980 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
981 FIXME("(%p)->(%p)\n", This
, p
);
985 static HRESULT WINAPI
DOMEvent_get_currentTarget(IDOMEvent
*iface
, IEventTarget
**p
)
987 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
988 FIXME("(%p)->(%p)\n", This
, p
);
992 static HRESULT WINAPI
DOMEvent_get_defaultPrevented(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
994 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
995 FIXME("(%p)->(%p)\n", This
, p
);
999 static HRESULT WINAPI
DOMEvent_get_eventPhase(IDOMEvent
*iface
, USHORT
*p
)
1001 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1003 TRACE("(%p)->(%p)\n", This
, p
);
1009 static HRESULT WINAPI
DOMEvent_get_target(IDOMEvent
*iface
, IEventTarget
**p
)
1011 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1012 FIXME("(%p)->(%p)\n", This
, p
);
1016 static HRESULT WINAPI
DOMEvent_get_timeStamp(IDOMEvent
*iface
, ULONGLONG
*p
)
1018 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1019 FIXME("(%p)->(%p)\n", This
, p
);
1023 static HRESULT WINAPI
DOMEvent_get_type(IDOMEvent
*iface
, BSTR
*p
)
1025 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1026 FIXME("(%p)->(%p)\n", This
, p
);
1030 static HRESULT WINAPI
DOMEvent_initEvent(IDOMEvent
*iface
, BSTR type
, VARIANT_BOOL can_bubble
, VARIANT_BOOL cancelable
)
1032 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1033 FIXME("(%p)->()\n", This
);
1037 static HRESULT WINAPI
DOMEvent_preventDefault(IDOMEvent
*iface
)
1039 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1041 TRACE("(%p)\n", This
);
1043 This
->prevent_default
= TRUE
;
1044 nsIDOMEvent_PreventDefault(This
->nsevent
);
1048 static HRESULT WINAPI
DOMEvent_stopPropagation(IDOMEvent
*iface
)
1050 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1052 TRACE("(%p)\n", This
);
1054 This
->stop_propagation
= TRUE
;
1055 nsIDOMEvent_StopPropagation(This
->nsevent
);
1056 IDOMEvent_preventDefault(&This
->IDOMEvent_iface
);
1060 static HRESULT WINAPI
DOMEvent_stopImmediatePropagation(IDOMEvent
*iface
)
1062 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1063 FIXME("(%p)\n", This
);
1067 static HRESULT WINAPI
DOMEvent_get_isTrusted(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1069 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1070 FIXME("(%p)->(%p)\n", This
, p
);
1074 static HRESULT WINAPI
DOMEvent_put_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL v
)
1076 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1077 FIXME("(%p)->(%x)\n", This
, v
);
1081 static HRESULT WINAPI
DOMEvent_get_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1083 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1084 FIXME("(%p)->(%p)\n", This
, p
);
1088 static HRESULT WINAPI
DOMEvent_get_srcElement(IDOMEvent
*iface
, IHTMLElement
**p
)
1090 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1091 FIXME("(%p)->(%p)\n", This
, p
);
1095 static const IDOMEventVtbl DOMEventVtbl
= {
1096 DOMEvent_QueryInterface
,
1099 DOMEvent_GetTypeInfoCount
,
1100 DOMEvent_GetTypeInfo
,
1101 DOMEvent_GetIDsOfNames
,
1103 DOMEvent_get_bubbles
,
1104 DOMEvent_get_cancelable
,
1105 DOMEvent_get_currentTarget
,
1106 DOMEvent_get_defaultPrevented
,
1107 DOMEvent_get_eventPhase
,
1108 DOMEvent_get_target
,
1109 DOMEvent_get_timeStamp
,
1112 DOMEvent_preventDefault
,
1113 DOMEvent_stopPropagation
,
1114 DOMEvent_stopImmediatePropagation
,
1115 DOMEvent_get_isTrusted
,
1116 DOMEvent_put_cancelBubble
,
1117 DOMEvent_get_cancelBubble
,
1118 DOMEvent_get_srcElement
1121 static const tid_t DOMEvent_iface_tids
[] = {
1126 static dispex_static_data_t DOMEvent_dispex
= {
1132 static DOMEvent
*alloc_event(nsIDOMEvent
*nsevent
)
1136 event
= heap_alloc_zero(sizeof(*event
));
1140 init_dispex(&event
->dispex
, (IUnknown
*)&event
->IDOMEvent_iface
, &DOMEvent_dispex
);
1141 event
->IDOMEvent_iface
.lpVtbl
= &DOMEventVtbl
;
1143 nsIDOMEvent_AddRef(event
->nsevent
= nsevent
);
1144 event
->event_id
= EVENTID_LAST
;
1148 HRESULT
create_event_from_nsevent(nsIDOMEvent
*nsevent
, DOMEvent
**ret_event
)
1154 event
= alloc_event(nsevent
);
1156 return E_OUTOFMEMORY
;
1158 nsAString_Init(&nsstr
, NULL
);
1159 nsres
= nsIDOMEvent_GetType(event
->nsevent
, &nsstr
);
1160 if(NS_SUCCEEDED(nsres
)) {
1162 nsAString_GetData(&nsstr
, &type
);
1163 event
->event_id
= str_to_eid(type
);
1164 if(event
->event_id
== EVENTID_LAST
)
1165 FIXME("unknown event type %s\n", debugstr_w(type
));
1167 ERR("GetType failed: %08x\n", nsres
);
1169 nsAString_Finish(&nsstr
);
1175 HRESULT
create_document_event_str(HTMLDocumentNode
*doc
, const WCHAR
*type
, IDOMEvent
**ret_event
)
1177 nsIDOMEvent
*nsevent
;
1182 nsAString_InitDepend(&nsstr
, type
);
1183 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
1184 nsAString_Finish(&nsstr
);
1185 if(NS_FAILED(nsres
)) {
1186 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(type
), nsres
);
1190 event
= alloc_event(nsevent
);
1191 nsIDOMEvent_Release(nsevent
);
1193 return E_OUTOFMEMORY
;
1195 *ret_event
= &event
->IDOMEvent_iface
;
1199 HRESULT
create_document_event(HTMLDocumentNode
*doc
, eventid_t event_id
, DOMEvent
**ret_event
)
1201 nsIDOMEvent
*nsevent
;
1206 nsAString_InitDepend(&nsstr
, event_types
[event_info
[event_id
].type
]);
1207 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
1208 nsAString_Finish(&nsstr
);
1209 if(NS_FAILED(nsres
)) {
1210 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(event_types
[event_info
[event_id
].type
]), nsres
);
1214 event
= alloc_event(nsevent
);
1216 return E_OUTOFMEMORY
;
1218 event
->event_id
= event_id
;
1223 static HRESULT
call_disp_func(IDispatch
*disp
, DISPPARAMS
*dp
, VARIANT
*retv
)
1225 IDispatchEx
*dispex
;
1229 memset(&ei
, 0, sizeof(ei
));
1231 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1232 if(SUCCEEDED(hres
)) {
1233 hres
= IDispatchEx_InvokeEx(dispex
, 0, GetUserDefaultLCID(), DISPATCH_METHOD
, dp
, retv
, &ei
, NULL
);
1234 IDispatchEx_Release(dispex
);
1236 TRACE("Could not get IDispatchEx interface: %08x\n", hres
);
1237 hres
= IDispatch_Invoke(disp
, 0, &IID_NULL
, GetUserDefaultLCID(), DISPATCH_METHOD
,
1238 dp
, retv
, &ei
, NULL
);
1244 static HRESULT
call_cp_func(IDispatch
*disp
, DISPID dispid
, IHTMLEventObj
*event_obj
, VARIANT
*retv
)
1246 DISPPARAMS dp
= {NULL
,NULL
,0,0};
1252 V_VT(&event_arg
) = VT_DISPATCH
;
1253 V_DISPATCH(&event_arg
) = (IDispatch
*)event_obj
;
1254 dp
.rgvarg
= &event_arg
;
1258 memset(&ei
, 0, sizeof(ei
));
1259 return IDispatch_Invoke(disp
, dispid
, &IID_NULL
, 0, DISPATCH_METHOD
, &dp
, retv
, &ei
, &argerr
);
1262 static BOOL
is_cp_event(cp_static_data_t
*data
, DISPID dispid
)
1271 hres
= get_dispids(data
->tid
, &data
->id_cnt
, &data
->ids
);
1277 max
= data
->id_cnt
-1;
1280 if(data
->ids
[i
] == dispid
)
1283 if(data
->ids
[i
] < dispid
)
1292 static void call_event_handlers(EventTarget
*event_target
, DOMEvent
*event
)
1294 const eventid_t eid
= event
->event_id
;
1295 const listener_container_t
*container
= get_listener_container(event_target
, eid
, FALSE
);
1296 const BOOL cancelable
= event_info
[eid
].flags
& EVENT_CANCELABLE
;
1297 const BOOL use_quirks
= use_event_quirks(event_target
);
1298 event_listener_t
*listener
, listeners_buf
[8], *listeners
= listeners_buf
;
1299 unsigned listeners_cnt
, listeners_size
;
1300 ConnectionPointContainer
*cp_container
= NULL
;
1301 const event_target_vtbl_t
*vtbl
;
1305 if(use_quirks
&& container
&& !list_empty(&container
->listeners
)
1306 && event
->phase
!= DEP_CAPTURING_PHASE
) {
1307 listener
= LIST_ENTRY(list_tail(&container
->listeners
), event_listener_t
, entry
);
1308 if(listener
&& listener
->function
&& listener
->type
== LISTENER_TYPE_ONEVENT
) {
1309 DISPID named_arg
= DISPID_THIS
;
1311 DISPPARAMS dp
= {&arg
, &named_arg
, 1, 1};
1313 V_VT(&arg
) = VT_DISPATCH
;
1314 V_DISPATCH(&arg
) = (IDispatch
*)&event_target
->dispex
.IDispatchEx_iface
;
1315 V_VT(&v
) = VT_EMPTY
;
1317 TRACE("%s >>>\n", debugstr_w(event_info
[eid
].name
));
1318 hres
= call_disp_func(listener
->function
, &dp
, &v
);
1320 TRACE("%s <<< %s\n", debugstr_w(event_info
[eid
].name
), debugstr_variant(&v
));
1323 if(V_VT(&v
) == VT_BOOL
) {
1325 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1326 }else if(V_VT(&v
) != VT_EMPTY
) {
1327 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1332 WARN("%s <<< %08x\n", debugstr_w(event_info
[eid
].name
), hres
);
1338 listeners_size
= sizeof(listeners_buf
)/sizeof(*listeners_buf
);
1341 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
1342 if(!listener
->function
)
1344 switch(listener
->type
) {
1345 case LISTENER_TYPE_ONEVENT
:
1346 if(use_quirks
|| event
->phase
== DEP_CAPTURING_PHASE
)
1349 case LISTENER_TYPE_CAPTURE
:
1350 if(event
->phase
== DEP_BUBBLING_PHASE
|| event
->in_fire_event
)
1353 case LISTENER_TYPE_BUBBLE
:
1354 if(event
->in_fire_event
)
1357 case LISTENER_TYPE_ATTACHED
:
1358 if(event
->phase
== DEP_CAPTURING_PHASE
)
1363 if(listeners_cnt
== listeners_size
) {
1364 event_listener_t
*new_listeners
;
1365 if(listeners
== listeners_buf
) {
1366 new_listeners
= heap_alloc(listeners_size
* 2 * sizeof(*new_listeners
));
1369 memcpy(new_listeners
, listeners
, listeners_cnt
* sizeof(*listeners
));
1371 new_listeners
= heap_realloc(listeners
, listeners_size
* 2 * sizeof(*new_listeners
));
1373 listeners
= new_listeners
;
1374 listeners_size
*= 2;
1377 listeners
[listeners_cnt
].type
= listener
->type
;
1378 IDispatch_AddRef(listeners
[listeners_cnt
].function
= listener
->function
);
1383 for(listener
= listeners
; listener
< listeners
+ listeners_cnt
; listener
++) {
1384 if(listener
->type
!= LISTENER_TYPE_ATTACHED
) {
1385 DISPID named_arg
= DISPID_THIS
;
1387 DISPPARAMS dp
= {args
, &named_arg
, 2, 1};
1389 V_VT(args
) = VT_DISPATCH
;
1390 V_DISPATCH(args
) = (IDispatch
*)&event_target
->dispex
.IDispatchEx_iface
;
1391 V_VT(args
+1) = VT_DISPATCH
;
1392 V_DISPATCH(args
+1) = event
->in_fire_event
1393 ? (IDispatch
*)event
->event_obj
: (IDispatch
*)&event
->IDOMEvent_iface
;
1394 V_VT(&v
) = VT_EMPTY
;
1396 TRACE("%s >>>\n", debugstr_w(event_info
[event
->event_id
].name
));
1397 hres
= call_disp_func(listener
->function
, &dp
, &v
);
1399 TRACE("%s <<< %s\n", debugstr_w(event_info
[event
->event_id
].name
),
1400 debugstr_variant(&v
));
1403 if(V_VT(&v
) == VT_BOOL
) {
1405 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1406 }else if(V_VT(&v
) != VT_EMPTY
) {
1407 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1412 WARN("%s <<< %08x\n", debugstr_w(event_info
[event
->event_id
].name
), hres
);
1416 DISPPARAMS dp
= {&arg
, NULL
, 1, 0};
1418 V_VT(&arg
) = VT_DISPATCH
;
1419 V_DISPATCH(&arg
) = (IDispatch
*)event
->event_obj
;
1420 V_VT(&v
) = VT_EMPTY
;
1422 TRACE("%s attached >>>\n", debugstr_w(event_info
[eid
].name
));
1423 hres
= call_disp_func(listener
->function
, &dp
, &v
);
1425 TRACE("%s attached <<<\n", debugstr_w(event_info
[eid
].name
));
1428 if(V_VT(&v
) == VT_BOOL
) {
1430 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1431 }else if(V_VT(&v
) != VT_EMPTY
) {
1432 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1437 WARN("%s attached <<< %08x\n", debugstr_w(event_info
[eid
].name
), hres
);
1442 for(listener
= listeners
; listener
< listeners
+ listeners_cnt
; listener
++)
1443 IDispatch_Release(listener
->function
);
1444 if(listeners
!= listeners_buf
)
1445 heap_free(listeners
);
1446 if(event
->phase
== DEP_CAPTURING_PHASE
)
1449 if((vtbl
= dispex_get_vtbl(&event_target
->dispex
)) && vtbl
->get_cp_container
)
1450 cp_container
= vtbl
->get_cp_container(&event_target
->dispex
);
1452 if(cp_container
->cps
) {
1453 ConnectionPoint
*cp
;
1456 for(j
=0; cp_container
->cp_entries
[j
].riid
; j
++) {
1457 cp
= cp_container
->cps
+ j
;
1458 if(!cp
->sinks_size
|| !is_cp_event(cp
->data
, event_info
[eid
].dispid
))
1461 for(i
=0; i
< cp
->sinks_size
; i
++) {
1462 if(!cp
->sinks
[i
].disp
)
1465 V_VT(&v
) = VT_EMPTY
;
1467 TRACE("cp %s [%u] >>>\n", debugstr_w(event_info
[eid
].name
), i
);
1468 hres
= call_cp_func(cp
->sinks
[i
].disp
, event_info
[eid
].dispid
,
1469 cp
->data
->pass_event_arg
? event
->event_obj
: NULL
, &v
);
1471 TRACE("cp %s [%u] <<<\n", debugstr_w(event_info
[eid
].name
), i
);
1474 if(V_VT(&v
) == VT_BOOL
) {
1476 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1477 }else if(V_VT(&v
) != VT_EMPTY
) {
1478 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1483 WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info
[eid
].name
), i
, hres
);
1488 IConnectionPointContainer_Release(&cp_container
->IConnectionPointContainer_iface
);
1492 void dispatch_event(EventTarget
*event_target
, DOMEvent
*event
)
1494 EventTarget
*target_chain_buf
[8], **target_chain
= target_chain_buf
;
1495 unsigned chain_cnt
, chain_buf_size
, i
;
1496 const event_target_vtbl_t
*vtbl
, *target_vtbl
;
1497 HTMLEventObj
*event_obj_ref
= NULL
;
1498 IHTMLEventObj
*prev_event
= NULL
;
1503 if(event
->event_id
== EVENTID_LAST
) {
1504 FIXME("Unsupported on unknown events\n");
1508 TRACE("(%p) %s\n", event_target
, debugstr_w(event_info
[event
->event_id
].name
));
1510 event_flags
= event_info
[event
->event_id
].flags
;
1511 iter
= event_target
;
1512 IDispatchEx_AddRef(&event_target
->dispex
.IDispatchEx_iface
);
1515 chain_buf_size
= sizeof(target_chain_buf
)/sizeof(*target_chain_buf
);
1518 if(chain_cnt
== chain_buf_size
) {
1519 EventTarget
**new_chain
;
1520 if(target_chain
== target_chain_buf
) {
1521 new_chain
= heap_alloc(chain_buf_size
* 2 * sizeof(*new_chain
));
1524 memcpy(new_chain
, target_chain
, chain_buf_size
* sizeof(*new_chain
));
1526 new_chain
= heap_realloc(target_chain
, chain_buf_size
* 2 * sizeof(*new_chain
));
1530 chain_buf_size
*= 2;
1531 target_chain
= new_chain
;
1534 target_chain
[chain_cnt
++] = iter
;
1536 if(!(vtbl
= dispex_get_vtbl(&iter
->dispex
)) || !vtbl
->get_parent_event_target
)
1538 iter
= vtbl
->get_parent_event_target(&iter
->dispex
);
1541 if(!event
->event_obj
&& !event
->no_event_obj
) {
1542 event_obj_ref
= alloc_event_obj(event
);
1544 event_obj_ref
->type
= event_info
+ event
->event_id
;
1545 event
->event_obj
= &event_obj_ref
->IHTMLEventObj_iface
;
1549 target_vtbl
= dispex_get_vtbl(&event_target
->dispex
);
1550 if(target_vtbl
&& target_vtbl
->set_current_event
)
1551 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, event
->event_obj
);
1553 event
->target
= event_target
;
1554 IDispatchEx_AddRef(&event_target
->dispex
.IDispatchEx_iface
);
1556 event
->phase
= DEP_CAPTURING_PHASE
;
1558 while(!event
->stop_propagation
&& i
)
1559 call_event_handlers(target_chain
[i
--], event
);
1561 if(!event
->stop_propagation
) {
1562 event
->phase
= DEP_AT_TARGET
;
1563 call_event_handlers(target_chain
[0], event
);
1566 if(event_flags
& EVENT_BUBBLES
) {
1567 event
->phase
= DEP_BUBBLING_PHASE
;
1568 for(i
= 1; !event
->stop_propagation
&& i
< chain_cnt
; i
++)
1569 call_event_handlers(target_chain
[i
], event
);
1572 if(target_vtbl
&& target_vtbl
->set_current_event
) {
1573 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, prev_event
);
1575 IHTMLEventObj_Release(prev_event
);
1578 if(event_flags
& EVENT_HASDEFAULTHANDLERS
) {
1579 for(i
= 0; !event
->prevent_default
&& i
< chain_cnt
; i
++) {
1580 BOOL prevent_default
= FALSE
;
1581 vtbl
= dispex_get_vtbl(&target_chain
[i
]->dispex
);
1582 if(!vtbl
|| !vtbl
->handle_event_default
)
1584 hres
= vtbl
->handle_event_default(&event_target
->dispex
, event
->event_id
,
1585 event
->nsevent
, &prevent_default
);
1586 if(FAILED(hres
) || event
->stop_propagation
)
1589 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1594 event
->event_obj
= NULL
;
1595 IHTMLEventObj_Release(&event_obj_ref
->IHTMLEventObj_iface
);
1598 for(i
= 0; i
< chain_cnt
; i
++)
1599 IDispatchEx_Release(&target_chain
[i
]->dispex
.IDispatchEx_iface
);
1600 if(target_chain
!= target_chain_buf
)
1601 heap_free(target_chain
);
1604 HRESULT
fire_event(HTMLDOMNode
*node
, const WCHAR
*event_name
, VARIANT
*event_var
, VARIANT_BOOL
*cancelled
)
1606 HTMLEventObj
*event_obj
= NULL
;
1608 HRESULT hres
= S_OK
;
1610 eid
= attr_to_eid(event_name
);
1611 if(eid
== EVENTID_LAST
) {
1612 WARN("unknown event %s\n", debugstr_w(event_name
));
1613 return E_INVALIDARG
;
1616 if(event_var
&& V_VT(event_var
) != VT_EMPTY
&& V_VT(event_var
) != VT_ERROR
) {
1617 if(V_VT(event_var
) != VT_DISPATCH
) {
1618 FIXME("event_var %s not supported\n", debugstr_variant(event_var
));
1622 if(V_DISPATCH(event_var
)) {
1623 IHTMLEventObj
*event_iface
;
1625 hres
= IDispatch_QueryInterface(V_DISPATCH(event_var
), &IID_IHTMLEventObj
, (void**)&event_iface
);
1627 FIXME("No IHTMLEventObj iface\n");
1631 event_obj
= unsafe_impl_from_IHTMLEventObj(event_iface
);
1633 ERR("Not our IHTMLEventObj?\n");
1634 IHTMLEventObj_Release(event_iface
);
1641 event_obj
= alloc_event_obj(NULL
);
1643 return E_OUTOFMEMORY
;
1646 event_obj
->type
= event_info
+ eid
;
1647 if(!event_obj
->event
)
1648 hres
= create_document_event(node
->doc
, eid
, &event_obj
->event
);
1650 if(SUCCEEDED(hres
)) {
1651 event_obj
->event
->event_obj
= &event_obj
->IHTMLEventObj_iface
;
1652 event_obj
->event
->in_fire_event
++;
1653 dispatch_event(&node
->event_target
, event_obj
->event
);
1654 event_obj
->event
->in_fire_event
--;
1655 event_obj
->event
->event_obj
= NULL
;
1658 IHTMLEventObj_Release(&event_obj
->IHTMLEventObj_iface
);
1662 *cancelled
= VARIANT_TRUE
; /* FIXME */
1666 HRESULT
ensure_doc_nsevent_handler(HTMLDocumentNode
*doc
, eventid_t eid
)
1668 nsIDOMNode
*nsnode
= NULL
;
1670 TRACE("%s\n", debugstr_w(event_info
[eid
].name
));
1676 case EVENTID_FOCUSIN
:
1677 doc
->event_vector
[eid
] = TRUE
;
1678 eid
= EVENTID_FOCUS
;
1680 case EVENTID_FOCUSOUT
:
1681 doc
->event_vector
[eid
] = TRUE
;
1688 if(doc
->event_vector
[eid
] || !(event_info
[eid
].flags
& (EVENT_DEFAULTLISTENER
|EVENT_BIND_TO_BODY
)))
1691 if(event_info
[eid
].flags
& EVENT_BIND_TO_BODY
) {
1692 nsnode
= doc
->node
.nsnode
;
1693 nsIDOMNode_AddRef(nsnode
);
1696 doc
->event_vector
[eid
] = TRUE
;
1697 add_nsevent_listener(doc
, nsnode
, event_info
[eid
].name
);
1700 nsIDOMNode_Release(nsnode
);
1704 void detach_events(HTMLDocumentNode
*doc
)
1706 if(doc
->event_vector
) {
1709 for(i
=0; i
< EVENTID_LAST
; i
++) {
1710 if(doc
->event_vector
[i
]) {
1711 detach_nsevent(doc
, event_info
[i
].name
);
1712 doc
->event_vector
[i
] = FALSE
;
1717 release_nsevents(doc
);
1720 static HRESULT
get_event_dispex_ref(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
, VARIANT
**ret
)
1725 strcpyW(buf
+2, event_info
[eid
].name
);
1726 return dispex_get_dprop_ref(&event_target
->dispex
, buf
, alloc
, ret
);
1729 static event_listener_t
*get_onevent_listener(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
)
1731 listener_container_t
*container
;
1732 event_listener_t
*listener
;
1734 container
= get_listener_container(event_target
, eid
, alloc
);
1738 LIST_FOR_EACH_ENTRY_REV(listener
, &container
->listeners
, event_listener_t
, entry
) {
1739 if(listener
->type
== LISTENER_TYPE_ONEVENT
)
1746 listener
= heap_alloc(sizeof(*listener
));
1750 listener
->type
= LISTENER_TYPE_ONEVENT
;
1751 listener
->function
= NULL
;
1752 list_add_tail(&container
->listeners
, &listener
->entry
);
1756 static void remove_event_handler(EventTarget
*event_target
, eventid_t eid
)
1758 event_listener_t
*listener
;
1762 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &store
);
1764 VariantClear(store
);
1766 listener
= get_onevent_listener(event_target
, eid
, FALSE
);
1767 if(listener
&& listener
->function
) {
1768 IDispatch_Release(listener
->function
);
1769 listener
->function
= NULL
;
1773 static HRESULT
set_event_handler_disp(EventTarget
*event_target
, eventid_t eid
, IDispatch
*disp
)
1775 event_listener_t
*listener
;
1777 if(event_info
[eid
].flags
& EVENT_FIXME
)
1778 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
1780 remove_event_handler(event_target
, eid
);
1784 listener
= get_onevent_listener(event_target
, eid
, TRUE
);
1786 return E_OUTOFMEMORY
;
1788 if(listener
->function
)
1789 IDispatch_Release(listener
->function
);
1791 IDispatch_AddRef(listener
->function
= disp
);
1795 HRESULT
set_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
1799 if(use_event_quirks(event_target
)) {
1800 WARN("attempt to set to VT_EMPTY in quirks mode\n");
1805 remove_event_handler(event_target
, eid
);
1809 return set_event_handler_disp(event_target
, eid
, V_DISPATCH(var
));
1815 if(!use_event_quirks(event_target
))
1816 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var
)));
1819 * Setting event handler to string is a rare case and we don't want to
1820 * complicate nor increase memory of listener_container_t for that. Instead,
1821 * we store the value in DispatchEx, which can already handle custom
1824 remove_event_handler(event_target
, eid
);
1826 hres
= get_event_dispex_ref(event_target
, eid
, TRUE
, &v
);
1830 V_BSTR(v
) = SysAllocString(V_BSTR(var
));
1832 return E_OUTOFMEMORY
;
1838 FIXME("not handler %s\n", debugstr_variant(var
));
1845 HRESULT
get_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
1847 event_listener_t
*listener
;
1851 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &v
);
1852 if(SUCCEEDED(hres
) && V_VT(v
) != VT_EMPTY
) {
1853 V_VT(var
) = VT_EMPTY
;
1854 return VariantCopy(var
, v
);
1857 listener
= get_onevent_listener(event_target
, eid
, FALSE
);
1858 if(listener
&& listener
->function
) {
1859 V_VT(var
) = VT_DISPATCH
;
1860 V_DISPATCH(var
) = listener
->function
;
1861 IDispatch_AddRef(V_DISPATCH(var
));
1863 V_VT(var
) = VT_NULL
;
1869 HRESULT
attach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
, VARIANT_BOOL
*res
)
1871 listener_container_t
*container
;
1872 event_listener_t
*listener
;
1875 eid
= attr_to_eid(name
);
1876 if(eid
== EVENTID_LAST
) {
1877 WARN("Unknown event\n");
1878 *res
= VARIANT_TRUE
;
1882 container
= get_listener_container(event_target
, eid
, TRUE
);
1884 return E_OUTOFMEMORY
;
1886 listener
= heap_alloc(sizeof(*listener
));
1888 return E_OUTOFMEMORY
;
1890 listener
->type
= LISTENER_TYPE_ATTACHED
;
1891 IDispatch_AddRef(listener
->function
= disp
);
1892 if(use_event_quirks(event_target
))
1893 list_add_head(&container
->listeners
, &listener
->entry
);
1895 list_add_tail(&container
->listeners
, &listener
->entry
);
1897 *res
= VARIANT_TRUE
;
1901 HRESULT
detach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
)
1905 eid
= attr_to_eid(name
);
1906 if(eid
== EVENTID_LAST
) {
1907 WARN("Unknown event\n");
1911 remove_event_listener(event_target
, eid
, LISTENER_TYPE_ATTACHED
, disp
);
1915 void bind_target_event(HTMLDocumentNode
*doc
, EventTarget
*event_target
, const WCHAR
*event
, IDispatch
*disp
)
1919 TRACE("(%p %p %s %p)\n", doc
, event_target
, debugstr_w(event
), disp
);
1921 eid
= attr_to_eid(event
);
1922 if(eid
== EVENTID_LAST
) {
1923 WARN("Unsupported event %s\n", debugstr_w(event
));
1927 set_event_handler_disp(event_target
, eid
, disp
);
1930 void update_doc_cp_events(HTMLDocumentNode
*doc
, cp_static_data_t
*cp
)
1934 for(i
=0; i
< EVENTID_LAST
; i
++) {
1935 if((event_info
[i
].flags
& EVENT_DEFAULTLISTENER
) && is_cp_event(cp
, event_info
[i
].dispid
))
1936 ensure_doc_nsevent_handler(doc
, i
);
1940 void check_event_attr(HTMLDocumentNode
*doc
, nsIDOMHTMLElement
*nselem
)
1942 nsIDOMMozNamedAttrMap
*attr_map
;
1943 const PRUnichar
*name
, *value
;
1944 nsAString name_str
, value_str
;
1945 HTMLDOMNode
*node
= NULL
;
1954 nsres
= nsIDOMHTMLElement_HasAttributes(nselem
, &has_attrs
);
1955 if(NS_FAILED(nsres
) || !has_attrs
)
1958 nsres
= nsIDOMHTMLElement_GetAttributes(nselem
, &attr_map
);
1959 if(NS_FAILED(nsres
))
1962 nsres
= nsIDOMMozNamedAttrMap_GetLength(attr_map
, &length
);
1963 assert(nsres
== NS_OK
);
1965 nsAString_Init(&name_str
, NULL
);
1966 nsAString_Init(&value_str
, NULL
);
1968 for(i
= 0; i
< length
; i
++) {
1969 nsres
= nsIDOMMozNamedAttrMap_Item(attr_map
, i
, &attr
);
1970 if(NS_FAILED(nsres
))
1973 nsres
= nsIDOMAttr_GetName(attr
, &name_str
);
1974 if(NS_FAILED(nsres
)) {
1975 nsIDOMAttr_Release(attr
);
1979 nsAString_GetData(&name_str
, &name
);
1980 eid
= attr_to_eid(name
);
1981 if(eid
== EVENTID_LAST
) {
1982 nsIDOMAttr_Release(attr
);
1986 nsres
= nsIDOMAttr_GetValue(attr
, &value_str
);
1987 nsIDOMAttr_Release(attr
);
1988 if(NS_FAILED(nsres
))
1991 nsAString_GetData(&value_str
, &value
);
1995 TRACE("%p.%s = %s\n", nselem
, debugstr_w(name
), debugstr_w(value
));
1997 disp
= script_parse_event(doc
->window
, value
);
2002 hres
= get_node(doc
, (nsIDOMNode
*)nselem
, TRUE
, &node
);
2004 IDispatch_Release(disp
);
2009 set_event_handler_disp(get_node_event_prop_target(node
, eid
), eid
, disp
);
2010 IDispatch_Release(disp
);
2015 nsAString_Finish(&name_str
);
2016 nsAString_Finish(&value_str
);
2017 nsIDOMMozNamedAttrMap_Release(attr_map
);
2020 HRESULT
doc_init_events(HTMLDocumentNode
*doc
)
2025 doc
->event_vector
= heap_alloc_zero(EVENTID_LAST
*sizeof(BOOL
));
2026 if(!doc
->event_vector
)
2027 return E_OUTOFMEMORY
;
2031 for(i
=0; i
< EVENTID_LAST
; i
++) {
2032 if(event_info
[i
].flags
& EVENT_HASDEFAULTHANDLERS
) {
2033 hres
= ensure_doc_nsevent_handler(doc
, i
);
2042 static inline EventTarget
*impl_from_IEventTarget(IEventTarget
*iface
)
2044 return CONTAINING_RECORD(iface
, EventTarget
, IEventTarget_iface
);
2047 static HRESULT WINAPI
EventTarget_QueryInterface(IEventTarget
*iface
, REFIID riid
, void **ppv
)
2049 EventTarget
*This
= impl_from_IEventTarget(iface
);
2050 return IDispatchEx_QueryInterface(&This
->dispex
.IDispatchEx_iface
, riid
, ppv
);
2053 static ULONG WINAPI
EventTarget_AddRef(IEventTarget
*iface
)
2055 EventTarget
*This
= impl_from_IEventTarget(iface
);
2056 return IDispatchEx_AddRef(&This
->dispex
.IDispatchEx_iface
);
2059 static ULONG WINAPI
EventTarget_Release(IEventTarget
*iface
)
2061 EventTarget
*This
= impl_from_IEventTarget(iface
);
2062 return IDispatchEx_Release(&This
->dispex
.IDispatchEx_iface
);
2065 static HRESULT WINAPI
EventTarget_GetTypeInfoCount(IEventTarget
*iface
, UINT
*pctinfo
)
2067 EventTarget
*This
= impl_from_IEventTarget(iface
);
2068 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
2071 static HRESULT WINAPI
EventTarget_GetTypeInfo(IEventTarget
*iface
, UINT iTInfo
,
2072 LCID lcid
, ITypeInfo
**ppTInfo
)
2074 EventTarget
*This
= impl_from_IEventTarget(iface
);
2075 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
2078 static HRESULT WINAPI
EventTarget_GetIDsOfNames(IEventTarget
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
2079 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
2081 EventTarget
*This
= impl_from_IEventTarget(iface
);
2082 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
,
2083 rgszNames
, cNames
, lcid
, rgDispId
);
2086 static HRESULT WINAPI
EventTarget_Invoke(IEventTarget
*iface
, DISPID dispIdMember
,
2087 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
2088 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
2090 EventTarget
*This
= impl_from_IEventTarget(iface
);
2091 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
,
2092 riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2095 static HRESULT WINAPI
EventTarget_addEventListener(IEventTarget
*iface
, BSTR type
,
2096 IDispatch
*function
, VARIANT_BOOL capture
)
2098 EventTarget
*This
= impl_from_IEventTarget(iface
);
2099 listener_type_t listener_type
= capture
? LISTENER_TYPE_CAPTURE
: LISTENER_TYPE_BUBBLE
;
2100 listener_container_t
*container
;
2101 event_listener_t
*listener
;
2104 TRACE("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), function
, capture
);
2106 eid
= str_to_eid(type
);
2107 if(eid
== EVENTID_LAST
) {
2108 FIXME("Unsupported on event %s\n", debugstr_w(type
));
2113 container
= get_listener_container(This
, eid
, TRUE
);
2115 return E_OUTOFMEMORY
;
2117 /* check for duplicates */
2118 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
2119 if(listener
->type
== listener_type
&& listener
->function
== function
)
2123 listener
= heap_alloc(sizeof(*listener
));
2125 return E_OUTOFMEMORY
;
2127 listener
->type
= listener_type
;
2128 IDispatch_AddRef(listener
->function
= function
);
2129 list_add_tail(&container
->listeners
, &listener
->entry
);
2133 static HRESULT WINAPI
EventTarget_removeEventListener(IEventTarget
*iface
, BSTR type
,
2134 IDispatch
*listener
, VARIANT_BOOL capture
)
2136 EventTarget
*This
= impl_from_IEventTarget(iface
);
2139 TRACE("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), listener
, capture
);
2141 eid
= str_to_eid(type
);
2142 if(eid
== EVENTID_LAST
) {
2143 FIXME("Unsupported on event %s\n", debugstr_w(type
));
2147 remove_event_listener(This
, eid
, capture
? LISTENER_TYPE_CAPTURE
: LISTENER_TYPE_BUBBLE
, listener
);
2151 static HRESULT WINAPI
EventTarget_dispatchEvent(IEventTarget
*iface
, IDOMEvent
*event
, VARIANT_BOOL
*result
)
2153 EventTarget
*This
= impl_from_IEventTarget(iface
);
2154 FIXME("(%p)->(%p %p)\n", This
, event
, result
);
2158 static const IEventTargetVtbl EventTargetVtbl
= {
2159 EventTarget_QueryInterface
,
2161 EventTarget_Release
,
2162 EventTarget_GetTypeInfoCount
,
2163 EventTarget_GetTypeInfo
,
2164 EventTarget_GetIDsOfNames
,
2166 EventTarget_addEventListener
,
2167 EventTarget_removeEventListener
,
2168 EventTarget_dispatchEvent
2171 #define DELAY_INIT_VTBL ((const IEventTargetVtbl*)1)
2173 static BOOL
use_event_quirks(EventTarget
*event_target
)
2175 if(event_target
->IEventTarget_iface
.lpVtbl
== DELAY_INIT_VTBL
) {
2176 event_target
->IEventTarget_iface
.lpVtbl
=
2177 dispex_compat_mode(&event_target
->dispex
) >= COMPAT_MODE_IE9
2178 ? &EventTargetVtbl
: NULL
;
2180 return !event_target
->IEventTarget_iface
.lpVtbl
;
2183 HRESULT
EventTarget_QI(EventTarget
*event_target
, REFIID riid
, void **ppv
)
2185 if(IsEqualGUID(riid
, &IID_IEventTarget
)) {
2186 if(use_event_quirks(event_target
)) {
2187 WARN("IEventTarget queried, but not supported by in document mode\n");
2189 return E_NOINTERFACE
;
2191 IEventTarget_AddRef(&event_target
->IEventTarget_iface
);
2192 *ppv
= &event_target
->IEventTarget_iface
;
2196 if(dispex_query_interface(&event_target
->dispex
, riid
, ppv
))
2197 return *ppv
? S_OK
: E_NOINTERFACE
;
2199 WARN("(%p)->(%s %p)\n", event_target
, debugstr_mshtml_guid(riid
), ppv
);
2201 return E_NOINTERFACE
;
2204 static int event_id_cmp(const void *key
, const struct wine_rb_entry
*entry
)
2206 return (INT_PTR
)key
- WINE_RB_ENTRY_VALUE(entry
, listener_container_t
, entry
)->event_id
;
2209 void EventTarget_Init(EventTarget
*event_target
, IUnknown
*outer
, dispex_static_data_t
*dispex_data
,
2210 compat_mode_t compat_mode
)
2212 init_dispex_with_compat_mode(&event_target
->dispex
, outer
, dispex_data
, compat_mode
);
2213 wine_rb_init(&event_target
->handler_map
, event_id_cmp
);
2216 * IEventTarget is supported by the object or not depending on compatibility mode.
2217 * We use NULL vtbl for objects in compatibility mode not supporting the interface.
2218 * For targets that don't know compatibility mode at creation time, we set vtbl
2219 * to special DELAY_INIT_VTBL value so that vtbl will be set to proper value
2222 if(compat_mode
== COMPAT_MODE_QUIRKS
&& dispex_data
->vtbl
&& dispex_data
->vtbl
->get_compat_mode
)
2223 event_target
->IEventTarget_iface
.lpVtbl
= DELAY_INIT_VTBL
;
2224 else if(compat_mode
< COMPAT_MODE_IE9
)
2225 event_target
->IEventTarget_iface
.lpVtbl
= NULL
;
2227 event_target
->IEventTarget_iface
.lpVtbl
= &EventTargetVtbl
;
2230 void release_event_target(EventTarget
*event_target
)
2232 listener_container_t
*iter
, *iter2
;
2234 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter
, iter2
, &event_target
->handler_map
, listener_container_t
, entry
) {
2235 while(!list_empty(&iter
->listeners
)) {
2236 event_listener_t
*listener
= LIST_ENTRY(list_head(&iter
->listeners
), event_listener_t
, entry
);
2237 if(listener
->function
)
2238 IDispatch_Release(listener
->function
);
2239 list_remove(&listener
->entry
);
2240 heap_free(listener
);