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
;
53 struct list listeners
;
55 } listener_container_t
;
63 static const WCHAR abortW
[] = {'a','b','o','r','t',0};
64 static const WCHAR beforeactivateW
[] = {'b','e','f','o','r','e','a','c','t','i','v','a','t','e',0};
65 static const WCHAR beforeunloadW
[] = {'b','e','f','o','r','e','u','n','l','o','a','d',0};
66 static const WCHAR blurW
[] = {'b','l','u','r',0};
67 static const WCHAR changeW
[] = {'c','h','a','n','g','e',0};
68 static const WCHAR clickW
[] = {'c','l','i','c','k',0};
69 static const WCHAR contextmenuW
[] = {'c','o','n','t','e','x','t','m','e','n','u',0};
70 static const WCHAR dataavailableW
[] = {'d','a','t','a','a','v','a','i','l','a','b','l','e',0};
71 static const WCHAR dblclickW
[] = {'d','b','l','c','l','i','c','k',0};
72 static const WCHAR dragW
[] = {'d','r','a','g',0};
73 static const WCHAR dragstartW
[] = {'d','r','a','g','s','t','a','r','t',0};
74 static const WCHAR errorW
[] = {'e','r','r','o','r',0};
75 static const WCHAR focusW
[] = {'f','o','c','u','s',0};
76 static const WCHAR focusinW
[] = {'f','o','c','u','s','i','n',0};
77 static const WCHAR focusoutW
[] = {'f','o','c','u','s','o','u','t',0};
78 static const WCHAR helpW
[] = {'h','e','l','p',0};
79 static const WCHAR keydownW
[] = {'k','e','y','d','o','w','n',0};
80 static const WCHAR keypressW
[] = {'k','e','y','p','r','e','s','s',0};
81 static const WCHAR keyupW
[] = {'k','e','y','u','p',0};
82 static const WCHAR loadW
[] = {'l','o','a','d',0};
83 static const WCHAR messageW
[] = {'m','e','s','s','a','g','e',0};
84 static const WCHAR mousedownW
[] = {'m','o','u','s','e','d','o','w','n',0};
85 static const WCHAR mousemoveW
[] = {'m','o','u','s','e','m','o','v','e',0};
86 static const WCHAR mouseoutW
[] = {'m','o','u','s','e','o','u','t',0};
87 static const WCHAR mouseoverW
[] = {'m','o','u','s','e','o','v','e','r',0};
88 static const WCHAR mouseupW
[] = {'m','o','u','s','e','u','p',0};
89 static const WCHAR mousewheelW
[] = {'m','o','u','s','e','w','h','e','e','l',0};
90 static const WCHAR pasteW
[] = {'p','a','s','t','e',0};
91 static const WCHAR readystatechangeW
[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
92 static const WCHAR resizeW
[] = {'r','e','s','i','z','e',0};
93 static const WCHAR scrollW
[] = {'s','c','r','o','l','l',0};
94 static const WCHAR selectstartW
[] = {'s','e','l','e','c','t','s','t','a','r','t',0};
95 static const WCHAR selectionchangeW
[] = {'s','e','l','e','c','t','i','o','n','c','h','a','n','g','e',0};
96 static const WCHAR submitW
[] = {'s','u','b','m','i','t',0};
97 static const WCHAR unloadW
[] = {'u','n','l','o','a','d',0};
98 static const WCHAR DOMContentLoadedW
[] = {'D','O','M','C','o','n','t','e','n','t','L','o','a','d','e','d',0};
100 static const WCHAR EventW
[] = {'E','v','e','n','t',0};
101 static const WCHAR UIEventW
[] = {'U','I','E','v','e','n','t',0};
102 static const WCHAR KeyboardEventW
[] = {'K','e','y','b','o','a','r','d','E','v','e','n','t',0};
103 static const WCHAR MouseEventW
[] = {'M','o','u','s','e','E','v','e','n','t',0};
116 static const WCHAR
*event_types
[] = {
134 #define EVENT_DEFAULTLISTENER 0x0001
135 #define EVENT_BUBBLES 0x0002
136 #define EVENT_BIND_TO_BODY 0x0008
137 #define EVENT_CANCELABLE 0x0010
138 #define EVENT_HASDEFAULTHANDLERS 0x0020
139 #define EVENT_FIXME 0x0040
141 static const event_info_t event_info
[] = {
142 {abortW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONABORT
,
144 {beforeactivateW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREACTIVATE
,
145 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
146 {beforeunloadW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREUNLOAD
,
147 EVENT_DEFAULTLISTENER
| EVENT_CANCELABLE
},
148 {blurW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONBLUR
,
149 EVENT_DEFAULTLISTENER
},
150 {changeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONCHANGE
,
151 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
},
152 {clickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCLICK
,
153 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
154 {contextmenuW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCONTEXTMENU
,
155 EVENT_BUBBLES
| EVENT_CANCELABLE
},
156 {dataavailableW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONDATAAVAILABLE
,
157 EVENT_FIXME
| EVENT_BUBBLES
},
158 {dblclickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONDBLCLICK
,
159 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
160 {DOMContentLoadedW
, EVENT_TYPE_EVENT
, 0,
161 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
162 {dragW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAG
,
163 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
164 {dragstartW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAGSTART
,
165 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
166 {errorW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONERROR
,
168 {focusW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUS
,
169 EVENT_DEFAULTLISTENER
},
170 {focusinW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSIN
,
172 {focusoutW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSOUT
,
174 {helpW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONHELP
,
175 EVENT_BUBBLES
| EVENT_CANCELABLE
},
176 {keydownW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYDOWN
,
177 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
178 {keypressW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYPRESS
,
179 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
180 {keyupW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYUP
,
181 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
182 {loadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONLOAD
,
184 {messageW
, EVENT_TYPE_MESSAGE
, DISPID_EVMETH_ONMESSAGE
,
186 {mousedownW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEDOWN
,
187 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
188 {mousemoveW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEMOVE
,
189 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
190 {mouseoutW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOUT
,
191 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
192 {mouseoverW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOVER
,
193 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
194 {mouseupW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEUP
,
195 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
196 {mousewheelW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEWHEEL
,
198 {pasteW
, EVENT_TYPE_CLIPBOARD
, DISPID_EVMETH_ONPASTE
,
199 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
200 {readystatechangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONREADYSTATECHANGE
,
202 {resizeW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONRESIZE
,
203 EVENT_DEFAULTLISTENER
},
204 {scrollW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONSCROLL
,
205 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
/* FIXME: not for elements */},
206 {selectionchangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTIONCHANGE
,
208 {selectstartW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTSTART
,
209 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
210 {submitW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSUBMIT
,
211 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
212 {unloadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONUNLOAD
,
216 static eventid_t
str_to_eid(const WCHAR
*str
)
220 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
221 if(!strcmpW(event_info
[i
].name
, str
))
228 static eventid_t
attr_to_eid(const WCHAR
*str
)
232 if((str
[0] != 'o' && str
[0] != 'O') || (str
[1] != 'n' && str
[1] != 'N'))
235 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
236 if(!strcmpW(event_info
[i
].name
, str
+2) && event_info
[i
].dispid
)
243 static listener_container_t
*get_listener_container(EventTarget
*event_target
, const WCHAR
*type
, BOOL alloc
)
245 const event_target_vtbl_t
*vtbl
;
246 listener_container_t
*container
;
247 struct wine_rb_entry
*entry
;
251 entry
= wine_rb_get(&event_target
->handler_map
, type
);
253 return WINE_RB_ENTRY_VALUE(entry
, listener_container_t
, entry
);
257 eid
= str_to_eid(type
);
258 if(eid
!= EVENTID_LAST
&& (event_info
[eid
].flags
& EVENT_FIXME
))
259 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
261 type_len
= strlenW(type
);
262 container
= heap_alloc(FIELD_OFFSET(listener_container_t
, type
[type_len
+1]));
265 memcpy(container
->type
, type
, (type_len
+ 1) * sizeof(WCHAR
));
266 list_init(&container
->listeners
);
267 vtbl
= dispex_get_vtbl(&event_target
->dispex
);
269 vtbl
->bind_event(&event_target
->dispex
, eid
);
271 FIXME("Unsupported event binding on target %p\n", event_target
);
273 wine_rb_put(&event_target
->handler_map
, container
->type
, &container
->entry
);
277 static void remove_event_listener(EventTarget
*event_target
, const WCHAR
*type_name
, listener_type_t type
, IDispatch
*function
)
279 listener_container_t
*container
;
280 event_listener_t
*listener
;
282 container
= get_listener_container(event_target
, type_name
, FALSE
);
286 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
287 if(listener
->function
== function
&& listener
->type
== type
) {
288 IDispatch_Release(listener
->function
);
289 list_remove(&listener
->entry
);
296 static HRESULT
get_gecko_target(IEventTarget
*,nsIDOMEventTarget
**);
300 IHTMLEventObj IHTMLEventObj_iface
;
305 VARIANT return_value
;
308 static inline HTMLEventObj
*impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
310 return CONTAINING_RECORD(iface
, HTMLEventObj
, IHTMLEventObj_iface
);
313 static HRESULT WINAPI
HTMLEventObj_QueryInterface(IHTMLEventObj
*iface
, REFIID riid
, void **ppv
)
315 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
317 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
319 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
320 *ppv
= &This
->IHTMLEventObj_iface
;
321 }else if(IsEqualGUID(&IID_IHTMLEventObj
, riid
)) {
322 *ppv
= &This
->IHTMLEventObj_iface
;
323 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
324 return *ppv
? S_OK
: E_NOINTERFACE
;
327 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
328 return E_NOINTERFACE
;
331 IUnknown_AddRef((IUnknown
*)*ppv
);
335 static ULONG WINAPI
HTMLEventObj_AddRef(IHTMLEventObj
*iface
)
337 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
338 LONG ref
= InterlockedIncrement(&This
->ref
);
340 TRACE("(%p) ref=%d\n", This
, ref
);
345 static ULONG WINAPI
HTMLEventObj_Release(IHTMLEventObj
*iface
)
347 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
348 LONG ref
= InterlockedDecrement(&This
->ref
);
350 TRACE("(%p) ref=%d\n", This
, ref
);
354 IDOMEvent_Release(&This
->event
->IDOMEvent_iface
);
355 release_dispex(&This
->dispex
);
362 static HRESULT WINAPI
HTMLEventObj_GetTypeInfoCount(IHTMLEventObj
*iface
, UINT
*pctinfo
)
364 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
365 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
368 static HRESULT WINAPI
HTMLEventObj_GetTypeInfo(IHTMLEventObj
*iface
, UINT iTInfo
,
369 LCID lcid
, ITypeInfo
**ppTInfo
)
371 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
372 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
375 static HRESULT WINAPI
HTMLEventObj_GetIDsOfNames(IHTMLEventObj
*iface
, REFIID riid
,
376 LPOLESTR
*rgszNames
, UINT cNames
,
377 LCID lcid
, DISPID
*rgDispId
)
379 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
380 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
384 static HRESULT WINAPI
HTMLEventObj_Invoke(IHTMLEventObj
*iface
, DISPID dispIdMember
,
385 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
386 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
388 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
389 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
390 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
393 static HRESULT WINAPI
HTMLEventObj_get_srcElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
395 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
397 TRACE("(%p)->(%p)\n", This
, p
);
404 return IDOMEvent_get_srcElement(&This
->event
->IDOMEvent_iface
, p
);
407 static HRESULT WINAPI
HTMLEventObj_get_altKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
409 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
410 cpp_bool ret
= FALSE
;
412 TRACE("(%p)->(%p)\n", This
, p
);
414 if(This
->event
&& This
->event
->mouse_event
)
415 return IDOMMouseEvent_get_altKey(&This
->event
->IDOMMouseEvent_iface
, p
);
417 if(This
->event
&& This
->event
->keyboard_event
)
418 return IDOMKeyboardEvent_get_altKey(&This
->event
->IDOMKeyboardEvent_iface
, p
);
420 *p
= variant_bool(ret
);
424 static HRESULT WINAPI
HTMLEventObj_get_ctrlKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
426 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
427 cpp_bool ret
= FALSE
;
429 TRACE("(%p)->(%p)\n", This
, p
);
431 if(This
->event
&& This
->event
->mouse_event
)
432 return IDOMMouseEvent_get_ctrlKey(&This
->event
->IDOMMouseEvent_iface
, p
);
434 if(This
->event
&& This
->event
->keyboard_event
)
435 return IDOMKeyboardEvent_get_ctrlKey(&This
->event
->IDOMKeyboardEvent_iface
, p
);
437 *p
= variant_bool(ret
);
441 static HRESULT WINAPI
HTMLEventObj_get_shiftKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
443 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
444 cpp_bool ret
= FALSE
;
446 TRACE("(%p)->(%p)\n", This
, p
);
448 if(This
->event
&& This
->event
->mouse_event
)
449 return IDOMMouseEvent_get_shiftKey(&This
->event
->IDOMMouseEvent_iface
, p
);
451 if(This
->event
&& This
->event
->keyboard_event
)
452 return IDOMKeyboardEvent_get_shiftKey(&This
->event
->IDOMKeyboardEvent_iface
, p
);
454 *p
= variant_bool(ret
);
458 static HRESULT WINAPI
HTMLEventObj_put_returnValue(IHTMLEventObj
*iface
, VARIANT v
)
460 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
462 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&v
));
464 if(V_VT(&v
) != VT_BOOL
) {
465 FIXME("unsupported value %s\n", debugstr_variant(&v
));
466 return DISP_E_BADVARTYPE
;
469 This
->return_value
= v
;
470 if(!V_BOOL(&v
) && This
->event
)
471 IDOMEvent_preventDefault(&This
->event
->IDOMEvent_iface
);
475 static HRESULT WINAPI
HTMLEventObj_get_returnValue(IHTMLEventObj
*iface
, VARIANT
*p
)
477 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
479 TRACE("(%p)->(%p)\n", This
, p
);
482 return VariantCopy(p
, &This
->return_value
);
485 static HRESULT WINAPI
HTMLEventObj_put_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL v
)
487 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
489 TRACE("(%p)->(%x)\n", This
, v
);
492 IDOMEvent_stopPropagation(&This
->event
->IDOMEvent_iface
);
496 static HRESULT WINAPI
HTMLEventObj_get_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
498 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
500 TRACE("(%p)->(%p)\n", This
, p
);
502 *p
= variant_bool(This
->event
&& This
->event
->stop_propagation
);
506 static HRESULT WINAPI
HTMLEventObj_get_fromElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
508 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
510 FIXME("(%p)->(%p)\n", This
, p
);
516 static HRESULT WINAPI
HTMLEventObj_get_toElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
518 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
520 FIXME("(%p)->(%p)\n", This
, p
);
526 static HRESULT WINAPI
HTMLEventObj_put_keyCode(IHTMLEventObj
*iface
, LONG v
)
528 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
529 FIXME("(%p)->(%d)\n", This
, v
);
533 static HRESULT WINAPI
HTMLEventObj_get_keyCode(IHTMLEventObj
*iface
, LONG
*p
)
535 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
537 TRACE("(%p)->(%p)\n", This
, p
);
539 if(This
->event
&& This
->event
->keyboard_event
)
540 return IDOMKeyboardEvent_get_keyCode(&This
->event
->IDOMKeyboardEvent_iface
, p
);
546 static HRESULT WINAPI
HTMLEventObj_get_button(IHTMLEventObj
*iface
, LONG
*p
)
548 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
551 TRACE("(%p)->(%p)\n", This
, p
);
553 if(This
->event
&& This
->event
->mouse_event
) {
555 hres
= IDOMMouseEvent_get_button(&This
->event
->IDOMMouseEvent_iface
, &button
);
564 static HRESULT WINAPI
HTMLEventObj_get_type(IHTMLEventObj
*iface
, BSTR
*p
)
566 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
568 TRACE("(%p)->(%p)\n", This
, p
);
575 return IDOMEvent_get_type(&This
->event
->IDOMEvent_iface
, p
);
578 static HRESULT WINAPI
HTMLEventObj_get_qualifier(IHTMLEventObj
*iface
, BSTR
*p
)
580 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
582 FIXME("(%p)->(%p)\n", This
, p
);
588 static HRESULT WINAPI
HTMLEventObj_get_reason(IHTMLEventObj
*iface
, LONG
*p
)
590 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
592 FIXME("(%p)->(%p)\n", This
, p
);
598 static HRESULT WINAPI
HTMLEventObj_get_x(IHTMLEventObj
*iface
, LONG
*p
)
600 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
603 TRACE("(%p)->(%p)\n", This
, p
);
605 if(This
->event
&& This
->event
->ui_event
) {
608 /* NOTE: pageX is not exactly right here. */
609 nsres
= nsIDOMUIEvent_GetPageX(This
->event
->ui_event
, &x
);
610 assert(nsres
== NS_OK
);
617 static HRESULT WINAPI
HTMLEventObj_get_y(IHTMLEventObj
*iface
, LONG
*p
)
619 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
622 TRACE("(%p)->(%p)\n", This
, p
);
624 if(This
->event
&& This
->event
->ui_event
) {
627 /* NOTE: pageY is not exactly right here. */
628 nsres
= nsIDOMUIEvent_GetPageY(This
->event
->ui_event
, &y
);
629 assert(nsres
== NS_OK
);
636 static HRESULT WINAPI
HTMLEventObj_get_clientX(IHTMLEventObj
*iface
, LONG
*p
)
638 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
640 TRACE("(%p)->(%p)\n", This
, p
);
642 if(This
->event
&& This
->event
->mouse_event
)
643 return IDOMMouseEvent_get_clientX(&This
->event
->IDOMMouseEvent_iface
, p
);
649 static HRESULT WINAPI
HTMLEventObj_get_clientY(IHTMLEventObj
*iface
, LONG
*p
)
651 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
653 TRACE("(%p)->(%p)\n", This
, p
);
655 if(This
->event
&& This
->event
->mouse_event
)
656 return IDOMMouseEvent_get_clientY(&This
->event
->IDOMMouseEvent_iface
, p
);
662 static HRESULT WINAPI
HTMLEventObj_get_offsetX(IHTMLEventObj
*iface
, LONG
*p
)
664 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
666 TRACE("(%p)->(%p)\n", This
, p
);
668 if(This
->event
&& This
->event
->mouse_event
)
669 return IDOMMouseEvent_get_offsetX(&This
->event
->IDOMMouseEvent_iface
, p
);
675 static HRESULT WINAPI
HTMLEventObj_get_offsetY(IHTMLEventObj
*iface
, LONG
*p
)
677 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
679 TRACE("(%p)->(%p)\n", This
, p
);
681 if(This
->event
&& This
->event
->mouse_event
)
682 return IDOMMouseEvent_get_offsetY(&This
->event
->IDOMMouseEvent_iface
, p
);
688 static HRESULT WINAPI
HTMLEventObj_get_screenX(IHTMLEventObj
*iface
, LONG
*p
)
690 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
692 TRACE("(%p)->(%p)\n", This
, p
);
694 if(This
->event
&& This
->event
->mouse_event
)
695 return IDOMMouseEvent_get_screenX(&This
->event
->IDOMMouseEvent_iface
, p
);
701 static HRESULT WINAPI
HTMLEventObj_get_screenY(IHTMLEventObj
*iface
, LONG
*p
)
703 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
705 TRACE("(%p)->(%p)\n", This
, p
);
707 if(This
->event
&& This
->event
->mouse_event
)
708 return IDOMMouseEvent_get_screenY(&This
->event
->IDOMMouseEvent_iface
, p
);
714 static HRESULT WINAPI
HTMLEventObj_get_srcFilter(IHTMLEventObj
*iface
, IDispatch
**p
)
716 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
718 FIXME("(%p)->(%p)\n", This
, p
);
724 static const IHTMLEventObjVtbl HTMLEventObjVtbl
= {
725 HTMLEventObj_QueryInterface
,
727 HTMLEventObj_Release
,
728 HTMLEventObj_GetTypeInfoCount
,
729 HTMLEventObj_GetTypeInfo
,
730 HTMLEventObj_GetIDsOfNames
,
732 HTMLEventObj_get_srcElement
,
733 HTMLEventObj_get_altKey
,
734 HTMLEventObj_get_ctrlKey
,
735 HTMLEventObj_get_shiftKey
,
736 HTMLEventObj_put_returnValue
,
737 HTMLEventObj_get_returnValue
,
738 HTMLEventObj_put_cancelBubble
,
739 HTMLEventObj_get_cancelBubble
,
740 HTMLEventObj_get_fromElement
,
741 HTMLEventObj_get_toElement
,
742 HTMLEventObj_put_keyCode
,
743 HTMLEventObj_get_keyCode
,
744 HTMLEventObj_get_button
,
745 HTMLEventObj_get_type
,
746 HTMLEventObj_get_qualifier
,
747 HTMLEventObj_get_reason
,
750 HTMLEventObj_get_clientX
,
751 HTMLEventObj_get_clientY
,
752 HTMLEventObj_get_offsetX
,
753 HTMLEventObj_get_offsetY
,
754 HTMLEventObj_get_screenX
,
755 HTMLEventObj_get_screenY
,
756 HTMLEventObj_get_srcFilter
759 static inline HTMLEventObj
*unsafe_impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
761 return iface
->lpVtbl
== &HTMLEventObjVtbl
? impl_from_IHTMLEventObj(iface
) : NULL
;
764 static const tid_t HTMLEventObj_iface_tids
[] = {
769 static dispex_static_data_t HTMLEventObj_dispex
= {
772 HTMLEventObj_iface_tids
775 static HTMLEventObj
*alloc_event_obj(DOMEvent
*event
)
777 HTMLEventObj
*event_obj
;
779 event_obj
= heap_alloc_zero(sizeof(*event_obj
));
783 event_obj
->IHTMLEventObj_iface
.lpVtbl
= &HTMLEventObjVtbl
;
785 event_obj
->event
= event
;
787 IDOMEvent_AddRef(&event
->IDOMEvent_iface
);
789 init_dispex(&event_obj
->dispex
, (IUnknown
*)&event_obj
->IHTMLEventObj_iface
, &HTMLEventObj_dispex
);
793 HRESULT
create_event_obj(IHTMLEventObj
**ret
)
795 HTMLEventObj
*event_obj
;
797 event_obj
= alloc_event_obj(NULL
);
799 return E_OUTOFMEMORY
;
801 *ret
= &event_obj
->IHTMLEventObj_iface
;
805 static inline DOMEvent
*impl_from_IDOMEvent(IDOMEvent
*iface
)
807 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMEvent_iface
);
810 static const IDOMEventVtbl DOMEventVtbl
;
812 static inline DOMEvent
*unsafe_impl_from_IDOMEvent(IDOMEvent
*iface
)
814 return iface
&& iface
->lpVtbl
== &DOMEventVtbl
? impl_from_IDOMEvent(iface
) : NULL
;
817 static HRESULT WINAPI
DOMEvent_QueryInterface(IDOMEvent
*iface
, REFIID riid
, void **ppv
)
819 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
821 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
823 if(IsEqualGUID(&IID_IUnknown
, riid
))
824 *ppv
= &This
->IDOMEvent_iface
;
825 else if(IsEqualGUID(&IID_IDOMEvent
, riid
))
826 *ppv
= &This
->IDOMEvent_iface
;
827 else if(This
->ui_event
&& IsEqualGUID(&IID_IDOMUIEvent
, riid
))
828 *ppv
= &This
->IDOMUIEvent_iface
;
829 else if(This
->mouse_event
&& IsEqualGUID(&IID_IDOMMouseEvent
, riid
))
830 *ppv
= &This
->IDOMMouseEvent_iface
;
831 else if(This
->keyboard_event
&& IsEqualGUID(&IID_IDOMKeyboardEvent
, riid
))
832 *ppv
= &This
->IDOMKeyboardEvent_iface
;
833 else if(dispex_query_interface(&This
->dispex
, riid
, ppv
))
834 return *ppv
? S_OK
: E_NOINTERFACE
;
837 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
838 return E_NOINTERFACE
;
841 IUnknown_AddRef((IUnknown
*)*ppv
);
845 static ULONG WINAPI
DOMEvent_AddRef(IDOMEvent
*iface
)
847 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
848 LONG ref
= InterlockedIncrement(&This
->ref
);
850 TRACE("(%p) ref=%u\n", This
, ref
);
855 static ULONG WINAPI
DOMEvent_Release(IDOMEvent
*iface
)
857 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
858 LONG ref
= InterlockedDecrement(&This
->ref
);
860 TRACE("(%p) ref=%u\n", This
, ref
);
864 nsIDOMUIEvent_Release(This
->ui_event
);
865 if(This
->mouse_event
)
866 nsIDOMMouseEvent_Release(This
->mouse_event
);
868 IEventTarget_Release(&This
->target
->IEventTarget_iface
);
869 nsIDOMEvent_Release(This
->nsevent
);
870 release_dispex(&This
->dispex
);
871 heap_free(This
->type
);
878 static HRESULT WINAPI
DOMEvent_GetTypeInfoCount(IDOMEvent
*iface
, UINT
*pctinfo
)
880 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
881 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
884 static HRESULT WINAPI
DOMEvent_GetTypeInfo(IDOMEvent
*iface
, UINT iTInfo
,
885 LCID lcid
, ITypeInfo
**ppTInfo
)
887 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
888 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
891 static HRESULT WINAPI
DOMEvent_GetIDsOfNames(IDOMEvent
*iface
, REFIID riid
,
892 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
894 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
895 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
899 static HRESULT WINAPI
DOMEvent_Invoke(IDOMEvent
*iface
, DISPID dispIdMember
,
900 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
901 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
903 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
904 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
905 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
908 static HRESULT WINAPI
DOMEvent_get_bubbles(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
910 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
912 TRACE("(%p)->(%p)\n", This
, p
);
914 *p
= variant_bool(This
->bubbles
);
918 static HRESULT WINAPI
DOMEvent_get_cancelable(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
920 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
922 TRACE("(%p)->(%p)\n", This
, p
);
924 *p
= variant_bool(This
->cancelable
);
928 static HRESULT WINAPI
DOMEvent_get_currentTarget(IDOMEvent
*iface
, IEventTarget
**p
)
930 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
932 TRACE("(%p)->(%p)\n", This
, p
);
934 if(This
->current_target
)
935 IEventTarget_AddRef(*p
= &This
->current_target
->IEventTarget_iface
);
941 static HRESULT WINAPI
DOMEvent_get_defaultPrevented(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
943 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
945 TRACE("(%p)->(%p)\n", This
, p
);
947 *p
= variant_bool(This
->prevent_default
);
951 static HRESULT WINAPI
DOMEvent_get_eventPhase(IDOMEvent
*iface
, USHORT
*p
)
953 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
955 TRACE("(%p)->(%p)\n", This
, p
);
961 static HRESULT WINAPI
DOMEvent_get_target(IDOMEvent
*iface
, IEventTarget
**p
)
963 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
965 TRACE("(%p)->(%p)\n", This
, p
);
968 IEventTarget_AddRef(*p
= &This
->target
->IEventTarget_iface
);
974 static HRESULT WINAPI
DOMEvent_get_timeStamp(IDOMEvent
*iface
, ULONGLONG
*p
)
976 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
978 TRACE("(%p)->(%p)\n", This
, p
);
980 *p
= This
->time_stamp
;
984 static HRESULT WINAPI
DOMEvent_get_type(IDOMEvent
*iface
, BSTR
*p
)
986 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
988 TRACE("(%p)->(%p)\n", This
, p
);
991 *p
= SysAllocString(This
->type
);
993 return E_OUTOFMEMORY
;
1001 #define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \
1002 ((void (WINAPI*)(void*,nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \
1003 &call_thiscall_func)((_this)->lpVtbl->InitEvent,_this,type,bubbles,cancelable)
1007 static HRESULT WINAPI
DOMEvent_initEvent(IDOMEvent
*iface
, BSTR type
, VARIANT_BOOL can_bubble
, VARIANT_BOOL cancelable
)
1009 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1012 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_w(type
), can_bubble
, cancelable
);
1015 TRACE("called on already dispatched event\n");
1019 heap_free(This
->type
);
1020 This
->type
= heap_strdupW(type
);
1022 return E_OUTOFMEMORY
;
1023 This
->event_id
= str_to_eid(type
);
1025 This
->bubbles
= !!can_bubble
;
1026 This
->cancelable
= !!cancelable
;
1028 nsAString_InitDepend(&nsstr
, type
);
1029 nsIDOMEvent_InitEvent(This
->nsevent
, &nsstr
, This
->bubbles
, This
->cancelable
);
1030 nsAString_Finish(&nsstr
);
1035 static HRESULT WINAPI
DOMEvent_preventDefault(IDOMEvent
*iface
)
1037 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1039 TRACE("(%p)\n", This
);
1041 if(This
->current_target
&& This
->cancelable
) {
1042 This
->prevent_default
= TRUE
;
1043 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
);
1059 static HRESULT WINAPI
DOMEvent_stopImmediatePropagation(IDOMEvent
*iface
)
1061 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1063 TRACE("(%p)\n", This
);
1065 This
->stop_immediate_propagation
= This
->stop_propagation
= TRUE
;
1066 nsIDOMEvent_StopImmediatePropagation(This
->nsevent
);
1070 static HRESULT WINAPI
DOMEvent_get_isTrusted(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1072 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1073 FIXME("(%p)->(%p)\n", This
, p
);
1077 static HRESULT WINAPI
DOMEvent_put_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL v
)
1079 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1080 FIXME("(%p)->(%x)\n", This
, v
);
1084 static HRESULT WINAPI
DOMEvent_get_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1086 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1087 FIXME("(%p)->(%p)\n", This
, p
);
1091 static HRESULT WINAPI
DOMEvent_get_srcElement(IDOMEvent
*iface
, IHTMLElement
**p
)
1093 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1095 TRACE("(%p)->(%p)\n", This
, p
);
1098 IDispatchEx_QueryInterface(&This
->target
->dispex
.IDispatchEx_iface
, &IID_IHTMLElement
, (void**)p
);
1104 static const IDOMEventVtbl DOMEventVtbl
= {
1105 DOMEvent_QueryInterface
,
1108 DOMEvent_GetTypeInfoCount
,
1109 DOMEvent_GetTypeInfo
,
1110 DOMEvent_GetIDsOfNames
,
1112 DOMEvent_get_bubbles
,
1113 DOMEvent_get_cancelable
,
1114 DOMEvent_get_currentTarget
,
1115 DOMEvent_get_defaultPrevented
,
1116 DOMEvent_get_eventPhase
,
1117 DOMEvent_get_target
,
1118 DOMEvent_get_timeStamp
,
1121 DOMEvent_preventDefault
,
1122 DOMEvent_stopPropagation
,
1123 DOMEvent_stopImmediatePropagation
,
1124 DOMEvent_get_isTrusted
,
1125 DOMEvent_put_cancelBubble
,
1126 DOMEvent_get_cancelBubble
,
1127 DOMEvent_get_srcElement
1130 static inline DOMEvent
*impl_from_IDOMUIEvent(IDOMUIEvent
*iface
)
1132 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMUIEvent_iface
);
1135 static HRESULT WINAPI
DOMUIEvent_QueryInterface(IDOMUIEvent
*iface
, REFIID riid
, void **ppv
)
1137 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1138 return IDOMEvent_QueryInterface(&This
->IDOMEvent_iface
, riid
, ppv
);
1141 static ULONG WINAPI
DOMUIEvent_AddRef(IDOMUIEvent
*iface
)
1143 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1144 return IDOMEvent_AddRef(&This
->IDOMEvent_iface
);
1147 static ULONG WINAPI
DOMUIEvent_Release(IDOMUIEvent
*iface
)
1149 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1150 return IDOMEvent_Release(&This
->IDOMEvent_iface
);
1153 static HRESULT WINAPI
DOMUIEvent_GetTypeInfoCount(IDOMUIEvent
*iface
, UINT
*pctinfo
)
1155 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1156 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1159 static HRESULT WINAPI
DOMUIEvent_GetTypeInfo(IDOMUIEvent
*iface
, UINT iTInfo
,
1160 LCID lcid
, ITypeInfo
**ppTInfo
)
1162 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1163 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1166 static HRESULT WINAPI
DOMUIEvent_GetIDsOfNames(IDOMUIEvent
*iface
, REFIID riid
,
1167 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1169 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1170 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
1174 static HRESULT WINAPI
DOMUIEvent_Invoke(IDOMUIEvent
*iface
, DISPID dispIdMember
,
1175 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1176 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1178 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1179 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
1180 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1183 static HRESULT WINAPI
DOMUIEvent_get_view(IDOMUIEvent
*iface
, IHTMLWindow2
**p
)
1185 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1186 mozIDOMWindowProxy
*moz_window
;
1187 HTMLOuterWindow
*view
= NULL
;
1190 TRACE("(%p)->(%p)\n", This
, p
);
1192 nsres
= nsIDOMUIEvent_GetView(This
->ui_event
, &moz_window
);
1193 if(NS_FAILED(nsres
))
1197 view
= mozwindow_to_window(moz_window
);
1198 mozIDOMWindowProxy_Release(moz_window
);
1201 IHTMLWindow2_AddRef((*p
= &view
->base
.inner_window
->base
.IHTMLWindow2_iface
));
1207 static HRESULT WINAPI
DOMUIEvent_get_detail(IDOMUIEvent
*iface
, LONG
*p
)
1209 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1213 TRACE("(%p)->(%p)\n", This
, p
);
1215 nsres
= nsIDOMUIEvent_GetDetail(This
->ui_event
, &detail
);
1216 if(NS_FAILED(nsres
))
1223 static HRESULT WINAPI
DOMUIEvent_initUIEvent(IDOMUIEvent
*iface
, BSTR type
, VARIANT_BOOL can_bubble
,
1224 VARIANT_BOOL cancelable
, IHTMLWindow2
*view
, LONG detail
)
1226 DOMEvent
*This
= impl_from_IDOMUIEvent(iface
);
1231 TRACE("(%p)->(%s %x %x %p %x)\n", This
, debugstr_w(type
), can_bubble
, cancelable
, view
, detail
);
1234 TRACE("called on already dispatched event\n");
1239 FIXME("view argument is not supported\n");
1241 hres
= IDOMEvent_initEvent(&This
->IDOMEvent_iface
, type
, can_bubble
, cancelable
);
1245 nsAString_InitDepend(&type_str
, type
);
1246 nsres
= nsIDOMUIEvent_InitUIEvent(This
->ui_event
, &type_str
, can_bubble
, cancelable
,
1247 NULL
/* FIXME */, detail
);
1248 nsAString_Finish(&type_str
);
1249 if(NS_FAILED(nsres
)) {
1250 FIXME("InitUIEvent failed: %08x\n", nsres
);
1257 static const IDOMUIEventVtbl DOMUIEventVtbl
= {
1258 DOMUIEvent_QueryInterface
,
1261 DOMUIEvent_GetTypeInfoCount
,
1262 DOMUIEvent_GetTypeInfo
,
1263 DOMUIEvent_GetIDsOfNames
,
1265 DOMUIEvent_get_view
,
1266 DOMUIEvent_get_detail
,
1267 DOMUIEvent_initUIEvent
1270 static inline DOMEvent
*impl_from_IDOMMouseEvent(IDOMMouseEvent
*iface
)
1272 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMMouseEvent_iface
);
1275 static HRESULT WINAPI
DOMMouseEvent_QueryInterface(IDOMMouseEvent
*iface
, REFIID riid
, void **ppv
)
1277 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1278 return IDOMEvent_QueryInterface(&This
->IDOMEvent_iface
, riid
, ppv
);
1281 static ULONG WINAPI
DOMMouseEvent_AddRef(IDOMMouseEvent
*iface
)
1283 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1284 return IDOMEvent_AddRef(&This
->IDOMEvent_iface
);
1287 static ULONG WINAPI
DOMMouseEvent_Release(IDOMMouseEvent
*iface
)
1289 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1290 return IDOMEvent_Release(&This
->IDOMEvent_iface
);
1293 static HRESULT WINAPI
DOMMouseEvent_GetTypeInfoCount(IDOMMouseEvent
*iface
, UINT
*pctinfo
)
1295 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1296 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1299 static HRESULT WINAPI
DOMMouseEvent_GetTypeInfo(IDOMMouseEvent
*iface
, UINT iTInfo
,
1300 LCID lcid
, ITypeInfo
**ppTInfo
)
1302 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1303 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1306 static HRESULT WINAPI
DOMMouseEvent_GetIDsOfNames(IDOMMouseEvent
*iface
, REFIID riid
,
1307 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1309 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1310 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
1314 static HRESULT WINAPI
DOMMouseEvent_Invoke(IDOMMouseEvent
*iface
, DISPID dispIdMember
,
1315 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1316 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1318 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1319 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
1320 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1323 static HRESULT WINAPI
DOMMouseEvent_get_screenX(IDOMMouseEvent
*iface
, LONG
*p
)
1325 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1329 TRACE("(%p)->(%p)\n", This
, p
);
1331 nsres
= nsIDOMMouseEvent_GetScreenX(This
->mouse_event
, &screen_x
);
1332 if(NS_FAILED(nsres
))
1339 static HRESULT WINAPI
DOMMouseEvent_get_screenY(IDOMMouseEvent
*iface
, LONG
*p
)
1341 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1345 TRACE("(%p)->(%p)\n", This
, p
);
1347 nsres
= nsIDOMMouseEvent_GetScreenY(This
->mouse_event
, &screen_y
);
1348 if(NS_FAILED(nsres
))
1355 static HRESULT WINAPI
DOMMouseEvent_get_clientX(IDOMMouseEvent
*iface
, LONG
*p
)
1357 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1361 TRACE("(%p)->(%p)\n", This
, p
);
1363 nsres
= nsIDOMMouseEvent_GetClientX(This
->mouse_event
, &client_x
);
1364 if(NS_FAILED(nsres
))
1371 static HRESULT WINAPI
DOMMouseEvent_get_clientY(IDOMMouseEvent
*iface
, LONG
*p
)
1373 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1377 TRACE("(%p)->(%p)\n", This
, p
);
1379 nsres
= nsIDOMMouseEvent_GetClientY(This
->mouse_event
, &client_y
);
1380 if(NS_FAILED(nsres
))
1387 static HRESULT WINAPI
DOMMouseEvent_get_ctrlKey(IDOMMouseEvent
*iface
, VARIANT_BOOL
*p
)
1389 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1393 TRACE("(%p)->(%p)\n", This
, p
);
1395 nsres
= nsIDOMMouseEvent_GetCtrlKey(This
->mouse_event
, &r
);
1396 if(NS_FAILED(nsres
))
1399 *p
= variant_bool(r
);
1403 static HRESULT WINAPI
DOMMouseEvent_get_shiftKey(IDOMMouseEvent
*iface
, VARIANT_BOOL
*p
)
1405 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1409 TRACE("(%p)->(%p)\n", This
, p
);
1411 nsres
= nsIDOMMouseEvent_GetShiftKey(This
->mouse_event
, &r
);
1412 if(NS_FAILED(nsres
))
1415 *p
= variant_bool(r
);
1419 static HRESULT WINAPI
DOMMouseEvent_get_altKey(IDOMMouseEvent
*iface
, VARIANT_BOOL
*p
)
1421 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1425 TRACE("(%p)->(%p)\n", This
, p
);
1427 nsres
= nsIDOMMouseEvent_GetAltKey(This
->mouse_event
, &r
);
1428 if(NS_FAILED(nsres
))
1431 *p
= variant_bool(r
);
1435 static HRESULT WINAPI
DOMMouseEvent_get_metaKey(IDOMMouseEvent
*iface
, VARIANT_BOOL
*p
)
1437 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1441 TRACE("(%p)->(%p)\n", This
, p
);
1443 nsres
= nsIDOMMouseEvent_GetMetaKey(This
->mouse_event
, &r
);
1444 if(NS_FAILED(nsres
))
1447 *p
= variant_bool(r
);
1451 static HRESULT WINAPI
DOMMouseEvent_get_button(IDOMMouseEvent
*iface
, USHORT
*p
)
1453 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1457 TRACE("(%p)->(%p)\n", This
, p
);
1459 nsres
= nsIDOMMouseEvent_GetButton(This
->mouse_event
, &r
);
1460 if(NS_FAILED(nsres
))
1467 static HRESULT WINAPI
DOMMouseEvent_get_relatedTarget(IDOMMouseEvent
*iface
, IEventTarget
**p
)
1469 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1470 nsIDOMEventTarget
*related_target
;
1471 nsIDOMNode
*target_node
;
1476 TRACE("(%p)->(%p)\n", This
, p
);
1478 nsres
= nsIDOMMouseEvent_GetRelatedTarget(This
->mouse_event
, &related_target
);
1479 if(NS_FAILED(nsres
))
1482 if(!related_target
) {
1487 nsres
= nsIDOMEventTarget_QueryInterface(related_target
, &IID_nsIDOMNode
, (void**)&target_node
);
1488 nsIDOMEventTarget_Release(related_target
);
1489 if(NS_FAILED(nsres
)) {
1490 FIXME("Only node targets supported\n");
1494 hres
= get_node(target_node
, TRUE
, &node
);
1495 nsIDOMNode_Release(target_node
);
1499 *p
= &node
->event_target
.IEventTarget_iface
;
1503 static HRESULT WINAPI
DOMMouseEvent_initMouseEvent(IDOMMouseEvent
*iface
, BSTR type
,
1504 VARIANT_BOOL can_bubble
, VARIANT_BOOL cancelable
, IHTMLWindow2
*view
, LONG detail
,
1505 LONG screen_x
, LONG screen_y
, LONG client_x
, LONG client_y
, VARIANT_BOOL ctrl_key
,
1506 VARIANT_BOOL alt_key
, VARIANT_BOOL shift_key
, VARIANT_BOOL meta_key
, USHORT button
,
1507 IEventTarget
*related_target
)
1509 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1510 nsIDOMEventTarget
*nstarget
= NULL
;
1515 TRACE("(%p)->(%s %x %x %p %d %d %d %d %d %x %x %x %x %u %p)\n", This
, debugstr_w(type
),
1516 can_bubble
, cancelable
, view
, detail
, screen_x
, screen_y
, client_x
, client_y
,
1517 ctrl_key
, alt_key
, shift_key
, meta_key
, button
, related_target
);
1520 TRACE("called on already dispatched event\n");
1525 FIXME("view argument is not supported\n");
1527 if(related_target
) {
1528 hres
= get_gecko_target(related_target
, &nstarget
);
1533 hres
= IDOMEvent_initEvent(&This
->IDOMEvent_iface
, type
, can_bubble
, cancelable
);
1534 if(SUCCEEDED(hres
)) {
1535 nsAString_InitDepend(&type_str
, type
);
1536 nsres
= nsIDOMMouseEvent_InitMouseEvent(This
->mouse_event
, &type_str
, can_bubble
, cancelable
,
1537 NULL
/* FIXME */, detail
, screen_x
, screen_y
,
1538 client_x
, client_y
, ctrl_key
, alt_key
, shift_key
,
1539 meta_key
, button
, nstarget
);
1540 nsAString_Finish(&type_str
);
1541 if(NS_FAILED(nsres
)) {
1542 FIXME("InitMouseEvent failed: %08x\n", nsres
);
1548 nsIDOMEventTarget_Release(nstarget
);
1552 static HRESULT WINAPI
DOMMouseEvent_getModifierState(IDOMMouseEvent
*iface
, BSTR key
,
1553 VARIANT_BOOL
*activated
)
1555 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1556 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(key
), activated
);
1560 static HRESULT WINAPI
DOMMouseEvent_get_buttons(IDOMMouseEvent
*iface
, USHORT
*p
)
1562 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1566 TRACE("(%p)->(%p)\n", This
, p
);
1568 nsres
= nsIDOMMouseEvent_GetButtons(This
->mouse_event
, &r
);
1569 if(NS_FAILED(nsres
))
1576 static HRESULT WINAPI
DOMMouseEvent_get_fromElement(IDOMMouseEvent
*iface
, IHTMLElement
**p
)
1578 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1579 FIXME("(%p)->(%p)\n", This
, p
);
1583 static HRESULT WINAPI
DOMMouseEvent_get_toElement(IDOMMouseEvent
*iface
, IHTMLElement
**p
)
1585 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1586 FIXME("(%p)->(%p)\n", This
, p
);
1590 static HRESULT WINAPI
DOMMouseEvent_get_x(IDOMMouseEvent
*iface
, LONG
*p
)
1592 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1593 FIXME("(%p)->(%p)\n", This
, p
);
1597 static HRESULT WINAPI
DOMMouseEvent_get_y(IDOMMouseEvent
*iface
, LONG
*p
)
1599 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1600 FIXME("(%p)->(%p)\n", This
, p
);
1604 static HRESULT WINAPI
DOMMouseEvent_get_offsetX(IDOMMouseEvent
*iface
, LONG
*p
)
1606 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1608 FIXME("(%p)->(%p) returning 0\n", This
, p
);
1614 static HRESULT WINAPI
DOMMouseEvent_get_offsetY(IDOMMouseEvent
*iface
, LONG
*p
)
1616 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1618 FIXME("(%p)->(%p) returning 0\n", This
, p
);
1624 static HRESULT WINAPI
DOMMouseEvent_get_pageX(IDOMMouseEvent
*iface
, LONG
*p
)
1626 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1630 TRACE("(%p)->(%p)\n", This
, p
);
1632 nsres
= nsIDOMMouseEvent_GetPageX(This
->mouse_event
, &r
);
1633 if(NS_FAILED(nsres
))
1640 static HRESULT WINAPI
DOMMouseEvent_get_pageY(IDOMMouseEvent
*iface
, LONG
*p
)
1642 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1646 TRACE("(%p)->(%p)\n", This
, p
);
1648 nsres
= nsIDOMMouseEvent_GetPageY(This
->mouse_event
, &r
);
1649 if(NS_FAILED(nsres
))
1656 static HRESULT WINAPI
DOMMouseEvent_get_layerX(IDOMMouseEvent
*iface
, LONG
*p
)
1658 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1659 FIXME("(%p)->(%p)\n", This
, p
);
1663 static HRESULT WINAPI
DOMMouseEvent_get_layerY(IDOMMouseEvent
*iface
, LONG
*p
)
1665 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1666 FIXME("(%p)->(%p)\n", This
, p
);
1670 static HRESULT WINAPI
DOMMouseEvent_get_which(IDOMMouseEvent
*iface
, USHORT
*p
)
1672 DOMEvent
*This
= impl_from_IDOMMouseEvent(iface
);
1676 TRACE("(%p)->(%p)\n", This
, p
);
1678 nsres
= nsIDOMMouseEvent_GetWhich(This
->mouse_event
, &r
);
1679 if(NS_FAILED(nsres
))
1686 static const IDOMMouseEventVtbl DOMMouseEventVtbl
= {
1687 DOMMouseEvent_QueryInterface
,
1688 DOMMouseEvent_AddRef
,
1689 DOMMouseEvent_Release
,
1690 DOMMouseEvent_GetTypeInfoCount
,
1691 DOMMouseEvent_GetTypeInfo
,
1692 DOMMouseEvent_GetIDsOfNames
,
1693 DOMMouseEvent_Invoke
,
1694 DOMMouseEvent_get_screenX
,
1695 DOMMouseEvent_get_screenY
,
1696 DOMMouseEvent_get_clientX
,
1697 DOMMouseEvent_get_clientY
,
1698 DOMMouseEvent_get_ctrlKey
,
1699 DOMMouseEvent_get_shiftKey
,
1700 DOMMouseEvent_get_altKey
,
1701 DOMMouseEvent_get_metaKey
,
1702 DOMMouseEvent_get_button
,
1703 DOMMouseEvent_get_relatedTarget
,
1704 DOMMouseEvent_initMouseEvent
,
1705 DOMMouseEvent_getModifierState
,
1706 DOMMouseEvent_get_buttons
,
1707 DOMMouseEvent_get_fromElement
,
1708 DOMMouseEvent_get_toElement
,
1709 DOMMouseEvent_get_x
,
1710 DOMMouseEvent_get_y
,
1711 DOMMouseEvent_get_offsetX
,
1712 DOMMouseEvent_get_offsetY
,
1713 DOMMouseEvent_get_pageX
,
1714 DOMMouseEvent_get_pageY
,
1715 DOMMouseEvent_get_layerX
,
1716 DOMMouseEvent_get_layerY
,
1717 DOMMouseEvent_get_which
1720 static inline DOMEvent
*impl_from_IDOMKeyboardEvent(IDOMKeyboardEvent
*iface
)
1722 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMKeyboardEvent_iface
);
1725 static HRESULT WINAPI
DOMKeyboardEvent_QueryInterface(IDOMKeyboardEvent
*iface
, REFIID riid
, void **ppv
)
1727 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1728 return IDOMEvent_QueryInterface(&This
->IDOMEvent_iface
, riid
, ppv
);
1731 static ULONG WINAPI
DOMKeyboardEvent_AddRef(IDOMKeyboardEvent
*iface
)
1733 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1734 return IDOMEvent_AddRef(&This
->IDOMEvent_iface
);
1737 static ULONG WINAPI
DOMKeyboardEvent_Release(IDOMKeyboardEvent
*iface
)
1739 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1740 return IDOMEvent_Release(&This
->IDOMEvent_iface
);
1743 static HRESULT WINAPI
DOMKeyboardEvent_GetTypeInfoCount(IDOMKeyboardEvent
*iface
, UINT
*pctinfo
)
1745 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1746 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1749 static HRESULT WINAPI
DOMKeyboardEvent_GetTypeInfo(IDOMKeyboardEvent
*iface
, UINT iTInfo
,
1750 LCID lcid
, ITypeInfo
**ppTInfo
)
1752 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1753 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1756 static HRESULT WINAPI
DOMKeyboardEvent_GetIDsOfNames(IDOMKeyboardEvent
*iface
, REFIID riid
,
1757 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1759 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1760 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
1764 static HRESULT WINAPI
DOMKeyboardEvent_Invoke(IDOMKeyboardEvent
*iface
, DISPID dispIdMember
,
1765 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1766 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1768 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1769 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
1770 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1773 static HRESULT WINAPI
DOMKeyboardEvent_get_key(IDOMKeyboardEvent
*iface
, BSTR
*p
)
1775 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1779 TRACE("(%p)->(%p)\n", This
, p
);
1782 nsAString_Init(&key_str
, NULL
);
1783 nsres
= nsIDOMKeyEvent_GetKey(This
->keyboard_event
, &key_str
);
1784 return return_nsstr(nsres
, &key_str
, p
);
1787 static HRESULT WINAPI
DOMKeyboardEvent_get_location(IDOMKeyboardEvent
*iface
, ULONG
*p
)
1789 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1793 TRACE("(%p)->(%p)\n", This
, p
);
1795 nsres
= nsIDOMKeyEvent_GetLocation(This
->keyboard_event
, &r
);
1796 if(NS_FAILED(nsres
))
1803 static HRESULT WINAPI
DOMKeyboardEvent_get_ctrlKey(IDOMKeyboardEvent
*iface
, VARIANT_BOOL
*p
)
1805 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1809 TRACE("(%p)->(%p)\n", This
, p
);
1811 nsres
= nsIDOMKeyEvent_GetCtrlKey(This
->keyboard_event
, &r
);
1812 if(NS_FAILED(nsres
))
1815 *p
= variant_bool(r
);
1819 static HRESULT WINAPI
DOMKeyboardEvent_get_shiftKey(IDOMKeyboardEvent
*iface
, VARIANT_BOOL
*p
)
1821 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1825 TRACE("(%p)->(%p)\n", This
, p
);
1827 nsres
= nsIDOMKeyEvent_GetShiftKey(This
->keyboard_event
, &r
);
1828 if(NS_FAILED(nsres
))
1831 *p
= variant_bool(r
);
1835 static HRESULT WINAPI
DOMKeyboardEvent_get_altKey(IDOMKeyboardEvent
*iface
, VARIANT_BOOL
*p
)
1837 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1841 TRACE("(%p)->(%p)\n", This
, p
);
1843 nsres
= nsIDOMKeyEvent_GetAltKey(This
->keyboard_event
, &r
);
1844 if(NS_FAILED(nsres
))
1847 *p
= variant_bool(r
);
1851 static HRESULT WINAPI
DOMKeyboardEvent_get_metaKey(IDOMKeyboardEvent
*iface
, VARIANT_BOOL
*p
)
1853 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1857 TRACE("(%p)->(%p)\n", This
, p
);
1859 nsres
= nsIDOMKeyEvent_GetMetaKey(This
->keyboard_event
, &r
);
1860 if(NS_FAILED(nsres
))
1863 *p
= variant_bool(r
);
1867 static HRESULT WINAPI
DOMKeyboardEvent_get_repeat(IDOMKeyboardEvent
*iface
, VARIANT_BOOL
*p
)
1869 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1873 TRACE("(%p)->(%p)\n", This
, p
);
1875 nsres
= nsIDOMKeyEvent_GetRepeat(This
->keyboard_event
, &r
);
1876 if(NS_FAILED(nsres
))
1879 *p
= variant_bool(r
);
1883 static HRESULT WINAPI
DOMKeyboardEvent_getModifierState(IDOMKeyboardEvent
*iface
, BSTR key
,
1884 VARIANT_BOOL
*state
)
1886 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1887 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(key
), state
);
1891 static HRESULT WINAPI
DOMKeyboardEvent_initKeyboardEvent(IDOMKeyboardEvent
*iface
, BSTR type
,
1892 VARIANT_BOOL can_bubble
, VARIANT_BOOL cancelable
, IHTMLWindow2
*view
, BSTR key
,
1893 ULONG location
, BSTR modifiers_list
, VARIANT_BOOL repeat
, BSTR locale
)
1895 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1896 FIXME("(%p)->(%s %x %x %p %s %u %s %x %s)\n", This
, debugstr_w(type
), can_bubble
,
1897 cancelable
, view
, debugstr_w(key
), location
, debugstr_w(modifiers_list
),
1898 repeat
, debugstr_w(locale
));
1902 static HRESULT WINAPI
DOMKeyboardEvent_get_keyCode(IDOMKeyboardEvent
*iface
, LONG
*p
)
1904 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1908 TRACE("(%p)->(%p)\n", This
, p
);
1910 nsres
= nsIDOMKeyEvent_GetKeyCode(This
->keyboard_event
, &r
);
1911 if(NS_FAILED(nsres
))
1918 static HRESULT WINAPI
DOMKeyboardEvent_get_charCode(IDOMKeyboardEvent
*iface
, LONG
*p
)
1920 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1924 TRACE("(%p)->(%p)\n", This
, p
);
1926 nsres
= nsIDOMKeyEvent_GetKeyCode(This
->keyboard_event
, &r
);
1927 if(NS_FAILED(nsres
))
1934 static HRESULT WINAPI
DOMKeyboardEvent_get_which(IDOMKeyboardEvent
*iface
, LONG
*p
)
1936 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1940 TRACE("(%p)->(%p)\n", This
, p
);
1942 nsres
= nsIDOMKeyEvent_GetWhich(This
->keyboard_event
, &r
);
1943 if(NS_FAILED(nsres
))
1950 static HRESULT WINAPI
DOMKeyboardEvent_get_char(IDOMKeyboardEvent
*iface
, VARIANT
*p
)
1952 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1953 FIXME("(%p)->(%p)\n", This
, p
);
1957 static HRESULT WINAPI
DOMKeyboardEvent_get_locale(IDOMKeyboardEvent
*iface
, BSTR
*p
)
1959 DOMEvent
*This
= impl_from_IDOMKeyboardEvent(iface
);
1960 FIXME("(%p)->(%p)\n", This
, p
);
1964 static const IDOMKeyboardEventVtbl DOMKeyboardEventVtbl
= {
1965 DOMKeyboardEvent_QueryInterface
,
1966 DOMKeyboardEvent_AddRef
,
1967 DOMKeyboardEvent_Release
,
1968 DOMKeyboardEvent_GetTypeInfoCount
,
1969 DOMKeyboardEvent_GetTypeInfo
,
1970 DOMKeyboardEvent_GetIDsOfNames
,
1971 DOMKeyboardEvent_Invoke
,
1972 DOMKeyboardEvent_get_key
,
1973 DOMKeyboardEvent_get_location
,
1974 DOMKeyboardEvent_get_ctrlKey
,
1975 DOMKeyboardEvent_get_shiftKey
,
1976 DOMKeyboardEvent_get_altKey
,
1977 DOMKeyboardEvent_get_metaKey
,
1978 DOMKeyboardEvent_get_repeat
,
1979 DOMKeyboardEvent_getModifierState
,
1980 DOMKeyboardEvent_initKeyboardEvent
,
1981 DOMKeyboardEvent_get_keyCode
,
1982 DOMKeyboardEvent_get_charCode
,
1983 DOMKeyboardEvent_get_which
,
1984 DOMKeyboardEvent_get_char
,
1985 DOMKeyboardEvent_get_locale
1988 static const tid_t DOMEvent_iface_tids
[] = {
1993 static dispex_static_data_t DOMEvent_dispex
= {
1999 static const tid_t DOMUIEvent_iface_tids
[] = {
2005 static dispex_static_data_t DOMUIEvent_dispex
= {
2008 DOMUIEvent_iface_tids
2011 static const tid_t DOMMouseEvent_iface_tids
[] = {
2018 static dispex_static_data_t DOMMouseEvent_dispex
= {
2020 DispDOMMouseEvent_tid
,
2021 DOMMouseEvent_iface_tids
2024 static const tid_t DOMKeyboardEvent_iface_tids
[] = {
2027 IDOMKeyboardEvent_tid
,
2031 static dispex_static_data_t DOMKeyboardEvent_dispex
= {
2033 DispDOMKeyboardEvent_tid
,
2034 DOMKeyboardEvent_iface_tids
2037 static DOMEvent
*alloc_event(nsIDOMEvent
*nsevent
, eventid_t event_id
)
2039 dispex_static_data_t
*dispex_data
= &DOMEvent_dispex
;
2044 /* 1601 to 1970 is 369 years plus 89 leap days */
2045 const ULONGLONG time_epoch
= (ULONGLONG
)(369 * 365 + 89) * 86400 * 1000;
2047 event
= heap_alloc_zero(sizeof(*event
));
2051 event
->IDOMEvent_iface
.lpVtbl
= &DOMEventVtbl
;
2052 event
->IDOMUIEvent_iface
.lpVtbl
= &DOMUIEventVtbl
;
2053 event
->IDOMMouseEvent_iface
.lpVtbl
= &DOMMouseEventVtbl
;
2054 event
->IDOMKeyboardEvent_iface
.lpVtbl
= &DOMKeyboardEventVtbl
;
2056 event
->event_id
= event_id
;
2057 if(event_id
!= EVENTID_LAST
) {
2058 event
->type
= heap_strdupW(event_info
[event_id
].name
);
2063 event
->bubbles
= (event_info
[event_id
].flags
& EVENT_BUBBLES
) != 0;
2064 event
->cancelable
= (event_info
[event_id
].flags
& EVENT_CANCELABLE
) != 0;
2066 nsIDOMEvent_AddRef(event
->nsevent
= nsevent
);
2068 GetSystemTimeAsFileTime(&time
);
2069 event
->time_stamp
= (((ULONGLONG
)time
.dwHighDateTime
<<32) + time
.dwLowDateTime
) / 10000
2072 nsres
= nsIDOMEvent_QueryInterface(nsevent
, &IID_nsIDOMUIEvent
, (void**)&event
->ui_event
);
2073 if(NS_SUCCEEDED(nsres
))
2074 dispex_data
= &DOMUIEvent_dispex
;
2076 event
->ui_event
= NULL
;
2078 nsres
= nsIDOMEvent_QueryInterface(nsevent
, &IID_nsIDOMMouseEvent
, (void**)&event
->mouse_event
);
2079 if(NS_SUCCEEDED(nsres
))
2080 dispex_data
= &DOMMouseEvent_dispex
;
2082 event
->mouse_event
= NULL
;
2084 nsres
= nsIDOMEvent_QueryInterface(nsevent
, &IID_nsIDOMKeyEvent
, (void**)&event
->keyboard_event
);
2085 if(NS_SUCCEEDED(nsres
))
2086 dispex_data
= &DOMKeyboardEvent_dispex
;
2088 event
->keyboard_event
= NULL
;
2090 init_dispex(&event
->dispex
, (IUnknown
*)&event
->IDOMEvent_iface
, dispex_data
);
2094 HRESULT
create_event_from_nsevent(nsIDOMEvent
*nsevent
, DOMEvent
**ret_event
)
2096 eventid_t event_id
= EVENTID_LAST
;
2101 nsAString_Init(&nsstr
, NULL
);
2102 nsres
= nsIDOMEvent_GetType(nsevent
, &nsstr
);
2103 if(NS_SUCCEEDED(nsres
)) {
2105 nsAString_GetData(&nsstr
, &type
);
2106 event_id
= str_to_eid(type
);
2107 if(event_id
== EVENTID_LAST
)
2108 FIXME("unknown event type %s\n", debugstr_w(type
));
2110 ERR("GetType failed: %08x\n", nsres
);
2112 nsAString_Finish(&nsstr
);
2114 event
= alloc_event(nsevent
, event_id
);
2116 return E_OUTOFMEMORY
;
2122 HRESULT
create_document_event_str(HTMLDocumentNode
*doc
, const WCHAR
*type
, IDOMEvent
**ret_event
)
2124 nsIDOMEvent
*nsevent
;
2129 nsAString_InitDepend(&nsstr
, type
);
2130 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
2131 nsAString_Finish(&nsstr
);
2132 if(NS_FAILED(nsres
)) {
2133 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(type
), nsres
);
2137 event
= alloc_event(nsevent
, EVENTID_LAST
);
2138 nsIDOMEvent_Release(nsevent
);
2140 return E_OUTOFMEMORY
;
2142 *ret_event
= &event
->IDOMEvent_iface
;
2146 HRESULT
create_document_event(HTMLDocumentNode
*doc
, eventid_t event_id
, DOMEvent
**ret_event
)
2148 nsIDOMEvent
*nsevent
;
2153 nsAString_InitDepend(&nsstr
, event_types
[event_info
[event_id
].type
]);
2154 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
2155 nsAString_Finish(&nsstr
);
2156 if(NS_FAILED(nsres
)) {
2157 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(event_types
[event_info
[event_id
].type
]), nsres
);
2161 event
= alloc_event(nsevent
, event_id
);
2163 return E_OUTOFMEMORY
;
2165 event
->event_id
= event_id
;
2170 static HRESULT
call_disp_func(IDispatch
*disp
, DISPPARAMS
*dp
, VARIANT
*retv
)
2172 IDispatchEx
*dispex
;
2176 memset(&ei
, 0, sizeof(ei
));
2178 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
2179 if(SUCCEEDED(hres
)) {
2180 hres
= IDispatchEx_InvokeEx(dispex
, 0, GetUserDefaultLCID(), DISPATCH_METHOD
, dp
, retv
, &ei
, NULL
);
2181 IDispatchEx_Release(dispex
);
2183 TRACE("Could not get IDispatchEx interface: %08x\n", hres
);
2184 hres
= IDispatch_Invoke(disp
, 0, &IID_NULL
, GetUserDefaultLCID(), DISPATCH_METHOD
,
2185 dp
, retv
, &ei
, NULL
);
2191 static HRESULT
call_cp_func(IDispatch
*disp
, DISPID dispid
, IHTMLEventObj
*event_obj
, VARIANT
*retv
)
2193 DISPPARAMS dp
= {NULL
,NULL
,0,0};
2199 V_VT(&event_arg
) = VT_DISPATCH
;
2200 V_DISPATCH(&event_arg
) = (IDispatch
*)event_obj
;
2201 dp
.rgvarg
= &event_arg
;
2205 memset(&ei
, 0, sizeof(ei
));
2206 return IDispatch_Invoke(disp
, dispid
, &IID_NULL
, 0, DISPATCH_METHOD
, &dp
, retv
, &ei
, &argerr
);
2209 static BOOL
use_event_quirks(EventTarget
*event_target
)
2211 return dispex_compat_mode(&event_target
->dispex
) < COMPAT_MODE_IE9
;
2214 static BOOL
is_cp_event(cp_static_data_t
*data
, DISPID dispid
)
2223 hres
= get_dispids(data
->tid
, &data
->id_cnt
, &data
->ids
);
2229 max
= data
->id_cnt
-1;
2232 if(data
->ids
[i
] == dispid
)
2235 if(data
->ids
[i
] < dispid
)
2244 static void call_event_handlers(EventTarget
*event_target
, DOMEvent
*event
, dispatch_mode_t dispatch_mode
)
2246 const listener_container_t
*container
= get_listener_container(event_target
, event
->type
, FALSE
);
2247 const BOOL use_quirks
= use_event_quirks(event_target
);
2248 event_listener_t
*listener
, listeners_buf
[8], *listeners
= listeners_buf
;
2249 unsigned listeners_cnt
, listeners_size
;
2250 ConnectionPointContainer
*cp_container
= NULL
;
2251 const event_target_vtbl_t
*vtbl
= NULL
;
2255 assert(!event
->current_target
);
2256 event
->current_target
= event_target
;
2258 if(use_quirks
&& container
&& !list_empty(&container
->listeners
)
2259 && event
->phase
!= DEP_CAPTURING_PHASE
) {
2260 listener
= LIST_ENTRY(list_tail(&container
->listeners
), event_listener_t
, entry
);
2261 if(listener
&& listener
->function
&& listener
->type
== LISTENER_TYPE_ONEVENT
) {
2262 DISPID named_arg
= DISPID_THIS
;
2264 DISPPARAMS dp
= {&arg
, &named_arg
, 1, 1};
2266 V_VT(&arg
) = VT_DISPATCH
;
2267 V_DISPATCH(&arg
) = (IDispatch
*)&event_target
->dispex
.IDispatchEx_iface
;
2268 V_VT(&v
) = VT_EMPTY
;
2270 TRACE("%s >>>\n", debugstr_w(event
->type
));
2271 hres
= call_disp_func(listener
->function
, &dp
, &v
);
2273 TRACE("%s <<< %s\n", debugstr_w(event
->type
), debugstr_variant(&v
));
2275 if(event
->cancelable
) {
2276 if(V_VT(&v
) == VT_BOOL
) {
2278 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
2279 }else if(V_VT(&v
) != VT_EMPTY
) {
2280 FIXME("unhandled result %s\n", debugstr_variant(&v
));
2285 WARN("%s <<< %08x\n", debugstr_w(event
->type
), hres
);
2291 listeners_size
= sizeof(listeners_buf
)/sizeof(*listeners_buf
);
2294 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
2295 if(!listener
->function
)
2297 switch(listener
->type
) {
2298 case LISTENER_TYPE_ONEVENT
:
2299 if(use_quirks
|| event
->phase
== DEP_CAPTURING_PHASE
)
2302 case LISTENER_TYPE_CAPTURE
:
2303 if(event
->phase
== DEP_BUBBLING_PHASE
|| dispatch_mode
== DISPATCH_LEGACY
)
2306 case LISTENER_TYPE_BUBBLE
:
2307 if(event
->phase
== DEP_CAPTURING_PHASE
|| dispatch_mode
== DISPATCH_LEGACY
)
2310 case LISTENER_TYPE_ATTACHED
:
2311 if(event
->phase
== DEP_CAPTURING_PHASE
|| dispatch_mode
== DISPATCH_STANDARD
)
2316 if(listeners_cnt
== listeners_size
) {
2317 event_listener_t
*new_listeners
;
2318 if(listeners
== listeners_buf
) {
2319 new_listeners
= heap_alloc(listeners_size
* 2 * sizeof(*new_listeners
));
2322 memcpy(new_listeners
, listeners
, listeners_cnt
* sizeof(*listeners
));
2324 new_listeners
= heap_realloc(listeners
, listeners_size
* 2 * sizeof(*new_listeners
));
2326 listeners
= new_listeners
;
2327 listeners_size
*= 2;
2330 listeners
[listeners_cnt
].type
= listener
->type
;
2331 IDispatch_AddRef(listeners
[listeners_cnt
].function
= listener
->function
);
2336 for(listener
= listeners
; !event
->stop_immediate_propagation
2337 && listener
< listeners
+ listeners_cnt
; listener
++) {
2338 if(listener
->type
!= LISTENER_TYPE_ATTACHED
) {
2339 DISPID named_arg
= DISPID_THIS
;
2341 DISPPARAMS dp
= {args
, &named_arg
, 2, 1};
2343 V_VT(args
) = VT_DISPATCH
;
2344 V_DISPATCH(args
) = (IDispatch
*)&event_target
->dispex
.IDispatchEx_iface
;
2345 V_VT(args
+1) = VT_DISPATCH
;
2346 V_DISPATCH(args
+1) = dispatch_mode
== DISPATCH_LEGACY
2347 ? (IDispatch
*)event
->event_obj
: (IDispatch
*)&event
->IDOMEvent_iface
;
2348 V_VT(&v
) = VT_EMPTY
;
2350 TRACE("%s >>>\n", debugstr_w(event
->type
));
2351 hres
= call_disp_func(listener
->function
, &dp
, &v
);
2353 TRACE("%s <<< %s\n", debugstr_w(event
->type
),
2354 debugstr_variant(&v
));
2356 if(event
->cancelable
) {
2357 if(V_VT(&v
) == VT_BOOL
) {
2359 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
2360 }else if(V_VT(&v
) != VT_EMPTY
) {
2361 FIXME("unhandled result %s\n", debugstr_variant(&v
));
2366 WARN("%s <<< %08x\n", debugstr_w(event
->type
), hres
);
2370 DISPPARAMS dp
= {&arg
, NULL
, 1, 0};
2372 V_VT(&arg
) = VT_DISPATCH
;
2373 V_DISPATCH(&arg
) = (IDispatch
*)event
->event_obj
;
2374 V_VT(&v
) = VT_EMPTY
;
2376 TRACE("%s attached >>>\n", debugstr_w(event
->type
));
2377 hres
= call_disp_func(listener
->function
, &dp
, &v
);
2379 TRACE("%s attached <<<\n", debugstr_w(event
->type
));
2381 if(event
->cancelable
) {
2382 if(V_VT(&v
) == VT_BOOL
) {
2384 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
2385 }else if(V_VT(&v
) != VT_EMPTY
) {
2386 FIXME("unhandled result %s\n", debugstr_variant(&v
));
2391 WARN("%s attached <<< %08x\n", debugstr_w(event
->type
), hres
);
2396 for(listener
= listeners
; listener
< listeners
+ listeners_cnt
; listener
++)
2397 IDispatch_Release(listener
->function
);
2398 if(listeners
!= listeners_buf
)
2399 heap_free(listeners
);
2401 if(event
->phase
!= DEP_CAPTURING_PHASE
&& event
->event_id
!= EVENTID_LAST
2402 && event_info
[event
->event_id
].dispid
&& (vtbl
= dispex_get_vtbl(&event_target
->dispex
))
2403 && vtbl
->get_cp_container
)
2404 cp_container
= vtbl
->get_cp_container(&event_target
->dispex
);
2406 if(cp_container
->cps
) {
2407 ConnectionPoint
*cp
;
2410 for(j
=0; cp_container
->cp_entries
[j
].riid
; j
++) {
2411 cp
= cp_container
->cps
+ j
;
2412 if(!cp
->sinks_size
|| !is_cp_event(cp
->data
, event_info
[event
->event_id
].dispid
))
2415 for(i
=0; i
< cp
->sinks_size
; i
++) {
2416 if(!cp
->sinks
[i
].disp
)
2419 V_VT(&v
) = VT_EMPTY
;
2421 TRACE("cp %s [%u] >>>\n", debugstr_w(event
->type
), i
);
2422 hres
= call_cp_func(cp
->sinks
[i
].disp
, event_info
[event
->event_id
].dispid
,
2423 cp
->data
->pass_event_arg
? event
->event_obj
: NULL
, &v
);
2425 TRACE("cp %s [%u] <<<\n", debugstr_w(event
->type
), i
);
2427 if(event
->cancelable
) {
2428 if(V_VT(&v
) == VT_BOOL
) {
2430 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
2431 }else if(V_VT(&v
) != VT_EMPTY
) {
2432 FIXME("unhandled result %s\n", debugstr_variant(&v
));
2437 WARN("cp %s [%u] <<< %08x\n", debugstr_w(event
->type
), i
, hres
);
2442 IConnectionPointContainer_Release(&cp_container
->IConnectionPointContainer_iface
);
2445 event
->current_target
= NULL
;
2448 static HRESULT
dispatch_event_object(EventTarget
*event_target
, DOMEvent
*event
,
2449 dispatch_mode_t dispatch_mode
, VARIANT_BOOL
*r
)
2451 EventTarget
*target_chain_buf
[8], **target_chain
= target_chain_buf
;
2452 unsigned chain_cnt
, chain_buf_size
, i
;
2453 const event_target_vtbl_t
*vtbl
, *target_vtbl
;
2454 HTMLEventObj
*event_obj_ref
= NULL
;
2455 IHTMLEventObj
*prev_event
= NULL
;
2459 TRACE("(%p) %s\n", event_target
, debugstr_w(event
->type
));
2462 FIXME("Uninitialized event.\n");
2466 if(event
->current_target
) {
2467 FIXME("event is being dispatched.\n");
2471 iter
= event_target
;
2472 IEventTarget_AddRef(&event_target
->IEventTarget_iface
);
2475 chain_buf_size
= sizeof(target_chain_buf
)/sizeof(*target_chain_buf
);
2478 if(chain_cnt
== chain_buf_size
) {
2479 EventTarget
**new_chain
;
2480 if(target_chain
== target_chain_buf
) {
2481 new_chain
= heap_alloc(chain_buf_size
* 2 * sizeof(*new_chain
));
2484 memcpy(new_chain
, target_chain
, chain_buf_size
* sizeof(*new_chain
));
2486 new_chain
= heap_realloc(target_chain
, chain_buf_size
* 2 * sizeof(*new_chain
));
2490 chain_buf_size
*= 2;
2491 target_chain
= new_chain
;
2494 target_chain
[chain_cnt
++] = iter
;
2496 if(!(vtbl
= dispex_get_vtbl(&iter
->dispex
)) || !vtbl
->get_parent_event_target
)
2498 iter
= vtbl
->get_parent_event_target(&iter
->dispex
);
2501 if(!event
->event_obj
&& !event
->no_event_obj
) {
2502 event_obj_ref
= alloc_event_obj(event
);
2504 event
->event_obj
= &event_obj_ref
->IHTMLEventObj_iface
;
2507 target_vtbl
= dispex_get_vtbl(&event_target
->dispex
);
2508 if(target_vtbl
&& target_vtbl
->set_current_event
)
2509 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, event
->event_obj
);
2512 IEventTarget_Release(&event
->target
->IEventTarget_iface
);
2513 event
->target
= event_target
;
2514 IEventTarget_AddRef(&event_target
->IEventTarget_iface
);
2516 event
->phase
= DEP_CAPTURING_PHASE
;
2518 while(!event
->stop_propagation
&& i
)
2519 call_event_handlers(target_chain
[i
--], event
, dispatch_mode
);
2521 if(!event
->stop_propagation
) {
2522 event
->phase
= DEP_AT_TARGET
;
2523 call_event_handlers(target_chain
[0], event
, dispatch_mode
);
2526 if(event
->bubbles
) {
2527 event
->phase
= DEP_BUBBLING_PHASE
;
2528 for(i
= 1; !event
->stop_propagation
&& i
< chain_cnt
; i
++)
2529 call_event_handlers(target_chain
[i
], event
, dispatch_mode
);
2533 *r
= variant_bool(!event
->prevent_default
);
2535 if(target_vtbl
&& target_vtbl
->set_current_event
) {
2536 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, prev_event
);
2538 IHTMLEventObj_Release(prev_event
);
2541 if(event
->event_id
!= EVENTID_LAST
&& (event_info
[event
->event_id
].flags
& EVENT_HASDEFAULTHANDLERS
)) {
2542 for(i
= 0; !event
->prevent_default
&& i
< chain_cnt
; i
++) {
2543 BOOL prevent_default
= FALSE
;
2544 vtbl
= dispex_get_vtbl(&target_chain
[i
]->dispex
);
2545 if(!vtbl
|| !vtbl
->handle_event_default
)
2547 hres
= vtbl
->handle_event_default(&event_target
->dispex
, event
->event_id
,
2548 event
->nsevent
, &prevent_default
);
2549 if(FAILED(hres
) || event
->stop_propagation
)
2552 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
2556 event
->prevent_default
= FALSE
;
2558 event
->event_obj
= NULL
;
2559 IHTMLEventObj_Release(&event_obj_ref
->IHTMLEventObj_iface
);
2562 for(i
= 0; i
< chain_cnt
; i
++)
2563 IEventTarget_Release(&target_chain
[i
]->IEventTarget_iface
);
2564 if(target_chain
!= target_chain_buf
)
2565 heap_free(target_chain
);
2570 void dispatch_event(EventTarget
*event_target
, DOMEvent
*event
)
2572 dispatch_event_object(event_target
, event
, DISPATCH_BOTH
, NULL
);
2575 HRESULT
fire_event(HTMLDOMNode
*node
, const WCHAR
*event_name
, VARIANT
*event_var
, VARIANT_BOOL
*cancelled
)
2577 HTMLEventObj
*event_obj
= NULL
;
2579 HRESULT hres
= S_OK
;
2581 eid
= attr_to_eid(event_name
);
2582 if(eid
== EVENTID_LAST
) {
2583 WARN("unknown event %s\n", debugstr_w(event_name
));
2584 return E_INVALIDARG
;
2587 if(event_var
&& V_VT(event_var
) != VT_EMPTY
&& V_VT(event_var
) != VT_ERROR
) {
2588 if(V_VT(event_var
) != VT_DISPATCH
) {
2589 FIXME("event_var %s not supported\n", debugstr_variant(event_var
));
2593 if(V_DISPATCH(event_var
)) {
2594 IHTMLEventObj
*event_iface
;
2596 hres
= IDispatch_QueryInterface(V_DISPATCH(event_var
), &IID_IHTMLEventObj
, (void**)&event_iface
);
2598 FIXME("No IHTMLEventObj iface\n");
2602 event_obj
= unsafe_impl_from_IHTMLEventObj(event_iface
);
2604 ERR("Not our IHTMLEventObj?\n");
2605 IHTMLEventObj_Release(event_iface
);
2612 event_obj
= alloc_event_obj(NULL
);
2614 return E_OUTOFMEMORY
;
2617 if(!event_obj
->event
)
2618 hres
= create_document_event(node
->doc
, eid
, &event_obj
->event
);
2620 if(SUCCEEDED(hres
)) {
2621 event_obj
->event
->event_obj
= &event_obj
->IHTMLEventObj_iface
;
2622 dispatch_event_object(&node
->event_target
, event_obj
->event
, DISPATCH_LEGACY
, NULL
);
2623 event_obj
->event
->event_obj
= NULL
;
2626 IHTMLEventObj_Release(&event_obj
->IHTMLEventObj_iface
);
2630 *cancelled
= VARIANT_TRUE
; /* FIXME */
2634 HRESULT
ensure_doc_nsevent_handler(HTMLDocumentNode
*doc
, eventid_t eid
)
2636 nsIDOMNode
*nsnode
= NULL
;
2638 TRACE("%s\n", debugstr_w(event_info
[eid
].name
));
2644 case EVENTID_FOCUSIN
:
2645 doc
->event_vector
[eid
] = TRUE
;
2646 eid
= EVENTID_FOCUS
;
2648 case EVENTID_FOCUSOUT
:
2649 doc
->event_vector
[eid
] = TRUE
;
2656 if(doc
->event_vector
[eid
] || !(event_info
[eid
].flags
& (EVENT_DEFAULTLISTENER
|EVENT_BIND_TO_BODY
)))
2659 if(event_info
[eid
].flags
& EVENT_BIND_TO_BODY
) {
2660 nsnode
= doc
->node
.nsnode
;
2661 nsIDOMNode_AddRef(nsnode
);
2664 doc
->event_vector
[eid
] = TRUE
;
2665 add_nsevent_listener(doc
, nsnode
, event_info
[eid
].name
);
2668 nsIDOMNode_Release(nsnode
);
2672 void detach_events(HTMLDocumentNode
*doc
)
2674 if(doc
->event_vector
) {
2677 for(i
=0; i
< EVENTID_LAST
; i
++) {
2678 if(doc
->event_vector
[i
]) {
2679 detach_nsevent(doc
, event_info
[i
].name
);
2680 doc
->event_vector
[i
] = FALSE
;
2685 release_nsevents(doc
);
2688 static HRESULT
get_event_dispex_ref(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
, VARIANT
**ret
)
2693 strcpyW(buf
+2, event_info
[eid
].name
);
2694 return dispex_get_dprop_ref(&event_target
->dispex
, buf
, alloc
, ret
);
2697 static event_listener_t
*get_onevent_listener(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
)
2699 listener_container_t
*container
;
2700 event_listener_t
*listener
;
2702 container
= get_listener_container(event_target
, event_info
[eid
].name
, alloc
);
2706 LIST_FOR_EACH_ENTRY_REV(listener
, &container
->listeners
, event_listener_t
, entry
) {
2707 if(listener
->type
== LISTENER_TYPE_ONEVENT
)
2714 listener
= heap_alloc(sizeof(*listener
));
2718 listener
->type
= LISTENER_TYPE_ONEVENT
;
2719 listener
->function
= NULL
;
2720 list_add_tail(&container
->listeners
, &listener
->entry
);
2724 static void remove_event_handler(EventTarget
*event_target
, eventid_t eid
)
2726 event_listener_t
*listener
;
2730 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &store
);
2732 VariantClear(store
);
2734 listener
= get_onevent_listener(event_target
, eid
, FALSE
);
2735 if(listener
&& listener
->function
) {
2736 IDispatch_Release(listener
->function
);
2737 listener
->function
= NULL
;
2741 static HRESULT
set_event_handler_disp(EventTarget
*event_target
, eventid_t eid
, IDispatch
*disp
)
2743 event_listener_t
*listener
;
2745 if(event_info
[eid
].flags
& EVENT_FIXME
)
2746 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
2748 remove_event_handler(event_target
, eid
);
2752 listener
= get_onevent_listener(event_target
, eid
, TRUE
);
2754 return E_OUTOFMEMORY
;
2756 if(listener
->function
)
2757 IDispatch_Release(listener
->function
);
2759 IDispatch_AddRef(listener
->function
= disp
);
2763 HRESULT
set_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
2767 if(use_event_quirks(event_target
)) {
2768 WARN("attempt to set to VT_EMPTY in quirks mode\n");
2773 remove_event_handler(event_target
, eid
);
2777 return set_event_handler_disp(event_target
, eid
, V_DISPATCH(var
));
2783 if(!use_event_quirks(event_target
))
2784 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var
)));
2787 * Setting event handler to string is a rare case and we don't want to
2788 * complicate nor increase memory of listener_container_t for that. Instead,
2789 * we store the value in DispatchEx, which can already handle custom
2792 remove_event_handler(event_target
, eid
);
2794 hres
= get_event_dispex_ref(event_target
, eid
, TRUE
, &v
);
2798 V_BSTR(v
) = SysAllocString(V_BSTR(var
));
2800 return E_OUTOFMEMORY
;
2806 FIXME("not handler %s\n", debugstr_variant(var
));
2813 HRESULT
get_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
2815 event_listener_t
*listener
;
2819 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &v
);
2820 if(SUCCEEDED(hres
) && V_VT(v
) != VT_EMPTY
) {
2821 V_VT(var
) = VT_EMPTY
;
2822 return VariantCopy(var
, v
);
2825 listener
= get_onevent_listener(event_target
, eid
, FALSE
);
2826 if(listener
&& listener
->function
) {
2827 V_VT(var
) = VT_DISPATCH
;
2828 V_DISPATCH(var
) = listener
->function
;
2829 IDispatch_AddRef(V_DISPATCH(var
));
2831 V_VT(var
) = VT_NULL
;
2837 HRESULT
attach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
, VARIANT_BOOL
*res
)
2839 listener_container_t
*container
;
2840 event_listener_t
*listener
;
2843 eid
= attr_to_eid(name
);
2844 if(eid
== EVENTID_LAST
) {
2845 WARN("Unknown event\n");
2846 *res
= VARIANT_TRUE
;
2850 container
= get_listener_container(event_target
, event_info
[eid
].name
, TRUE
);
2852 return E_OUTOFMEMORY
;
2854 listener
= heap_alloc(sizeof(*listener
));
2856 return E_OUTOFMEMORY
;
2858 listener
->type
= LISTENER_TYPE_ATTACHED
;
2859 IDispatch_AddRef(listener
->function
= disp
);
2860 if(use_event_quirks(event_target
))
2861 list_add_head(&container
->listeners
, &listener
->entry
);
2863 list_add_tail(&container
->listeners
, &listener
->entry
);
2865 *res
= VARIANT_TRUE
;
2869 HRESULT
detach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
)
2873 eid
= attr_to_eid(name
);
2874 if(eid
== EVENTID_LAST
) {
2875 WARN("Unknown event\n");
2879 remove_event_listener(event_target
, event_info
[eid
].name
, LISTENER_TYPE_ATTACHED
, disp
);
2883 void bind_target_event(HTMLDocumentNode
*doc
, EventTarget
*event_target
, const WCHAR
*event
, IDispatch
*disp
)
2887 TRACE("(%p %p %s %p)\n", doc
, event_target
, debugstr_w(event
), disp
);
2889 eid
= attr_to_eid(event
);
2890 if(eid
== EVENTID_LAST
) {
2891 WARN("Unsupported event %s\n", debugstr_w(event
));
2895 set_event_handler_disp(event_target
, eid
, disp
);
2898 void update_doc_cp_events(HTMLDocumentNode
*doc
, cp_static_data_t
*cp
)
2902 for(i
=0; i
< EVENTID_LAST
; i
++) {
2903 if((event_info
[i
].flags
& EVENT_DEFAULTLISTENER
) && is_cp_event(cp
, event_info
[i
].dispid
))
2904 ensure_doc_nsevent_handler(doc
, i
);
2908 void check_event_attr(HTMLDocumentNode
*doc
, nsIDOMElement
*nselem
)
2910 nsIDOMMozNamedAttrMap
*attr_map
;
2911 const PRUnichar
*name
, *value
;
2912 nsAString name_str
, value_str
;
2913 HTMLDOMNode
*node
= NULL
;
2922 nsres
= nsIDOMElement_HasAttributes(nselem
, &has_attrs
);
2923 if(NS_FAILED(nsres
) || !has_attrs
)
2926 nsres
= nsIDOMElement_GetAttributes(nselem
, &attr_map
);
2927 if(NS_FAILED(nsres
))
2930 nsres
= nsIDOMMozNamedAttrMap_GetLength(attr_map
, &length
);
2931 assert(nsres
== NS_OK
);
2933 nsAString_Init(&name_str
, NULL
);
2934 nsAString_Init(&value_str
, NULL
);
2936 for(i
= 0; i
< length
; i
++) {
2937 nsres
= nsIDOMMozNamedAttrMap_Item(attr_map
, i
, &attr
);
2938 if(NS_FAILED(nsres
))
2941 nsres
= nsIDOMAttr_GetName(attr
, &name_str
);
2942 if(NS_FAILED(nsres
)) {
2943 nsIDOMAttr_Release(attr
);
2947 nsAString_GetData(&name_str
, &name
);
2948 eid
= attr_to_eid(name
);
2949 if(eid
== EVENTID_LAST
) {
2950 nsIDOMAttr_Release(attr
);
2954 nsres
= nsIDOMAttr_GetValue(attr
, &value_str
);
2955 nsIDOMAttr_Release(attr
);
2956 if(NS_FAILED(nsres
))
2959 nsAString_GetData(&value_str
, &value
);
2963 TRACE("%p.%s = %s\n", nselem
, debugstr_w(name
), debugstr_w(value
));
2965 disp
= script_parse_event(doc
->window
, value
);
2970 hres
= get_node((nsIDOMNode
*)nselem
, TRUE
, &node
);
2972 IDispatch_Release(disp
);
2977 set_event_handler_disp(get_node_event_prop_target(node
, eid
), eid
, disp
);
2978 IDispatch_Release(disp
);
2983 nsAString_Finish(&name_str
);
2984 nsAString_Finish(&value_str
);
2985 nsIDOMMozNamedAttrMap_Release(attr_map
);
2988 HRESULT
doc_init_events(HTMLDocumentNode
*doc
)
2993 doc
->event_vector
= heap_alloc_zero(EVENTID_LAST
*sizeof(BOOL
));
2994 if(!doc
->event_vector
)
2995 return E_OUTOFMEMORY
;
2999 for(i
=0; i
< EVENTID_LAST
; i
++) {
3000 if(event_info
[i
].flags
& EVENT_HASDEFAULTHANDLERS
) {
3001 hres
= ensure_doc_nsevent_handler(doc
, i
);
3010 static inline EventTarget
*impl_from_IEventTarget(IEventTarget
*iface
)
3012 return CONTAINING_RECORD(iface
, EventTarget
, IEventTarget_iface
);
3015 static HRESULT WINAPI
EventTarget_QueryInterface(IEventTarget
*iface
, REFIID riid
, void **ppv
)
3017 EventTarget
*This
= impl_from_IEventTarget(iface
);
3018 return IDispatchEx_QueryInterface(&This
->dispex
.IDispatchEx_iface
, riid
, ppv
);
3021 static ULONG WINAPI
EventTarget_AddRef(IEventTarget
*iface
)
3023 EventTarget
*This
= impl_from_IEventTarget(iface
);
3024 return IDispatchEx_AddRef(&This
->dispex
.IDispatchEx_iface
);
3027 static ULONG WINAPI
EventTarget_Release(IEventTarget
*iface
)
3029 EventTarget
*This
= impl_from_IEventTarget(iface
);
3030 return IDispatchEx_Release(&This
->dispex
.IDispatchEx_iface
);
3033 static HRESULT WINAPI
EventTarget_GetTypeInfoCount(IEventTarget
*iface
, UINT
*pctinfo
)
3035 EventTarget
*This
= impl_from_IEventTarget(iface
);
3036 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
3039 static HRESULT WINAPI
EventTarget_GetTypeInfo(IEventTarget
*iface
, UINT iTInfo
,
3040 LCID lcid
, ITypeInfo
**ppTInfo
)
3042 EventTarget
*This
= impl_from_IEventTarget(iface
);
3043 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
3046 static HRESULT WINAPI
EventTarget_GetIDsOfNames(IEventTarget
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
3047 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
3049 EventTarget
*This
= impl_from_IEventTarget(iface
);
3050 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
,
3051 rgszNames
, cNames
, lcid
, rgDispId
);
3054 static HRESULT WINAPI
EventTarget_Invoke(IEventTarget
*iface
, DISPID dispIdMember
,
3055 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
3056 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
3058 EventTarget
*This
= impl_from_IEventTarget(iface
);
3059 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
,
3060 riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
3063 static HRESULT WINAPI
EventTarget_addEventListener(IEventTarget
*iface
, BSTR type
,
3064 IDispatch
*function
, VARIANT_BOOL capture
)
3066 EventTarget
*This
= impl_from_IEventTarget(iface
);
3067 listener_type_t listener_type
= capture
? LISTENER_TYPE_CAPTURE
: LISTENER_TYPE_BUBBLE
;
3068 listener_container_t
*container
;
3069 event_listener_t
*listener
;
3071 TRACE("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), function
, capture
);
3073 container
= get_listener_container(This
, type
, TRUE
);
3075 return E_OUTOFMEMORY
;
3077 /* check for duplicates */
3078 LIST_FOR_EACH_ENTRY(listener
, &container
->listeners
, event_listener_t
, entry
) {
3079 if(listener
->type
== listener_type
&& listener
->function
== function
)
3083 listener
= heap_alloc(sizeof(*listener
));
3085 return E_OUTOFMEMORY
;
3087 listener
->type
= listener_type
;
3088 IDispatch_AddRef(listener
->function
= function
);
3089 list_add_tail(&container
->listeners
, &listener
->entry
);
3093 static HRESULT WINAPI
EventTarget_removeEventListener(IEventTarget
*iface
, BSTR type
,
3094 IDispatch
*listener
, VARIANT_BOOL capture
)
3096 EventTarget
*This
= impl_from_IEventTarget(iface
);
3098 TRACE("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), listener
, capture
);
3100 remove_event_listener(This
, type
, capture
? LISTENER_TYPE_CAPTURE
: LISTENER_TYPE_BUBBLE
, listener
);
3104 static HRESULT WINAPI
EventTarget_dispatchEvent(IEventTarget
*iface
, IDOMEvent
*event_iface
, VARIANT_BOOL
*result
)
3106 EventTarget
*This
= impl_from_IEventTarget(iface
);
3107 DOMEvent
*event
= unsafe_impl_from_IDOMEvent(event_iface
);
3109 TRACE("(%p)->(%p %p)\n", This
, event
, result
);
3112 WARN("Invalid event\n");
3113 return E_INVALIDARG
;
3116 return dispatch_event_object(This
, event
, DISPATCH_STANDARD
, result
);
3119 static HRESULT
IEventTarget_addEventListener_hook(DispatchEx
*dispex
, LCID lcid
, WORD flags
,
3120 DISPPARAMS
*dp
, VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
3122 /* If only two arguments were given, implicitly set capture to false */
3123 if((flags
& DISPATCH_METHOD
) && dp
->cArgs
== 2 && !dp
->cNamedArgs
) {
3125 DISPPARAMS new_dp
= {args
, NULL
, 3, 0};
3126 V_VT(args
) = VT_BOOL
;
3127 V_BOOL(args
) = VARIANT_FALSE
;
3128 args
[1] = dp
->rgvarg
[0];
3129 args
[2] = dp
->rgvarg
[1];
3131 TRACE("implicit capture\n");
3133 return IDispatchEx_InvokeEx(&dispex
->IDispatchEx_iface
, DISPID_IEVENTTARGET_ADDEVENTLISTENER
,
3134 lcid
, flags
, &new_dp
, res
, ei
, caller
);
3137 return S_FALSE
; /* fallback to default */
3140 static HRESULT
IEventTarget_removeEventListener_hook(DispatchEx
*dispex
, LCID lcid
, WORD flags
,
3141 DISPPARAMS
*dp
, VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
3143 /* If only two arguments were given, implicitly set capture to false */
3144 if((flags
& DISPATCH_METHOD
) && dp
->cArgs
== 2 && !dp
->cNamedArgs
) {
3146 DISPPARAMS new_dp
= {args
, NULL
, 3, 0};
3147 V_VT(args
) = VT_BOOL
;
3148 V_BOOL(args
) = VARIANT_FALSE
;
3149 args
[1] = dp
->rgvarg
[0];
3150 args
[2] = dp
->rgvarg
[1];
3152 TRACE("implicit capture\n");
3154 return IDispatchEx_InvokeEx(&dispex
->IDispatchEx_iface
, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER
,
3155 lcid
, flags
, &new_dp
, res
, ei
, caller
);
3158 return S_FALSE
; /* fallback to default */
3161 static const IEventTargetVtbl EventTargetVtbl
= {
3162 EventTarget_QueryInterface
,
3164 EventTarget_Release
,
3165 EventTarget_GetTypeInfoCount
,
3166 EventTarget_GetTypeInfo
,
3167 EventTarget_GetIDsOfNames
,
3169 EventTarget_addEventListener
,
3170 EventTarget_removeEventListener
,
3171 EventTarget_dispatchEvent
3174 static EventTarget
*unsafe_impl_from_IEventTarget(IEventTarget
*iface
)
3176 return iface
&& iface
->lpVtbl
== &EventTargetVtbl
? impl_from_IEventTarget(iface
) : NULL
;
3179 static HRESULT
get_gecko_target(IEventTarget
*target
, nsIDOMEventTarget
**ret
)
3181 EventTarget
*event_target
= unsafe_impl_from_IEventTarget(target
);
3182 const event_target_vtbl_t
*vtbl
;
3186 WARN("Not our IEventTarget implementation\n");
3187 return E_INVALIDARG
;
3190 vtbl
= (const event_target_vtbl_t
*)dispex_get_vtbl(&event_target
->dispex
);
3191 nsres
= nsISupports_QueryInterface(vtbl
->get_gecko_target(&event_target
->dispex
),
3192 &IID_nsIDOMEventTarget
, (void**)ret
);
3193 assert(nsres
== NS_OK
);
3197 HRESULT
EventTarget_QI(EventTarget
*event_target
, REFIID riid
, void **ppv
)
3199 if(IsEqualGUID(riid
, &IID_IEventTarget
)) {
3200 if(use_event_quirks(event_target
)) {
3201 WARN("IEventTarget queried, but not supported by in document mode\n");
3203 return E_NOINTERFACE
;
3205 IEventTarget_AddRef(&event_target
->IEventTarget_iface
);
3206 *ppv
= &event_target
->IEventTarget_iface
;
3210 if(dispex_query_interface(&event_target
->dispex
, riid
, ppv
))
3211 return *ppv
? S_OK
: E_NOINTERFACE
;
3213 WARN("(%p)->(%s %p)\n", event_target
, debugstr_mshtml_guid(riid
), ppv
);
3215 return E_NOINTERFACE
;
3218 void EventTarget_init_dispex_info(dispex_data_t
*dispex_info
, compat_mode_t compat_mode
)
3220 static const dispex_hook_t IEventTarget_hooks
[] = {
3221 {DISPID_IEVENTTARGET_ADDEVENTLISTENER
, IEventTarget_addEventListener_hook
},
3222 {DISPID_IEVENTTARGET_REMOVEEVENTLISTENER
, IEventTarget_removeEventListener_hook
},
3226 if(compat_mode
>= COMPAT_MODE_IE9
)
3227 dispex_info_add_interface(dispex_info
, IEventTarget_tid
, IEventTarget_hooks
);
3230 static int event_id_cmp(const void *key
, const struct wine_rb_entry
*entry
)
3232 return strcmpW(key
, WINE_RB_ENTRY_VALUE(entry
, listener_container_t
, entry
)->type
);
3235 void EventTarget_Init(EventTarget
*event_target
, IUnknown
*outer
, dispex_static_data_t
*dispex_data
,
3236 compat_mode_t compat_mode
)
3238 init_dispex_with_compat_mode(&event_target
->dispex
, outer
, dispex_data
, compat_mode
);
3239 event_target
->IEventTarget_iface
.lpVtbl
= &EventTargetVtbl
;
3240 wine_rb_init(&event_target
->handler_map
, event_id_cmp
);
3243 void release_event_target(EventTarget
*event_target
)
3245 listener_container_t
*iter
, *iter2
;
3247 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter
, iter2
, &event_target
->handler_map
, listener_container_t
, entry
) {
3248 while(!list_empty(&iter
->listeners
)) {
3249 event_listener_t
*listener
= LIST_ENTRY(list_head(&iter
->listeners
), event_listener_t
, entry
);
3250 if(listener
->function
)
3251 IDispatch_Release(listener
->function
);
3252 list_remove(&listener
->entry
);
3253 heap_free(listener
);