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 struct wine_rb_entry entry
;
41 IDispatch
*handler_prop
;
46 static const WCHAR abortW
[] = {'a','b','o','r','t',0};
47 static const WCHAR beforeactivateW
[] = {'b','e','f','o','r','e','a','c','t','i','v','a','t','e',0};
48 static const WCHAR beforeunloadW
[] = {'b','e','f','o','r','e','u','n','l','o','a','d',0};
49 static const WCHAR blurW
[] = {'b','l','u','r',0};
50 static const WCHAR changeW
[] = {'c','h','a','n','g','e',0};
51 static const WCHAR clickW
[] = {'c','l','i','c','k',0};
52 static const WCHAR contextmenuW
[] = {'c','o','n','t','e','x','t','m','e','n','u',0};
53 static const WCHAR dataavailableW
[] = {'d','a','t','a','a','v','a','i','l','a','b','l','e',0};
54 static const WCHAR dblclickW
[] = {'d','b','l','c','l','i','c','k',0};
55 static const WCHAR dragW
[] = {'d','r','a','g',0};
56 static const WCHAR dragstartW
[] = {'d','r','a','g','s','t','a','r','t',0};
57 static const WCHAR errorW
[] = {'e','r','r','o','r',0};
58 static const WCHAR focusW
[] = {'f','o','c','u','s',0};
59 static const WCHAR focusinW
[] = {'f','o','c','u','s','i','n',0};
60 static const WCHAR focusoutW
[] = {'f','o','c','u','s','o','u','t',0};
61 static const WCHAR helpW
[] = {'h','e','l','p',0};
62 static const WCHAR keydownW
[] = {'k','e','y','d','o','w','n',0};
63 static const WCHAR keypressW
[] = {'k','e','y','p','r','e','s','s',0};
64 static const WCHAR keyupW
[] = {'k','e','y','u','p',0};
65 static const WCHAR loadW
[] = {'l','o','a','d',0};
66 static const WCHAR messageW
[] = {'m','e','s','s','a','g','e',0};
67 static const WCHAR mousedownW
[] = {'m','o','u','s','e','d','o','w','n',0};
68 static const WCHAR mousemoveW
[] = {'m','o','u','s','e','m','o','v','e',0};
69 static const WCHAR mouseoutW
[] = {'m','o','u','s','e','o','u','t',0};
70 static const WCHAR mouseoverW
[] = {'m','o','u','s','e','o','v','e','r',0};
71 static const WCHAR mouseupW
[] = {'m','o','u','s','e','u','p',0};
72 static const WCHAR mousewheelW
[] = {'m','o','u','s','e','w','h','e','e','l',0};
73 static const WCHAR pasteW
[] = {'p','a','s','t','e',0};
74 static const WCHAR readystatechangeW
[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
75 static const WCHAR resizeW
[] = {'r','e','s','i','z','e',0};
76 static const WCHAR scrollW
[] = {'s','c','r','o','l','l',0};
77 static const WCHAR selectstartW
[] = {'s','e','l','e','c','t','s','t','a','r','t',0};
78 static const WCHAR selectionchangeW
[] = {'s','e','l','e','c','t','i','o','n','c','h','a','n','g','e',0};
79 static const WCHAR submitW
[] = {'s','u','b','m','i','t',0};
80 static const WCHAR unloadW
[] = {'u','n','l','o','a','d',0};
82 static const WCHAR EventW
[] = {'E','v','e','n','t',0};
83 static const WCHAR UIEventW
[] = {'U','I','E','v','e','n','t',0};
84 static const WCHAR KeyboardEventW
[] = {'K','e','y','b','o','a','r','d','E','v','e','n','t',0};
85 static const WCHAR MouseEventW
[] = {'M','o','u','s','e','E','v','e','n','t',0};
98 static const WCHAR
*event_types
[] = {
116 #define EVENT_DEFAULTLISTENER 0x0001
117 #define EVENT_BUBBLES 0x0002
118 #define EVENT_BIND_TO_BODY 0x0008
119 #define EVENT_CANCELABLE 0x0010
120 #define EVENT_HASDEFAULTHANDLERS 0x0020
121 #define EVENT_FIXME 0x0040
123 static const event_info_t event_info
[] = {
124 {abortW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONABORT
,
126 {beforeactivateW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREACTIVATE
,
127 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
128 {beforeunloadW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONBEFOREUNLOAD
,
129 EVENT_DEFAULTLISTENER
| EVENT_CANCELABLE
},
130 {blurW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONBLUR
,
131 EVENT_DEFAULTLISTENER
},
132 {changeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONCHANGE
,
133 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
},
134 {clickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCLICK
,
135 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
136 {contextmenuW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONCONTEXTMENU
,
137 EVENT_BUBBLES
| EVENT_CANCELABLE
},
138 {dataavailableW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONDATAAVAILABLE
,
139 EVENT_FIXME
| EVENT_BUBBLES
},
140 {dblclickW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONDBLCLICK
,
141 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
142 {dragW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAG
,
143 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
144 {dragstartW
, EVENT_TYPE_DRAG
, DISPID_EVMETH_ONDRAGSTART
,
145 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
146 {errorW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONERROR
,
148 {focusW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUS
,
149 EVENT_DEFAULTLISTENER
},
150 {focusinW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSIN
,
152 {focusoutW
, EVENT_TYPE_FOCUS
, DISPID_EVMETH_ONFOCUSOUT
,
154 {helpW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONHELP
,
155 EVENT_BUBBLES
| EVENT_CANCELABLE
},
156 {keydownW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYDOWN
,
157 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
158 {keypressW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYPRESS
,
159 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
160 {keyupW
, EVENT_TYPE_KEYBOARD
, DISPID_EVMETH_ONKEYUP
,
161 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
162 {loadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONLOAD
,
164 {messageW
, EVENT_TYPE_MESSAGE
, DISPID_EVMETH_ONMESSAGE
,
166 {mousedownW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEDOWN
,
167 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
168 {mousemoveW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEMOVE
,
169 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
170 {mouseoutW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOUT
,
171 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
172 {mouseoverW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEOVER
,
173 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
174 {mouseupW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEUP
,
175 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
176 {mousewheelW
, EVENT_TYPE_MOUSE
, DISPID_EVMETH_ONMOUSEWHEEL
,
178 {pasteW
, EVENT_TYPE_CLIPBOARD
, DISPID_EVMETH_ONPASTE
,
179 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
180 {readystatechangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONREADYSTATECHANGE
,
182 {resizeW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONRESIZE
,
183 EVENT_DEFAULTLISTENER
},
184 {scrollW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONSCROLL
,
185 EVENT_DEFAULTLISTENER
| EVENT_BUBBLES
/* FIXME: not for elements */},
186 {selectionchangeW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTIONCHANGE
,
188 {selectstartW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSELECTSTART
,
189 EVENT_FIXME
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
190 {submitW
, EVENT_TYPE_EVENT
, DISPID_EVMETH_ONSUBMIT
,
191 EVENT_DEFAULTLISTENER
| EVENT_HASDEFAULTHANDLERS
| EVENT_BUBBLES
| EVENT_CANCELABLE
},
192 {unloadW
, EVENT_TYPE_UIEVENT
, DISPID_EVMETH_ONUNLOAD
,
196 static BOOL
use_event_quirks(EventTarget
*);
198 static eventid_t
str_to_eid(const WCHAR
*str
)
202 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
203 if(!strcmpW(event_info
[i
].name
, str
))
207 ERR("unknown type %s\n", debugstr_w(str
));
211 static eventid_t
attr_to_eid(const WCHAR
*str
)
215 if((str
[0] != 'o' && str
[0] != 'O') || (str
[1] != 'n' && str
[1] != 'N'))
218 for(i
=0; i
< sizeof(event_info
)/sizeof(event_info
[0]); i
++) {
219 if(!strcmpW(event_info
[i
].name
, str
+2))
228 IHTMLEventObj IHTMLEventObj_iface
;
232 const event_info_t
*type
;
234 VARIANT return_value
;
237 static inline HTMLEventObj
*impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
239 return CONTAINING_RECORD(iface
, HTMLEventObj
, IHTMLEventObj_iface
);
242 static HRESULT WINAPI
HTMLEventObj_QueryInterface(IHTMLEventObj
*iface
, REFIID riid
, void **ppv
)
244 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
246 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
248 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
249 *ppv
= &This
->IHTMLEventObj_iface
;
250 }else if(IsEqualGUID(&IID_IHTMLEventObj
, riid
)) {
251 *ppv
= &This
->IHTMLEventObj_iface
;
252 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
253 return *ppv
? S_OK
: E_NOINTERFACE
;
256 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
257 return E_NOINTERFACE
;
260 IUnknown_AddRef((IUnknown
*)*ppv
);
264 static ULONG WINAPI
HTMLEventObj_AddRef(IHTMLEventObj
*iface
)
266 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
267 LONG ref
= InterlockedIncrement(&This
->ref
);
269 TRACE("(%p) ref=%d\n", This
, ref
);
274 static ULONG WINAPI
HTMLEventObj_Release(IHTMLEventObj
*iface
)
276 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
277 LONG ref
= InterlockedDecrement(&This
->ref
);
279 TRACE("(%p) ref=%d\n", This
, ref
);
283 IDOMEvent_Release(&This
->event
->IDOMEvent_iface
);
284 release_dispex(&This
->dispex
);
291 static HRESULT WINAPI
HTMLEventObj_GetTypeInfoCount(IHTMLEventObj
*iface
, UINT
*pctinfo
)
293 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
294 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
297 static HRESULT WINAPI
HTMLEventObj_GetTypeInfo(IHTMLEventObj
*iface
, UINT iTInfo
,
298 LCID lcid
, ITypeInfo
**ppTInfo
)
300 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
301 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
304 static HRESULT WINAPI
HTMLEventObj_GetIDsOfNames(IHTMLEventObj
*iface
, REFIID riid
,
305 LPOLESTR
*rgszNames
, UINT cNames
,
306 LCID lcid
, DISPID
*rgDispId
)
308 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
309 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
313 static HRESULT WINAPI
HTMLEventObj_Invoke(IHTMLEventObj
*iface
, DISPID dispIdMember
,
314 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
315 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
317 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
318 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
319 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
322 static HRESULT WINAPI
HTMLEventObj_get_srcElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
324 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
326 TRACE("(%p)->(%p)\n", This
, p
);
329 if(This
->event
&& This
->event
->target
)
330 IDispatchEx_QueryInterface(&This
->event
->target
->dispex
.IDispatchEx_iface
, &IID_IHTMLElement
, (void**)p
);
334 static HRESULT WINAPI
HTMLEventObj_get_altKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
336 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
337 cpp_bool ret
= FALSE
;
339 TRACE("(%p)->(%p)\n", This
, p
);
342 nsIDOMKeyEvent
*key_event
;
345 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
346 if(NS_SUCCEEDED(nsres
)) {
347 nsIDOMKeyEvent_GetAltKey(key_event
, &ret
);
348 nsIDOMKeyEvent_Release(key_event
);
350 nsIDOMMouseEvent
*mouse_event
;
352 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
353 if(NS_SUCCEEDED(nsres
)) {
354 nsIDOMMouseEvent_GetAltKey(mouse_event
, &ret
);
355 nsIDOMMouseEvent_Release(mouse_event
);
360 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
364 static HRESULT WINAPI
HTMLEventObj_get_ctrlKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
366 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
367 cpp_bool ret
= FALSE
;
369 TRACE("(%p)->(%p)\n", This
, p
);
372 nsIDOMKeyEvent
*key_event
;
375 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
376 if(NS_SUCCEEDED(nsres
)) {
377 nsIDOMKeyEvent_GetCtrlKey(key_event
, &ret
);
378 nsIDOMKeyEvent_Release(key_event
);
380 nsIDOMMouseEvent
*mouse_event
;
382 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
383 if(NS_SUCCEEDED(nsres
)) {
384 nsIDOMMouseEvent_GetCtrlKey(mouse_event
, &ret
);
385 nsIDOMMouseEvent_Release(mouse_event
);
390 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
394 static HRESULT WINAPI
HTMLEventObj_get_shiftKey(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
396 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
397 cpp_bool ret
= FALSE
;
399 TRACE("(%p)->(%p)\n", This
, p
);
402 nsIDOMKeyEvent
*key_event
;
405 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
406 if(NS_SUCCEEDED(nsres
)) {
407 nsIDOMKeyEvent_GetShiftKey(key_event
, &ret
);
408 nsIDOMKeyEvent_Release(key_event
);
410 nsIDOMMouseEvent
*mouse_event
;
412 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
413 if(NS_SUCCEEDED(nsres
)) {
414 nsIDOMMouseEvent_GetShiftKey(mouse_event
, &ret
);
415 nsIDOMMouseEvent_Release(mouse_event
);
420 *p
= ret
? VARIANT_TRUE
: VARIANT_FALSE
;
424 static HRESULT WINAPI
HTMLEventObj_put_returnValue(IHTMLEventObj
*iface
, VARIANT v
)
426 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
428 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&v
));
430 if(V_VT(&v
) != VT_BOOL
) {
431 FIXME("unsupported value %s\n", debugstr_variant(&v
));
432 return DISP_E_BADVARTYPE
;
435 This
->return_value
= v
;
436 if(!V_BOOL(&v
) && This
->event
)
437 IDOMEvent_preventDefault(&This
->event
->IDOMEvent_iface
);
441 static HRESULT WINAPI
HTMLEventObj_get_returnValue(IHTMLEventObj
*iface
, VARIANT
*p
)
443 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
445 TRACE("(%p)->(%p)\n", This
, p
);
448 return VariantCopy(p
, &This
->return_value
);
451 static HRESULT WINAPI
HTMLEventObj_put_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL v
)
453 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
455 TRACE("(%p)->(%x)\n", This
, v
);
458 IDOMEvent_stopPropagation(&This
->event
->IDOMEvent_iface
);
462 static HRESULT WINAPI
HTMLEventObj_get_cancelBubble(IHTMLEventObj
*iface
, VARIANT_BOOL
*p
)
464 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
466 TRACE("(%p)->(%p)\n", This
, p
);
468 *p
= This
->event
&& This
->event
->stop_propagation
? VARIANT_TRUE
: VARIANT_FALSE
;
472 static HRESULT WINAPI
HTMLEventObj_get_fromElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
474 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
476 FIXME("(%p)->(%p)\n", This
, p
);
482 static HRESULT WINAPI
HTMLEventObj_get_toElement(IHTMLEventObj
*iface
, IHTMLElement
**p
)
484 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
486 FIXME("(%p)->(%p)\n", This
, p
);
492 static HRESULT WINAPI
HTMLEventObj_put_keyCode(IHTMLEventObj
*iface
, LONG v
)
494 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
495 FIXME("(%p)->(%d)\n", This
, v
);
499 static HRESULT WINAPI
HTMLEventObj_get_keyCode(IHTMLEventObj
*iface
, LONG
*p
)
501 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
504 TRACE("(%p)->(%p)\n", This
, p
);
507 nsIDOMKeyEvent
*key_event
;
510 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMKeyEvent
, (void**)&key_event
);
511 if(NS_SUCCEEDED(nsres
)) {
512 nsIDOMKeyEvent_GetKeyCode(key_event
, &key_code
);
513 nsIDOMKeyEvent_Release(key_event
);
521 static HRESULT WINAPI
HTMLEventObj_get_button(IHTMLEventObj
*iface
, LONG
*p
)
523 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
526 TRACE("(%p)->(%p)\n", This
, p
);
529 nsIDOMMouseEvent
*mouse_event
;
532 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
533 if(NS_SUCCEEDED(nsres
)) {
534 nsIDOMMouseEvent_GetButton(mouse_event
, &button
);
535 nsIDOMMouseEvent_Release(mouse_event
);
543 static HRESULT WINAPI
HTMLEventObj_get_type(IHTMLEventObj
*iface
, BSTR
*p
)
545 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
547 TRACE("(%p)->(%p)\n", This
, p
);
554 *p
= SysAllocString(This
->type
->name
);
555 return *p
? S_OK
: E_OUTOFMEMORY
;
558 static HRESULT WINAPI
HTMLEventObj_get_qualifier(IHTMLEventObj
*iface
, BSTR
*p
)
560 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
562 FIXME("(%p)->(%p)\n", This
, p
);
568 static HRESULT WINAPI
HTMLEventObj_get_reason(IHTMLEventObj
*iface
, LONG
*p
)
570 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
572 FIXME("(%p)->(%p)\n", This
, p
);
578 static HRESULT WINAPI
HTMLEventObj_get_x(IHTMLEventObj
*iface
, LONG
*p
)
580 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
583 TRACE("(%p)->(%p)\n", This
, p
);
586 nsIDOMUIEvent
*ui_event
;
589 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMUIEvent
, (void**)&ui_event
);
590 if(NS_SUCCEEDED(nsres
)) {
591 /* NOTE: pageX is not exactly right here. */
592 nsres
= nsIDOMUIEvent_GetPageX(ui_event
, &x
);
593 assert(nsres
== NS_OK
);
594 nsIDOMUIEvent_Release(ui_event
);
602 static HRESULT WINAPI
HTMLEventObj_get_y(IHTMLEventObj
*iface
, LONG
*p
)
604 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
607 TRACE("(%p)->(%p)\n", This
, p
);
610 nsIDOMUIEvent
*ui_event
;
613 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMUIEvent
, (void**)&ui_event
);
614 if(NS_SUCCEEDED(nsres
)) {
615 /* NOTE: pageY is not exactly right here. */
616 nsres
= nsIDOMUIEvent_GetPageY(ui_event
, &y
);
617 assert(nsres
== NS_OK
);
618 nsIDOMUIEvent_Release(ui_event
);
626 static HRESULT WINAPI
HTMLEventObj_get_clientX(IHTMLEventObj
*iface
, LONG
*p
)
628 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
631 TRACE("(%p)->(%p)\n", This
, p
);
634 nsIDOMMouseEvent
*mouse_event
;
637 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
638 if(NS_SUCCEEDED(nsres
)) {
639 nsIDOMMouseEvent_GetClientX(mouse_event
, &x
);
640 nsIDOMMouseEvent_Release(mouse_event
);
648 static HRESULT WINAPI
HTMLEventObj_get_clientY(IHTMLEventObj
*iface
, LONG
*p
)
650 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
653 TRACE("(%p)->(%p)\n", This
, p
);
656 nsIDOMMouseEvent
*mouse_event
;
659 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
660 if(NS_SUCCEEDED(nsres
)) {
661 nsIDOMMouseEvent_GetClientY(mouse_event
, &y
);
662 nsIDOMMouseEvent_Release(mouse_event
);
670 static HRESULT WINAPI
HTMLEventObj_get_offsetX(IHTMLEventObj
*iface
, LONG
*p
)
672 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
674 FIXME("(%p)->(%p)\n", This
, p
);
680 static HRESULT WINAPI
HTMLEventObj_get_offsetY(IHTMLEventObj
*iface
, LONG
*p
)
682 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
684 FIXME("(%p)->(%p)\n", This
, p
);
690 static HRESULT WINAPI
HTMLEventObj_get_screenX(IHTMLEventObj
*iface
, LONG
*p
)
692 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
695 TRACE("(%p)->(%p)\n", This
, p
);
698 nsIDOMMouseEvent
*mouse_event
;
701 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
702 if(NS_SUCCEEDED(nsres
)) {
703 nsIDOMMouseEvent_GetScreenX(mouse_event
, &x
);
704 nsIDOMMouseEvent_Release(mouse_event
);
712 static HRESULT WINAPI
HTMLEventObj_get_screenY(IHTMLEventObj
*iface
, LONG
*p
)
714 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
717 TRACE("(%p)->(%p)\n", This
, p
);
720 nsIDOMMouseEvent
*mouse_event
;
723 nsres
= nsIDOMEvent_QueryInterface(This
->event
->nsevent
, &IID_nsIDOMMouseEvent
, (void**)&mouse_event
);
724 if(NS_SUCCEEDED(nsres
)) {
725 nsIDOMMouseEvent_GetScreenY(mouse_event
, &y
);
726 nsIDOMMouseEvent_Release(mouse_event
);
734 static HRESULT WINAPI
HTMLEventObj_get_srcFilter(IHTMLEventObj
*iface
, IDispatch
**p
)
736 HTMLEventObj
*This
= impl_from_IHTMLEventObj(iface
);
738 FIXME("(%p)->(%p)\n", This
, p
);
744 static const IHTMLEventObjVtbl HTMLEventObjVtbl
= {
745 HTMLEventObj_QueryInterface
,
747 HTMLEventObj_Release
,
748 HTMLEventObj_GetTypeInfoCount
,
749 HTMLEventObj_GetTypeInfo
,
750 HTMLEventObj_GetIDsOfNames
,
752 HTMLEventObj_get_srcElement
,
753 HTMLEventObj_get_altKey
,
754 HTMLEventObj_get_ctrlKey
,
755 HTMLEventObj_get_shiftKey
,
756 HTMLEventObj_put_returnValue
,
757 HTMLEventObj_get_returnValue
,
758 HTMLEventObj_put_cancelBubble
,
759 HTMLEventObj_get_cancelBubble
,
760 HTMLEventObj_get_fromElement
,
761 HTMLEventObj_get_toElement
,
762 HTMLEventObj_put_keyCode
,
763 HTMLEventObj_get_keyCode
,
764 HTMLEventObj_get_button
,
765 HTMLEventObj_get_type
,
766 HTMLEventObj_get_qualifier
,
767 HTMLEventObj_get_reason
,
770 HTMLEventObj_get_clientX
,
771 HTMLEventObj_get_clientY
,
772 HTMLEventObj_get_offsetX
,
773 HTMLEventObj_get_offsetY
,
774 HTMLEventObj_get_screenX
,
775 HTMLEventObj_get_screenY
,
776 HTMLEventObj_get_srcFilter
779 static inline HTMLEventObj
*unsafe_impl_from_IHTMLEventObj(IHTMLEventObj
*iface
)
781 return iface
->lpVtbl
== &HTMLEventObjVtbl
? impl_from_IHTMLEventObj(iface
) : NULL
;
784 static const tid_t HTMLEventObj_iface_tids
[] = {
789 static dispex_static_data_t HTMLEventObj_dispex
= {
792 HTMLEventObj_iface_tids
795 static HTMLEventObj
*alloc_event_obj(DOMEvent
*event
)
797 HTMLEventObj
*event_obj
;
799 event_obj
= heap_alloc_zero(sizeof(*event_obj
));
803 event_obj
->IHTMLEventObj_iface
.lpVtbl
= &HTMLEventObjVtbl
;
805 event_obj
->event
= event
;
807 IDOMEvent_AddRef(&event
->IDOMEvent_iface
);
809 init_dispex(&event_obj
->dispex
, (IUnknown
*)&event_obj
->IHTMLEventObj_iface
, &HTMLEventObj_dispex
);
813 HRESULT
create_event_obj(IHTMLEventObj
**ret
)
815 HTMLEventObj
*event_obj
;
817 event_obj
= alloc_event_obj(NULL
);
819 return E_OUTOFMEMORY
;
821 *ret
= &event_obj
->IHTMLEventObj_iface
;
825 static inline DOMEvent
*impl_from_IDOMEvent(IDOMEvent
*iface
)
827 return CONTAINING_RECORD(iface
, DOMEvent
, IDOMEvent_iface
);
830 static HRESULT WINAPI
DOMEvent_QueryInterface(IDOMEvent
*iface
, REFIID riid
, void **ppv
)
832 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
834 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
836 if(IsEqualGUID(&IID_IUnknown
, riid
))
837 *ppv
= &This
->IDOMEvent_iface
;
838 else if(IsEqualGUID(&IID_IDOMEvent
, riid
))
839 *ppv
= &This
->IDOMEvent_iface
;
840 else if(dispex_query_interface(&This
->dispex
, riid
, ppv
))
841 return *ppv
? S_OK
: E_NOINTERFACE
;
844 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
845 return E_NOINTERFACE
;
848 IUnknown_AddRef((IUnknown
*)*ppv
);
852 static ULONG WINAPI
DOMEvent_AddRef(IDOMEvent
*iface
)
854 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
855 LONG ref
= InterlockedIncrement(&This
->ref
);
857 TRACE("(%p) ref=%u\n", This
, ref
);
862 static ULONG WINAPI
DOMEvent_Release(IDOMEvent
*iface
)
864 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
865 LONG ref
= InterlockedDecrement(&This
->ref
);
867 TRACE("(%p) ref=%u\n", This
, ref
);
871 IDispatchEx_Release(&This
->target
->dispex
.IDispatchEx_iface
);
872 nsIDOMEvent_Release(This
->nsevent
);
873 release_dispex(&This
->dispex
);
880 static HRESULT WINAPI
DOMEvent_GetTypeInfoCount(IDOMEvent
*iface
, UINT
*pctinfo
)
882 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
883 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
886 static HRESULT WINAPI
DOMEvent_GetTypeInfo(IDOMEvent
*iface
, UINT iTInfo
,
887 LCID lcid
, ITypeInfo
**ppTInfo
)
889 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
890 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
893 static HRESULT WINAPI
DOMEvent_GetIDsOfNames(IDOMEvent
*iface
, REFIID riid
,
894 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
896 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
897 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
901 static HRESULT WINAPI
DOMEvent_Invoke(IDOMEvent
*iface
, DISPID dispIdMember
,
902 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
903 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
905 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
906 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
907 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
910 static HRESULT WINAPI
DOMEvent_get_bubbles(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
912 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
913 FIXME("(%p)->(%p)\n", This
, p
);
917 static HRESULT WINAPI
DOMEvent_get_cancelable(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
919 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
920 FIXME("(%p)->(%p)\n", This
, p
);
924 static HRESULT WINAPI
DOMEvent_get_currentTarget(IDOMEvent
*iface
, IEventTarget
**p
)
926 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
927 FIXME("(%p)->(%p)\n", This
, p
);
931 static HRESULT WINAPI
DOMEvent_get_defaultPrevented(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
933 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
934 FIXME("(%p)->(%p)\n", This
, p
);
938 static HRESULT WINAPI
DOMEvent_get_eventPhase(IDOMEvent
*iface
, USHORT
*p
)
940 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
942 TRACE("(%p)->(%p)\n", This
, p
);
948 static HRESULT WINAPI
DOMEvent_get_target(IDOMEvent
*iface
, IEventTarget
**p
)
950 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
951 FIXME("(%p)->(%p)\n", This
, p
);
955 static HRESULT WINAPI
DOMEvent_get_timeStamp(IDOMEvent
*iface
, ULONGLONG
*p
)
957 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
958 FIXME("(%p)->(%p)\n", This
, p
);
962 static HRESULT WINAPI
DOMEvent_get_type(IDOMEvent
*iface
, BSTR
*p
)
964 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
965 FIXME("(%p)->(%p)\n", This
, p
);
969 static HRESULT WINAPI
DOMEvent_initEvent(IDOMEvent
*iface
, BSTR type
, VARIANT_BOOL can_bubble
, VARIANT_BOOL cancelable
)
971 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
972 FIXME("(%p)->()\n", This
);
976 static HRESULT WINAPI
DOMEvent_preventDefault(IDOMEvent
*iface
)
978 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
980 TRACE("(%p)\n", This
);
982 This
->prevent_default
= TRUE
;
983 nsIDOMEvent_PreventDefault(This
->nsevent
);
987 static HRESULT WINAPI
DOMEvent_stopPropagation(IDOMEvent
*iface
)
989 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
991 TRACE("(%p)\n", This
);
993 This
->stop_propagation
= TRUE
;
994 nsIDOMEvent_StopPropagation(This
->nsevent
);
995 IDOMEvent_preventDefault(&This
->IDOMEvent_iface
);
999 static HRESULT WINAPI
DOMEvent_stopImmediatePropagation(IDOMEvent
*iface
)
1001 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1002 FIXME("(%p)\n", This
);
1006 static HRESULT WINAPI
DOMEvent_get_isTrusted(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1008 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1009 FIXME("(%p)->(%p)\n", This
, p
);
1013 static HRESULT WINAPI
DOMEvent_put_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL v
)
1015 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1016 FIXME("(%p)->(%x)\n", This
, v
);
1020 static HRESULT WINAPI
DOMEvent_get_cancelBubble(IDOMEvent
*iface
, VARIANT_BOOL
*p
)
1022 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1023 FIXME("(%p)->(%p)\n", This
, p
);
1027 static HRESULT WINAPI
DOMEvent_get_srcElement(IDOMEvent
*iface
, IHTMLElement
**p
)
1029 DOMEvent
*This
= impl_from_IDOMEvent(iface
);
1030 FIXME("(%p)->(%p)\n", This
, p
);
1034 static const IDOMEventVtbl DOMEventVtbl
= {
1035 DOMEvent_QueryInterface
,
1038 DOMEvent_GetTypeInfoCount
,
1039 DOMEvent_GetTypeInfo
,
1040 DOMEvent_GetIDsOfNames
,
1042 DOMEvent_get_bubbles
,
1043 DOMEvent_get_cancelable
,
1044 DOMEvent_get_currentTarget
,
1045 DOMEvent_get_defaultPrevented
,
1046 DOMEvent_get_eventPhase
,
1047 DOMEvent_get_target
,
1048 DOMEvent_get_timeStamp
,
1051 DOMEvent_preventDefault
,
1052 DOMEvent_stopPropagation
,
1053 DOMEvent_stopImmediatePropagation
,
1054 DOMEvent_get_isTrusted
,
1055 DOMEvent_put_cancelBubble
,
1056 DOMEvent_get_cancelBubble
,
1057 DOMEvent_get_srcElement
1060 static const tid_t DOMEvent_iface_tids
[] = {
1065 static dispex_static_data_t DOMEvent_dispex
= {
1071 static DOMEvent
*alloc_event(nsIDOMEvent
*nsevent
)
1075 event
= heap_alloc_zero(sizeof(*event
));
1079 init_dispex(&event
->dispex
, (IUnknown
*)&event
->IDOMEvent_iface
, &DOMEvent_dispex
);
1080 event
->IDOMEvent_iface
.lpVtbl
= &DOMEventVtbl
;
1082 nsIDOMEvent_AddRef(event
->nsevent
= nsevent
);
1083 event
->event_id
= EVENTID_LAST
;
1087 HRESULT
create_event_from_nsevent(nsIDOMEvent
*nsevent
, DOMEvent
**ret_event
)
1093 event
= alloc_event(nsevent
);
1095 return E_OUTOFMEMORY
;
1097 nsAString_Init(&nsstr
, NULL
);
1098 nsres
= nsIDOMEvent_GetType(event
->nsevent
, &nsstr
);
1099 if(NS_SUCCEEDED(nsres
)) {
1101 nsAString_GetData(&nsstr
, &type
);
1102 event
->event_id
= str_to_eid(type
);
1103 if(event
->event_id
== EVENTID_LAST
)
1104 FIXME("unknown event type %s\n", debugstr_w(type
));
1106 ERR("GetType failed: %08x\n", nsres
);
1108 nsAString_Finish(&nsstr
);
1114 HRESULT
create_document_event_str(HTMLDocumentNode
*doc
, const WCHAR
*type
, IDOMEvent
**ret_event
)
1116 nsIDOMEvent
*nsevent
;
1121 nsAString_InitDepend(&nsstr
, type
);
1122 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
1123 nsAString_Finish(&nsstr
);
1124 if(NS_FAILED(nsres
)) {
1125 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(type
), nsres
);
1129 event
= alloc_event(nsevent
);
1130 nsIDOMEvent_Release(nsevent
);
1132 return E_OUTOFMEMORY
;
1134 *ret_event
= &event
->IDOMEvent_iface
;
1138 HRESULT
create_document_event(HTMLDocumentNode
*doc
, eventid_t event_id
, DOMEvent
**ret_event
)
1140 nsIDOMEvent
*nsevent
;
1145 nsAString_InitDepend(&nsstr
, event_types
[event_info
[event_id
].type
]);
1146 nsres
= nsIDOMHTMLDocument_CreateEvent(doc
->nsdoc
, &nsstr
, &nsevent
);
1147 nsAString_Finish(&nsstr
);
1148 if(NS_FAILED(nsres
)) {
1149 FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(event_types
[event_info
[event_id
].type
]), nsres
);
1153 event
= alloc_event(nsevent
);
1155 return E_OUTOFMEMORY
;
1157 event
->event_id
= event_id
;
1162 static handler_vector_t
*get_handler_vector(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
)
1164 const event_target_vtbl_t
*vtbl
;
1165 handler_vector_t
*handler_vector
;
1166 struct wine_rb_entry
*entry
;
1168 entry
= wine_rb_get(&event_target
->handler_map
, (const void*)eid
);
1170 return WINE_RB_ENTRY_VALUE(entry
, handler_vector_t
, entry
);
1174 handler_vector
= heap_alloc_zero(sizeof(*handler_vector
));
1178 handler_vector
->event_id
= eid
;
1179 vtbl
= dispex_get_vtbl(&event_target
->dispex
);
1180 if(vtbl
->bind_event
)
1181 vtbl
->bind_event(&event_target
->dispex
, eid
);
1183 FIXME("Unsupported event binding on target %p\n", event_target
);
1185 wine_rb_put(&event_target
->handler_map
, (const void*)eid
, &handler_vector
->entry
);
1186 return handler_vector
;
1189 static HRESULT
call_disp_func(IDispatch
*disp
, DISPPARAMS
*dp
, VARIANT
*retv
)
1191 IDispatchEx
*dispex
;
1195 memset(&ei
, 0, sizeof(ei
));
1197 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
1198 if(SUCCEEDED(hres
)) {
1199 hres
= IDispatchEx_InvokeEx(dispex
, 0, GetUserDefaultLCID(), DISPATCH_METHOD
, dp
, retv
, &ei
, NULL
);
1200 IDispatchEx_Release(dispex
);
1202 TRACE("Could not get IDispatchEx interface: %08x\n", hres
);
1203 hres
= IDispatch_Invoke(disp
, 0, &IID_NULL
, GetUserDefaultLCID(), DISPATCH_METHOD
,
1204 dp
, retv
, &ei
, NULL
);
1210 static HRESULT
call_cp_func(IDispatch
*disp
, DISPID dispid
, IHTMLEventObj
*event_obj
, VARIANT
*retv
)
1212 DISPPARAMS dp
= {NULL
,NULL
,0,0};
1218 V_VT(&event_arg
) = VT_DISPATCH
;
1219 V_DISPATCH(&event_arg
) = (IDispatch
*)event_obj
;
1220 dp
.rgvarg
= &event_arg
;
1224 memset(&ei
, 0, sizeof(ei
));
1225 return IDispatch_Invoke(disp
, dispid
, &IID_NULL
, 0, DISPATCH_METHOD
, &dp
, retv
, &ei
, &argerr
);
1228 static BOOL
is_cp_event(cp_static_data_t
*data
, DISPID dispid
)
1237 hres
= get_dispids(data
->tid
, &data
->id_cnt
, &data
->ids
);
1243 max
= data
->id_cnt
-1;
1246 if(data
->ids
[i
] == dispid
)
1249 if(data
->ids
[i
] < dispid
)
1258 static void call_event_handlers(EventTarget
*event_target
, DOMEvent
*event
)
1260 const eventid_t eid
= event
->event_id
;
1261 handler_vector_t
*handler_vector
= get_handler_vector(event_target
, eid
, FALSE
);
1262 const BOOL cancelable
= event_info
[eid
].flags
& EVENT_CANCELABLE
;
1263 ConnectionPointContainer
*cp_container
= NULL
;
1264 const event_target_vtbl_t
*vtbl
;
1268 if(handler_vector
&& handler_vector
->handler_prop
) {
1269 DISPID named_arg
= DISPID_THIS
;
1271 DISPPARAMS dp
= {&arg
, &named_arg
, 1, 1};
1273 if(!use_event_quirks(event_target
))
1274 FIXME("Event argument not supported\n");
1276 V_VT(&arg
) = VT_DISPATCH
;
1277 V_DISPATCH(&arg
) = (IDispatch
*)&event_target
->dispex
.IDispatchEx_iface
;
1278 V_VT(&v
) = VT_EMPTY
;
1280 TRACE("%s >>>\n", debugstr_w(event_info
[eid
].name
));
1281 hres
= call_disp_func(handler_vector
->handler_prop
, &dp
, &v
);
1283 TRACE("%s <<< %s\n", debugstr_w(event_info
[eid
].name
), debugstr_variant(&v
));
1286 if(V_VT(&v
) == VT_BOOL
) {
1288 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1289 }else if(V_VT(&v
) != VT_EMPTY
) {
1290 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1295 WARN("%s <<< %08x\n", debugstr_w(event_info
[eid
].name
), hres
);
1299 if(handler_vector
&& handler_vector
->handler_cnt
) {
1301 DISPPARAMS dp
= {&arg
, NULL
, 1, 0};
1304 V_VT(&arg
) = VT_DISPATCH
;
1305 V_DISPATCH(&arg
) = (IDispatch
*)event
->event_obj
;
1307 i
= handler_vector
->handler_cnt
;
1309 if(handler_vector
->handlers
[i
]) {
1310 V_VT(&v
) = VT_EMPTY
;
1312 TRACE("%s [%d] >>>\n", debugstr_w(event_info
[eid
].name
), i
);
1313 hres
= call_disp_func(handler_vector
->handlers
[i
], &dp
, &v
);
1315 TRACE("%s [%d] <<<\n", debugstr_w(event_info
[eid
].name
), i
);
1318 if(V_VT(&v
) == VT_BOOL
) {
1320 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1321 }else if(V_VT(&v
) != VT_EMPTY
) {
1322 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1327 WARN("%s [%d] <<< %08x\n", debugstr_w(event_info
[eid
].name
), i
, hres
);
1333 if((vtbl
= dispex_get_vtbl(&event_target
->dispex
)) && vtbl
->get_cp_container
)
1334 cp_container
= vtbl
->get_cp_container(&event_target
->dispex
);
1336 if(cp_container
->cps
) {
1337 ConnectionPoint
*cp
;
1340 for(j
=0; cp_container
->cp_entries
[j
].riid
; j
++) {
1341 cp
= cp_container
->cps
+ j
;
1342 if(!cp
->sinks_size
|| !is_cp_event(cp
->data
, event_info
[eid
].dispid
))
1345 for(i
=0; i
< cp
->sinks_size
; i
++) {
1346 if(!cp
->sinks
[i
].disp
)
1349 V_VT(&v
) = VT_EMPTY
;
1351 TRACE("cp %s [%u] >>>\n", debugstr_w(event_info
[eid
].name
), i
);
1352 hres
= call_cp_func(cp
->sinks
[i
].disp
, event_info
[eid
].dispid
,
1353 cp
->data
->pass_event_arg
? event
->event_obj
: NULL
, &v
);
1355 TRACE("cp %s [%u] <<<\n", debugstr_w(event_info
[eid
].name
), i
);
1358 if(V_VT(&v
) == VT_BOOL
) {
1360 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1361 }else if(V_VT(&v
) != VT_EMPTY
) {
1362 FIXME("unhandled result %s\n", debugstr_variant(&v
));
1367 WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info
[eid
].name
), i
, hres
);
1372 IConnectionPointContainer_Release(&cp_container
->IConnectionPointContainer_iface
);
1376 void dispatch_event(EventTarget
*event_target
, DOMEvent
*event
)
1378 EventTarget
*target_chain_buf
[8], **target_chain
= target_chain_buf
;
1379 unsigned chain_cnt
, chain_buf_size
, i
;
1380 const event_target_vtbl_t
*vtbl
, *target_vtbl
;
1381 HTMLEventObj
*event_obj_ref
= NULL
;
1382 IHTMLEventObj
*prev_event
= NULL
;
1387 if(event
->event_id
== EVENTID_LAST
) {
1388 FIXME("Unsupported on unknown events\n");
1392 TRACE("(%p) %s\n", event_target
, debugstr_w(event_info
[event
->event_id
].name
));
1394 event_flags
= event_info
[event
->event_id
].flags
;
1395 iter
= event_target
;
1396 IDispatchEx_AddRef(&event_target
->dispex
.IDispatchEx_iface
);
1399 chain_buf_size
= sizeof(target_chain_buf
)/sizeof(*target_chain_buf
);
1402 if(chain_cnt
== chain_buf_size
) {
1403 EventTarget
**new_chain
;
1404 if(target_chain
== target_chain_buf
) {
1405 new_chain
= heap_alloc(chain_buf_size
* 2 * sizeof(*new_chain
));
1408 memcpy(new_chain
, target_chain
, chain_buf_size
* sizeof(*new_chain
));
1410 new_chain
= heap_realloc(target_chain
, chain_buf_size
* 2 * sizeof(*new_chain
));
1414 chain_buf_size
*= 2;
1415 target_chain
= new_chain
;
1418 target_chain
[chain_cnt
++] = iter
;
1420 if(!(vtbl
= dispex_get_vtbl(&iter
->dispex
)) || !vtbl
->get_parent_event_target
)
1422 iter
= vtbl
->get_parent_event_target(&iter
->dispex
);
1425 if(!event
->event_obj
&& !event
->no_event_obj
) {
1426 event_obj_ref
= alloc_event_obj(event
);
1428 event_obj_ref
->type
= event_info
+ event
->event_id
;
1429 event
->event_obj
= &event_obj_ref
->IHTMLEventObj_iface
;
1433 target_vtbl
= dispex_get_vtbl(&event_target
->dispex
);
1434 if(target_vtbl
&& target_vtbl
->set_current_event
)
1435 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, event
->event_obj
);
1437 event
->target
= event_target
;
1438 IDispatchEx_AddRef(&event_target
->dispex
.IDispatchEx_iface
);
1440 event
->phase
= DEP_AT_TARGET
;
1441 call_event_handlers(target_chain
[0], event
);
1443 if(event_flags
& EVENT_BUBBLES
) {
1444 event
->phase
= DEP_BUBBLING_PHASE
;
1445 for(i
= 1; !event
->stop_propagation
&& i
< chain_cnt
; i
++)
1446 call_event_handlers(target_chain
[i
], event
);
1449 if(target_vtbl
&& target_vtbl
->set_current_event
) {
1450 prev_event
= target_vtbl
->set_current_event(&event_target
->dispex
, prev_event
);
1452 IHTMLEventObj_Release(prev_event
);
1455 if(event_flags
& EVENT_HASDEFAULTHANDLERS
) {
1456 for(i
= 0; !event
->prevent_default
&& i
< chain_cnt
; i
++) {
1457 BOOL prevent_default
= FALSE
;
1458 vtbl
= dispex_get_vtbl(&target_chain
[i
]->dispex
);
1459 if(!vtbl
|| !vtbl
->handle_event_default
)
1461 hres
= vtbl
->handle_event_default(&event_target
->dispex
, event
->event_id
,
1462 event
->nsevent
, &prevent_default
);
1463 if(FAILED(hres
) || event
->stop_propagation
)
1466 IDOMEvent_preventDefault(&event
->IDOMEvent_iface
);
1471 event
->event_obj
= NULL
;
1472 IHTMLEventObj_Release(&event_obj_ref
->IHTMLEventObj_iface
);
1475 for(i
= 0; i
< chain_cnt
; i
++)
1476 IDispatchEx_Release(&target_chain
[i
]->dispex
.IDispatchEx_iface
);
1477 if(target_chain
!= target_chain_buf
)
1478 heap_free(target_chain
);
1481 HRESULT
fire_event(HTMLDOMNode
*node
, const WCHAR
*event_name
, VARIANT
*event_var
, VARIANT_BOOL
*cancelled
)
1483 HTMLEventObj
*event_obj
= NULL
;
1485 HRESULT hres
= S_OK
;
1487 eid
= attr_to_eid(event_name
);
1488 if(eid
== EVENTID_LAST
) {
1489 WARN("unknown event %s\n", debugstr_w(event_name
));
1490 return E_INVALIDARG
;
1493 if(event_var
&& V_VT(event_var
) != VT_EMPTY
&& V_VT(event_var
) != VT_ERROR
) {
1494 if(V_VT(event_var
) != VT_DISPATCH
) {
1495 FIXME("event_var %s not supported\n", debugstr_variant(event_var
));
1499 if(V_DISPATCH(event_var
)) {
1500 IHTMLEventObj
*event_iface
;
1502 hres
= IDispatch_QueryInterface(V_DISPATCH(event_var
), &IID_IHTMLEventObj
, (void**)&event_iface
);
1504 FIXME("No IHTMLEventObj iface\n");
1508 event_obj
= unsafe_impl_from_IHTMLEventObj(event_iface
);
1510 ERR("Not our IHTMLEventObj?\n");
1511 IHTMLEventObj_Release(event_iface
);
1518 event_obj
= alloc_event_obj(NULL
);
1520 return E_OUTOFMEMORY
;
1523 event_obj
->type
= event_info
+ eid
;
1524 if(!event_obj
->event
)
1525 hres
= create_document_event(node
->doc
, eid
, &event_obj
->event
);
1527 if(SUCCEEDED(hres
)) {
1528 event_obj
->event
->event_obj
= &event_obj
->IHTMLEventObj_iface
;
1529 dispatch_event(&node
->event_target
, event_obj
->event
);
1530 event_obj
->event
->event_obj
= NULL
;
1533 IHTMLEventObj_Release(&event_obj
->IHTMLEventObj_iface
);
1537 *cancelled
= VARIANT_TRUE
; /* FIXME */
1541 HRESULT
ensure_doc_nsevent_handler(HTMLDocumentNode
*doc
, eventid_t eid
)
1543 nsIDOMNode
*nsnode
= NULL
;
1545 TRACE("%s\n", debugstr_w(event_info
[eid
].name
));
1551 case EVENTID_FOCUSIN
:
1552 doc
->event_vector
[eid
] = TRUE
;
1553 eid
= EVENTID_FOCUS
;
1555 case EVENTID_FOCUSOUT
:
1556 doc
->event_vector
[eid
] = TRUE
;
1563 if(doc
->event_vector
[eid
] || !(event_info
[eid
].flags
& (EVENT_DEFAULTLISTENER
|EVENT_BIND_TO_BODY
)))
1566 if(event_info
[eid
].flags
& EVENT_BIND_TO_BODY
) {
1567 nsnode
= doc
->node
.nsnode
;
1568 nsIDOMNode_AddRef(nsnode
);
1571 doc
->event_vector
[eid
] = TRUE
;
1572 add_nsevent_listener(doc
, nsnode
, event_info
[eid
].name
);
1575 nsIDOMNode_Release(nsnode
);
1579 void detach_events(HTMLDocumentNode
*doc
)
1581 if(doc
->event_vector
) {
1584 for(i
=0; i
< EVENTID_LAST
; i
++) {
1585 if(doc
->event_vector
[i
]) {
1586 detach_nsevent(doc
, event_info
[i
].name
);
1587 doc
->event_vector
[i
] = FALSE
;
1592 release_nsevents(doc
);
1595 static HRESULT
get_event_dispex_ref(EventTarget
*event_target
, eventid_t eid
, BOOL alloc
, VARIANT
**ret
)
1600 strcpyW(buf
+2, event_info
[eid
].name
);
1601 return dispex_get_dprop_ref(&event_target
->dispex
, buf
, alloc
, ret
);
1604 static void remove_event_handler(EventTarget
*event_target
, eventid_t eid
)
1606 handler_vector_t
*handler_vector
;
1610 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &store
);
1612 VariantClear(store
);
1614 handler_vector
= get_handler_vector(event_target
, eid
, FALSE
);
1615 if(handler_vector
&& handler_vector
->handler_prop
) {
1616 IDispatch_Release(handler_vector
->handler_prop
);
1617 handler_vector
->handler_prop
= NULL
;
1621 static HRESULT
set_event_handler_disp(EventTarget
*event_target
, eventid_t eid
, IDispatch
*disp
)
1623 handler_vector_t
*handler_vector
;
1625 if(event_info
[eid
].flags
& EVENT_FIXME
)
1626 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
1628 remove_event_handler(event_target
, eid
);
1632 handler_vector
= get_handler_vector(event_target
, eid
, TRUE
);
1634 return E_OUTOFMEMORY
;
1636 if(handler_vector
->handler_prop
)
1637 IDispatch_Release(handler_vector
->handler_prop
);
1639 handler_vector
->handler_prop
= disp
;
1640 IDispatch_AddRef(disp
);
1644 HRESULT
set_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
1648 if(use_event_quirks(event_target
)) {
1649 WARN("attempt to set to VT_EMPTY in quirks mode\n");
1654 remove_event_handler(event_target
, eid
);
1658 return set_event_handler_disp(event_target
, eid
, V_DISPATCH(var
));
1664 if(!use_event_quirks(event_target
))
1665 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var
)));
1668 * Setting event handler to string is a rare case and we don't want to
1669 * complicate nor increase memory of handler_vector_t for that. Instead,
1670 * we store the value in DispatchEx, which can already handle custom
1673 remove_event_handler(event_target
, eid
);
1675 hres
= get_event_dispex_ref(event_target
, eid
, TRUE
, &v
);
1679 V_BSTR(v
) = SysAllocString(V_BSTR(var
));
1681 return E_OUTOFMEMORY
;
1687 FIXME("not handler %s\n", debugstr_variant(var
));
1694 HRESULT
get_event_handler(EventTarget
*event_target
, eventid_t eid
, VARIANT
*var
)
1696 handler_vector_t
*handler_vector
;
1700 hres
= get_event_dispex_ref(event_target
, eid
, FALSE
, &v
);
1701 if(SUCCEEDED(hres
) && V_VT(v
) != VT_EMPTY
) {
1702 V_VT(var
) = VT_EMPTY
;
1703 return VariantCopy(var
, v
);
1706 handler_vector
= get_handler_vector(event_target
, eid
, FALSE
);
1707 if(handler_vector
&& handler_vector
->handler_prop
) {
1708 V_VT(var
) = VT_DISPATCH
;
1709 V_DISPATCH(var
) = handler_vector
->handler_prop
;
1710 IDispatch_AddRef(V_DISPATCH(var
));
1712 V_VT(var
) = VT_NULL
;
1718 HRESULT
attach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
, VARIANT_BOOL
*res
)
1720 handler_vector_t
*handler_vector
;
1724 eid
= attr_to_eid(name
);
1725 if(eid
== EVENTID_LAST
) {
1726 WARN("Unknown event\n");
1727 *res
= VARIANT_TRUE
;
1731 if(event_info
[eid
].flags
& EVENT_FIXME
)
1732 FIXME("unimplemented event %s\n", debugstr_w(event_info
[eid
].name
));
1734 handler_vector
= get_handler_vector(event_target
, eid
, TRUE
);
1736 return E_OUTOFMEMORY
;
1738 while(i
< handler_vector
->handler_cnt
&& handler_vector
->handlers
[i
])
1740 if(i
== handler_vector
->handler_cnt
) {
1742 handler_vector
->handlers
= heap_realloc_zero(handler_vector
->handlers
,
1743 (i
+ 1) * sizeof(*handler_vector
->handlers
));
1745 handler_vector
->handlers
= heap_alloc_zero(sizeof(*handler_vector
->handlers
));
1746 if(!handler_vector
->handlers
)
1747 return E_OUTOFMEMORY
;
1748 handler_vector
->handler_cnt
++;
1751 IDispatch_AddRef(disp
);
1752 handler_vector
->handlers
[i
] = disp
;
1754 *res
= VARIANT_TRUE
;
1758 HRESULT
detach_event(EventTarget
*event_target
, BSTR name
, IDispatch
*disp
)
1760 handler_vector_t
*handler_vector
;
1764 eid
= attr_to_eid(name
);
1765 if(eid
== EVENTID_LAST
) {
1766 WARN("Unknown event\n");
1770 handler_vector
= get_handler_vector(event_target
, eid
, FALSE
);
1774 for(i
= 0; i
< handler_vector
->handler_cnt
; i
++) {
1775 if(handler_vector
->handlers
[i
] == disp
) {
1776 IDispatch_Release(handler_vector
->handlers
[i
]);
1777 handler_vector
->handlers
[i
] = NULL
;
1784 void bind_target_event(HTMLDocumentNode
*doc
, EventTarget
*event_target
, const WCHAR
*event
, IDispatch
*disp
)
1788 TRACE("(%p %p %s %p)\n", doc
, event_target
, debugstr_w(event
), disp
);
1790 eid
= attr_to_eid(event
);
1791 if(eid
== EVENTID_LAST
) {
1792 WARN("Unsupported event %s\n", debugstr_w(event
));
1796 set_event_handler_disp(event_target
, eid
, disp
);
1799 void update_doc_cp_events(HTMLDocumentNode
*doc
, cp_static_data_t
*cp
)
1803 for(i
=0; i
< EVENTID_LAST
; i
++) {
1804 if((event_info
[i
].flags
& EVENT_DEFAULTLISTENER
) && is_cp_event(cp
, event_info
[i
].dispid
))
1805 ensure_doc_nsevent_handler(doc
, i
);
1809 void check_event_attr(HTMLDocumentNode
*doc
, nsIDOMHTMLElement
*nselem
)
1811 nsIDOMMozNamedAttrMap
*attr_map
;
1812 const PRUnichar
*name
, *value
;
1813 nsAString name_str
, value_str
;
1814 HTMLDOMNode
*node
= NULL
;
1823 nsres
= nsIDOMHTMLElement_HasAttributes(nselem
, &has_attrs
);
1824 if(NS_FAILED(nsres
) || !has_attrs
)
1827 nsres
= nsIDOMHTMLElement_GetAttributes(nselem
, &attr_map
);
1828 if(NS_FAILED(nsres
))
1831 nsres
= nsIDOMMozNamedAttrMap_GetLength(attr_map
, &length
);
1832 assert(nsres
== NS_OK
);
1834 nsAString_Init(&name_str
, NULL
);
1835 nsAString_Init(&value_str
, NULL
);
1837 for(i
= 0; i
< length
; i
++) {
1838 nsres
= nsIDOMMozNamedAttrMap_Item(attr_map
, i
, &attr
);
1839 if(NS_FAILED(nsres
))
1842 nsres
= nsIDOMAttr_GetName(attr
, &name_str
);
1843 if(NS_FAILED(nsres
)) {
1844 nsIDOMAttr_Release(attr
);
1848 nsAString_GetData(&name_str
, &name
);
1849 eid
= attr_to_eid(name
);
1850 if(eid
== EVENTID_LAST
) {
1851 nsIDOMAttr_Release(attr
);
1855 nsres
= nsIDOMAttr_GetValue(attr
, &value_str
);
1856 nsIDOMAttr_Release(attr
);
1857 if(NS_FAILED(nsres
))
1860 nsAString_GetData(&value_str
, &value
);
1864 TRACE("%p.%s = %s\n", nselem
, debugstr_w(name
), debugstr_w(value
));
1866 disp
= script_parse_event(doc
->window
, value
);
1871 hres
= get_node(doc
, (nsIDOMNode
*)nselem
, TRUE
, &node
);
1873 IDispatch_Release(disp
);
1878 set_event_handler_disp(get_node_event_prop_target(node
, eid
), eid
, disp
);
1879 IDispatch_Release(disp
);
1884 nsAString_Finish(&name_str
);
1885 nsAString_Finish(&value_str
);
1886 nsIDOMMozNamedAttrMap_Release(attr_map
);
1889 HRESULT
doc_init_events(HTMLDocumentNode
*doc
)
1894 doc
->event_vector
= heap_alloc_zero(EVENTID_LAST
*sizeof(BOOL
));
1895 if(!doc
->event_vector
)
1896 return E_OUTOFMEMORY
;
1900 for(i
=0; i
< EVENTID_LAST
; i
++) {
1901 if(event_info
[i
].flags
& EVENT_HASDEFAULTHANDLERS
) {
1902 hres
= ensure_doc_nsevent_handler(doc
, i
);
1911 static inline EventTarget
*impl_from_IEventTarget(IEventTarget
*iface
)
1913 return CONTAINING_RECORD(iface
, EventTarget
, IEventTarget_iface
);
1916 static HRESULT WINAPI
EventTarget_QueryInterface(IEventTarget
*iface
, REFIID riid
, void **ppv
)
1918 EventTarget
*This
= impl_from_IEventTarget(iface
);
1919 return IDispatchEx_QueryInterface(&This
->dispex
.IDispatchEx_iface
, riid
, ppv
);
1922 static ULONG WINAPI
EventTarget_AddRef(IEventTarget
*iface
)
1924 EventTarget
*This
= impl_from_IEventTarget(iface
);
1925 return IDispatchEx_AddRef(&This
->dispex
.IDispatchEx_iface
);
1928 static ULONG WINAPI
EventTarget_Release(IEventTarget
*iface
)
1930 EventTarget
*This
= impl_from_IEventTarget(iface
);
1931 return IDispatchEx_Release(&This
->dispex
.IDispatchEx_iface
);
1934 static HRESULT WINAPI
EventTarget_GetTypeInfoCount(IEventTarget
*iface
, UINT
*pctinfo
)
1936 EventTarget
*This
= impl_from_IEventTarget(iface
);
1937 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1940 static HRESULT WINAPI
EventTarget_GetTypeInfo(IEventTarget
*iface
, UINT iTInfo
,
1941 LCID lcid
, ITypeInfo
**ppTInfo
)
1943 EventTarget
*This
= impl_from_IEventTarget(iface
);
1944 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1947 static HRESULT WINAPI
EventTarget_GetIDsOfNames(IEventTarget
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
1948 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1950 EventTarget
*This
= impl_from_IEventTarget(iface
);
1951 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
,
1952 rgszNames
, cNames
, lcid
, rgDispId
);
1955 static HRESULT WINAPI
EventTarget_Invoke(IEventTarget
*iface
, DISPID dispIdMember
,
1956 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1957 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1959 EventTarget
*This
= impl_from_IEventTarget(iface
);
1960 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
,
1961 riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1964 static HRESULT WINAPI
EventTarget_addEventListener(IEventTarget
*iface
, BSTR type
,
1965 IDispatch
*listener
, VARIANT_BOOL capture
)
1967 EventTarget
*This
= impl_from_IEventTarget(iface
);
1968 FIXME("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), listener
, capture
);
1972 static HRESULT WINAPI
EventTarget_removeEventListener(IEventTarget
*iface
, BSTR type
,
1973 IDispatch
*listener
, VARIANT_BOOL capture
)
1975 EventTarget
*This
= impl_from_IEventTarget(iface
);
1976 FIXME("(%p)->(%s %p %x)\n", This
, debugstr_w(type
), listener
, capture
);
1980 static HRESULT WINAPI
EventTarget_dispatchEvent(IEventTarget
*iface
, IDOMEvent
*event
, VARIANT_BOOL
*result
)
1982 EventTarget
*This
= impl_from_IEventTarget(iface
);
1983 FIXME("(%p)->(%p %p)\n", This
, event
, result
);
1987 static const IEventTargetVtbl EventTargetVtbl
= {
1988 EventTarget_QueryInterface
,
1990 EventTarget_Release
,
1991 EventTarget_GetTypeInfoCount
,
1992 EventTarget_GetTypeInfo
,
1993 EventTarget_GetIDsOfNames
,
1995 EventTarget_addEventListener
,
1996 EventTarget_removeEventListener
,
1997 EventTarget_dispatchEvent
2000 #define DELAY_INIT_VTBL ((const IEventTargetVtbl*)1)
2002 static BOOL
use_event_quirks(EventTarget
*event_target
)
2004 if(event_target
->IEventTarget_iface
.lpVtbl
== DELAY_INIT_VTBL
) {
2005 event_target
->IEventTarget_iface
.lpVtbl
=
2006 dispex_compat_mode(&event_target
->dispex
) >= COMPAT_MODE_IE9
2007 ? &EventTargetVtbl
: NULL
;
2009 return !event_target
->IEventTarget_iface
.lpVtbl
;
2012 HRESULT
EventTarget_QI(EventTarget
*event_target
, REFIID riid
, void **ppv
)
2014 if(IsEqualGUID(riid
, &IID_IEventTarget
)) {
2015 if(use_event_quirks(event_target
)) {
2016 WARN("IEventTarget queried, but not supported by in document mode\n");
2018 return E_NOINTERFACE
;
2020 IEventTarget_AddRef(&event_target
->IEventTarget_iface
);
2021 *ppv
= &event_target
->IEventTarget_iface
;
2025 if(dispex_query_interface(&event_target
->dispex
, riid
, ppv
))
2026 return *ppv
? S_OK
: E_NOINTERFACE
;
2028 WARN("(%p)->(%s %p)\n", event_target
, debugstr_mshtml_guid(riid
), ppv
);
2030 return E_NOINTERFACE
;
2033 static int event_id_cmp(const void *key
, const struct wine_rb_entry
*entry
)
2035 return (INT_PTR
)key
- WINE_RB_ENTRY_VALUE(entry
, handler_vector_t
, entry
)->event_id
;
2038 void EventTarget_Init(EventTarget
*event_target
, IUnknown
*outer
, dispex_static_data_t
*dispex_data
,
2039 compat_mode_t compat_mode
)
2041 init_dispex_with_compat_mode(&event_target
->dispex
, outer
, dispex_data
, compat_mode
);
2042 wine_rb_init(&event_target
->handler_map
, event_id_cmp
);
2045 * IEventTarget is supported by the object or not depending on compatibility mode.
2046 * We use NULL vtbl for objects in compatibility mode not supporting the interface.
2047 * For targets that don't know compatibility mode at creation time, we set vtbl
2048 * to special DELAY_INIT_VTBL value so that vtbl will be set to proper value
2051 if(compat_mode
== COMPAT_MODE_QUIRKS
&& dispex_data
->vtbl
&& dispex_data
->vtbl
->get_compat_mode
)
2052 event_target
->IEventTarget_iface
.lpVtbl
= DELAY_INIT_VTBL
;
2053 else if(compat_mode
< COMPAT_MODE_IE9
)
2054 event_target
->IEventTarget_iface
.lpVtbl
= NULL
;
2056 event_target
->IEventTarget_iface
.lpVtbl
= &EventTargetVtbl
;
2059 void release_event_target(EventTarget
*event_target
)
2061 handler_vector_t
*iter
, *iter2
;
2064 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter
, iter2
, &event_target
->handler_map
, handler_vector_t
, entry
) {
2065 if(iter
->handler_prop
)
2066 IDispatch_Release(iter
->handler_prop
);
2067 for(i
= 0; i
< iter
->handler_cnt
; i
++)
2068 if(iter
->handlers
[i
])
2069 IDispatch_Release(iter
->handlers
[i
]);
2070 heap_free(iter
->handlers
);