mshtml: Improved IDOMMouseEvent::offset[XY] stubs.
[wine.git] / dlls / mshtml / htmlevent.c
blob6c7547538139404253d0a453efcc58ad2e2fcedc
1 /*
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
19 #include <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "mshtmdid.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
32 #include "htmlscript.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38 typedef enum {
39 LISTENER_TYPE_CAPTURE,
40 LISTENER_TYPE_BUBBLE,
41 LISTENER_TYPE_ONEVENT,
42 LISTENER_TYPE_ATTACHED
43 } listener_type_t;
45 typedef struct {
46 struct list entry;
47 listener_type_t type;
48 IDispatch *function;
49 } event_listener_t;
51 typedef struct {
52 struct wine_rb_entry entry;
53 struct list listeners;
54 WCHAR type[1];
55 } listener_container_t;
57 typedef enum {
58 DISPATCH_BOTH,
59 DISPATCH_STANDARD,
60 DISPATCH_LEGACY
61 } dispatch_mode_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};
105 typedef enum {
106 EVENT_TYPE_EVENT,
107 EVENT_TYPE_UIEVENT,
108 EVENT_TYPE_KEYBOARD,
109 EVENT_TYPE_MOUSE,
110 EVENT_TYPE_FOCUS,
111 EVENT_TYPE_DRAG,
112 EVENT_TYPE_MESSAGE,
113 EVENT_TYPE_CLIPBOARD
114 } event_type_t;
116 static const WCHAR *event_types[] = {
117 EventW,
118 UIEventW,
119 KeyboardEventW,
120 MouseEventW,
121 EventW, /* FIXME */
122 EventW, /* FIXME */
123 EventW, /* FIXME */
124 EventW /* FIXME */
127 typedef struct {
128 const WCHAR *name;
129 event_type_t type;
130 DISPID dispid;
131 DWORD flags;
132 } event_info_t;
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,
143 EVENT_BIND_TO_BODY},
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,
167 EVENT_BIND_TO_BODY},
168 {focusW, EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUS,
169 EVENT_DEFAULTLISTENER},
170 {focusinW, EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSIN,
171 EVENT_BUBBLES},
172 {focusoutW, EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSOUT,
173 EVENT_BUBBLES},
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,
183 EVENT_BIND_TO_BODY},
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,
197 EVENT_FIXME},
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,
207 EVENT_FIXME},
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,
213 EVENT_FIXME}
216 static eventid_t str_to_eid(const WCHAR *str)
218 int i;
220 for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) {
221 if(!strcmpW(event_info[i].name, str))
222 return i;
225 return EVENTID_LAST;
228 static eventid_t attr_to_eid(const WCHAR *str)
230 int i;
232 if((str[0] != 'o' && str[0] != 'O') || (str[1] != 'n' && str[1] != 'N'))
233 return EVENTID_LAST;
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)
237 return i;
240 return EVENTID_LAST;
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;
248 size_t type_len;
249 eventid_t eid;
251 entry = wine_rb_get(&event_target->handler_map, type);
252 if(entry)
253 return WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry);
254 if(!alloc)
255 return NULL;
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]));
263 if(!container)
264 return NULL;
265 memcpy(container->type, type, (type_len + 1) * sizeof(WCHAR));
266 list_init(&container->listeners);
267 vtbl = dispex_get_vtbl(&event_target->dispex);
268 if(vtbl->bind_event)
269 vtbl->bind_event(&event_target->dispex, eid);
270 else
271 FIXME("Unsupported event binding on target %p\n", event_target);
273 wine_rb_put(&event_target->handler_map, container->type, &container->entry);
274 return container;
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);
283 if(!container)
284 return;
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);
290 heap_free(listener);
291 break;
296 static HRESULT get_gecko_target(IEventTarget*,nsIDOMEventTarget**);
298 typedef struct {
299 DispatchEx dispex;
300 IHTMLEventObj IHTMLEventObj_iface;
302 LONG ref;
304 DOMEvent *event;
305 VARIANT return_value;
306 } HTMLEventObj;
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;
325 }else {
326 *ppv = NULL;
327 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
328 return E_NOINTERFACE;
331 IUnknown_AddRef((IUnknown*)*ppv);
332 return S_OK;
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);
342 return 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);
352 if(!ref) {
353 if(This->event)
354 IDOMEvent_Release(&This->event->IDOMEvent_iface);
355 release_dispex(&This->dispex);
356 heap_free(This);
359 return ref;
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,
381 lcid, rgDispId);
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);
399 if(!This->event) {
400 *p = NULL;
401 return S_OK;
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);
421 return S_OK;
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);
438 return S_OK;
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);
455 return S_OK;
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);
472 return S_OK;
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);
481 V_VT(p) = VT_EMPTY;
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);
491 if(This->event)
492 IDOMEvent_stopPropagation(&This->event->IDOMEvent_iface);
493 return S_OK;
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);
503 return S_OK;
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);
512 *p = NULL;
513 return S_OK;
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);
522 *p = NULL;
523 return S_OK;
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);
530 return E_NOTIMPL;
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);
542 *p = 0;
543 return S_OK;
546 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p)
548 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
549 USHORT button = 0;
551 TRACE("(%p)->(%p)\n", This, p);
553 if(This->event && This->event->mouse_event) {
554 HRESULT hres;
555 hres = IDOMMouseEvent_get_button(&This->event->IDOMMouseEvent_iface, &button);
556 if(FAILED(hres))
557 return hres;
560 *p = button;
561 return S_OK;
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);
570 if(!This->event) {
571 *p = NULL;
572 return S_OK;
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);
584 *p = NULL;
585 return S_OK;
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);
594 *p = 0;
595 return S_OK;
598 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p)
600 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
601 LONG x = 0;
603 TRACE("(%p)->(%p)\n", This, p);
605 if(This->event && This->event->ui_event) {
606 nsresult nsres;
608 /* NOTE: pageX is not exactly right here. */
609 nsres = nsIDOMUIEvent_GetPageX(This->event->ui_event, &x);
610 assert(nsres == NS_OK);
613 *p = x;
614 return S_OK;
617 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p)
619 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
620 LONG y = 0;
622 TRACE("(%p)->(%p)\n", This, p);
624 if(This->event && This->event->ui_event) {
625 nsresult nsres;
627 /* NOTE: pageY is not exactly right here. */
628 nsres = nsIDOMUIEvent_GetPageY(This->event->ui_event, &y);
629 assert(nsres == NS_OK);
632 *p = y;
633 return S_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);
645 *p = 0;
646 return S_OK;
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);
658 *p = 0;
659 return S_OK;
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);
671 *p = 0;
672 return S_OK;
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);
684 *p = 0;
685 return S_OK;
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);
697 *p = 0;
698 return S_OK;
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);
710 *p = 0;
711 return S_OK;
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);
720 *p = NULL;
721 return S_OK;
724 static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
725 HTMLEventObj_QueryInterface,
726 HTMLEventObj_AddRef,
727 HTMLEventObj_Release,
728 HTMLEventObj_GetTypeInfoCount,
729 HTMLEventObj_GetTypeInfo,
730 HTMLEventObj_GetIDsOfNames,
731 HTMLEventObj_Invoke,
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,
748 HTMLEventObj_get_x,
749 HTMLEventObj_get_y,
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[] = {
765 IHTMLEventObj_tid,
769 static dispex_static_data_t HTMLEventObj_dispex = {
770 NULL,
771 DispCEventObj_tid,
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));
780 if(!event_obj)
781 return NULL;
783 event_obj->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
784 event_obj->ref = 1;
785 event_obj->event = event;
786 if(event)
787 IDOMEvent_AddRef(&event->IDOMEvent_iface);
789 init_dispex(&event_obj->dispex, (IUnknown*)&event_obj->IHTMLEventObj_iface, &HTMLEventObj_dispex);
790 return event_obj;
793 HRESULT create_event_obj(IHTMLEventObj **ret)
795 HTMLEventObj *event_obj;
797 event_obj = alloc_event_obj(NULL);
798 if(!event_obj)
799 return E_OUTOFMEMORY;
801 *ret = &event_obj->IHTMLEventObj_iface;
802 return S_OK;
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;
835 else {
836 *ppv = NULL;
837 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
838 return E_NOINTERFACE;
841 IUnknown_AddRef((IUnknown*)*ppv);
842 return S_OK;
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);
852 return 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);
862 if(!ref) {
863 if(This->ui_event)
864 nsIDOMUIEvent_Release(This->ui_event);
865 if(This->mouse_event)
866 nsIDOMMouseEvent_Release(This->mouse_event);
867 if(This->target)
868 IEventTarget_Release(&This->target->IEventTarget_iface);
869 nsIDOMEvent_Release(This->nsevent);
870 release_dispex(&This->dispex);
871 heap_free(This->type);
872 heap_free(This);
875 return ref;
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,
896 lcid, rgDispId);
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);
915 return S_OK;
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);
925 return S_OK;
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);
936 else
937 *p = NULL;
938 return S_OK;
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);
948 return S_OK;
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);
957 *p = This->phase;
958 return S_OK;
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);
967 if(This->target)
968 IEventTarget_AddRef(*p = &This->target->IEventTarget_iface);
969 else
970 *p = NULL;
971 return S_OK;
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;
981 return S_OK;
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);
990 if(This->type) {
991 *p = SysAllocString(This->type);
992 if(!*p)
993 return E_OUTOFMEMORY;
994 }else {
995 *p = NULL;
997 return S_OK;
1000 #ifdef __i386__
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)
1005 #endif
1007 static HRESULT WINAPI DOMEvent_initEvent(IDOMEvent *iface, BSTR type, VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable)
1009 DOMEvent *This = impl_from_IDOMEvent(iface);
1010 nsAString nsstr;
1012 TRACE("(%p)->(%s %x %x)\n", This, debugstr_w(type), can_bubble, cancelable);
1014 if(This->target) {
1015 TRACE("called on already dispatched event\n");
1016 return S_OK;
1019 heap_free(This->type);
1020 This->type = heap_strdupW(type);
1021 if(!This->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);
1032 return S_OK;
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);
1045 return S_OK;
1048 static HRESULT WINAPI DOMEvent_stopPropagation(IDOMEvent *iface)
1050 DOMEvent *This = impl_from_IDOMEvent(iface);
1052 TRACE("(%p)\n", This);
1054 This->stop_propagation = TRUE;
1055 nsIDOMEvent_StopPropagation(This->nsevent);
1056 return S_OK;
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);
1067 return S_OK;
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);
1074 return E_NOTIMPL;
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);
1081 return E_NOTIMPL;
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);
1088 return E_NOTIMPL;
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);
1097 if(This->target)
1098 IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
1099 else
1100 *p = NULL;
1101 return S_OK;
1104 static const IDOMEventVtbl DOMEventVtbl = {
1105 DOMEvent_QueryInterface,
1106 DOMEvent_AddRef,
1107 DOMEvent_Release,
1108 DOMEvent_GetTypeInfoCount,
1109 DOMEvent_GetTypeInfo,
1110 DOMEvent_GetIDsOfNames,
1111 DOMEvent_Invoke,
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,
1119 DOMEvent_get_type,
1120 DOMEvent_initEvent,
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,
1171 lcid, rgDispId);
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;
1188 nsresult nsres;
1190 TRACE("(%p)->(%p)\n", This, p);
1192 nsres = nsIDOMUIEvent_GetView(This->ui_event, &moz_window);
1193 if(NS_FAILED(nsres))
1194 return E_FAIL;
1196 if(moz_window) {
1197 view = mozwindow_to_window(moz_window);
1198 mozIDOMWindowProxy_Release(moz_window);
1200 if(view)
1201 IHTMLWindow2_AddRef((*p = &view->base.inner_window->base.IHTMLWindow2_iface));
1202 else
1203 *p = NULL;
1204 return S_OK;
1207 static HRESULT WINAPI DOMUIEvent_get_detail(IDOMUIEvent *iface, LONG *p)
1209 DOMEvent *This = impl_from_IDOMUIEvent(iface);
1210 INT32 detail;
1211 nsresult nsres;
1213 TRACE("(%p)->(%p)\n", This, p);
1215 nsres = nsIDOMUIEvent_GetDetail(This->ui_event, &detail);
1216 if(NS_FAILED(nsres))
1217 return E_FAIL;
1219 *p = detail;
1220 return S_OK;
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);
1227 nsAString type_str;
1228 nsresult nsres;
1229 HRESULT hres;
1231 TRACE("(%p)->(%s %x %x %p %x)\n", This, debugstr_w(type), can_bubble, cancelable, view, detail);
1233 if(This->target) {
1234 TRACE("called on already dispatched event\n");
1235 return S_OK;
1238 if(view)
1239 FIXME("view argument is not supported\n");
1241 hres = IDOMEvent_initEvent(&This->IDOMEvent_iface, type, can_bubble, cancelable);
1242 if(FAILED(hres))
1243 return hres;
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);
1251 return E_FAIL;
1254 return S_OK;
1257 static const IDOMUIEventVtbl DOMUIEventVtbl = {
1258 DOMUIEvent_QueryInterface,
1259 DOMUIEvent_AddRef,
1260 DOMUIEvent_Release,
1261 DOMUIEvent_GetTypeInfoCount,
1262 DOMUIEvent_GetTypeInfo,
1263 DOMUIEvent_GetIDsOfNames,
1264 DOMUIEvent_Invoke,
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,
1311 lcid, rgDispId);
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);
1326 INT32 screen_x;
1327 nsresult nsres;
1329 TRACE("(%p)->(%p)\n", This, p);
1331 nsres = nsIDOMMouseEvent_GetScreenX(This->mouse_event, &screen_x);
1332 if(NS_FAILED(nsres))
1333 return E_FAIL;
1335 *p = screen_x;
1336 return S_OK;
1339 static HRESULT WINAPI DOMMouseEvent_get_screenY(IDOMMouseEvent *iface, LONG *p)
1341 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1342 INT32 screen_y;
1343 nsresult nsres;
1345 TRACE("(%p)->(%p)\n", This, p);
1347 nsres = nsIDOMMouseEvent_GetScreenY(This->mouse_event, &screen_y);
1348 if(NS_FAILED(nsres))
1349 return E_FAIL;
1351 *p = screen_y;
1352 return S_OK;
1355 static HRESULT WINAPI DOMMouseEvent_get_clientX(IDOMMouseEvent *iface, LONG *p)
1357 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1358 INT32 client_x;
1359 nsresult nsres;
1361 TRACE("(%p)->(%p)\n", This, p);
1363 nsres = nsIDOMMouseEvent_GetClientX(This->mouse_event, &client_x);
1364 if(NS_FAILED(nsres))
1365 return E_FAIL;
1367 *p = client_x;
1368 return S_OK;
1371 static HRESULT WINAPI DOMMouseEvent_get_clientY(IDOMMouseEvent *iface, LONG *p)
1373 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1374 INT32 client_y;
1375 nsresult nsres;
1377 TRACE("(%p)->(%p)\n", This, p);
1379 nsres = nsIDOMMouseEvent_GetClientY(This->mouse_event, &client_y);
1380 if(NS_FAILED(nsres))
1381 return E_FAIL;
1383 *p = client_y;
1384 return S_OK;
1387 static HRESULT WINAPI DOMMouseEvent_get_ctrlKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1389 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1390 cpp_bool r;
1391 nsresult nsres;
1393 TRACE("(%p)->(%p)\n", This, p);
1395 nsres = nsIDOMMouseEvent_GetCtrlKey(This->mouse_event, &r);
1396 if(NS_FAILED(nsres))
1397 return E_FAIL;
1399 *p = variant_bool(r);
1400 return S_OK;
1403 static HRESULT WINAPI DOMMouseEvent_get_shiftKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1405 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1406 cpp_bool r;
1407 nsresult nsres;
1409 TRACE("(%p)->(%p)\n", This, p);
1411 nsres = nsIDOMMouseEvent_GetShiftKey(This->mouse_event, &r);
1412 if(NS_FAILED(nsres))
1413 return E_FAIL;
1415 *p = variant_bool(r);
1416 return S_OK;
1419 static HRESULT WINAPI DOMMouseEvent_get_altKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1421 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1422 cpp_bool r;
1423 nsresult nsres;
1425 TRACE("(%p)->(%p)\n", This, p);
1427 nsres = nsIDOMMouseEvent_GetAltKey(This->mouse_event, &r);
1428 if(NS_FAILED(nsres))
1429 return E_FAIL;
1431 *p = variant_bool(r);
1432 return S_OK;
1435 static HRESULT WINAPI DOMMouseEvent_get_metaKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1437 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1438 cpp_bool r;
1439 nsresult nsres;
1441 TRACE("(%p)->(%p)\n", This, p);
1443 nsres = nsIDOMMouseEvent_GetMetaKey(This->mouse_event, &r);
1444 if(NS_FAILED(nsres))
1445 return E_FAIL;
1447 *p = variant_bool(r);
1448 return S_OK;
1451 static HRESULT WINAPI DOMMouseEvent_get_button(IDOMMouseEvent *iface, USHORT *p)
1453 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1454 INT16 r;
1455 nsresult nsres;
1457 TRACE("(%p)->(%p)\n", This, p);
1459 nsres = nsIDOMMouseEvent_GetButton(This->mouse_event, &r);
1460 if(NS_FAILED(nsres))
1461 return E_FAIL;
1463 *p = r;
1464 return S_OK;
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;
1472 HTMLDOMNode *node;
1473 HRESULT hres;
1474 nsresult nsres;
1476 TRACE("(%p)->(%p)\n", This, p);
1478 nsres = nsIDOMMouseEvent_GetRelatedTarget(This->mouse_event, &related_target);
1479 if(NS_FAILED(nsres))
1480 return E_FAIL;
1482 if(!related_target) {
1483 *p = NULL;
1484 return S_OK;
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");
1491 return E_NOTIMPL;
1494 hres = get_node(target_node, TRUE, &node);
1495 nsIDOMNode_Release(target_node);
1496 if(FAILED(hres))
1497 return hres;
1499 *p = &node->event_target.IEventTarget_iface;
1500 return S_OK;
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;
1511 nsAString type_str;
1512 nsresult nsres;
1513 HRESULT hres;
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);
1519 if(This->target) {
1520 TRACE("called on already dispatched event\n");
1521 return S_OK;
1524 if(view)
1525 FIXME("view argument is not supported\n");
1527 if(related_target) {
1528 hres = get_gecko_target(related_target, &nstarget);
1529 if(FAILED(hres))
1530 return hres;
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);
1543 return E_FAIL;
1547 if(nstarget)
1548 nsIDOMEventTarget_Release(nstarget);
1549 return S_OK;
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);
1557 return E_NOTIMPL;
1560 static HRESULT WINAPI DOMMouseEvent_get_buttons(IDOMMouseEvent *iface, USHORT *p)
1562 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1563 UINT16 r;
1564 nsresult nsres;
1566 TRACE("(%p)->(%p)\n", This, p);
1568 nsres = nsIDOMMouseEvent_GetButtons(This->mouse_event, &r);
1569 if(NS_FAILED(nsres))
1570 return E_FAIL;
1572 *p = r;
1573 return S_OK;
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);
1580 return E_NOTIMPL;
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);
1587 return E_NOTIMPL;
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);
1594 return E_NOTIMPL;
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);
1601 return E_NOTIMPL;
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);
1610 *p = 0;
1611 return S_OK;
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);
1620 *p = 0;
1621 return S_OK;
1624 static HRESULT WINAPI DOMMouseEvent_get_pageX(IDOMMouseEvent *iface, LONG *p)
1626 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1627 INT32 r;
1628 nsresult nsres;
1630 TRACE("(%p)->(%p)\n", This, p);
1632 nsres = nsIDOMMouseEvent_GetPageX(This->mouse_event, &r);
1633 if(NS_FAILED(nsres))
1634 return E_FAIL;
1636 *p = r;
1637 return S_OK;
1640 static HRESULT WINAPI DOMMouseEvent_get_pageY(IDOMMouseEvent *iface, LONG *p)
1642 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1643 INT32 r;
1644 nsresult nsres;
1646 TRACE("(%p)->(%p)\n", This, p);
1648 nsres = nsIDOMMouseEvent_GetPageY(This->mouse_event, &r);
1649 if(NS_FAILED(nsres))
1650 return E_FAIL;
1652 *p = r;
1653 return S_OK;
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);
1660 return E_NOTIMPL;
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);
1667 return E_NOTIMPL;
1670 static HRESULT WINAPI DOMMouseEvent_get_which(IDOMMouseEvent *iface, USHORT *p)
1672 DOMEvent *This = impl_from_IDOMMouseEvent(iface);
1673 UINT32 r;
1674 nsresult nsres;
1676 TRACE("(%p)->(%p)\n", This, p);
1678 nsres = nsIDOMMouseEvent_GetWhich(This->mouse_event, &r);
1679 if(NS_FAILED(nsres))
1680 return E_FAIL;
1682 *p = r;
1683 return S_OK;
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,
1761 lcid, rgDispId);
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);
1776 nsAString key_str;
1777 nsresult nsres;
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);
1790 UINT32 r;
1791 nsresult nsres;
1793 TRACE("(%p)->(%p)\n", This, p);
1795 nsres = nsIDOMKeyEvent_GetLocation(This->keyboard_event, &r);
1796 if(NS_FAILED(nsres))
1797 return E_FAIL;
1799 *p = r;
1800 return S_OK;
1803 static HRESULT WINAPI DOMKeyboardEvent_get_ctrlKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1805 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1806 cpp_bool r;
1807 nsresult nsres;
1809 TRACE("(%p)->(%p)\n", This, p);
1811 nsres = nsIDOMKeyEvent_GetCtrlKey(This->keyboard_event, &r);
1812 if(NS_FAILED(nsres))
1813 return E_FAIL;
1815 *p = variant_bool(r);
1816 return S_OK;
1819 static HRESULT WINAPI DOMKeyboardEvent_get_shiftKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1821 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1822 cpp_bool r;
1823 nsresult nsres;
1825 TRACE("(%p)->(%p)\n", This, p);
1827 nsres = nsIDOMKeyEvent_GetShiftKey(This->keyboard_event, &r);
1828 if(NS_FAILED(nsres))
1829 return E_FAIL;
1831 *p = variant_bool(r);
1832 return S_OK;
1835 static HRESULT WINAPI DOMKeyboardEvent_get_altKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1837 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1838 cpp_bool r;
1839 nsresult nsres;
1841 TRACE("(%p)->(%p)\n", This, p);
1843 nsres = nsIDOMKeyEvent_GetAltKey(This->keyboard_event, &r);
1844 if(NS_FAILED(nsres))
1845 return E_FAIL;
1847 *p = variant_bool(r);
1848 return S_OK;
1851 static HRESULT WINAPI DOMKeyboardEvent_get_metaKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1853 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1854 cpp_bool r;
1855 nsresult nsres;
1857 TRACE("(%p)->(%p)\n", This, p);
1859 nsres = nsIDOMKeyEvent_GetMetaKey(This->keyboard_event, &r);
1860 if(NS_FAILED(nsres))
1861 return E_FAIL;
1863 *p = variant_bool(r);
1864 return S_OK;
1867 static HRESULT WINAPI DOMKeyboardEvent_get_repeat(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1869 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1870 cpp_bool r;
1871 nsresult nsres;
1873 TRACE("(%p)->(%p)\n", This, p);
1875 nsres = nsIDOMKeyEvent_GetRepeat(This->keyboard_event, &r);
1876 if(NS_FAILED(nsres))
1877 return E_FAIL;
1879 *p = variant_bool(r);
1880 return S_OK;
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);
1888 return E_NOTIMPL;
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));
1899 return E_NOTIMPL;
1902 static HRESULT WINAPI DOMKeyboardEvent_get_keyCode(IDOMKeyboardEvent *iface, LONG *p)
1904 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1905 UINT32 r;
1906 nsresult nsres;
1908 TRACE("(%p)->(%p)\n", This, p);
1910 nsres = nsIDOMKeyEvent_GetKeyCode(This->keyboard_event, &r);
1911 if(NS_FAILED(nsres))
1912 return E_FAIL;
1914 *p = r;
1915 return S_OK;
1918 static HRESULT WINAPI DOMKeyboardEvent_get_charCode(IDOMKeyboardEvent *iface, LONG *p)
1920 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1921 UINT32 r;
1922 nsresult nsres;
1924 TRACE("(%p)->(%p)\n", This, p);
1926 nsres = nsIDOMKeyEvent_GetKeyCode(This->keyboard_event, &r);
1927 if(NS_FAILED(nsres))
1928 return E_FAIL;
1930 *p = r;
1931 return S_OK;
1934 static HRESULT WINAPI DOMKeyboardEvent_get_which(IDOMKeyboardEvent *iface, LONG *p)
1936 DOMEvent *This = impl_from_IDOMKeyboardEvent(iface);
1937 UINT32 r;
1938 nsresult nsres;
1940 TRACE("(%p)->(%p)\n", This, p);
1942 nsres = nsIDOMKeyEvent_GetWhich(This->keyboard_event, &r);
1943 if(NS_FAILED(nsres))
1944 return E_FAIL;
1946 *p = r;
1947 return S_OK;
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);
1954 return E_NOTIMPL;
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);
1961 return E_NOTIMPL;
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[] = {
1989 IDOMEvent_tid,
1993 static dispex_static_data_t DOMEvent_dispex = {
1994 NULL,
1995 DispDOMEvent_tid,
1996 DOMEvent_iface_tids
1999 static const tid_t DOMUIEvent_iface_tids[] = {
2000 IDOMEvent_tid,
2001 IDOMUIEvent_tid,
2005 static dispex_static_data_t DOMUIEvent_dispex = {
2006 NULL,
2007 DispDOMUIEvent_tid,
2008 DOMUIEvent_iface_tids
2011 static const tid_t DOMMouseEvent_iface_tids[] = {
2012 IDOMEvent_tid,
2013 IDOMUIEvent_tid,
2014 IDOMMouseEvent_tid,
2018 static dispex_static_data_t DOMMouseEvent_dispex = {
2019 NULL,
2020 DispDOMMouseEvent_tid,
2021 DOMMouseEvent_iface_tids
2024 static const tid_t DOMKeyboardEvent_iface_tids[] = {
2025 IDOMEvent_tid,
2026 IDOMUIEvent_tid,
2027 IDOMKeyboardEvent_tid,
2031 static dispex_static_data_t DOMKeyboardEvent_dispex = {
2032 NULL,
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;
2040 DOMEvent *event;
2041 FILETIME time;
2042 nsresult nsres;
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));
2048 if(!event)
2049 return NULL;
2051 event->IDOMEvent_iface.lpVtbl = &DOMEventVtbl;
2052 event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
2053 event->IDOMMouseEvent_iface.lpVtbl = &DOMMouseEventVtbl;
2054 event->IDOMKeyboardEvent_iface.lpVtbl = &DOMKeyboardEventVtbl;
2055 event->ref = 1;
2056 event->event_id = event_id;
2057 if(event_id != EVENTID_LAST) {
2058 event->type = heap_strdupW(event_info[event_id].name);
2059 if(!event->type) {
2060 heap_free(event);
2061 return NULL;
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
2070 - time_epoch;
2072 nsres = nsIDOMEvent_QueryInterface(nsevent, &IID_nsIDOMUIEvent, (void**)&event->ui_event);
2073 if(NS_SUCCEEDED(nsres))
2074 dispex_data = &DOMUIEvent_dispex;
2075 else
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;
2081 else
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;
2087 else
2088 event->keyboard_event = NULL;
2090 init_dispex(&event->dispex, (IUnknown*)&event->IDOMEvent_iface, dispex_data);
2091 return event;
2094 HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, DOMEvent **ret_event)
2096 eventid_t event_id = EVENTID_LAST;
2097 DOMEvent *event;
2098 nsAString nsstr;
2099 nsresult nsres;
2101 nsAString_Init(&nsstr, NULL);
2102 nsres = nsIDOMEvent_GetType(nsevent, &nsstr);
2103 if(NS_SUCCEEDED(nsres)) {
2104 const WCHAR *type;
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));
2109 }else {
2110 ERR("GetType failed: %08x\n", nsres);
2112 nsAString_Finish(&nsstr);
2114 event = alloc_event(nsevent, event_id);
2115 if(!event)
2116 return E_OUTOFMEMORY;
2118 *ret_event = event;
2119 return S_OK;
2122 HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOMEvent **ret_event)
2124 nsIDOMEvent *nsevent;
2125 DOMEvent *event;
2126 nsAString nsstr;
2127 nsresult nsres;
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);
2134 return E_FAIL;
2137 event = alloc_event(nsevent, EVENTID_LAST);
2138 nsIDOMEvent_Release(nsevent);
2139 if(!event)
2140 return E_OUTOFMEMORY;
2142 *ret_event = &event->IDOMEvent_iface;
2143 return S_OK;
2146 HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEvent **ret_event)
2148 nsIDOMEvent *nsevent;
2149 DOMEvent *event;
2150 nsAString nsstr;
2151 nsresult nsres;
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);
2158 return E_FAIL;
2161 event = alloc_event(nsevent, event_id);
2162 if(!event)
2163 return E_OUTOFMEMORY;
2165 event->event_id = event_id;
2166 *ret_event = event;
2167 return S_OK;
2170 static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
2172 IDispatchEx *dispex;
2173 EXCEPINFO ei;
2174 HRESULT hres;
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);
2182 }else {
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);
2188 return hres;
2191 static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, IHTMLEventObj *event_obj, VARIANT *retv)
2193 DISPPARAMS dp = {NULL,NULL,0,0};
2194 VARIANT event_arg;
2195 ULONG argerr;
2196 EXCEPINFO ei;
2198 if(event_obj) {
2199 V_VT(&event_arg) = VT_DISPATCH;
2200 V_DISPATCH(&event_arg) = (IDispatch*)event_obj;
2201 dp.rgvarg = &event_arg;
2202 dp.cArgs = 1;
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)
2216 int min, max, i;
2217 HRESULT hres;
2219 if(!data)
2220 return FALSE;
2222 if(!data->ids) {
2223 hres = get_dispids(data->tid, &data->id_cnt, &data->ids);
2224 if(FAILED(hres))
2225 return FALSE;
2228 min = 0;
2229 max = data->id_cnt-1;
2230 while(min <= max) {
2231 i = (min+max)/2;
2232 if(data->ids[i] == dispid)
2233 return TRUE;
2235 if(data->ids[i] < dispid)
2236 min = i+1;
2237 else
2238 max = i-1;
2241 return FALSE;
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;
2252 VARIANT v;
2253 HRESULT hres;
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;
2263 VARIANTARG arg;
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);
2272 if(hres == S_OK) {
2273 TRACE("%s <<< %s\n", debugstr_w(event->type), debugstr_variant(&v));
2275 if(event->cancelable) {
2276 if(V_VT(&v) == VT_BOOL) {
2277 if(!V_BOOL(&v))
2278 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
2279 }else if(V_VT(&v) != VT_EMPTY) {
2280 FIXME("unhandled result %s\n", debugstr_variant(&v));
2283 VariantClear(&v);
2284 }else {
2285 WARN("%s <<< %08x\n", debugstr_w(event->type), hres);
2290 listeners_cnt = 0;
2291 listeners_size = sizeof(listeners_buf)/sizeof(*listeners_buf);
2293 if(container) {
2294 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
2295 if(!listener->function)
2296 continue;
2297 switch(listener->type) {
2298 case LISTENER_TYPE_ONEVENT:
2299 if(use_quirks || event->phase == DEP_CAPTURING_PHASE)
2300 continue;
2301 break;
2302 case LISTENER_TYPE_CAPTURE:
2303 if(event->phase == DEP_BUBBLING_PHASE || dispatch_mode == DISPATCH_LEGACY)
2304 continue;
2305 break;
2306 case LISTENER_TYPE_BUBBLE:
2307 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_LEGACY)
2308 continue;
2309 break;
2310 case LISTENER_TYPE_ATTACHED:
2311 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_STANDARD)
2312 continue;
2313 break;
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));
2320 if(!new_listeners)
2321 break;
2322 memcpy(new_listeners, listeners, listeners_cnt * sizeof(*listeners));
2323 }else {
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);
2332 listeners_cnt++;
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;
2340 VARIANTARG args[2];
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);
2352 if(hres == S_OK) {
2353 TRACE("%s <<< %s\n", debugstr_w(event->type),
2354 debugstr_variant(&v));
2356 if(event->cancelable) {
2357 if(V_VT(&v) == VT_BOOL) {
2358 if(!V_BOOL(&v))
2359 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
2360 }else if(V_VT(&v) != VT_EMPTY) {
2361 FIXME("unhandled result %s\n", debugstr_variant(&v));
2364 VariantClear(&v);
2365 }else {
2366 WARN("%s <<< %08x\n", debugstr_w(event->type), hres);
2368 }else {
2369 VARIANTARG arg;
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);
2378 if(hres == S_OK) {
2379 TRACE("%s attached <<<\n", debugstr_w(event->type));
2381 if(event->cancelable) {
2382 if(V_VT(&v) == VT_BOOL) {
2383 if(!V_BOOL(&v))
2384 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
2385 }else if(V_VT(&v) != VT_EMPTY) {
2386 FIXME("unhandled result %s\n", debugstr_variant(&v));
2389 VariantClear(&v);
2390 }else {
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);
2405 if(cp_container) {
2406 if(cp_container->cps) {
2407 ConnectionPoint *cp;
2408 unsigned i, j;
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))
2413 continue;
2415 for(i=0; i < cp->sinks_size; i++) {
2416 if(!cp->sinks[i].disp)
2417 continue;
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);
2424 if(hres == S_OK) {
2425 TRACE("cp %s [%u] <<<\n", debugstr_w(event->type), i);
2427 if(event->cancelable) {
2428 if(V_VT(&v) == VT_BOOL) {
2429 if(!V_BOOL(&v))
2430 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
2431 }else if(V_VT(&v) != VT_EMPTY) {
2432 FIXME("unhandled result %s\n", debugstr_variant(&v));
2435 VariantClear(&v);
2436 }else {
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;
2456 EventTarget *iter;
2457 HRESULT hres;
2459 TRACE("(%p) %s\n", event_target, debugstr_w(event->type));
2461 if(!event->type) {
2462 FIXME("Uninitialized event.\n");
2463 return E_FAIL;
2466 if(event->current_target) {
2467 FIXME("event is being dispatched.\n");
2468 return E_FAIL;
2471 iter = event_target;
2472 IEventTarget_AddRef(&event_target->IEventTarget_iface);
2474 chain_cnt = 0;
2475 chain_buf_size = sizeof(target_chain_buf)/sizeof(*target_chain_buf);
2477 do {
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));
2482 if(!new_chain)
2483 break;
2484 memcpy(new_chain, target_chain, chain_buf_size * sizeof(*new_chain));
2485 }else {
2486 new_chain = heap_realloc(target_chain, chain_buf_size * 2 * sizeof(*new_chain));
2487 if(!new_chain)
2488 break;
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)
2497 break;
2498 iter = vtbl->get_parent_event_target(&iter->dispex);
2499 } while(iter);
2501 if(!event->event_obj && !event->no_event_obj) {
2502 event_obj_ref = alloc_event_obj(event);
2503 if(event_obj_ref)
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);
2511 if(event->target)
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;
2517 i = chain_cnt-1;
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);
2532 if(r)
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);
2537 if(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)
2546 continue;
2547 hres = vtbl->handle_event_default(&event_target->dispex, event->event_id,
2548 event->nsevent, &prevent_default);
2549 if(FAILED(hres) || event->stop_propagation)
2550 break;
2551 if(prevent_default)
2552 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
2556 event->prevent_default = FALSE;
2557 if(event_obj_ref) {
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);
2567 return S_OK;
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;
2578 eventid_t eid;
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));
2590 return E_NOTIMPL;
2593 if(V_DISPATCH(event_var)) {
2594 IHTMLEventObj *event_iface;
2596 hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
2597 if(FAILED(hres)) {
2598 FIXME("No IHTMLEventObj iface\n");
2599 return hres;
2602 event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
2603 if(!event_obj) {
2604 ERR("Not our IHTMLEventObj?\n");
2605 IHTMLEventObj_Release(event_iface);
2606 return E_FAIL;
2611 if(!event_obj) {
2612 event_obj = alloc_event_obj(NULL);
2613 if(!event_obj)
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);
2627 if(FAILED(hres))
2628 return hres;
2630 *cancelled = VARIANT_TRUE; /* FIXME */
2631 return S_OK;
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));
2640 if(!doc->nsdoc)
2641 return S_OK;
2643 switch(eid) {
2644 case EVENTID_FOCUSIN:
2645 doc->event_vector[eid] = TRUE;
2646 eid = EVENTID_FOCUS;
2647 break;
2648 case EVENTID_FOCUSOUT:
2649 doc->event_vector[eid] = TRUE;
2650 eid = EVENTID_BLUR;
2651 break;
2652 default:
2653 break;
2656 if(doc->event_vector[eid] || !(event_info[eid].flags & (EVENT_DEFAULTLISTENER|EVENT_BIND_TO_BODY)))
2657 return S_OK;
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);
2667 if(nsnode)
2668 nsIDOMNode_Release(nsnode);
2669 return S_OK;
2672 void detach_events(HTMLDocumentNode *doc)
2674 if(doc->event_vector) {
2675 int i;
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)
2690 WCHAR buf[64];
2691 buf[0] = 'o';
2692 buf[1] = 'n';
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);
2703 if(!container)
2704 return NULL;
2706 LIST_FOR_EACH_ENTRY_REV(listener, &container->listeners, event_listener_t, entry) {
2707 if(listener->type == LISTENER_TYPE_ONEVENT)
2708 return listener;
2711 if(!alloc)
2712 return NULL;
2714 listener = heap_alloc(sizeof(*listener));
2715 if(!listener)
2716 return NULL;
2718 listener->type = LISTENER_TYPE_ONEVENT;
2719 listener->function = NULL;
2720 list_add_tail(&container->listeners, &listener->entry);
2721 return listener;
2724 static void remove_event_handler(EventTarget *event_target, eventid_t eid)
2726 event_listener_t *listener;
2727 VARIANT *store;
2728 HRESULT hres;
2730 hres = get_event_dispex_ref(event_target, eid, FALSE, &store);
2731 if(SUCCEEDED(hres))
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);
2749 if(!disp)
2750 return S_OK;
2752 listener = get_onevent_listener(event_target, eid, TRUE);
2753 if(!listener)
2754 return E_OUTOFMEMORY;
2756 if(listener->function)
2757 IDispatch_Release(listener->function);
2759 IDispatch_AddRef(listener->function = disp);
2760 return S_OK;
2763 HRESULT set_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
2765 switch(V_VT(var)) {
2766 case VT_EMPTY:
2767 if(use_event_quirks(event_target)) {
2768 WARN("attempt to set to VT_EMPTY in quirks mode\n");
2769 return E_NOTIMPL;
2771 /* fall through */
2772 case VT_NULL:
2773 remove_event_handler(event_target, eid);
2774 return S_OK;
2776 case VT_DISPATCH:
2777 return set_event_handler_disp(event_target, eid, V_DISPATCH(var));
2779 case VT_BSTR: {
2780 VARIANT *v;
2781 HRESULT hres;
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
2790 * properties.
2792 remove_event_handler(event_target, eid);
2794 hres = get_event_dispex_ref(event_target, eid, TRUE, &v);
2795 if(FAILED(hres))
2796 return hres;
2798 V_BSTR(v) = SysAllocString(V_BSTR(var));
2799 if(!V_BSTR(v))
2800 return E_OUTOFMEMORY;
2801 V_VT(v) = VT_BSTR;
2802 return S_OK;
2805 default:
2806 FIXME("not handler %s\n", debugstr_variant(var));
2807 return E_NOTIMPL;
2810 return S_OK;
2813 HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
2815 event_listener_t *listener;
2816 VARIANT *v;
2817 HRESULT hres;
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));
2830 }else {
2831 V_VT(var) = VT_NULL;
2834 return S_OK;
2837 HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
2839 listener_container_t *container;
2840 event_listener_t *listener;
2841 eventid_t eid;
2843 eid = attr_to_eid(name);
2844 if(eid == EVENTID_LAST) {
2845 WARN("Unknown event\n");
2846 *res = VARIANT_TRUE;
2847 return S_OK;
2850 container = get_listener_container(event_target, event_info[eid].name, TRUE);
2851 if(!container)
2852 return E_OUTOFMEMORY;
2854 listener = heap_alloc(sizeof(*listener));
2855 if(!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);
2862 else
2863 list_add_tail(&container->listeners, &listener->entry);
2865 *res = VARIANT_TRUE;
2866 return S_OK;
2869 HRESULT detach_event(EventTarget *event_target, BSTR name, IDispatch *disp)
2871 eventid_t eid;
2873 eid = attr_to_eid(name);
2874 if(eid == EVENTID_LAST) {
2875 WARN("Unknown event\n");
2876 return S_OK;
2879 remove_event_listener(event_target, event_info[eid].name, LISTENER_TYPE_ATTACHED, disp);
2880 return S_OK;
2883 void bind_target_event(HTMLDocumentNode *doc, EventTarget *event_target, const WCHAR *event, IDispatch *disp)
2885 eventid_t eid;
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));
2892 return;
2895 set_event_handler_disp(event_target, eid, disp);
2898 void update_doc_cp_events(HTMLDocumentNode *doc, cp_static_data_t *cp)
2900 int i;
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;
2914 cpp_bool has_attrs;
2915 nsIDOMAttr *attr;
2916 IDispatch *disp;
2917 UINT32 length, i;
2918 eventid_t eid;
2919 nsresult nsres;
2920 HRESULT hres;
2922 nsres = nsIDOMElement_HasAttributes(nselem, &has_attrs);
2923 if(NS_FAILED(nsres) || !has_attrs)
2924 return;
2926 nsres = nsIDOMElement_GetAttributes(nselem, &attr_map);
2927 if(NS_FAILED(nsres))
2928 return;
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))
2939 continue;
2941 nsres = nsIDOMAttr_GetName(attr, &name_str);
2942 if(NS_FAILED(nsres)) {
2943 nsIDOMAttr_Release(attr);
2944 continue;
2947 nsAString_GetData(&name_str, &name);
2948 eid = attr_to_eid(name);
2949 if(eid == EVENTID_LAST) {
2950 nsIDOMAttr_Release(attr);
2951 continue;
2954 nsres = nsIDOMAttr_GetValue(attr, &value_str);
2955 nsIDOMAttr_Release(attr);
2956 if(NS_FAILED(nsres))
2957 continue;
2959 nsAString_GetData(&value_str, &value);
2960 if(!*value)
2961 continue;
2963 TRACE("%p.%s = %s\n", nselem, debugstr_w(name), debugstr_w(value));
2965 disp = script_parse_event(doc->window, value);
2966 if(!disp)
2967 continue;
2969 if(!node) {
2970 hres = get_node((nsIDOMNode*)nselem, TRUE, &node);
2971 if(FAILED(hres)) {
2972 IDispatch_Release(disp);
2973 break;
2977 set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp);
2978 IDispatch_Release(disp);
2981 if(node)
2982 node_release(node);
2983 nsAString_Finish(&name_str);
2984 nsAString_Finish(&value_str);
2985 nsIDOMMozNamedAttrMap_Release(attr_map);
2988 HRESULT doc_init_events(HTMLDocumentNode *doc)
2990 unsigned i;
2991 HRESULT hres;
2993 doc->event_vector = heap_alloc_zero(EVENTID_LAST*sizeof(BOOL));
2994 if(!doc->event_vector)
2995 return E_OUTOFMEMORY;
2997 init_nsevents(doc);
2999 for(i=0; i < EVENTID_LAST; i++) {
3000 if(event_info[i].flags & EVENT_HASDEFAULTHANDLERS) {
3001 hres = ensure_doc_nsevent_handler(doc, i);
3002 if(FAILED(hres))
3003 return hres;
3007 return S_OK;
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);
3074 if(!container)
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)
3080 return S_OK;
3083 listener = heap_alloc(sizeof(*listener));
3084 if(!listener)
3085 return E_OUTOFMEMORY;
3087 listener->type = listener_type;
3088 IDispatch_AddRef(listener->function = function);
3089 list_add_tail(&container->listeners, &listener->entry);
3090 return S_OK;
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);
3101 return S_OK;
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);
3111 if(!event) {
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) {
3124 VARIANT args[3];
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) {
3145 VARIANT args[3];
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,
3163 EventTarget_AddRef,
3164 EventTarget_Release,
3165 EventTarget_GetTypeInfoCount,
3166 EventTarget_GetTypeInfo,
3167 EventTarget_GetIDsOfNames,
3168 EventTarget_Invoke,
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;
3183 nsresult nsres;
3185 if(!event_target) {
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);
3194 return S_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");
3202 *ppv = NULL;
3203 return E_NOINTERFACE;
3205 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3206 *ppv = &event_target->IEventTarget_iface;
3207 return S_OK;
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);
3214 *ppv = NULL;
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},
3223 {DISPID_UNKNOWN}
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);
3255 heap_free(iter);