wined3d: Destroy the Vulkan command pool after cleaning up resources.
[wine.git] / dlls / mshtml / htmlevent.c
blob7d13ac5b3fb85059c2e85a7df113f12fa29545ce
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>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27 #include "mshtmdid.h"
29 #include "mshtml_private.h"
30 #include "htmlevent.h"
31 #include "htmlscript.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37 typedef enum {
38 LISTENER_TYPE_CAPTURE,
39 LISTENER_TYPE_BUBBLE,
40 LISTENER_TYPE_ONEVENT,
41 LISTENER_TYPE_ATTACHED
42 } listener_type_t;
44 typedef struct {
45 struct list entry;
46 listener_type_t type;
47 IDispatch *function;
48 } event_listener_t;
50 typedef struct {
51 struct wine_rb_entry entry;
52 struct list listeners;
53 WCHAR type[1];
54 } listener_container_t;
56 typedef enum {
57 DISPATCH_BOTH,
58 DISPATCH_STANDARD,
59 DISPATCH_LEGACY
60 } dispatch_mode_t;
62 typedef enum {
63 EVENT_TYPE_EVENT,
64 EVENT_TYPE_UIEVENT,
65 EVENT_TYPE_KEYBOARD,
66 EVENT_TYPE_MOUSE,
67 EVENT_TYPE_FOCUS,
68 EVENT_TYPE_DRAG,
69 EVENT_TYPE_MESSAGE,
70 EVENT_TYPE_PROGRESS,
71 EVENT_TYPE_CLIPBOARD
72 } event_type_t;
74 static const WCHAR *event_types[] = {
75 L"Event",
76 L"UIEvent",
77 L"KeyboardEvent",
78 L"MouseEvent",
79 L"Event", /* FIXME */
80 L"Event", /* FIXME */
81 L"Event", /* We don't use Gecko's message events */
82 L"ProgressEvent",
83 L"Event" /* FIXME */
86 typedef struct {
87 const WCHAR *name;
88 event_type_t type;
89 DISPID dispid;
90 DWORD flags;
91 } event_info_t;
93 /* Use Gecko default listener (it's registered on window object for DOM nodes). */
94 #define EVENT_DEFAULTLISTENER 0x0001
95 /* Register Gecko listener on target itself (unlike EVENT_DEFAULTLISTENER). */
96 #define EVENT_BIND_TO_TARGET 0x0002
97 /* Event bubbles by default (unless explicitly specified otherwise). */
98 #define EVENT_BUBBLES 0x0004
99 /* Event is cancelable by default (unless explicitly specified otherwise). */
100 #define EVENT_CANCELABLE 0x0008
101 /* Event may have default handler (so we always have to register Gecko listener). */
102 #define EVENT_HASDEFAULTHANDLERS 0x0020
103 /* Ecent is not supported properly, print FIXME message when it's used. */
104 #define EVENT_FIXME 0x0040
106 /* mouse event flags for fromElement and toElement implementation */
107 #define EVENT_MOUSE_TO_RELATED 0x0100
108 #define EVENT_MOUSE_FROM_RELATED 0x0200
110 /* Keep these sorted case sensitively */
111 static const event_info_t event_info[] = {
112 {L"DOMContentLoaded", EVENT_TYPE_EVENT, 0,
113 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
114 {L"abort", EVENT_TYPE_EVENT, DISPID_EVMETH_ONABORT,
115 EVENT_BIND_TO_TARGET},
116 {L"animationend", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONEND,
117 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
118 {L"animationstart", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONSTART,
119 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
120 {L"beforeactivate", EVENT_TYPE_EVENT, DISPID_EVMETH_ONBEFOREACTIVATE,
121 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
122 {L"beforeunload", EVENT_TYPE_EVENT, DISPID_EVMETH_ONBEFOREUNLOAD,
123 EVENT_DEFAULTLISTENER | EVENT_CANCELABLE },
124 {L"blur", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONBLUR,
125 EVENT_DEFAULTLISTENER},
126 {L"change", EVENT_TYPE_EVENT, DISPID_EVMETH_ONCHANGE,
127 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
128 {L"click", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONCLICK,
129 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE },
130 {L"contextmenu", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONCONTEXTMENU,
131 EVENT_BUBBLES | EVENT_CANCELABLE},
132 {L"dataavailable", EVENT_TYPE_EVENT, DISPID_EVMETH_ONDATAAVAILABLE,
133 EVENT_FIXME | EVENT_BUBBLES},
134 {L"dblclick", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONDBLCLICK,
135 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
136 {L"drag", EVENT_TYPE_DRAG, DISPID_EVMETH_ONDRAG,
137 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
138 {L"dragstart", EVENT_TYPE_DRAG, DISPID_EVMETH_ONDRAGSTART,
139 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
140 {L"error", EVENT_TYPE_EVENT, DISPID_EVMETH_ONERROR,
141 EVENT_BIND_TO_TARGET},
142 {L"focus", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUS,
143 EVENT_DEFAULTLISTENER},
144 {L"focusin", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSIN,
145 EVENT_BUBBLES},
146 {L"focusout", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSOUT,
147 EVENT_BUBBLES},
148 {L"help", EVENT_TYPE_EVENT, DISPID_EVMETH_ONHELP,
149 EVENT_BUBBLES | EVENT_CANCELABLE},
150 {L"input", EVENT_TYPE_EVENT, DISPID_UNKNOWN,
151 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
152 {L"keydown", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYDOWN,
153 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE },
154 {L"keypress", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYPRESS,
155 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
156 {L"keyup", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYUP,
157 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
158 {L"load", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONLOAD,
159 EVENT_BIND_TO_TARGET},
160 {L"loadend", EVENT_TYPE_PROGRESS, DISPID_EVPROP_LOADEND,
161 EVENT_BIND_TO_TARGET},
162 {L"loadstart", EVENT_TYPE_PROGRESS, DISPID_EVPROP_LOADSTART,
163 EVENT_BIND_TO_TARGET},
164 {L"message", EVENT_TYPE_MESSAGE, DISPID_EVMETH_ONMESSAGE,
166 {L"mousedown", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEDOWN,
167 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
168 {L"mousemove", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEMOVE,
169 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_FROM_RELATED},
170 {L"mouseout", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEOUT,
171 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_TO_RELATED},
172 {L"mouseover", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEOVER,
173 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_FROM_RELATED},
174 {L"mouseup", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEUP,
175 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
176 {L"mousewheel", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEWHEEL,
177 EVENT_FIXME},
178 {L"msthumbnailclick", EVENT_TYPE_MOUSE, DISPID_EVPROP_ONMSTHUMBNAILCLICK,
179 EVENT_FIXME},
180 {L"paste", EVENT_TYPE_CLIPBOARD, DISPID_EVMETH_ONPASTE,
181 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
182 {L"progress", EVENT_TYPE_PROGRESS, DISPID_EVPROP_PROGRESS,
183 EVENT_BIND_TO_TARGET},
184 {L"readystatechange", EVENT_TYPE_EVENT, DISPID_EVMETH_ONREADYSTATECHANGE,
186 {L"resize", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONRESIZE,
187 EVENT_DEFAULTLISTENER},
188 {L"scroll", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONSCROLL,
189 EVENT_DEFAULTLISTENER | EVENT_BUBBLES /* FIXME: not for elements */},
190 {L"selectionchange", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSELECTIONCHANGE,
191 EVENT_FIXME},
192 {L"selectstart", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSELECTSTART,
193 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
194 {L"storage", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSTORAGE,
196 {L"storagecommit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSTORAGECOMMIT,
198 {L"submit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSUBMIT,
199 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE},
200 {L"timeout", EVENT_TYPE_PROGRESS, DISPID_EVPROP_TIMEOUT,
201 EVENT_BIND_TO_TARGET},
202 {L"unload", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONUNLOAD,
203 EVENT_FIXME}
206 C_ASSERT(ARRAY_SIZE(event_info) == EVENTID_LAST);
208 static eventid_t str_to_eid(const WCHAR *str)
210 unsigned i, a = 0, b = ARRAY_SIZE(event_info);
211 int c;
213 while(a < b) {
214 i = (a + b) / 2;
215 if(!(c = wcscmp(event_info[i].name, str)))
216 return i;
217 if(c > 0) b = i;
218 else a = i + 1;
221 return EVENTID_LAST;
224 static eventid_t attr_to_eid(const WCHAR *str)
226 unsigned i, a = 0, b = ARRAY_SIZE(event_info);
227 int c;
229 if((str[0] != 'o' && str[0] != 'O') || (str[1] != 'n' && str[1] != 'N'))
230 return EVENTID_LAST;
232 while(a < b) {
233 i = (a + b) / 2;
234 if(!(c = wcscmp(event_info[i].name, str+2)))
235 return event_info[i].dispid ? i : EVENTID_LAST;
236 if(c > 0) b = i;
237 else a = i + 1;
240 return EVENTID_LAST;
243 const WCHAR *get_event_name(eventid_t eid)
245 return event_info[eid].name;
248 static listener_container_t *get_listener_container(EventTarget *event_target, const WCHAR *type, BOOL alloc)
250 const event_target_vtbl_t *vtbl;
251 listener_container_t *container;
252 struct wine_rb_entry *entry;
253 size_t type_len;
254 eventid_t eid;
256 entry = wine_rb_get(&event_target->handler_map, type);
257 if(entry)
258 return WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry);
259 if(!alloc)
260 return NULL;
262 eid = str_to_eid(type);
263 if(eid != EVENTID_LAST && (event_info[eid].flags & EVENT_FIXME))
264 FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
266 type_len = lstrlenW(type);
267 container = heap_alloc(FIELD_OFFSET(listener_container_t, type[type_len+1]));
268 if(!container)
269 return NULL;
270 memcpy(container->type, type, (type_len + 1) * sizeof(WCHAR));
271 list_init(&container->listeners);
272 vtbl = dispex_get_vtbl(&event_target->dispex);
273 if (!vtbl->bind_event)
274 FIXME("Unsupported event binding on target %p\n", event_target);
275 else if(eid != EVENTID_LAST)
276 vtbl->bind_event(&event_target->dispex, eid);
278 wine_rb_put(&event_target->handler_map, container->type, &container->entry);
279 return container;
282 static void remove_event_listener(EventTarget *event_target, const WCHAR *type_name, listener_type_t type, IDispatch *function)
284 listener_container_t *container;
285 event_listener_t *listener;
287 container = get_listener_container(event_target, type_name, FALSE);
288 if(!container)
289 return;
291 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
292 if(listener->function == function && listener->type == type) {
293 IDispatch_Release(listener->function);
294 list_remove(&listener->entry);
295 heap_free(listener);
296 break;
301 static HRESULT get_gecko_target(IEventTarget*,nsIDOMEventTarget**);
303 typedef struct {
304 DOMEvent event;
305 IDOMUIEvent IDOMUIEvent_iface;
306 nsIDOMUIEvent *nsevent;
307 } DOMUIEvent;
309 static DOMUIEvent *DOMUIEvent_from_DOMEvent(DOMEvent *event)
311 return CONTAINING_RECORD(event, DOMUIEvent, event);
314 typedef struct {
315 DispatchEx dispex;
316 IHTMLEventObj IHTMLEventObj_iface;
318 LONG ref;
320 DOMEvent *event;
321 VARIANT return_value;
322 } HTMLEventObj;
324 static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
326 return CONTAINING_RECORD(iface, HTMLEventObj, IHTMLEventObj_iface);
329 static HRESULT WINAPI HTMLEventObj_QueryInterface(IHTMLEventObj *iface, REFIID riid, void **ppv)
331 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
333 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
335 if(IsEqualGUID(&IID_IUnknown, riid)) {
336 *ppv = &This->IHTMLEventObj_iface;
337 }else if(IsEqualGUID(&IID_IHTMLEventObj, riid)) {
338 *ppv = &This->IHTMLEventObj_iface;
339 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
340 return *ppv ? S_OK : E_NOINTERFACE;
341 }else {
342 *ppv = NULL;
343 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
344 return E_NOINTERFACE;
347 IUnknown_AddRef((IUnknown*)*ppv);
348 return S_OK;
351 static ULONG WINAPI HTMLEventObj_AddRef(IHTMLEventObj *iface)
353 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
354 LONG ref = InterlockedIncrement(&This->ref);
356 TRACE("(%p) ref=%ld\n", This, ref);
358 return ref;
361 static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface)
363 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
364 LONG ref = InterlockedDecrement(&This->ref);
366 TRACE("(%p) ref=%ld\n", This, ref);
368 if(!ref) {
369 if(This->event)
370 IDOMEvent_Release(&This->event->IDOMEvent_iface);
371 release_dispex(&This->dispex);
372 heap_free(This);
375 return ref;
378 static HRESULT WINAPI HTMLEventObj_GetTypeInfoCount(IHTMLEventObj *iface, UINT *pctinfo)
380 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
381 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
384 static HRESULT WINAPI HTMLEventObj_GetTypeInfo(IHTMLEventObj *iface, UINT iTInfo,
385 LCID lcid, ITypeInfo **ppTInfo)
387 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
388 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
391 static HRESULT WINAPI HTMLEventObj_GetIDsOfNames(IHTMLEventObj *iface, REFIID riid,
392 LPOLESTR *rgszNames, UINT cNames,
393 LCID lcid, DISPID *rgDispId)
395 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
396 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
397 lcid, rgDispId);
400 static HRESULT WINAPI HTMLEventObj_Invoke(IHTMLEventObj *iface, DISPID dispIdMember,
401 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
402 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
404 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
405 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
406 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
409 static HRESULT WINAPI HTMLEventObj_get_srcElement(IHTMLEventObj *iface, IHTMLElement **p)
411 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
413 TRACE("(%p)->(%p)\n", This, p);
415 if(!This->event) {
416 *p = NULL;
417 return S_OK;
420 return IDOMEvent_get_srcElement(&This->event->IDOMEvent_iface, p);
423 static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
425 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
426 IDOMKeyboardEvent *keyboard_event;
427 IDOMMouseEvent *mouse_event;
428 cpp_bool ret = FALSE;
430 TRACE("(%p)->(%p)\n", This, p);
432 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
433 HRESULT hres = IDOMMouseEvent_get_altKey(mouse_event, p);
434 IDOMMouseEvent_Release(mouse_event);
435 return hres;
438 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
439 HRESULT hres = IDOMKeyboardEvent_get_altKey(keyboard_event, p);
440 IDOMKeyboardEvent_Release(keyboard_event);
441 return hres;
444 *p = variant_bool(ret);
445 return S_OK;
448 static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
450 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
451 IDOMKeyboardEvent *keyboard_event;
452 IDOMMouseEvent *mouse_event;
453 cpp_bool ret = FALSE;
455 TRACE("(%p)->(%p)\n", This, p);
457 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
458 HRESULT hres = IDOMMouseEvent_get_ctrlKey(mouse_event, p);
459 IDOMMouseEvent_Release(mouse_event);
460 return hres;
463 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
464 HRESULT hres = IDOMKeyboardEvent_get_ctrlKey(keyboard_event, p);
465 IDOMKeyboardEvent_Release(keyboard_event);
466 return hres;
469 *p = variant_bool(ret);
470 return S_OK;
473 static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
475 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
476 IDOMKeyboardEvent *keyboard_event;
477 IDOMMouseEvent *mouse_event;
478 cpp_bool ret = FALSE;
480 TRACE("(%p)->(%p)\n", This, p);
482 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
483 HRESULT hres = IDOMMouseEvent_get_shiftKey(mouse_event, p);
484 IDOMMouseEvent_Release(mouse_event);
485 return hres;
488 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
489 HRESULT hres = IDOMKeyboardEvent_get_shiftKey(keyboard_event, p);
490 IDOMKeyboardEvent_Release(keyboard_event);
491 return hres;
494 *p = variant_bool(ret);
495 return S_OK;
498 static HRESULT WINAPI HTMLEventObj_put_returnValue(IHTMLEventObj *iface, VARIANT v)
500 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
502 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
504 if(V_VT(&v) != VT_BOOL) {
505 FIXME("unsupported value %s\n", debugstr_variant(&v));
506 return DISP_E_BADVARTYPE;
509 This->return_value = v;
510 if(!V_BOOL(&v) && This->event)
511 IDOMEvent_preventDefault(&This->event->IDOMEvent_iface);
512 return S_OK;
515 static HRESULT WINAPI HTMLEventObj_get_returnValue(IHTMLEventObj *iface, VARIANT *p)
517 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
519 TRACE("(%p)->(%p)\n", This, p);
521 V_VT(p) = VT_EMPTY;
522 return VariantCopy(p, &This->return_value);
525 static HRESULT WINAPI HTMLEventObj_put_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL v)
527 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
529 TRACE("(%p)->(%x)\n", This, v);
531 if(This->event)
532 IDOMEvent_stopPropagation(&This->event->IDOMEvent_iface);
533 return S_OK;
536 static HRESULT WINAPI HTMLEventObj_get_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL *p)
538 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
540 TRACE("(%p)->(%p)\n", This, p);
542 *p = variant_bool(This->event && This->event->stop_propagation);
543 return S_OK;
546 static HRESULT WINAPI HTMLEventObj_get_fromElement(IHTMLEventObj *iface, IHTMLElement **p)
548 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
549 IDOMMouseEvent *mouse_event;
551 TRACE("(%p)->(%p)\n", This, p);
553 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
554 HRESULT hres = IDOMMouseEvent_get_fromElement(mouse_event, p);
555 IDOMMouseEvent_Release(mouse_event);
556 return hres;
559 *p = NULL;
560 return S_OK;
563 static HRESULT WINAPI HTMLEventObj_get_toElement(IHTMLEventObj *iface, IHTMLElement **p)
565 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
566 IDOMMouseEvent *mouse_event;
568 TRACE("(%p)->(%p)\n", This, p);
570 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
571 HRESULT hres = IDOMMouseEvent_get_toElement(mouse_event, p);
572 IDOMMouseEvent_Release(mouse_event);
573 return hres;
576 *p = NULL;
577 return S_OK;
580 static HRESULT WINAPI HTMLEventObj_put_keyCode(IHTMLEventObj *iface, LONG v)
582 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
583 FIXME("(%p)->(%ld)\n", This, v);
584 return E_NOTIMPL;
587 static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, LONG *p)
589 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
590 IDOMKeyboardEvent *keyboard_event;
592 TRACE("(%p)->(%p)\n", This, p);
594 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
595 HRESULT hres = IDOMKeyboardEvent_get_keyCode(keyboard_event, p);
596 IDOMKeyboardEvent_Release(keyboard_event);
597 return hres;
600 *p = 0;
601 return S_OK;
604 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p)
606 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
607 IDOMMouseEvent *mouse_event;
608 USHORT button = 0;
610 TRACE("(%p)->(%p)\n", This, p);
612 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
613 HRESULT hres = IDOMMouseEvent_get_button(mouse_event, &button);
614 IDOMMouseEvent_Release(mouse_event);
615 if(FAILED(hres))
616 return hres;
619 *p = button;
620 return S_OK;
623 static HRESULT WINAPI HTMLEventObj_get_type(IHTMLEventObj *iface, BSTR *p)
625 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
627 TRACE("(%p)->(%p)\n", This, p);
629 if(!This->event) {
630 *p = NULL;
631 return S_OK;
634 return IDOMEvent_get_type(&This->event->IDOMEvent_iface, p);
637 static HRESULT WINAPI HTMLEventObj_get_qualifier(IHTMLEventObj *iface, BSTR *p)
639 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
641 FIXME("(%p)->(%p)\n", This, p);
643 *p = NULL;
644 return S_OK;
647 static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, LONG *p)
649 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
651 FIXME("(%p)->(%p)\n", This, p);
653 *p = 0;
654 return S_OK;
657 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p)
659 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
660 LONG x = 0;
662 TRACE("(%p)->(%p)\n", This, p);
664 if(This->event) {
665 nsIDOMUIEvent *ui_event;
666 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
668 if(NS_SUCCEEDED(nsres)) {
669 /* NOTE: pageX is not exactly right here. */
670 nsres = nsIDOMUIEvent_GetPageX(ui_event, &x);
671 assert(nsres == NS_OK);
672 nsIDOMUIEvent_Release(ui_event);
676 *p = x;
677 return S_OK;
680 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p)
682 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
683 LONG y = 0;
685 TRACE("(%p)->(%p)\n", This, p);
687 if(This->event) {
688 nsIDOMUIEvent *ui_event;
689 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
691 if(NS_SUCCEEDED(nsres)) {
692 /* NOTE: pageY is not exactly right here. */
693 nsres = nsIDOMUIEvent_GetPageY(ui_event, &y);
694 assert(nsres == NS_OK);
695 nsIDOMUIEvent_Release(ui_event);
699 *p = y;
700 return S_OK;
703 static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, LONG *p)
705 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
706 IDOMMouseEvent *mouse_event;
708 TRACE("(%p)->(%p)\n", This, p);
710 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
711 HRESULT hres = IDOMMouseEvent_get_clientX(mouse_event, p);
712 IDOMMouseEvent_Release(mouse_event);
713 return hres;
716 *p = 0;
717 return S_OK;
720 static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, LONG *p)
722 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
723 IDOMMouseEvent *mouse_event;
725 TRACE("(%p)->(%p)\n", This, p);
727 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
728 HRESULT hres = IDOMMouseEvent_get_clientY(mouse_event, p);
729 IDOMMouseEvent_Release(mouse_event);
730 return hres;
733 *p = 0;
734 return S_OK;
737 static HRESULT WINAPI HTMLEventObj_get_offsetX(IHTMLEventObj *iface, LONG *p)
739 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
740 IDOMMouseEvent *mouse_event;
742 TRACE("(%p)->(%p)\n", This, p);
744 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
745 HRESULT hres = IDOMMouseEvent_get_offsetX(mouse_event, p);
746 IDOMMouseEvent_Release(mouse_event);
747 return hres;
750 *p = 0;
751 return S_OK;
754 static HRESULT WINAPI HTMLEventObj_get_offsetY(IHTMLEventObj *iface, LONG *p)
756 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
757 IDOMMouseEvent *mouse_event;
759 TRACE("(%p)->(%p)\n", This, p);
761 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
762 HRESULT hres = IDOMMouseEvent_get_offsetY(mouse_event, p);
763 IDOMMouseEvent_Release(mouse_event);
764 return hres;
767 *p = 0;
768 return S_OK;
771 static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, LONG *p)
773 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
774 IDOMMouseEvent *mouse_event;
776 TRACE("(%p)->(%p)\n", This, p);
778 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
779 HRESULT hres = IDOMMouseEvent_get_screenX(mouse_event, p);
780 IDOMMouseEvent_Release(mouse_event);
781 return hres;
784 *p = 0;
785 return S_OK;
788 static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, LONG *p)
790 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
791 IDOMMouseEvent *mouse_event;
793 TRACE("(%p)->(%p)\n", This, p);
795 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
796 HRESULT hres = IDOMMouseEvent_get_screenY(mouse_event, p);
797 IDOMMouseEvent_Release(mouse_event);
798 return hres;
801 *p = 0;
802 return S_OK;
805 static HRESULT WINAPI HTMLEventObj_get_srcFilter(IHTMLEventObj *iface, IDispatch **p)
807 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
809 FIXME("(%p)->(%p)\n", This, p);
811 *p = NULL;
812 return S_OK;
815 static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
816 HTMLEventObj_QueryInterface,
817 HTMLEventObj_AddRef,
818 HTMLEventObj_Release,
819 HTMLEventObj_GetTypeInfoCount,
820 HTMLEventObj_GetTypeInfo,
821 HTMLEventObj_GetIDsOfNames,
822 HTMLEventObj_Invoke,
823 HTMLEventObj_get_srcElement,
824 HTMLEventObj_get_altKey,
825 HTMLEventObj_get_ctrlKey,
826 HTMLEventObj_get_shiftKey,
827 HTMLEventObj_put_returnValue,
828 HTMLEventObj_get_returnValue,
829 HTMLEventObj_put_cancelBubble,
830 HTMLEventObj_get_cancelBubble,
831 HTMLEventObj_get_fromElement,
832 HTMLEventObj_get_toElement,
833 HTMLEventObj_put_keyCode,
834 HTMLEventObj_get_keyCode,
835 HTMLEventObj_get_button,
836 HTMLEventObj_get_type,
837 HTMLEventObj_get_qualifier,
838 HTMLEventObj_get_reason,
839 HTMLEventObj_get_x,
840 HTMLEventObj_get_y,
841 HTMLEventObj_get_clientX,
842 HTMLEventObj_get_clientY,
843 HTMLEventObj_get_offsetX,
844 HTMLEventObj_get_offsetY,
845 HTMLEventObj_get_screenX,
846 HTMLEventObj_get_screenY,
847 HTMLEventObj_get_srcFilter
850 static inline HTMLEventObj *unsafe_impl_from_IHTMLEventObj(IHTMLEventObj *iface)
852 return iface->lpVtbl == &HTMLEventObjVtbl ? impl_from_IHTMLEventObj(iface) : NULL;
855 static const tid_t HTMLEventObj_iface_tids[] = {
856 IHTMLEventObj_tid,
860 static dispex_static_data_t HTMLEventObj_dispex = {
861 L"MSEventObj",
862 NULL,
863 DispCEventObj_tid,
864 HTMLEventObj_iface_tids
867 static HTMLEventObj *alloc_event_obj(DOMEvent *event, compat_mode_t compat_mode)
869 HTMLEventObj *event_obj;
871 event_obj = heap_alloc_zero(sizeof(*event_obj));
872 if(!event_obj)
873 return NULL;
875 event_obj->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
876 event_obj->ref = 1;
877 event_obj->event = event;
878 if(event)
879 IDOMEvent_AddRef(&event->IDOMEvent_iface);
881 init_dispatch(&event_obj->dispex, (IUnknown*)&event_obj->IHTMLEventObj_iface, &HTMLEventObj_dispex, compat_mode);
882 return event_obj;
885 HRESULT create_event_obj(compat_mode_t compat_mode, IHTMLEventObj **ret)
887 HTMLEventObj *event_obj;
889 event_obj = alloc_event_obj(NULL, compat_mode);
890 if(!event_obj)
891 return E_OUTOFMEMORY;
893 *ret = &event_obj->IHTMLEventObj_iface;
894 return S_OK;
897 static inline DOMEvent *impl_from_IDOMEvent(IDOMEvent *iface)
899 return CONTAINING_RECORD(iface, DOMEvent, IDOMEvent_iface);
902 static const IDOMEventVtbl DOMEventVtbl;
904 static inline DOMEvent *unsafe_impl_from_IDOMEvent(IDOMEvent *iface)
906 return iface && iface->lpVtbl == &DOMEventVtbl ? impl_from_IDOMEvent(iface) : NULL;
909 static HRESULT WINAPI DOMEvent_QueryInterface(IDOMEvent *iface, REFIID riid, void **ppv)
911 DOMEvent *This = impl_from_IDOMEvent(iface);
913 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
915 if(IsEqualGUID(&IID_IUnknown, riid))
916 *ppv = &This->IDOMEvent_iface;
917 else if(IsEqualGUID(&IID_IDOMEvent, riid))
918 *ppv = &This->IDOMEvent_iface;
919 else if(dispex_query_interface(&This->dispex, riid, ppv))
920 return *ppv ? S_OK : E_NOINTERFACE;
921 else if(!This->query_interface || !(*ppv = This->query_interface(This, riid))) {
922 *ppv = NULL;
923 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
924 return E_NOINTERFACE;
927 IUnknown_AddRef((IUnknown*)*ppv);
928 return S_OK;
931 static ULONG WINAPI DOMEvent_AddRef(IDOMEvent *iface)
933 DOMEvent *This = impl_from_IDOMEvent(iface);
934 LONG ref = InterlockedIncrement(&This->ref);
936 TRACE("(%p) ref=%lu\n", This, ref);
938 return ref;
941 static ULONG WINAPI DOMEvent_Release(IDOMEvent *iface)
943 DOMEvent *This = impl_from_IDOMEvent(iface);
944 LONG ref = InterlockedDecrement(&This->ref);
946 TRACE("(%p) ref=%lu\n", This, ref);
948 if(!ref) {
949 if(This->destroy)
950 This->destroy(This);
951 if(This->target)
952 IEventTarget_Release(&This->target->IEventTarget_iface);
953 nsIDOMEvent_Release(This->nsevent);
954 release_dispex(&This->dispex);
955 heap_free(This->type);
956 heap_free(This);
959 return ref;
962 static HRESULT WINAPI DOMEvent_GetTypeInfoCount(IDOMEvent *iface, UINT *pctinfo)
964 DOMEvent *This = impl_from_IDOMEvent(iface);
965 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
968 static HRESULT WINAPI DOMEvent_GetTypeInfo(IDOMEvent *iface, UINT iTInfo,
969 LCID lcid, ITypeInfo **ppTInfo)
971 DOMEvent *This = impl_from_IDOMEvent(iface);
972 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
975 static HRESULT WINAPI DOMEvent_GetIDsOfNames(IDOMEvent *iface, REFIID riid,
976 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
978 DOMEvent *This = impl_from_IDOMEvent(iface);
979 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
980 lcid, rgDispId);
983 static HRESULT WINAPI DOMEvent_Invoke(IDOMEvent *iface, DISPID dispIdMember,
984 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
985 EXCEPINFO *pExcepInfo, UINT *puArgErr)
987 DOMEvent *This = impl_from_IDOMEvent(iface);
988 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
989 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
992 static HRESULT WINAPI DOMEvent_get_bubbles(IDOMEvent *iface, VARIANT_BOOL *p)
994 DOMEvent *This = impl_from_IDOMEvent(iface);
996 TRACE("(%p)->(%p)\n", This, p);
998 *p = variant_bool(This->bubbles);
999 return S_OK;
1002 static HRESULT WINAPI DOMEvent_get_cancelable(IDOMEvent *iface, VARIANT_BOOL *p)
1004 DOMEvent *This = impl_from_IDOMEvent(iface);
1006 TRACE("(%p)->(%p)\n", This, p);
1008 *p = variant_bool(This->cancelable);
1009 return S_OK;
1012 static HRESULT WINAPI DOMEvent_get_currentTarget(IDOMEvent *iface, IEventTarget **p)
1014 DOMEvent *This = impl_from_IDOMEvent(iface);
1016 TRACE("(%p)->(%p)\n", This, p);
1018 if(This->current_target)
1019 IEventTarget_AddRef(*p = &This->current_target->IEventTarget_iface);
1020 else
1021 *p = NULL;
1022 return S_OK;
1025 static HRESULT WINAPI DOMEvent_get_defaultPrevented(IDOMEvent *iface, VARIANT_BOOL *p)
1027 DOMEvent *This = impl_from_IDOMEvent(iface);
1029 TRACE("(%p)->(%p)\n", This, p);
1031 *p = variant_bool(This->prevent_default);
1032 return S_OK;
1035 static HRESULT WINAPI DOMEvent_get_eventPhase(IDOMEvent *iface, USHORT *p)
1037 DOMEvent *This = impl_from_IDOMEvent(iface);
1039 TRACE("(%p)->(%p)\n", This, p);
1041 *p = This->phase;
1042 return S_OK;
1045 static HRESULT WINAPI DOMEvent_get_target(IDOMEvent *iface, IEventTarget **p)
1047 DOMEvent *This = impl_from_IDOMEvent(iface);
1049 TRACE("(%p)->(%p)\n", This, p);
1051 if(This->target)
1052 IEventTarget_AddRef(*p = &This->target->IEventTarget_iface);
1053 else
1054 *p = NULL;
1055 return S_OK;
1058 static HRESULT WINAPI DOMEvent_get_timeStamp(IDOMEvent *iface, ULONGLONG *p)
1060 DOMEvent *This = impl_from_IDOMEvent(iface);
1062 TRACE("(%p)->(%p)\n", This, p);
1064 *p = This->time_stamp;
1065 return S_OK;
1068 static HRESULT WINAPI DOMEvent_get_type(IDOMEvent *iface, BSTR *p)
1070 DOMEvent *This = impl_from_IDOMEvent(iface);
1072 TRACE("(%p)->(%p)\n", This, p);
1074 if(This->type) {
1075 *p = SysAllocString(This->type);
1076 if(!*p)
1077 return E_OUTOFMEMORY;
1078 }else {
1079 *p = NULL;
1081 return S_OK;
1084 #ifdef __i386__
1085 #define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \
1086 ((void (WINAPI*)(void*,nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \
1087 &call_thiscall_func)((_this)->lpVtbl->InitEvent,_this,type,bubbles,cancelable)
1089 #endif
1091 static HRESULT WINAPI DOMEvent_initEvent(IDOMEvent *iface, BSTR type, VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable)
1093 DOMEvent *This = impl_from_IDOMEvent(iface);
1094 nsAString nsstr;
1096 TRACE("(%p)->(%s %x %x)\n", This, debugstr_w(type), can_bubble, cancelable);
1098 if(This->target) {
1099 TRACE("called on already dispatched event\n");
1100 return S_OK;
1103 heap_free(This->type);
1104 This->type = heap_strdupW(type);
1105 if(!This->type)
1106 return E_OUTOFMEMORY;
1107 This->event_id = str_to_eid(type);
1109 This->bubbles = !!can_bubble;
1110 This->cancelable = !!cancelable;
1112 nsAString_InitDepend(&nsstr, type);
1113 nsIDOMEvent_InitEvent(This->nsevent, &nsstr, This->bubbles, This->cancelable);
1114 nsAString_Finish(&nsstr);
1116 return S_OK;
1119 static HRESULT WINAPI DOMEvent_preventDefault(IDOMEvent *iface)
1121 DOMEvent *This = impl_from_IDOMEvent(iface);
1123 TRACE("(%p)\n", This);
1125 if(This->current_target && This->cancelable) {
1126 This->prevent_default = TRUE;
1127 nsIDOMEvent_PreventDefault(This->nsevent);
1129 return S_OK;
1132 static HRESULT WINAPI DOMEvent_stopPropagation(IDOMEvent *iface)
1134 DOMEvent *This = impl_from_IDOMEvent(iface);
1136 TRACE("(%p)\n", This);
1138 This->stop_propagation = TRUE;
1139 nsIDOMEvent_StopPropagation(This->nsevent);
1140 return S_OK;
1143 static HRESULT WINAPI DOMEvent_stopImmediatePropagation(IDOMEvent *iface)
1145 DOMEvent *This = impl_from_IDOMEvent(iface);
1147 TRACE("(%p)\n", This);
1149 This->stop_immediate_propagation = This->stop_propagation = TRUE;
1150 nsIDOMEvent_StopImmediatePropagation(This->nsevent);
1151 return S_OK;
1154 static HRESULT WINAPI DOMEvent_get_isTrusted(IDOMEvent *iface, VARIANT_BOOL *p)
1156 DOMEvent *This = impl_from_IDOMEvent(iface);
1158 TRACE("(%p)->(%p)\n", This, p);
1160 *p = variant_bool(This->trusted);
1161 return S_OK;
1164 static HRESULT WINAPI DOMEvent_put_cancelBubble(IDOMEvent *iface, VARIANT_BOOL v)
1166 DOMEvent *This = impl_from_IDOMEvent(iface);
1167 FIXME("(%p)->(%x)\n", This, v);
1168 return E_NOTIMPL;
1171 static HRESULT WINAPI DOMEvent_get_cancelBubble(IDOMEvent *iface, VARIANT_BOOL *p)
1173 DOMEvent *This = impl_from_IDOMEvent(iface);
1174 FIXME("(%p)->(%p)\n", This, p);
1175 return E_NOTIMPL;
1178 static HRESULT WINAPI DOMEvent_get_srcElement(IDOMEvent *iface, IHTMLElement **p)
1180 DOMEvent *This = impl_from_IDOMEvent(iface);
1182 TRACE("(%p)->(%p)\n", This, p);
1184 if(This->target)
1185 IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
1186 else
1187 *p = NULL;
1188 return S_OK;
1191 static const IDOMEventVtbl DOMEventVtbl = {
1192 DOMEvent_QueryInterface,
1193 DOMEvent_AddRef,
1194 DOMEvent_Release,
1195 DOMEvent_GetTypeInfoCount,
1196 DOMEvent_GetTypeInfo,
1197 DOMEvent_GetIDsOfNames,
1198 DOMEvent_Invoke,
1199 DOMEvent_get_bubbles,
1200 DOMEvent_get_cancelable,
1201 DOMEvent_get_currentTarget,
1202 DOMEvent_get_defaultPrevented,
1203 DOMEvent_get_eventPhase,
1204 DOMEvent_get_target,
1205 DOMEvent_get_timeStamp,
1206 DOMEvent_get_type,
1207 DOMEvent_initEvent,
1208 DOMEvent_preventDefault,
1209 DOMEvent_stopPropagation,
1210 DOMEvent_stopImmediatePropagation,
1211 DOMEvent_get_isTrusted,
1212 DOMEvent_put_cancelBubble,
1213 DOMEvent_get_cancelBubble,
1214 DOMEvent_get_srcElement
1217 static inline DOMUIEvent *impl_from_IDOMUIEvent(IDOMUIEvent *iface)
1219 return CONTAINING_RECORD(iface, DOMUIEvent, IDOMUIEvent_iface);
1222 static HRESULT WINAPI DOMUIEvent_QueryInterface(IDOMUIEvent *iface, REFIID riid, void **ppv)
1224 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1225 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
1228 static ULONG WINAPI DOMUIEvent_AddRef(IDOMUIEvent *iface)
1230 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1231 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
1234 static ULONG WINAPI DOMUIEvent_Release(IDOMUIEvent *iface)
1236 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1237 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
1240 static HRESULT WINAPI DOMUIEvent_GetTypeInfoCount(IDOMUIEvent *iface, UINT *pctinfo)
1242 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1243 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
1246 static HRESULT WINAPI DOMUIEvent_GetTypeInfo(IDOMUIEvent *iface, UINT iTInfo,
1247 LCID lcid, ITypeInfo **ppTInfo)
1249 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1250 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1253 static HRESULT WINAPI DOMUIEvent_GetIDsOfNames(IDOMUIEvent *iface, REFIID riid,
1254 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1256 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1257 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1258 lcid, rgDispId);
1261 static HRESULT WINAPI DOMUIEvent_Invoke(IDOMUIEvent *iface, DISPID dispIdMember,
1262 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1263 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1265 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1266 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1267 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1270 static HRESULT WINAPI DOMUIEvent_get_view(IDOMUIEvent *iface, IHTMLWindow2 **p)
1272 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1273 mozIDOMWindowProxy *moz_window;
1274 HTMLOuterWindow *view = NULL;
1275 nsresult nsres;
1277 TRACE("(%p)->(%p)\n", This, p);
1279 nsres = nsIDOMUIEvent_GetView(This->nsevent, &moz_window);
1280 if(NS_FAILED(nsres))
1281 return E_FAIL;
1283 if(moz_window) {
1284 view = mozwindow_to_window(moz_window);
1285 mozIDOMWindowProxy_Release(moz_window);
1287 if(view)
1288 IHTMLWindow2_AddRef((*p = &view->base.inner_window->base.IHTMLWindow2_iface));
1289 else
1290 *p = NULL;
1291 return S_OK;
1294 static HRESULT WINAPI DOMUIEvent_get_detail(IDOMUIEvent *iface, LONG *p)
1296 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1297 LONG detail;
1298 nsresult nsres;
1300 TRACE("(%p)->(%p)\n", This, p);
1302 nsres = nsIDOMUIEvent_GetDetail(This->nsevent, &detail);
1303 if(NS_FAILED(nsres))
1304 return E_FAIL;
1306 *p = detail;
1307 return S_OK;
1310 static HRESULT WINAPI DOMUIEvent_initUIEvent(IDOMUIEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
1311 VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail)
1313 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1314 nsAString type_str;
1315 nsresult nsres;
1316 HRESULT hres;
1318 TRACE("(%p)->(%s %x %x %p %lx)\n", This, debugstr_w(type), can_bubble, cancelable, view, detail);
1320 if(This->event.target) {
1321 TRACE("called on already dispatched event\n");
1322 return S_OK;
1325 if(view)
1326 FIXME("view argument is not supported\n");
1328 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
1329 if(FAILED(hres))
1330 return hres;
1332 nsAString_InitDepend(&type_str, type);
1333 nsres = nsIDOMUIEvent_InitUIEvent(This->nsevent, &type_str, !!can_bubble, !!cancelable,
1334 NULL /* FIXME */, detail);
1335 nsAString_Finish(&type_str);
1336 if(NS_FAILED(nsres)) {
1337 FIXME("InitUIEvent failed: %08lx\n", nsres);
1338 return E_FAIL;
1341 return S_OK;
1344 static const IDOMUIEventVtbl DOMUIEventVtbl = {
1345 DOMUIEvent_QueryInterface,
1346 DOMUIEvent_AddRef,
1347 DOMUIEvent_Release,
1348 DOMUIEvent_GetTypeInfoCount,
1349 DOMUIEvent_GetTypeInfo,
1350 DOMUIEvent_GetIDsOfNames,
1351 DOMUIEvent_Invoke,
1352 DOMUIEvent_get_view,
1353 DOMUIEvent_get_detail,
1354 DOMUIEvent_initUIEvent
1357 static void *DOMUIEvent_query_interface(DOMEvent *event, REFIID riid)
1359 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(event);
1360 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1361 return &This->IDOMUIEvent_iface;
1362 return NULL;
1365 static void DOMUIEvent_destroy(DOMEvent *event)
1367 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(event);
1368 nsIDOMUIEvent_Release(This->nsevent);
1371 typedef struct {
1372 DOMUIEvent ui_event;
1373 IDOMMouseEvent IDOMMouseEvent_iface;
1374 nsIDOMMouseEvent *nsevent;
1375 } DOMMouseEvent;
1377 static inline DOMMouseEvent *impl_from_IDOMMouseEvent(IDOMMouseEvent *iface)
1379 return CONTAINING_RECORD(iface, DOMMouseEvent, IDOMMouseEvent_iface);
1382 static HRESULT WINAPI DOMMouseEvent_QueryInterface(IDOMMouseEvent *iface, REFIID riid, void **ppv)
1384 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1385 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1388 static ULONG WINAPI DOMMouseEvent_AddRef(IDOMMouseEvent *iface)
1390 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1391 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1394 static ULONG WINAPI DOMMouseEvent_Release(IDOMMouseEvent *iface)
1396 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1397 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
1400 static HRESULT WINAPI DOMMouseEvent_GetTypeInfoCount(IDOMMouseEvent *iface, UINT *pctinfo)
1402 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1403 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
1406 static HRESULT WINAPI DOMMouseEvent_GetTypeInfo(IDOMMouseEvent *iface, UINT iTInfo,
1407 LCID lcid, ITypeInfo **ppTInfo)
1409 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1410 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1413 static HRESULT WINAPI DOMMouseEvent_GetIDsOfNames(IDOMMouseEvent *iface, REFIID riid,
1414 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1416 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1417 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1418 lcid, rgDispId);
1421 static HRESULT WINAPI DOMMouseEvent_Invoke(IDOMMouseEvent *iface, DISPID dispIdMember,
1422 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1423 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1425 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1426 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1427 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1430 static HRESULT WINAPI DOMMouseEvent_get_screenX(IDOMMouseEvent *iface, LONG *p)
1432 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1433 LONG screen_x;
1434 nsresult nsres;
1436 TRACE("(%p)->(%p)\n", This, p);
1438 nsres = nsIDOMMouseEvent_GetScreenX(This->nsevent, &screen_x);
1439 if(NS_FAILED(nsres))
1440 return E_FAIL;
1442 *p = screen_x;
1443 return S_OK;
1446 static HRESULT WINAPI DOMMouseEvent_get_screenY(IDOMMouseEvent *iface, LONG *p)
1448 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1449 LONG screen_y;
1450 nsresult nsres;
1452 TRACE("(%p)->(%p)\n", This, p);
1454 nsres = nsIDOMMouseEvent_GetScreenY(This->nsevent, &screen_y);
1455 if(NS_FAILED(nsres))
1456 return E_FAIL;
1458 *p = screen_y;
1459 return S_OK;
1462 static HRESULT WINAPI DOMMouseEvent_get_clientX(IDOMMouseEvent *iface, LONG *p)
1464 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1465 LONG client_x;
1466 nsresult nsres;
1468 TRACE("(%p)->(%p)\n", This, p);
1470 nsres = nsIDOMMouseEvent_GetClientX(This->nsevent, &client_x);
1471 if(NS_FAILED(nsres))
1472 return E_FAIL;
1474 *p = client_x;
1475 return S_OK;
1478 static HRESULT WINAPI DOMMouseEvent_get_clientY(IDOMMouseEvent *iface, LONG *p)
1480 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1481 LONG client_y;
1482 nsresult nsres;
1484 TRACE("(%p)->(%p)\n", This, p);
1486 nsres = nsIDOMMouseEvent_GetClientY(This->nsevent, &client_y);
1487 if(NS_FAILED(nsres))
1488 return E_FAIL;
1490 *p = client_y;
1491 return S_OK;
1494 static HRESULT WINAPI DOMMouseEvent_get_ctrlKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1496 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1497 cpp_bool r;
1498 nsresult nsres;
1500 TRACE("(%p)->(%p)\n", This, p);
1502 nsres = nsIDOMMouseEvent_GetCtrlKey(This->nsevent, &r);
1503 if(NS_FAILED(nsres))
1504 return E_FAIL;
1506 *p = variant_bool(r);
1507 return S_OK;
1510 static HRESULT WINAPI DOMMouseEvent_get_shiftKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1512 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1513 cpp_bool r;
1514 nsresult nsres;
1516 TRACE("(%p)->(%p)\n", This, p);
1518 nsres = nsIDOMMouseEvent_GetShiftKey(This->nsevent, &r);
1519 if(NS_FAILED(nsres))
1520 return E_FAIL;
1522 *p = variant_bool(r);
1523 return S_OK;
1526 static HRESULT WINAPI DOMMouseEvent_get_altKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1528 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1529 cpp_bool r;
1530 nsresult nsres;
1532 TRACE("(%p)->(%p)\n", This, p);
1534 nsres = nsIDOMMouseEvent_GetAltKey(This->nsevent, &r);
1535 if(NS_FAILED(nsres))
1536 return E_FAIL;
1538 *p = variant_bool(r);
1539 return S_OK;
1542 static HRESULT WINAPI DOMMouseEvent_get_metaKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1544 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1545 cpp_bool r;
1546 nsresult nsres;
1548 TRACE("(%p)->(%p)\n", This, p);
1550 nsres = nsIDOMMouseEvent_GetMetaKey(This->nsevent, &r);
1551 if(NS_FAILED(nsres))
1552 return E_FAIL;
1554 *p = variant_bool(r);
1555 return S_OK;
1558 static HRESULT WINAPI DOMMouseEvent_get_button(IDOMMouseEvent *iface, USHORT *p)
1560 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1561 INT16 r;
1562 nsresult nsres;
1564 TRACE("(%p)->(%p)\n", This, p);
1566 nsres = nsIDOMMouseEvent_GetButton(This->nsevent, &r);
1567 if(NS_FAILED(nsres))
1568 return E_FAIL;
1570 *p = r;
1571 return S_OK;
1574 static HRESULT WINAPI DOMMouseEvent_get_relatedTarget(IDOMMouseEvent *iface, IEventTarget **p)
1576 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1577 nsIDOMEventTarget *related_target;
1578 nsIDOMNode *target_node;
1579 HTMLDOMNode *node;
1580 HRESULT hres;
1581 nsresult nsres;
1583 TRACE("(%p)->(%p)\n", This, p);
1585 nsres = nsIDOMMouseEvent_GetRelatedTarget(This->nsevent, &related_target);
1586 if(NS_FAILED(nsres))
1587 return E_FAIL;
1589 if(!related_target) {
1590 *p = NULL;
1591 return S_OK;
1594 nsres = nsIDOMEventTarget_QueryInterface(related_target, &IID_nsIDOMNode, (void**)&target_node);
1595 nsIDOMEventTarget_Release(related_target);
1596 if(NS_FAILED(nsres)) {
1597 FIXME("Only node targets supported\n");
1598 return E_NOTIMPL;
1601 hres = get_node(target_node, TRUE, &node);
1602 nsIDOMNode_Release(target_node);
1603 if(FAILED(hres))
1604 return hres;
1606 *p = &node->event_target.IEventTarget_iface;
1607 return S_OK;
1610 static HRESULT WINAPI DOMMouseEvent_initMouseEvent(IDOMMouseEvent *iface, BSTR type,
1611 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail,
1612 LONG screen_x, LONG screen_y, LONG client_x, LONG client_y, VARIANT_BOOL ctrl_key,
1613 VARIANT_BOOL alt_key, VARIANT_BOOL shift_key, VARIANT_BOOL meta_key, USHORT button,
1614 IEventTarget *related_target)
1616 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1617 nsIDOMEventTarget *nstarget = NULL;
1618 nsAString type_str;
1619 nsresult nsres;
1620 HRESULT hres;
1622 TRACE("(%p)->(%s %x %x %p %ld %ld %ld %ld %ld %x %x %x %x %u %p)\n", This, debugstr_w(type),
1623 can_bubble, cancelable, view, detail, screen_x, screen_y, client_x, client_y,
1624 ctrl_key, alt_key, shift_key, meta_key, button, related_target);
1626 if(This->ui_event.event.target) {
1627 TRACE("called on already dispatched event\n");
1628 return S_OK;
1631 if(view)
1632 FIXME("view argument is not supported\n");
1634 if(related_target) {
1635 hres = get_gecko_target(related_target, &nstarget);
1636 if(FAILED(hres))
1637 return hres;
1640 hres = IDOMEvent_initEvent(&This->ui_event.event.IDOMEvent_iface, type, can_bubble, cancelable);
1641 if(SUCCEEDED(hres)) {
1642 nsAString_InitDepend(&type_str, type);
1643 nsres = nsIDOMMouseEvent_InitMouseEvent(This->nsevent, &type_str, can_bubble, cancelable,
1644 NULL /* FIXME */, detail, screen_x, screen_y,
1645 client_x, client_y, !!ctrl_key, !!alt_key, !!shift_key,
1646 !!meta_key, button, nstarget);
1647 nsAString_Finish(&type_str);
1648 if(NS_FAILED(nsres)) {
1649 FIXME("InitMouseEvent failed: %08lx\n", nsres);
1650 return E_FAIL;
1654 if(nstarget)
1655 nsIDOMEventTarget_Release(nstarget);
1656 return S_OK;
1659 static HRESULT WINAPI DOMMouseEvent_getModifierState(IDOMMouseEvent *iface, BSTR key,
1660 VARIANT_BOOL *activated)
1662 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1663 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), activated);
1664 return E_NOTIMPL;
1667 static HRESULT WINAPI DOMMouseEvent_get_buttons(IDOMMouseEvent *iface, USHORT *p)
1669 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1670 UINT16 r;
1671 nsresult nsres;
1673 TRACE("(%p)->(%p)\n", This, p);
1675 nsres = nsIDOMMouseEvent_GetButtons(This->nsevent, &r);
1676 if(NS_FAILED(nsres))
1677 return E_FAIL;
1679 *p = r;
1680 return S_OK;
1683 static HRESULT WINAPI DOMMouseEvent_get_fromElement(IDOMMouseEvent *iface, IHTMLElement **p)
1685 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1686 eventid_t event_id = This->ui_event.event.event_id;
1687 IEventTarget *related_target = NULL;
1689 TRACE("(%p)->(%p)\n", This, p);
1691 if(event_id != EVENTID_LAST) {
1692 HRESULT hres = S_OK;
1693 if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1694 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1695 else if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1696 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1697 if(FAILED(hres))
1698 return hres;
1701 if(!related_target) {
1702 *p = NULL;
1703 return S_OK;
1706 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1707 return S_OK;
1710 static HRESULT WINAPI DOMMouseEvent_get_toElement(IDOMMouseEvent *iface, IHTMLElement **p)
1712 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1713 eventid_t event_id = This->ui_event.event.event_id;
1714 IEventTarget *related_target = NULL;
1716 TRACE("(%p)->(%p)\n", This, p);
1718 if(event_id != EVENTID_LAST) {
1719 HRESULT hres = S_OK;
1720 if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1721 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1722 else if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1723 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1724 if(FAILED(hres))
1725 return hres;
1728 if(!related_target) {
1729 *p = NULL;
1730 return S_OK;
1733 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1734 return S_OK;
1737 static HRESULT WINAPI DOMMouseEvent_get_x(IDOMMouseEvent *iface, LONG *p)
1739 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1740 FIXME("(%p)->(%p)\n", This, p);
1741 return E_NOTIMPL;
1744 static HRESULT WINAPI DOMMouseEvent_get_y(IDOMMouseEvent *iface, LONG *p)
1746 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1747 FIXME("(%p)->(%p)\n", This, p);
1748 return E_NOTIMPL;
1751 static HRESULT WINAPI DOMMouseEvent_get_offsetX(IDOMMouseEvent *iface, LONG *p)
1753 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1755 FIXME("(%p)->(%p) returning 0\n", This, p);
1757 *p = 0;
1758 return S_OK;
1761 static HRESULT WINAPI DOMMouseEvent_get_offsetY(IDOMMouseEvent *iface, LONG *p)
1763 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1765 FIXME("(%p)->(%p) returning 0\n", This, p);
1767 *p = 0;
1768 return S_OK;
1771 static HRESULT WINAPI DOMMouseEvent_get_pageX(IDOMMouseEvent *iface, LONG *p)
1773 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1774 LONG r;
1775 nsresult nsres;
1777 TRACE("(%p)->(%p)\n", This, p);
1779 nsres = nsIDOMMouseEvent_GetPageX(This->nsevent, &r);
1780 if(NS_FAILED(nsres))
1781 return E_FAIL;
1783 *p = r;
1784 return S_OK;
1787 static HRESULT WINAPI DOMMouseEvent_get_pageY(IDOMMouseEvent *iface, LONG *p)
1789 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1790 LONG r;
1791 nsresult nsres;
1793 TRACE("(%p)->(%p)\n", This, p);
1795 nsres = nsIDOMMouseEvent_GetPageY(This->nsevent, &r);
1796 if(NS_FAILED(nsres))
1797 return E_FAIL;
1799 *p = r;
1800 return S_OK;
1803 static HRESULT WINAPI DOMMouseEvent_get_layerX(IDOMMouseEvent *iface, LONG *p)
1805 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1806 nsresult nsres;
1807 LONG r;
1809 TRACE("(%p)->(%p)\n", This, p);
1811 nsres = nsIDOMMouseEvent_GetLayerX(This->nsevent, &r);
1812 if(NS_FAILED(nsres))
1813 return E_FAIL;
1815 *p = r;
1816 return S_OK;
1819 static HRESULT WINAPI DOMMouseEvent_get_layerY(IDOMMouseEvent *iface, LONG *p)
1821 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1822 nsresult nsres;
1823 LONG r;
1825 TRACE("(%p)->(%p)\n", This, p);
1827 nsres = nsIDOMMouseEvent_GetLayerY(This->nsevent, &r);
1828 if(NS_FAILED(nsres))
1829 return E_FAIL;
1831 *p = r;
1832 return S_OK;
1835 static HRESULT WINAPI DOMMouseEvent_get_which(IDOMMouseEvent *iface, USHORT *p)
1837 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1838 UINT32 r;
1839 nsresult nsres;
1841 TRACE("(%p)->(%p)\n", This, p);
1843 nsres = nsIDOMMouseEvent_GetWhich(This->nsevent, &r);
1844 if(NS_FAILED(nsres))
1845 return E_FAIL;
1847 *p = r;
1848 return S_OK;
1851 static const IDOMMouseEventVtbl DOMMouseEventVtbl = {
1852 DOMMouseEvent_QueryInterface,
1853 DOMMouseEvent_AddRef,
1854 DOMMouseEvent_Release,
1855 DOMMouseEvent_GetTypeInfoCount,
1856 DOMMouseEvent_GetTypeInfo,
1857 DOMMouseEvent_GetIDsOfNames,
1858 DOMMouseEvent_Invoke,
1859 DOMMouseEvent_get_screenX,
1860 DOMMouseEvent_get_screenY,
1861 DOMMouseEvent_get_clientX,
1862 DOMMouseEvent_get_clientY,
1863 DOMMouseEvent_get_ctrlKey,
1864 DOMMouseEvent_get_shiftKey,
1865 DOMMouseEvent_get_altKey,
1866 DOMMouseEvent_get_metaKey,
1867 DOMMouseEvent_get_button,
1868 DOMMouseEvent_get_relatedTarget,
1869 DOMMouseEvent_initMouseEvent,
1870 DOMMouseEvent_getModifierState,
1871 DOMMouseEvent_get_buttons,
1872 DOMMouseEvent_get_fromElement,
1873 DOMMouseEvent_get_toElement,
1874 DOMMouseEvent_get_x,
1875 DOMMouseEvent_get_y,
1876 DOMMouseEvent_get_offsetX,
1877 DOMMouseEvent_get_offsetY,
1878 DOMMouseEvent_get_pageX,
1879 DOMMouseEvent_get_pageY,
1880 DOMMouseEvent_get_layerX,
1881 DOMMouseEvent_get_layerY,
1882 DOMMouseEvent_get_which
1885 static DOMMouseEvent *DOMMouseEvent_from_DOMEvent(DOMEvent *event)
1887 return CONTAINING_RECORD(event, DOMMouseEvent, ui_event.event);
1890 static void *DOMMouseEvent_query_interface(DOMEvent *event, REFIID riid)
1892 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(event);
1893 if(IsEqualGUID(&IID_IDOMMouseEvent, riid))
1894 return &This->IDOMMouseEvent_iface;
1895 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1896 return &This->ui_event.IDOMUIEvent_iface;
1897 return NULL;
1900 static void DOMMouseEvent_destroy(DOMEvent *event)
1902 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(event);
1903 DOMUIEvent_destroy(&This->ui_event.event);
1904 nsIDOMMouseEvent_Release(This->nsevent);
1907 typedef struct {
1908 DOMUIEvent ui_event;
1909 IDOMKeyboardEvent IDOMKeyboardEvent_iface;
1910 nsIDOMKeyEvent *nsevent;
1911 } DOMKeyboardEvent;
1913 static inline DOMKeyboardEvent *impl_from_IDOMKeyboardEvent(IDOMKeyboardEvent *iface)
1915 return CONTAINING_RECORD(iface, DOMKeyboardEvent, IDOMKeyboardEvent_iface);
1918 static HRESULT WINAPI DOMKeyboardEvent_QueryInterface(IDOMKeyboardEvent *iface, REFIID riid, void **ppv)
1920 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1921 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1924 static ULONG WINAPI DOMKeyboardEvent_AddRef(IDOMKeyboardEvent *iface)
1926 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1927 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1930 static ULONG WINAPI DOMKeyboardEvent_Release(IDOMKeyboardEvent *iface)
1932 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1933 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
1936 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfoCount(IDOMKeyboardEvent *iface, UINT *pctinfo)
1938 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1939 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
1942 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfo(IDOMKeyboardEvent *iface, UINT iTInfo,
1943 LCID lcid, ITypeInfo **ppTInfo)
1945 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1946 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1949 static HRESULT WINAPI DOMKeyboardEvent_GetIDsOfNames(IDOMKeyboardEvent *iface, REFIID riid,
1950 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1952 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1953 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1954 lcid, rgDispId);
1957 static HRESULT WINAPI DOMKeyboardEvent_Invoke(IDOMKeyboardEvent *iface, DISPID dispIdMember,
1958 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1959 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1961 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1962 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1963 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1966 static HRESULT WINAPI DOMKeyboardEvent_get_key(IDOMKeyboardEvent *iface, BSTR *p)
1968 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1969 nsAString key_str;
1970 nsresult nsres;
1972 TRACE("(%p)->(%p)\n", This, p);
1975 nsAString_Init(&key_str, NULL);
1976 nsres = nsIDOMKeyEvent_GetKey(This->nsevent, &key_str);
1977 return return_nsstr(nsres, &key_str, p);
1980 static HRESULT WINAPI DOMKeyboardEvent_get_location(IDOMKeyboardEvent *iface, ULONG *p)
1982 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1983 UINT32 r;
1984 nsresult nsres;
1986 TRACE("(%p)->(%p)\n", This, p);
1988 nsres = nsIDOMKeyEvent_GetLocation(This->nsevent, &r);
1989 if(NS_FAILED(nsres))
1990 return E_FAIL;
1992 *p = r;
1993 return S_OK;
1996 static HRESULT WINAPI DOMKeyboardEvent_get_ctrlKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
1998 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1999 cpp_bool r;
2000 nsresult nsres;
2002 TRACE("(%p)->(%p)\n", This, p);
2004 nsres = nsIDOMKeyEvent_GetCtrlKey(This->nsevent, &r);
2005 if(NS_FAILED(nsres))
2006 return E_FAIL;
2008 *p = variant_bool(r);
2009 return S_OK;
2012 static HRESULT WINAPI DOMKeyboardEvent_get_shiftKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2014 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2015 cpp_bool r;
2016 nsresult nsres;
2018 TRACE("(%p)->(%p)\n", This, p);
2020 nsres = nsIDOMKeyEvent_GetShiftKey(This->nsevent, &r);
2021 if(NS_FAILED(nsres))
2022 return E_FAIL;
2024 *p = variant_bool(r);
2025 return S_OK;
2028 static HRESULT WINAPI DOMKeyboardEvent_get_altKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2030 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2031 cpp_bool r;
2032 nsresult nsres;
2034 TRACE("(%p)->(%p)\n", This, p);
2036 nsres = nsIDOMKeyEvent_GetAltKey(This->nsevent, &r);
2037 if(NS_FAILED(nsres))
2038 return E_FAIL;
2040 *p = variant_bool(r);
2041 return S_OK;
2044 static HRESULT WINAPI DOMKeyboardEvent_get_metaKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2046 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2047 cpp_bool r;
2048 nsresult nsres;
2050 TRACE("(%p)->(%p)\n", This, p);
2052 nsres = nsIDOMKeyEvent_GetMetaKey(This->nsevent, &r);
2053 if(NS_FAILED(nsres))
2054 return E_FAIL;
2056 *p = variant_bool(r);
2057 return S_OK;
2060 static HRESULT WINAPI DOMKeyboardEvent_get_repeat(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2062 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2063 cpp_bool r;
2064 nsresult nsres;
2066 TRACE("(%p)->(%p)\n", This, p);
2068 nsres = nsIDOMKeyEvent_GetRepeat(This->nsevent, &r);
2069 if(NS_FAILED(nsres))
2070 return E_FAIL;
2072 *p = variant_bool(r);
2073 return S_OK;
2076 static HRESULT WINAPI DOMKeyboardEvent_getModifierState(IDOMKeyboardEvent *iface, BSTR key,
2077 VARIANT_BOOL *state)
2079 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2080 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), state);
2081 return E_NOTIMPL;
2084 static HRESULT WINAPI DOMKeyboardEvent_initKeyboardEvent(IDOMKeyboardEvent *iface, BSTR type,
2085 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, BSTR key,
2086 ULONG location, BSTR modifiers_list, VARIANT_BOOL repeat, BSTR locale)
2088 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2089 FIXME("(%p)->(%s %x %x %p %s %lu %s %x %s)\n", This, debugstr_w(type), can_bubble,
2090 cancelable, view, debugstr_w(key), location, debugstr_w(modifiers_list),
2091 repeat, debugstr_w(locale));
2092 return E_NOTIMPL;
2095 static HRESULT WINAPI DOMKeyboardEvent_get_keyCode(IDOMKeyboardEvent *iface, LONG *p)
2097 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2098 UINT32 r;
2099 nsresult nsres;
2101 TRACE("(%p)->(%p)\n", This, p);
2103 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2104 if(NS_FAILED(nsres))
2105 return E_FAIL;
2107 *p = r;
2108 return S_OK;
2111 static HRESULT WINAPI DOMKeyboardEvent_get_charCode(IDOMKeyboardEvent *iface, LONG *p)
2113 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2114 UINT32 r;
2115 nsresult nsres;
2117 TRACE("(%p)->(%p)\n", This, p);
2119 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2120 if(NS_FAILED(nsres))
2121 return E_FAIL;
2123 *p = r;
2124 return S_OK;
2127 static HRESULT WINAPI DOMKeyboardEvent_get_which(IDOMKeyboardEvent *iface, LONG *p)
2129 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2130 UINT32 r;
2131 nsresult nsres;
2133 TRACE("(%p)->(%p)\n", This, p);
2135 nsres = nsIDOMKeyEvent_GetWhich(This->nsevent, &r);
2136 if(NS_FAILED(nsres))
2137 return E_FAIL;
2139 *p = r;
2140 return S_OK;
2143 static HRESULT WINAPI DOMKeyboardEvent_get_char(IDOMKeyboardEvent *iface, VARIANT *p)
2145 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2146 FIXME("(%p)->(%p)\n", This, p);
2147 return E_NOTIMPL;
2150 static HRESULT WINAPI DOMKeyboardEvent_get_locale(IDOMKeyboardEvent *iface, BSTR *p)
2152 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2153 FIXME("(%p)->(%p)\n", This, p);
2154 return E_NOTIMPL;
2157 static const IDOMKeyboardEventVtbl DOMKeyboardEventVtbl = {
2158 DOMKeyboardEvent_QueryInterface,
2159 DOMKeyboardEvent_AddRef,
2160 DOMKeyboardEvent_Release,
2161 DOMKeyboardEvent_GetTypeInfoCount,
2162 DOMKeyboardEvent_GetTypeInfo,
2163 DOMKeyboardEvent_GetIDsOfNames,
2164 DOMKeyboardEvent_Invoke,
2165 DOMKeyboardEvent_get_key,
2166 DOMKeyboardEvent_get_location,
2167 DOMKeyboardEvent_get_ctrlKey,
2168 DOMKeyboardEvent_get_shiftKey,
2169 DOMKeyboardEvent_get_altKey,
2170 DOMKeyboardEvent_get_metaKey,
2171 DOMKeyboardEvent_get_repeat,
2172 DOMKeyboardEvent_getModifierState,
2173 DOMKeyboardEvent_initKeyboardEvent,
2174 DOMKeyboardEvent_get_keyCode,
2175 DOMKeyboardEvent_get_charCode,
2176 DOMKeyboardEvent_get_which,
2177 DOMKeyboardEvent_get_char,
2178 DOMKeyboardEvent_get_locale
2181 static DOMKeyboardEvent *DOMKeyboardEvent_from_DOMEvent(DOMEvent *event)
2183 return CONTAINING_RECORD(event, DOMKeyboardEvent, ui_event.event);
2186 static void *DOMKeyboardEvent_query_interface(DOMEvent *event, REFIID riid)
2188 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(event);
2189 if(IsEqualGUID(&IID_IDOMKeyboardEvent, riid))
2190 return &This->IDOMKeyboardEvent_iface;
2191 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
2192 return &This->ui_event.IDOMUIEvent_iface;
2193 return NULL;
2196 static void DOMKeyboardEvent_destroy(DOMEvent *event)
2198 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(event);
2199 DOMUIEvent_destroy(&This->ui_event.event);
2200 nsIDOMKeyEvent_Release(This->nsevent);
2203 typedef struct {
2204 DOMEvent event;
2205 IDOMCustomEvent IDOMCustomEvent_iface;
2206 VARIANT detail;
2207 } DOMCustomEvent;
2209 static inline DOMCustomEvent *impl_from_IDOMCustomEvent(IDOMCustomEvent *iface)
2211 return CONTAINING_RECORD(iface, DOMCustomEvent, IDOMCustomEvent_iface);
2214 static HRESULT WINAPI DOMCustomEvent_QueryInterface(IDOMCustomEvent *iface, REFIID riid, void **ppv)
2216 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2217 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2220 static ULONG WINAPI DOMCustomEvent_AddRef(IDOMCustomEvent *iface)
2222 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2223 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2226 static ULONG WINAPI DOMCustomEvent_Release(IDOMCustomEvent *iface)
2228 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2229 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2232 static HRESULT WINAPI DOMCustomEvent_GetTypeInfoCount(IDOMCustomEvent *iface, UINT *pctinfo)
2234 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2235 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2238 static HRESULT WINAPI DOMCustomEvent_GetTypeInfo(IDOMCustomEvent *iface, UINT iTInfo,
2239 LCID lcid, ITypeInfo **ppTInfo)
2241 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2242 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2245 static HRESULT WINAPI DOMCustomEvent_GetIDsOfNames(IDOMCustomEvent *iface, REFIID riid,
2246 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2248 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2249 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2250 lcid, rgDispId);
2253 static HRESULT WINAPI DOMCustomEvent_Invoke(IDOMCustomEvent *iface, DISPID dispIdMember,
2254 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2255 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2257 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2258 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2259 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2262 static HRESULT WINAPI DOMCustomEvent_get_detail(IDOMCustomEvent *iface, VARIANT *p)
2264 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2266 TRACE("(%p)->(%p)\n", This, p);
2268 V_VT(p) = VT_EMPTY;
2269 return VariantCopy(p, &This->detail);
2272 static HRESULT WINAPI DOMCustomEvent_initCustomEvent(IDOMCustomEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2273 VARIANT_BOOL cancelable, VARIANT *detail)
2275 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2276 HRESULT hres;
2278 TRACE("(%p)->(%s %x %x %s)\n", This, debugstr_w(type), can_bubble, cancelable, debugstr_variant(detail));
2280 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
2281 if(FAILED(hres))
2282 return hres;
2284 return VariantCopy(&This->detail, detail);
2287 static const IDOMCustomEventVtbl DOMCustomEventVtbl = {
2288 DOMCustomEvent_QueryInterface,
2289 DOMCustomEvent_AddRef,
2290 DOMCustomEvent_Release,
2291 DOMCustomEvent_GetTypeInfoCount,
2292 DOMCustomEvent_GetTypeInfo,
2293 DOMCustomEvent_GetIDsOfNames,
2294 DOMCustomEvent_Invoke,
2295 DOMCustomEvent_get_detail,
2296 DOMCustomEvent_initCustomEvent
2299 static DOMCustomEvent *DOMCustomEvent_from_DOMEvent(DOMEvent *event)
2301 return CONTAINING_RECORD(event, DOMCustomEvent, event);
2304 static void *DOMCustomEvent_query_interface(DOMEvent *event, REFIID riid)
2306 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(event);
2307 if(IsEqualGUID(&IID_IDOMCustomEvent, riid))
2308 return &custom_event->IDOMCustomEvent_iface;
2309 return NULL;
2312 static void DOMCustomEvent_destroy(DOMEvent *event)
2314 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(event);
2315 VariantClear(&custom_event->detail);
2318 typedef struct {
2319 DOMEvent event;
2320 IDOMMessageEvent IDOMMessageEvent_iface;
2321 VARIANT data;
2322 } DOMMessageEvent;
2324 static inline DOMMessageEvent *impl_from_IDOMMessageEvent(IDOMMessageEvent *iface)
2326 return CONTAINING_RECORD(iface, DOMMessageEvent, IDOMMessageEvent_iface);
2329 static HRESULT WINAPI DOMMessageEvent_QueryInterface(IDOMMessageEvent *iface, REFIID riid, void **ppv)
2331 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2332 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2335 static ULONG WINAPI DOMMessageEvent_AddRef(IDOMMessageEvent *iface)
2337 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2338 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2341 static ULONG WINAPI DOMMessageEvent_Release(IDOMMessageEvent *iface)
2343 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2344 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2347 static HRESULT WINAPI DOMMessageEvent_GetTypeInfoCount(IDOMMessageEvent *iface, UINT *pctinfo)
2349 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2350 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2353 static HRESULT WINAPI DOMMessageEvent_GetTypeInfo(IDOMMessageEvent *iface, UINT iTInfo,
2354 LCID lcid, ITypeInfo **ppTInfo)
2356 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2357 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2360 static HRESULT WINAPI DOMMessageEvent_GetIDsOfNames(IDOMMessageEvent *iface, REFIID riid,
2361 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2363 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2364 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2365 lcid, rgDispId);
2368 static HRESULT WINAPI DOMMessageEvent_Invoke(IDOMMessageEvent *iface, DISPID dispIdMember,
2369 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2370 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2372 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2373 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2374 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2377 static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
2379 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2381 TRACE("(%p)->(%p)\n", This, p);
2383 if(V_VT(&This->data) != VT_BSTR) {
2384 FIXME("non-string data\n");
2385 return E_NOTIMPL;
2388 return (*p = SysAllocString(V_BSTR(&This->data))) ? S_OK : E_OUTOFMEMORY;
2391 static HRESULT DOMMessageEvent_get_data_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res,
2392 EXCEPINFO *ei, IServiceProvider *caller)
2394 DOMMessageEvent *This = CONTAINING_RECORD(dispex, DOMMessageEvent, event.dispex);
2396 if(!(flags & DISPATCH_PROPERTYGET) || !res)
2397 return S_FALSE;
2399 TRACE("(%p)->(%p)\n", This, res);
2401 V_VT(res) = VT_EMPTY;
2402 return VariantCopy(res, &This->data);
2405 static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR *p)
2407 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2408 FIXME("(%p)->(%p)\n", This, p);
2409 return E_NOTIMPL;
2412 static HRESULT WINAPI DOMMessageEvent_get_source(IDOMMessageEvent *iface, IHTMLWindow2 **p)
2414 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2415 FIXME("(%p)->(%p)\n", This, p);
2416 return E_NOTIMPL;
2419 static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2420 VARIANT_BOOL cancelable, BSTR data, BSTR origin,
2421 BSTR last_event_id, IHTMLWindow2 *source)
2423 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2424 FIXME("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2425 debugstr_w(data), debugstr_w(origin), debugstr_w(last_event_id), source);
2426 return E_NOTIMPL;
2429 static const IDOMMessageEventVtbl DOMMessageEventVtbl = {
2430 DOMMessageEvent_QueryInterface,
2431 DOMMessageEvent_AddRef,
2432 DOMMessageEvent_Release,
2433 DOMMessageEvent_GetTypeInfoCount,
2434 DOMMessageEvent_GetTypeInfo,
2435 DOMMessageEvent_GetIDsOfNames,
2436 DOMMessageEvent_Invoke,
2437 DOMMessageEvent_get_data,
2438 DOMMessageEvent_get_origin,
2439 DOMMessageEvent_get_source,
2440 DOMMessageEvent_initMessageEvent
2443 static DOMMessageEvent *DOMMessageEvent_from_DOMEvent(DOMEvent *event)
2445 return CONTAINING_RECORD(event, DOMMessageEvent, event);
2448 static void *DOMMessageEvent_query_interface(DOMEvent *event, REFIID riid)
2450 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(event);
2451 if(IsEqualGUID(&IID_IDOMMessageEvent, riid))
2452 return &message_event->IDOMMessageEvent_iface;
2453 return NULL;
2456 static void DOMMessageEvent_destroy(DOMEvent *event)
2458 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(event);
2459 VariantClear(&message_event->data);
2462 static void DOMMessageEvent_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
2464 static const dispex_hook_t hooks[] = {
2465 {DISPID_IDOMMESSAGEEVENT_DATA, DOMMessageEvent_get_data_hook},
2466 {DISPID_UNKNOWN}
2468 dispex_info_add_interface(info, IDOMMessageEvent_tid, compat_mode >= COMPAT_MODE_IE10 ? hooks : NULL);
2471 typedef struct {
2472 DOMEvent event;
2473 IDOMProgressEvent IDOMProgressEvent_iface;
2474 nsIDOMProgressEvent *nsevent;
2475 } DOMProgressEvent;
2477 static inline DOMProgressEvent *impl_from_IDOMProgressEvent(IDOMProgressEvent *iface)
2479 return CONTAINING_RECORD(iface, DOMProgressEvent, IDOMProgressEvent_iface);
2482 static HRESULT WINAPI DOMProgressEvent_QueryInterface(IDOMProgressEvent *iface, REFIID riid, void **ppv)
2484 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2485 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2488 static ULONG WINAPI DOMProgressEvent_AddRef(IDOMProgressEvent *iface)
2490 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2491 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2494 static ULONG WINAPI DOMProgressEvent_Release(IDOMProgressEvent *iface)
2496 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2497 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2500 static HRESULT WINAPI DOMProgressEvent_GetTypeInfoCount(IDOMProgressEvent *iface, UINT *pctinfo)
2502 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2503 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2506 static HRESULT WINAPI DOMProgressEvent_GetTypeInfo(IDOMProgressEvent *iface, UINT iTInfo,
2507 LCID lcid, ITypeInfo **ppTInfo)
2509 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2510 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2513 static HRESULT WINAPI DOMProgressEvent_GetIDsOfNames(IDOMProgressEvent *iface, REFIID riid,
2514 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2516 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2517 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2518 lcid, rgDispId);
2521 static HRESULT WINAPI DOMProgressEvent_Invoke(IDOMProgressEvent *iface, DISPID dispIdMember,
2522 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2523 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2525 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2526 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2527 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2530 static HRESULT WINAPI DOMProgressEvent_get_lengthComputable(IDOMProgressEvent *iface, VARIANT_BOOL *p)
2532 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2533 nsresult nsres;
2534 cpp_bool b;
2536 TRACE("(%p)->(%p)\n", This, p);
2538 nsres = nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b);
2539 if(NS_FAILED(nsres))
2540 return map_nsresult(nsres);
2542 *p = b ? VARIANT_TRUE : VARIANT_FALSE;
2543 return S_OK;
2546 static HRESULT WINAPI DOMProgressEvent_get_loaded(IDOMProgressEvent *iface, ULONGLONG *p)
2548 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2550 TRACE("(%p)->(%p)\n", This, p);
2552 return map_nsresult(nsIDOMProgressEvent_GetLoaded(This->nsevent, p));
2555 static HRESULT WINAPI DOMProgressEvent_get_total(IDOMProgressEvent *iface, ULONGLONG *p)
2557 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2558 cpp_bool b;
2560 TRACE("(%p)->(%p)\n", This, p);
2562 if(NS_FAILED(nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b)) || !b) {
2563 *p = ~0;
2564 return S_OK;
2567 return map_nsresult(nsIDOMProgressEvent_GetTotal(This->nsevent, p));
2570 static HRESULT WINAPI DOMProgressEvent_initProgressEvent(IDOMProgressEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2571 VARIANT_BOOL cancelable, VARIANT_BOOL lengthComputable,
2572 ULONGLONG loaded, ULONGLONG total)
2574 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2575 FIXME("(%p)->(%s %x %x %x %s %s)\n", This, debugstr_w(type), can_bubble, cancelable, lengthComputable,
2576 wine_dbgstr_longlong(loaded), wine_dbgstr_longlong(total));
2577 return E_NOTIMPL;
2580 static const IDOMProgressEventVtbl DOMProgressEventVtbl = {
2581 DOMProgressEvent_QueryInterface,
2582 DOMProgressEvent_AddRef,
2583 DOMProgressEvent_Release,
2584 DOMProgressEvent_GetTypeInfoCount,
2585 DOMProgressEvent_GetTypeInfo,
2586 DOMProgressEvent_GetIDsOfNames,
2587 DOMProgressEvent_Invoke,
2588 DOMProgressEvent_get_lengthComputable,
2589 DOMProgressEvent_get_loaded,
2590 DOMProgressEvent_get_total,
2591 DOMProgressEvent_initProgressEvent
2594 static DOMProgressEvent *DOMProgressEvent_from_DOMEvent(DOMEvent *event)
2596 return CONTAINING_RECORD(event, DOMProgressEvent, event);
2599 static void *DOMProgressEvent_query_interface(DOMEvent *event, REFIID riid)
2601 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
2602 if(IsEqualGUID(&IID_IDOMProgressEvent, riid))
2603 return &This->IDOMProgressEvent_iface;
2604 return NULL;
2607 static void DOMProgressEvent_destroy(DOMEvent *event)
2609 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
2610 nsIDOMProgressEvent_Release(This->nsevent);
2613 typedef struct {
2614 DOMEvent event;
2615 IDOMStorageEvent IDOMStorageEvent_iface;
2616 BSTR key;
2617 BSTR old_value;
2618 BSTR new_value;
2619 } DOMStorageEvent;
2621 static inline DOMStorageEvent *impl_from_IDOMStorageEvent(IDOMStorageEvent *iface)
2623 return CONTAINING_RECORD(iface, DOMStorageEvent, IDOMStorageEvent_iface);
2626 static HRESULT WINAPI DOMStorageEvent_QueryInterface(IDOMStorageEvent *iface, REFIID riid, void **ppv)
2628 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2629 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2632 static ULONG WINAPI DOMStorageEvent_AddRef(IDOMStorageEvent *iface)
2634 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2635 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2638 static ULONG WINAPI DOMStorageEvent_Release(IDOMStorageEvent *iface)
2640 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2641 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2644 static HRESULT WINAPI DOMStorageEvent_GetTypeInfoCount(IDOMStorageEvent *iface, UINT *pctinfo)
2646 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2647 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2650 static HRESULT WINAPI DOMStorageEvent_GetTypeInfo(IDOMStorageEvent *iface, UINT iTInfo,
2651 LCID lcid, ITypeInfo **ppTInfo)
2653 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2654 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2657 static HRESULT WINAPI DOMStorageEvent_GetIDsOfNames(IDOMStorageEvent *iface, REFIID riid,
2658 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2660 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2661 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2662 lcid, rgDispId);
2665 static HRESULT WINAPI DOMStorageEvent_Invoke(IDOMStorageEvent *iface, DISPID dispIdMember,
2666 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2667 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2669 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2670 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2671 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2674 static HRESULT WINAPI DOMStorageEvent_get_key(IDOMStorageEvent *iface, BSTR *p)
2676 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2678 TRACE("(%p)->(%p)\n", This, p);
2680 if(This->key)
2681 return (*p = SysAllocStringLen(This->key, SysStringLen(This->key))) ? S_OK : E_OUTOFMEMORY;
2682 *p = NULL;
2683 return S_OK;
2686 static HRESULT WINAPI DOMStorageEvent_get_oldValue(IDOMStorageEvent *iface, BSTR *p)
2688 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2690 TRACE("(%p)->(%p)\n", This, p);
2692 if(This->old_value)
2693 return (*p = SysAllocStringLen(This->old_value, SysStringLen(This->old_value))) ? S_OK : E_OUTOFMEMORY;
2694 *p = NULL;
2695 return S_OK;
2698 static HRESULT WINAPI DOMStorageEvent_get_newValue(IDOMStorageEvent *iface, BSTR *p)
2700 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2702 TRACE("(%p)->(%p)\n", This, p);
2704 if(This->new_value)
2705 return (*p = SysAllocStringLen(This->new_value, SysStringLen(This->new_value))) ? S_OK : E_OUTOFMEMORY;
2706 *p = NULL;
2707 return S_OK;
2710 static HRESULT WINAPI DOMStorageEvent_get_url(IDOMStorageEvent *iface, BSTR *p)
2712 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2713 FIXME("(%p)->(%p)\n", This, p);
2714 return E_NOTIMPL;
2717 static HRESULT WINAPI DOMStorageEvent_get_storageArea(IDOMStorageEvent *iface, IHTMLStorage **p)
2719 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2720 FIXME("(%p)->(%p)\n", This, p);
2721 return E_NOTIMPL;
2724 static HRESULT WINAPI DOMStorageEvent_initStorageEvent(IDOMStorageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2725 VARIANT_BOOL cancelable, BSTR keyArg, BSTR oldValueArg,
2726 BSTR newValueArg, BSTR urlArg, IHTMLStorage *storageAreaArg)
2728 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2729 FIXME("(%p)->(%s %x %x %s %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2730 debugstr_w(keyArg), debugstr_w(oldValueArg), debugstr_w(newValueArg), debugstr_w(urlArg), storageAreaArg);
2731 return E_NOTIMPL;
2734 static const IDOMStorageEventVtbl DOMStorageEventVtbl = {
2735 DOMStorageEvent_QueryInterface,
2736 DOMStorageEvent_AddRef,
2737 DOMStorageEvent_Release,
2738 DOMStorageEvent_GetTypeInfoCount,
2739 DOMStorageEvent_GetTypeInfo,
2740 DOMStorageEvent_GetIDsOfNames,
2741 DOMStorageEvent_Invoke,
2742 DOMStorageEvent_get_key,
2743 DOMStorageEvent_get_oldValue,
2744 DOMStorageEvent_get_newValue,
2745 DOMStorageEvent_get_url,
2746 DOMStorageEvent_get_storageArea,
2747 DOMStorageEvent_initStorageEvent
2750 static DOMStorageEvent *DOMStorageEvent_from_DOMEvent(DOMEvent *event)
2752 return CONTAINING_RECORD(event, DOMStorageEvent, event);
2755 static void *DOMStorageEvent_query_interface(DOMEvent *event, REFIID riid)
2757 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
2758 if(IsEqualGUID(&IID_IDOMStorageEvent, riid))
2759 return &storage_event->IDOMStorageEvent_iface;
2760 return NULL;
2763 static void DOMStorageEvent_destroy(DOMEvent *event)
2765 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
2766 SysFreeString(storage_event->key);
2767 SysFreeString(storage_event->old_value);
2768 SysFreeString(storage_event->new_value);
2771 static const tid_t DOMEvent_iface_tids[] = {
2772 IDOMEvent_tid,
2776 static dispex_static_data_t DOMEvent_dispex = {
2777 L"Event",
2778 NULL,
2779 DispDOMEvent_tid,
2780 DOMEvent_iface_tids
2783 static const tid_t DOMUIEvent_iface_tids[] = {
2784 IDOMEvent_tid,
2785 IDOMUIEvent_tid,
2789 static dispex_static_data_t DOMUIEvent_dispex = {
2790 L"UIEvent",
2791 NULL,
2792 DispDOMUIEvent_tid,
2793 DOMUIEvent_iface_tids
2796 static const tid_t DOMMouseEvent_iface_tids[] = {
2797 IDOMEvent_tid,
2798 IDOMUIEvent_tid,
2799 IDOMMouseEvent_tid,
2803 static dispex_static_data_t DOMMouseEvent_dispex = {
2804 L"MouseEvent",
2805 NULL,
2806 DispDOMMouseEvent_tid,
2807 DOMMouseEvent_iface_tids
2810 static const tid_t DOMKeyboardEvent_iface_tids[] = {
2811 IDOMEvent_tid,
2812 IDOMUIEvent_tid,
2813 IDOMKeyboardEvent_tid,
2817 static dispex_static_data_t DOMKeyboardEvent_dispex = {
2818 L"KeyboardEvent",
2819 NULL,
2820 DispDOMKeyboardEvent_tid,
2821 DOMKeyboardEvent_iface_tids
2824 static const tid_t DOMCustomEvent_iface_tids[] = {
2825 IDOMEvent_tid,
2826 IDOMCustomEvent_tid,
2830 static dispex_static_data_t DOMCustomEvent_dispex = {
2831 L"CustomEvent",
2832 NULL,
2833 DispDOMCustomEvent_tid,
2834 DOMCustomEvent_iface_tids
2837 static const tid_t DOMMessageEvent_iface_tids[] = {
2838 IDOMEvent_tid,
2842 dispex_static_data_t DOMMessageEvent_dispex = {
2843 L"MessageEvent",
2844 NULL,
2845 DispDOMMessageEvent_tid,
2846 DOMMessageEvent_iface_tids,
2847 DOMMessageEvent_init_dispex_info
2850 static const tid_t DOMProgressEvent_iface_tids[] = {
2851 IDOMEvent_tid,
2852 IDOMProgressEvent_tid,
2856 dispex_static_data_t DOMProgressEvent_dispex = {
2857 L"ProgressEvent",
2858 NULL,
2859 DispDOMProgressEvent_tid,
2860 DOMProgressEvent_iface_tids
2863 static const tid_t DOMStorageEvent_iface_tids[] = {
2864 IDOMEvent_tid,
2865 IDOMStorageEvent_tid,
2869 dispex_static_data_t DOMStorageEvent_dispex = {
2870 L"StorageEvent",
2871 NULL,
2872 DispDOMStorageEvent_tid,
2873 DOMStorageEvent_iface_tids
2876 static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, void *(*query_interface)(DOMEvent*,REFIID),
2877 void (*destroy)(DOMEvent*), nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2879 DOMEvent *event = heap_alloc_zero(size);
2881 if(!event)
2882 return NULL;
2883 event->IDOMEvent_iface.lpVtbl = &DOMEventVtbl;
2884 event->query_interface = query_interface;
2885 event->destroy = destroy;
2886 event->ref = 1;
2887 event->event_id = event_id;
2888 if(event_id != EVENTID_LAST) {
2889 event->type = heap_strdupW(event_info[event_id].name);
2890 if(!event->type) {
2891 heap_free(event);
2892 return NULL;
2894 event->bubbles = (event_info[event_id].flags & EVENT_BUBBLES) != 0;
2895 event->cancelable = (event_info[event_id].flags & EVENT_CANCELABLE) != 0;
2897 nsIDOMEvent_AddRef(event->nsevent = nsevent);
2899 event->time_stamp = get_time_stamp();
2901 init_dispatch(&event->dispex, (IUnknown*)&event->IDOMEvent_iface, dispex_data, compat_mode);
2902 return event;
2905 static void fill_parent_ui_event(nsIDOMEvent *nsevent, DOMUIEvent *ui_event)
2907 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
2908 nsIDOMEvent_QueryInterface(nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event->nsevent);
2911 static DOMEvent *ui_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2913 DOMUIEvent *ui_event = event_ctor(sizeof(DOMUIEvent), &DOMUIEvent_dispex,
2914 DOMUIEvent_query_interface, DOMUIEvent_destroy, nsevent, event_id, compat_mode);
2915 if(!ui_event) return NULL;
2916 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
2917 ui_event->nsevent = iface;
2918 return &ui_event->event;
2921 static DOMEvent *mouse_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2923 DOMMouseEvent *mouse_event = event_ctor(sizeof(DOMMouseEvent), &DOMMouseEvent_dispex,
2924 DOMMouseEvent_query_interface, DOMMouseEvent_destroy, nsevent, event_id, compat_mode);
2925 if(!mouse_event) return NULL;
2926 mouse_event->IDOMMouseEvent_iface.lpVtbl = &DOMMouseEventVtbl;
2927 mouse_event->nsevent = iface;
2928 fill_parent_ui_event(nsevent, &mouse_event->ui_event);
2929 return &mouse_event->ui_event.event;
2932 static DOMEvent *keyboard_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2934 DOMKeyboardEvent *keyboard_event = event_ctor(sizeof(DOMKeyboardEvent), &DOMKeyboardEvent_dispex,
2935 DOMKeyboardEvent_query_interface, DOMKeyboardEvent_destroy, nsevent, event_id, compat_mode);
2936 if(!keyboard_event) return NULL;
2937 keyboard_event->IDOMKeyboardEvent_iface.lpVtbl = &DOMKeyboardEventVtbl;
2938 keyboard_event->nsevent = iface;
2939 fill_parent_ui_event(nsevent, &keyboard_event->ui_event);
2940 return &keyboard_event->ui_event.event;
2943 static DOMEvent *custom_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2945 DOMCustomEvent *custom_event = event_ctor(sizeof(DOMCustomEvent), &DOMCustomEvent_dispex,
2946 DOMCustomEvent_query_interface, DOMCustomEvent_destroy, nsevent, event_id, compat_mode);
2947 if(!custom_event) return NULL;
2948 custom_event->IDOMCustomEvent_iface.lpVtbl = &DOMCustomEventVtbl;
2949 nsIDOMCustomEvent_Release(iface);
2950 return &custom_event->event;
2953 static DOMEvent *progress_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2955 DOMProgressEvent *progress_event;
2957 if(compat_mode < COMPAT_MODE_IE10)
2958 return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, NULL, NULL, nsevent, event_id, compat_mode);
2960 if(!(progress_event = event_ctor(sizeof(DOMProgressEvent), &DOMProgressEvent_dispex,
2961 DOMProgressEvent_query_interface, DOMProgressEvent_destroy, nsevent, event_id, compat_mode)))
2962 return NULL;
2963 progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
2964 progress_event->nsevent = iface;
2965 return &progress_event->event;
2968 static DOMEvent *message_event_ctor(nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2970 DOMMessageEvent *message_event = event_ctor(sizeof(DOMMessageEvent), &DOMMessageEvent_dispex,
2971 DOMMessageEvent_query_interface, DOMMessageEvent_destroy, nsevent, event_id, compat_mode);
2972 if(!message_event) return NULL;
2973 message_event->IDOMMessageEvent_iface.lpVtbl = &DOMMessageEventVtbl;
2974 return &message_event->event;
2977 static DOMEvent *storage_event_ctor(nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
2979 DOMStorageEvent *storage_event = event_ctor(sizeof(DOMStorageEvent), &DOMStorageEvent_dispex,
2980 DOMStorageEvent_query_interface, DOMStorageEvent_destroy, nsevent, event_id, compat_mode);
2981 if(!storage_event) return NULL;
2982 storage_event->IDOMStorageEvent_iface.lpVtbl = &DOMStorageEventVtbl;
2983 return &storage_event->event;
2986 static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, eventid_t event_id)
2988 static const struct {
2989 REFIID iid;
2990 DOMEvent *(*ctor)(void *iface, nsIDOMEvent *nsevent, eventid_t, compat_mode_t);
2991 } types_table[] = {
2992 { &IID_nsIDOMMouseEvent, mouse_event_ctor },
2993 { &IID_nsIDOMKeyEvent, keyboard_event_ctor },
2994 { &IID_nsIDOMUIEvent, ui_event_ctor },
2995 { &IID_nsIDOMCustomEvent, custom_event_ctor },
2996 { &IID_nsIDOMProgressEvent, progress_event_ctor },
2998 DOMEvent *event;
2999 unsigned i;
3001 switch(event_id) {
3002 case EVENTID_MESSAGE: return message_event_ctor(nsevent, event_id, compat_mode);
3003 case EVENTID_STORAGECOMMIT:
3004 case EVENTID_STORAGE: return storage_event_ctor(nsevent, event_id, compat_mode);
3005 default: break;
3008 for(i = 0; i < ARRAY_SIZE(types_table); i++) {
3009 void *iface;
3010 nsresult nsres = nsIDOMEvent_QueryInterface(nsevent, types_table[i].iid, &iface);
3011 if(NS_SUCCEEDED(nsres)) {
3012 /* Transfer the iface ownership to the ctor on success */
3013 if(!(event = types_table[i].ctor(iface, nsevent, event_id, compat_mode)))
3014 nsISupports_Release(iface);
3015 return event;
3019 return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, NULL, NULL, nsevent, event_id, compat_mode);
3022 HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, compat_mode_t compat_mode, DOMEvent **ret_event)
3024 eventid_t event_id = EVENTID_LAST;
3025 DOMEvent *event;
3026 nsAString nsstr;
3027 nsresult nsres;
3029 nsAString_Init(&nsstr, NULL);
3030 nsres = nsIDOMEvent_GetType(nsevent, &nsstr);
3031 if(NS_SUCCEEDED(nsres)) {
3032 const WCHAR *type;
3033 nsAString_GetData(&nsstr, &type);
3034 event_id = str_to_eid(type);
3035 if(event_id == EVENTID_LAST)
3036 FIXME("unknown event type %s\n", debugstr_w(type));
3037 }else {
3038 ERR("GetType failed: %08lx\n", nsres);
3040 nsAString_Finish(&nsstr);
3042 event = alloc_event(nsevent, compat_mode, event_id);
3043 if(!event)
3044 return E_OUTOFMEMORY;
3046 event->trusted = TRUE;
3047 *ret_event = event;
3048 return S_OK;
3051 HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOMEvent **ret_event)
3053 nsIDOMEvent *nsevent;
3054 DOMEvent *event;
3055 nsAString nsstr;
3056 nsresult nsres;
3058 nsAString_InitDepend(&nsstr, type);
3059 nsres = nsIDOMHTMLDocument_CreateEvent(doc->nsdoc, &nsstr, &nsevent);
3060 nsAString_Finish(&nsstr);
3061 if(NS_FAILED(nsres)) {
3062 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(type), nsres);
3063 return E_FAIL;
3066 event = alloc_event(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), EVENTID_LAST);
3067 nsIDOMEvent_Release(nsevent);
3068 if(!event)
3069 return E_OUTOFMEMORY;
3071 *ret_event = &event->IDOMEvent_iface;
3072 return S_OK;
3075 HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEvent **ret_event)
3077 nsIDOMEvent *nsevent;
3078 DOMEvent *event;
3079 nsAString nsstr;
3080 nsresult nsres;
3082 nsAString_InitDepend(&nsstr, event_types[event_info[event_id].type]);
3083 nsres = nsIDOMHTMLDocument_CreateEvent(doc->nsdoc, &nsstr, &nsevent);
3084 nsAString_Finish(&nsstr);
3085 if(NS_FAILED(nsres)) {
3086 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(event_types[event_info[event_id].type]), nsres);
3087 return E_FAIL;
3090 event = alloc_event(nsevent, doc->document_mode, event_id);
3091 if(!event)
3092 return E_OUTOFMEMORY;
3094 event->event_id = event_id;
3095 event->trusted = TRUE;
3096 *ret_event = event;
3097 return S_OK;
3100 HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **ret)
3102 DOMMessageEvent *message_event;
3103 DOMEvent *event;
3104 HRESULT hres;
3106 hres = create_document_event(doc, EVENTID_MESSAGE, &event);
3107 if(FAILED(hres))
3108 return hres;
3109 message_event = DOMMessageEvent_from_DOMEvent(event);
3111 V_VT(&message_event->data) = VT_EMPTY;
3112 hres = VariantCopy(&message_event->data, data);
3113 if(FAILED(hres)) {
3114 IDOMEvent_Release(&event->IDOMEvent_iface);
3115 return hres;
3118 *ret = event;
3119 return S_OK;
3122 HRESULT create_storage_event(HTMLDocumentNode *doc, BSTR key, BSTR old_value, BSTR new_value,
3123 BOOL commit, DOMEvent **ret)
3125 DOMStorageEvent *storage_event;
3126 DOMEvent *event;
3127 HRESULT hres;
3129 hres = create_document_event(doc, commit ? EVENTID_STORAGECOMMIT : EVENTID_STORAGE, &event);
3130 if(FAILED(hres))
3131 return hres;
3132 storage_event = DOMStorageEvent_from_DOMEvent(event);
3134 if(!commit) {
3135 if((key && !(storage_event->key = SysAllocString(key))) ||
3136 (old_value && !(storage_event->old_value = SysAllocString(old_value))) ||
3137 (new_value && !(storage_event->new_value = SysAllocString(new_value)))) {
3138 IDOMEvent_Release(&event->IDOMEvent_iface);
3139 return E_OUTOFMEMORY;
3143 *ret = event;
3144 return S_OK;
3147 static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
3149 IDispatchEx *dispex;
3150 EXCEPINFO ei;
3151 HRESULT hres;
3153 memset(&ei, 0, sizeof(ei));
3155 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
3156 if(SUCCEEDED(hres)) {
3157 hres = IDispatchEx_InvokeEx(dispex, 0, GetUserDefaultLCID(), DISPATCH_METHOD, dp, retv, &ei, NULL);
3158 IDispatchEx_Release(dispex);
3159 }else {
3160 TRACE("Could not get IDispatchEx interface: %08lx\n", hres);
3161 hres = IDispatch_Invoke(disp, 0, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD,
3162 dp, retv, &ei, NULL);
3165 return hres;
3168 static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, IHTMLEventObj *event_obj, VARIANT *retv)
3170 DISPPARAMS dp = {NULL,NULL,0,0};
3171 VARIANT event_arg;
3172 UINT argerr;
3173 EXCEPINFO ei;
3175 TRACE("%p,%ld,%p,%p\n", disp, dispid, event_obj, retv);
3177 if(event_obj) {
3178 V_VT(&event_arg) = VT_DISPATCH;
3179 V_DISPATCH(&event_arg) = (IDispatch*)event_obj;
3180 dp.rgvarg = &event_arg;
3181 dp.cArgs = 1;
3184 memset(&ei, 0, sizeof(ei));
3185 return IDispatch_Invoke(disp, dispid, &IID_NULL, 0, DISPATCH_METHOD, &dp, retv, &ei, &argerr);
3188 static BOOL use_event_quirks(EventTarget *event_target)
3190 return dispex_compat_mode(&event_target->dispex) < COMPAT_MODE_IE9;
3193 static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
3195 int min, max, i;
3196 HRESULT hres;
3198 if(!data || dispid == DISPID_UNKNOWN)
3199 return FALSE;
3201 if(!data->ids) {
3202 hres = get_dispids(data->tid, &data->id_cnt, &data->ids);
3203 if(FAILED(hres))
3204 return FALSE;
3207 min = 0;
3208 max = data->id_cnt-1;
3209 while(min <= max) {
3210 i = (min+max)/2;
3211 if(data->ids[i] == dispid)
3212 return TRUE;
3214 if(data->ids[i] < dispid)
3215 min = i+1;
3216 else
3217 max = i-1;
3220 return FALSE;
3223 static void call_event_handlers(EventTarget *event_target, DOMEvent *event, dispatch_mode_t dispatch_mode)
3225 const listener_container_t *container = get_listener_container(event_target, event->type, FALSE);
3226 event_listener_t *listener, listeners_buf[8], *listeners = listeners_buf;
3227 unsigned listeners_cnt, listeners_size;
3228 ConnectionPointContainer *cp_container = NULL;
3229 const event_target_vtbl_t *vtbl = NULL;
3230 BOOL skip_onevent_listener = FALSE;
3231 VARIANT v;
3232 HRESULT hres;
3234 assert(!event->current_target);
3235 event->current_target = event_target;
3237 if(container && !list_empty(&container->listeners) && event->phase != DEP_CAPTURING_PHASE) {
3238 listener = LIST_ENTRY(list_tail(&container->listeners), event_listener_t, entry);
3239 if(listener && listener->function && listener->type == LISTENER_TYPE_ONEVENT
3240 && use_event_quirks(event_target)) {
3241 DISPID named_arg = DISPID_THIS;
3242 VARIANTARG arg;
3243 DISPPARAMS dp = {&arg, &named_arg, 1, 1};
3245 skip_onevent_listener = TRUE;
3247 V_VT(&arg) = VT_DISPATCH;
3248 V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3249 V_VT(&v) = VT_EMPTY;
3251 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3252 hres = call_disp_func(listener->function, &dp, &v);
3253 if(hres == S_OK) {
3254 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type), debugstr_variant(&v));
3256 if(event->cancelable) {
3257 if(V_VT(&v) == VT_BOOL) {
3258 if(!V_BOOL(&v))
3259 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3260 }else if(V_VT(&v) != VT_EMPTY) {
3261 FIXME("unhandled result %s\n", debugstr_variant(&v));
3264 VariantClear(&v);
3265 }else {
3266 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3271 listeners_cnt = 0;
3272 listeners_size = ARRAY_SIZE(listeners_buf);
3274 if(container) {
3275 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
3276 if(!listener->function)
3277 continue;
3278 switch(listener->type) {
3279 case LISTENER_TYPE_ONEVENT:
3280 if(skip_onevent_listener || event->phase == DEP_CAPTURING_PHASE)
3281 continue;
3282 break;
3283 case LISTENER_TYPE_CAPTURE:
3284 if(event->phase == DEP_BUBBLING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3285 continue;
3286 break;
3287 case LISTENER_TYPE_BUBBLE:
3288 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3289 continue;
3290 break;
3291 case LISTENER_TYPE_ATTACHED:
3292 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_STANDARD)
3293 continue;
3294 break;
3297 if(listeners_cnt == listeners_size) {
3298 event_listener_t *new_listeners;
3299 if(listeners == listeners_buf) {
3300 new_listeners = heap_alloc(listeners_size * 2 * sizeof(*new_listeners));
3301 if(!new_listeners)
3302 break;
3303 memcpy(new_listeners, listeners, listeners_cnt * sizeof(*listeners));
3304 }else {
3305 new_listeners = heap_realloc(listeners, listeners_size * 2 * sizeof(*new_listeners));
3307 listeners = new_listeners;
3308 listeners_size *= 2;
3311 listeners[listeners_cnt].type = listener->type;
3312 IDispatch_AddRef(listeners[listeners_cnt].function = listener->function);
3313 listeners_cnt++;
3317 for(listener = listeners; !event->stop_immediate_propagation
3318 && listener < listeners + listeners_cnt; listener++) {
3319 if(listener->type != LISTENER_TYPE_ATTACHED) {
3320 DISPID named_arg = DISPID_THIS;
3321 VARIANTARG args[2];
3322 DISPPARAMS dp = {args, &named_arg, 2, 1};
3324 V_VT(args) = VT_DISPATCH;
3325 V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3326 V_VT(args+1) = VT_DISPATCH;
3327 V_DISPATCH(args+1) = dispatch_mode == DISPATCH_LEGACY
3328 ? (IDispatch*)event->event_obj : (IDispatch*)&event->IDOMEvent_iface;
3329 V_VT(&v) = VT_EMPTY;
3331 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3332 hres = call_disp_func(listener->function, &dp, &v);
3333 if(hres == S_OK) {
3334 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type),
3335 debugstr_variant(&v));
3337 if(event->cancelable) {
3338 if(V_VT(&v) == VT_BOOL) {
3339 if(!V_BOOL(&v))
3340 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3341 }else if(V_VT(&v) != VT_EMPTY) {
3342 FIXME("unhandled result %s\n", debugstr_variant(&v));
3345 VariantClear(&v);
3346 }else {
3347 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3349 }else {
3350 VARIANTARG arg;
3351 DISPPARAMS dp = {&arg, NULL, 1, 0};
3353 V_VT(&arg) = VT_DISPATCH;
3354 V_DISPATCH(&arg) = (IDispatch*)event->event_obj;
3355 V_VT(&v) = VT_EMPTY;
3357 TRACE("%p %s attached >>>\n", event_target, debugstr_w(event->type));
3358 hres = call_disp_func(listener->function, &dp, &v);
3359 if(hres == S_OK) {
3360 TRACE("%p %s attached <<<\n", event_target, debugstr_w(event->type));
3362 if(event->cancelable) {
3363 if(V_VT(&v) == VT_BOOL) {
3364 if(!V_BOOL(&v))
3365 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3366 }else if(V_VT(&v) != VT_EMPTY) {
3367 FIXME("unhandled result %s\n", debugstr_variant(&v));
3370 VariantClear(&v);
3371 }else {
3372 WARN("%p %s attached <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3377 for(listener = listeners; listener < listeners + listeners_cnt; listener++)
3378 IDispatch_Release(listener->function);
3379 if(listeners != listeners_buf)
3380 heap_free(listeners);
3382 if(event->phase != DEP_CAPTURING_PHASE && event->event_id != EVENTID_LAST
3383 && event_info[event->event_id].dispid && (vtbl = dispex_get_vtbl(&event_target->dispex))
3384 && vtbl->get_cp_container)
3385 cp_container = vtbl->get_cp_container(&event_target->dispex);
3386 if(cp_container) {
3387 if(cp_container->cps) {
3388 ConnectionPoint *cp;
3389 unsigned i, j;
3391 for(j=0; cp_container->cp_entries[j].riid; j++) {
3392 cp = cp_container->cps + j;
3393 if(!cp->sinks_size || !is_cp_event(cp->data, event_info[event->event_id].dispid))
3394 continue;
3396 for(i=0; i < cp->sinks_size; i++) {
3397 if(!cp->sinks[i].disp)
3398 continue;
3400 V_VT(&v) = VT_EMPTY;
3402 TRACE("%p cp %s [%u] >>>\n", event_target, debugstr_w(event->type), i);
3403 hres = call_cp_func(cp->sinks[i].disp, event_info[event->event_id].dispid,
3404 cp->data->pass_event_arg ? event->event_obj : NULL, &v);
3405 if(hres == S_OK) {
3406 TRACE("%p cp %s [%u] <<<\n", event_target, debugstr_w(event->type), i);
3408 if(event->cancelable) {
3409 if(V_VT(&v) == VT_BOOL) {
3410 if(!V_BOOL(&v))
3411 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3412 }else if(V_VT(&v) != VT_EMPTY) {
3413 FIXME("unhandled result %s\n", debugstr_variant(&v));
3416 VariantClear(&v);
3417 }else {
3418 WARN("%p cp %s [%u] <<< %08lx\n", event_target, debugstr_w(event->type), i, hres);
3423 IConnectionPointContainer_Release(&cp_container->IConnectionPointContainer_iface);
3426 event->current_target = NULL;
3429 static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event,
3430 dispatch_mode_t dispatch_mode, VARIANT_BOOL *r)
3432 EventTarget *target_chain_buf[8], **target_chain = target_chain_buf;
3433 unsigned chain_cnt, chain_buf_size, i;
3434 const event_target_vtbl_t *vtbl, *target_vtbl;
3435 HTMLEventObj *event_obj_ref = NULL;
3436 IHTMLEventObj *prev_event = NULL;
3437 EventTarget *iter;
3438 HRESULT hres;
3440 TRACE("(%p) %s\n", event_target, debugstr_w(event->type));
3442 if(!event->type) {
3443 FIXME("Uninitialized event.\n");
3444 return E_FAIL;
3447 if(event->current_target) {
3448 FIXME("event is being dispatched.\n");
3449 return E_FAIL;
3452 iter = event_target;
3453 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3455 chain_cnt = 0;
3456 chain_buf_size = ARRAY_SIZE(target_chain_buf);
3458 do {
3459 if(chain_cnt == chain_buf_size) {
3460 EventTarget **new_chain;
3461 if(target_chain == target_chain_buf) {
3462 new_chain = heap_alloc(chain_buf_size * 2 * sizeof(*new_chain));
3463 if(!new_chain)
3464 break;
3465 memcpy(new_chain, target_chain, chain_buf_size * sizeof(*new_chain));
3466 }else {
3467 new_chain = heap_realloc(target_chain, chain_buf_size * 2 * sizeof(*new_chain));
3468 if(!new_chain)
3469 break;
3471 chain_buf_size *= 2;
3472 target_chain = new_chain;
3475 target_chain[chain_cnt++] = iter;
3477 if(!(vtbl = dispex_get_vtbl(&iter->dispex)) || !vtbl->get_parent_event_target)
3478 break;
3479 iter = vtbl->get_parent_event_target(&iter->dispex);
3480 } while(iter);
3482 if(!event->event_obj && !event->no_event_obj) {
3483 event_obj_ref = alloc_event_obj(event, dispex_compat_mode(&event->dispex));
3484 if(event_obj_ref)
3485 event->event_obj = &event_obj_ref->IHTMLEventObj_iface;
3488 target_vtbl = dispex_get_vtbl(&event_target->dispex);
3489 if(target_vtbl && target_vtbl->set_current_event)
3490 prev_event = target_vtbl->set_current_event(&event_target->dispex, event->event_obj);
3492 if(event->target)
3493 IEventTarget_Release(&event->target->IEventTarget_iface);
3494 event->target = event_target;
3495 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3497 event->phase = DEP_CAPTURING_PHASE;
3498 i = chain_cnt-1;
3499 while(!event->stop_propagation && i)
3500 call_event_handlers(target_chain[i--], event, dispatch_mode);
3502 if(!event->stop_propagation) {
3503 event->phase = DEP_AT_TARGET;
3504 call_event_handlers(target_chain[0], event, dispatch_mode);
3507 if(event->bubbles) {
3508 event->phase = DEP_BUBBLING_PHASE;
3509 for(i = 1; !event->stop_propagation && i < chain_cnt; i++)
3510 call_event_handlers(target_chain[i], event, dispatch_mode);
3513 if(r)
3514 *r = variant_bool(!event->prevent_default);
3516 if(target_vtbl && target_vtbl->set_current_event) {
3517 prev_event = target_vtbl->set_current_event(&event_target->dispex, prev_event);
3518 if(prev_event)
3519 IHTMLEventObj_Release(prev_event);
3522 if(event->event_id != EVENTID_LAST && (event_info[event->event_id].flags & EVENT_HASDEFAULTHANDLERS)) {
3523 BOOL prevent_default = event->prevent_default;
3524 for(i = 0; !prevent_default && i < chain_cnt; i++) {
3525 vtbl = dispex_get_vtbl(&target_chain[i]->dispex);
3526 if(!vtbl || !vtbl->handle_event_default)
3527 continue;
3528 hres = vtbl->handle_event_default(&event_target->dispex, event->event_id,
3529 event->nsevent, &prevent_default);
3530 if(FAILED(hres) || event->stop_propagation)
3531 break;
3532 if(prevent_default)
3533 nsIDOMEvent_PreventDefault(event->nsevent);
3537 event->prevent_default = FALSE;
3538 if(event_obj_ref) {
3539 event->event_obj = NULL;
3540 IHTMLEventObj_Release(&event_obj_ref->IHTMLEventObj_iface);
3543 for(i = 0; i < chain_cnt; i++)
3544 IEventTarget_Release(&target_chain[i]->IEventTarget_iface);
3545 if(target_chain != target_chain_buf)
3546 heap_free(target_chain);
3548 return S_OK;
3551 void dispatch_event(EventTarget *event_target, DOMEvent *event)
3553 dispatch_event_object(event_target, event, DISPATCH_BOTH, NULL);
3556 * We may have registered multiple Gecko listeners for the same event type,
3557 * but we already dispatched event to all relevant targets. Stop event
3558 * propagation here to avoid events being dispatched multiple times.
3560 if(event->event_id != EVENTID_LAST && (event_info[event->event_id].flags & EVENT_BIND_TO_TARGET))
3561 nsIDOMEvent_StopPropagation(event->nsevent);
3564 HRESULT fire_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_var, VARIANT_BOOL *cancelled)
3566 HTMLEventObj *event_obj = NULL;
3567 eventid_t eid;
3568 HRESULT hres = S_OK;
3570 eid = attr_to_eid(event_name);
3571 if(eid == EVENTID_LAST) {
3572 WARN("unknown event %s\n", debugstr_w(event_name));
3573 return E_INVALIDARG;
3576 if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
3577 if(V_VT(event_var) != VT_DISPATCH) {
3578 FIXME("event_var %s not supported\n", debugstr_variant(event_var));
3579 return E_NOTIMPL;
3582 if(V_DISPATCH(event_var)) {
3583 IHTMLEventObj *event_iface;
3585 hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
3586 if(FAILED(hres)) {
3587 FIXME("No IHTMLEventObj iface\n");
3588 return hres;
3591 event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
3592 if(!event_obj) {
3593 ERR("Not our IHTMLEventObj?\n");
3594 IHTMLEventObj_Release(event_iface);
3595 return E_FAIL;
3600 if(!event_obj) {
3601 event_obj = alloc_event_obj(NULL, dispex_compat_mode(&node->event_target.dispex));
3602 if(!event_obj)
3603 return E_OUTOFMEMORY;
3606 if(!event_obj->event)
3607 hres = create_document_event(node->doc, eid, &event_obj->event);
3609 if(SUCCEEDED(hres)) {
3610 event_obj->event->event_obj = &event_obj->IHTMLEventObj_iface;
3611 dispatch_event_object(&node->event_target, event_obj->event, DISPATCH_LEGACY, NULL);
3612 event_obj->event->event_obj = NULL;
3615 IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
3616 if(FAILED(hres))
3617 return hres;
3619 *cancelled = VARIANT_TRUE; /* FIXME */
3620 return S_OK;
3623 HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, nsIDOMNode *nsnode, eventid_t eid)
3625 TRACE("%s\n", debugstr_w(event_info[eid].name));
3627 if(!doc->nsdoc)
3628 return S_OK;
3630 switch(eid) {
3631 case EVENTID_FOCUSIN:
3632 doc->event_vector[eid] = TRUE;
3633 eid = EVENTID_FOCUS;
3634 break;
3635 case EVENTID_FOCUSOUT:
3636 doc->event_vector[eid] = TRUE;
3637 eid = EVENTID_BLUR;
3638 break;
3639 case EVENTID_LAST:
3640 return S_OK;
3641 default:
3642 break;
3645 if(event_info[eid].flags & EVENT_DEFAULTLISTENER) {
3646 nsnode = NULL;
3647 }else if(event_info[eid].flags & EVENT_BIND_TO_TARGET) {
3648 if(!nsnode)
3649 nsnode = doc->node.nsnode;
3650 }else {
3651 return S_OK;
3654 if(!nsnode || nsnode == doc->node.nsnode) {
3655 if(doc->event_vector[eid])
3656 return S_OK;
3657 doc->event_vector[eid] = TRUE;
3660 add_nsevent_listener(doc, nsnode, event_info[eid].name);
3661 return S_OK;
3664 void detach_events(HTMLDocumentNode *doc)
3666 if(doc->event_vector) {
3667 int i;
3669 for(i=0; i < EVENTID_LAST; i++) {
3670 if(doc->event_vector[i]) {
3671 detach_nsevent(doc, event_info[i].name);
3672 doc->event_vector[i] = FALSE;
3677 release_nsevents(doc);
3680 static HRESULT get_event_dispex_ref(EventTarget *event_target, eventid_t eid, BOOL alloc, VARIANT **ret)
3682 WCHAR buf[64];
3683 buf[0] = 'o';
3684 buf[1] = 'n';
3685 lstrcpyW(buf+2, event_info[eid].name);
3686 return dispex_get_dprop_ref(&event_target->dispex, buf, alloc, ret);
3689 static event_listener_t *get_onevent_listener(EventTarget *event_target, eventid_t eid, BOOL alloc)
3691 listener_container_t *container;
3692 event_listener_t *listener;
3694 container = get_listener_container(event_target, event_info[eid].name, alloc);
3695 if(!container)
3696 return NULL;
3698 LIST_FOR_EACH_ENTRY_REV(listener, &container->listeners, event_listener_t, entry) {
3699 if(listener->type == LISTENER_TYPE_ONEVENT)
3700 return listener;
3703 if(!alloc)
3704 return NULL;
3706 listener = heap_alloc(sizeof(*listener));
3707 if(!listener)
3708 return NULL;
3710 listener->type = LISTENER_TYPE_ONEVENT;
3711 listener->function = NULL;
3712 list_add_tail(&container->listeners, &listener->entry);
3713 return listener;
3716 static void remove_event_handler(EventTarget *event_target, eventid_t eid)
3718 event_listener_t *listener;
3719 VARIANT *store;
3720 HRESULT hres;
3722 hres = get_event_dispex_ref(event_target, eid, FALSE, &store);
3723 if(SUCCEEDED(hres))
3724 VariantClear(store);
3726 listener = get_onevent_listener(event_target, eid, FALSE);
3727 if(listener && listener->function) {
3728 IDispatch_Release(listener->function);
3729 listener->function = NULL;
3733 static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp)
3735 event_listener_t *listener;
3737 if(event_info[eid].flags & EVENT_FIXME)
3738 FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
3740 remove_event_handler(event_target, eid);
3741 if(!disp)
3742 return S_OK;
3744 listener = get_onevent_listener(event_target, eid, TRUE);
3745 if(!listener)
3746 return E_OUTOFMEMORY;
3748 if(listener->function)
3749 IDispatch_Release(listener->function);
3751 IDispatch_AddRef(listener->function = disp);
3752 return S_OK;
3755 HRESULT set_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
3757 switch(V_VT(var)) {
3758 case VT_EMPTY:
3759 if(use_event_quirks(event_target)) {
3760 WARN("attempt to set to VT_EMPTY in quirks mode\n");
3761 return E_NOTIMPL;
3763 /* fall through */
3764 case VT_NULL:
3765 remove_event_handler(event_target, eid);
3766 return S_OK;
3768 case VT_DISPATCH:
3769 return set_event_handler_disp(event_target, eid, V_DISPATCH(var));
3771 case VT_BSTR: {
3772 VARIANT *v;
3773 HRESULT hres;
3775 if(!use_event_quirks(event_target))
3776 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var)));
3779 * Setting event handler to string is a rare case and we don't want to
3780 * complicate nor increase memory of listener_container_t for that. Instead,
3781 * we store the value in DispatchEx, which can already handle custom
3782 * properties.
3784 remove_event_handler(event_target, eid);
3786 hres = get_event_dispex_ref(event_target, eid, TRUE, &v);
3787 if(FAILED(hres))
3788 return hres;
3790 V_BSTR(v) = SysAllocString(V_BSTR(var));
3791 if(!V_BSTR(v))
3792 return E_OUTOFMEMORY;
3793 V_VT(v) = VT_BSTR;
3794 return S_OK;
3797 default:
3798 FIXME("not handler %s\n", debugstr_variant(var));
3799 return E_NOTIMPL;
3802 return S_OK;
3805 HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
3807 event_listener_t *listener;
3808 VARIANT *v;
3809 HRESULT hres;
3811 hres = get_event_dispex_ref(event_target, eid, FALSE, &v);
3812 if(SUCCEEDED(hres) && V_VT(v) != VT_EMPTY) {
3813 V_VT(var) = VT_EMPTY;
3814 return VariantCopy(var, v);
3817 listener = get_onevent_listener(event_target, eid, FALSE);
3818 if(listener && listener->function) {
3819 V_VT(var) = VT_DISPATCH;
3820 V_DISPATCH(var) = listener->function;
3821 IDispatch_AddRef(V_DISPATCH(var));
3822 }else {
3823 V_VT(var) = VT_NULL;
3826 return S_OK;
3829 HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
3831 listener_container_t *container;
3832 event_listener_t *listener;
3833 eventid_t eid;
3835 eid = attr_to_eid(name);
3836 if(eid == EVENTID_LAST) {
3837 WARN("Unknown event\n");
3838 *res = VARIANT_TRUE;
3839 return S_OK;
3842 container = get_listener_container(event_target, event_info[eid].name, TRUE);
3843 if(!container)
3844 return E_OUTOFMEMORY;
3846 listener = heap_alloc(sizeof(*listener));
3847 if(!listener)
3848 return E_OUTOFMEMORY;
3850 listener->type = LISTENER_TYPE_ATTACHED;
3851 IDispatch_AddRef(listener->function = disp);
3852 if(use_event_quirks(event_target))
3853 list_add_head(&container->listeners, &listener->entry);
3854 else
3855 list_add_tail(&container->listeners, &listener->entry);
3857 *res = VARIANT_TRUE;
3858 return S_OK;
3861 HRESULT detach_event(EventTarget *event_target, BSTR name, IDispatch *disp)
3863 eventid_t eid;
3865 eid = attr_to_eid(name);
3866 if(eid == EVENTID_LAST) {
3867 WARN("Unknown event\n");
3868 return S_OK;
3871 remove_event_listener(event_target, event_info[eid].name, LISTENER_TYPE_ATTACHED, disp);
3872 return S_OK;
3875 void bind_target_event(HTMLDocumentNode *doc, EventTarget *event_target, const WCHAR *event, IDispatch *disp)
3877 eventid_t eid;
3879 TRACE("(%p %p %s %p)\n", doc, event_target, debugstr_w(event), disp);
3881 eid = attr_to_eid(event);
3882 if(eid == EVENTID_LAST) {
3883 WARN("Unsupported event %s\n", debugstr_w(event));
3884 return;
3887 set_event_handler_disp(event_target, eid, disp);
3890 void update_doc_cp_events(HTMLDocumentNode *doc, cp_static_data_t *cp)
3892 int i;
3894 for(i=0; i < EVENTID_LAST; i++) {
3895 if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid))
3896 ensure_doc_nsevent_handler(doc, NULL, i);
3900 void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem)
3902 nsIDOMMozNamedAttrMap *attr_map;
3903 const PRUnichar *name, *value;
3904 nsAString name_str, value_str;
3905 HTMLDOMNode *node = NULL;
3906 cpp_bool has_attrs;
3907 nsIDOMAttr *attr;
3908 IDispatch *disp;
3909 UINT32 length, i;
3910 eventid_t eid;
3911 nsresult nsres;
3912 HRESULT hres;
3914 nsres = nsIDOMElement_HasAttributes(nselem, &has_attrs);
3915 if(NS_FAILED(nsres) || !has_attrs)
3916 return;
3918 nsres = nsIDOMElement_GetAttributes(nselem, &attr_map);
3919 if(NS_FAILED(nsres))
3920 return;
3922 nsres = nsIDOMMozNamedAttrMap_GetLength(attr_map, &length);
3923 assert(nsres == NS_OK);
3925 nsAString_Init(&name_str, NULL);
3926 nsAString_Init(&value_str, NULL);
3928 for(i = 0; i < length; i++) {
3929 nsres = nsIDOMMozNamedAttrMap_Item(attr_map, i, &attr);
3930 if(NS_FAILED(nsres))
3931 continue;
3933 nsres = nsIDOMAttr_GetName(attr, &name_str);
3934 if(NS_FAILED(nsres)) {
3935 nsIDOMAttr_Release(attr);
3936 continue;
3939 nsAString_GetData(&name_str, &name);
3940 eid = attr_to_eid(name);
3941 if(eid == EVENTID_LAST) {
3942 nsIDOMAttr_Release(attr);
3943 continue;
3946 nsres = nsIDOMAttr_GetValue(attr, &value_str);
3947 nsIDOMAttr_Release(attr);
3948 if(NS_FAILED(nsres))
3949 continue;
3951 nsAString_GetData(&value_str, &value);
3952 if(!*value)
3953 continue;
3955 TRACE("%p.%s = %s\n", nselem, debugstr_w(name), debugstr_w(value));
3957 disp = script_parse_event(doc->window, value);
3958 if(!disp)
3959 continue;
3961 if(!node) {
3962 hres = get_node((nsIDOMNode*)nselem, TRUE, &node);
3963 if(FAILED(hres)) {
3964 IDispatch_Release(disp);
3965 break;
3969 set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp);
3970 IDispatch_Release(disp);
3973 if(node)
3974 node_release(node);
3975 nsAString_Finish(&name_str);
3976 nsAString_Finish(&value_str);
3977 nsIDOMMozNamedAttrMap_Release(attr_map);
3980 HRESULT doc_init_events(HTMLDocumentNode *doc)
3982 unsigned i;
3983 HRESULT hres;
3985 doc->event_vector = heap_alloc_zero(EVENTID_LAST*sizeof(BOOL));
3986 if(!doc->event_vector)
3987 return E_OUTOFMEMORY;
3989 init_nsevents(doc);
3991 for(i=0; i < EVENTID_LAST; i++) {
3992 if(event_info[i].flags & EVENT_HASDEFAULTHANDLERS) {
3993 hres = ensure_doc_nsevent_handler(doc, NULL, i);
3994 if(FAILED(hres))
3995 return hres;
3999 return S_OK;
4002 static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
4004 return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
4007 static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
4009 EventTarget *This = impl_from_IEventTarget(iface);
4010 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
4013 static ULONG WINAPI EventTarget_AddRef(IEventTarget *iface)
4015 EventTarget *This = impl_from_IEventTarget(iface);
4016 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
4019 static ULONG WINAPI EventTarget_Release(IEventTarget *iface)
4021 EventTarget *This = impl_from_IEventTarget(iface);
4022 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
4025 static HRESULT WINAPI EventTarget_GetTypeInfoCount(IEventTarget *iface, UINT *pctinfo)
4027 EventTarget *This = impl_from_IEventTarget(iface);
4028 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
4031 static HRESULT WINAPI EventTarget_GetTypeInfo(IEventTarget *iface, UINT iTInfo,
4032 LCID lcid, ITypeInfo **ppTInfo)
4034 EventTarget *This = impl_from_IEventTarget(iface);
4035 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
4038 static HRESULT WINAPI EventTarget_GetIDsOfNames(IEventTarget *iface, REFIID riid, LPOLESTR *rgszNames,
4039 UINT cNames, LCID lcid, DISPID *rgDispId)
4041 EventTarget *This = impl_from_IEventTarget(iface);
4042 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid,
4043 rgszNames, cNames, lcid, rgDispId);
4046 static HRESULT WINAPI EventTarget_Invoke(IEventTarget *iface, DISPID dispIdMember,
4047 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
4048 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
4050 EventTarget *This = impl_from_IEventTarget(iface);
4051 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember,
4052 riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4055 static HRESULT WINAPI EventTarget_addEventListener(IEventTarget *iface, BSTR type,
4056 IDispatch *function, VARIANT_BOOL capture)
4058 EventTarget *This = impl_from_IEventTarget(iface);
4059 listener_type_t listener_type = capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE;
4060 listener_container_t *container;
4061 event_listener_t *listener;
4063 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), function, capture);
4065 container = get_listener_container(This, type, TRUE);
4066 if(!container)
4067 return E_OUTOFMEMORY;
4069 /* check for duplicates */
4070 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
4071 if(listener->type == listener_type && listener->function == function)
4072 return S_OK;
4075 listener = heap_alloc(sizeof(*listener));
4076 if(!listener)
4077 return E_OUTOFMEMORY;
4079 listener->type = listener_type;
4080 IDispatch_AddRef(listener->function = function);
4081 list_add_tail(&container->listeners, &listener->entry);
4082 return S_OK;
4085 static HRESULT WINAPI EventTarget_removeEventListener(IEventTarget *iface, BSTR type,
4086 IDispatch *listener, VARIANT_BOOL capture)
4088 EventTarget *This = impl_from_IEventTarget(iface);
4090 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
4092 remove_event_listener(This, type, capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE, listener);
4093 return S_OK;
4096 static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event_iface, VARIANT_BOOL *result)
4098 EventTarget *This = impl_from_IEventTarget(iface);
4099 DOMEvent *event = unsafe_impl_from_IDOMEvent(event_iface);
4101 TRACE("(%p)->(%p %p)\n", This, event, result);
4103 if(!event) {
4104 WARN("Invalid event\n");
4105 return E_INVALIDARG;
4108 return dispatch_event_object(This, event, DISPATCH_STANDARD, result);
4111 static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, WORD flags,
4112 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4114 /* If only two arguments were given, implicitly set capture to false */
4115 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4116 VARIANT args[3];
4117 DISPPARAMS new_dp = {args, NULL, 3, 0};
4118 V_VT(args) = VT_BOOL;
4119 V_BOOL(args) = VARIANT_FALSE;
4120 args[1] = dp->rgvarg[0];
4121 args[2] = dp->rgvarg[1];
4123 TRACE("implicit capture\n");
4125 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_ADDEVENTLISTENER, &new_dp, res, ei, caller);
4128 return S_FALSE; /* fallback to default */
4131 static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, WORD flags,
4132 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4134 /* If only two arguments were given, implicitly set capture to false */
4135 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4136 VARIANT args[3];
4137 DISPPARAMS new_dp = {args, NULL, 3, 0};
4138 V_VT(args) = VT_BOOL;
4139 V_BOOL(args) = VARIANT_FALSE;
4140 args[1] = dp->rgvarg[0];
4141 args[2] = dp->rgvarg[1];
4143 TRACE("implicit capture\n");
4145 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, &new_dp, res, ei, caller);
4148 return S_FALSE; /* fallback to default */
4151 static const IEventTargetVtbl EventTargetVtbl = {
4152 EventTarget_QueryInterface,
4153 EventTarget_AddRef,
4154 EventTarget_Release,
4155 EventTarget_GetTypeInfoCount,
4156 EventTarget_GetTypeInfo,
4157 EventTarget_GetIDsOfNames,
4158 EventTarget_Invoke,
4159 EventTarget_addEventListener,
4160 EventTarget_removeEventListener,
4161 EventTarget_dispatchEvent
4164 static EventTarget *unsafe_impl_from_IEventTarget(IEventTarget *iface)
4166 return iface && iface->lpVtbl == &EventTargetVtbl ? impl_from_IEventTarget(iface) : NULL;
4169 static HRESULT get_gecko_target(IEventTarget *target, nsIDOMEventTarget **ret)
4171 EventTarget *event_target = unsafe_impl_from_IEventTarget(target);
4172 const event_target_vtbl_t *vtbl;
4173 nsresult nsres;
4175 if(!event_target) {
4176 WARN("Not our IEventTarget implementation\n");
4177 return E_INVALIDARG;
4180 vtbl = (const event_target_vtbl_t*)dispex_get_vtbl(&event_target->dispex);
4181 nsres = nsISupports_QueryInterface(vtbl->get_gecko_target(&event_target->dispex),
4182 &IID_nsIDOMEventTarget, (void**)ret);
4183 assert(nsres == NS_OK);
4184 return S_OK;
4187 HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
4189 if(IsEqualGUID(riid, &IID_IEventTarget)) {
4190 if(use_event_quirks(event_target)) {
4191 WARN("IEventTarget queried, but not supported by in document mode\n");
4192 *ppv = NULL;
4193 return E_NOINTERFACE;
4195 IEventTarget_AddRef(&event_target->IEventTarget_iface);
4196 *ppv = &event_target->IEventTarget_iface;
4197 return S_OK;
4200 if(dispex_query_interface(&event_target->dispex, riid, ppv))
4201 return *ppv ? S_OK : E_NOINTERFACE;
4203 WARN("(%p)->(%s %p)\n", event_target, debugstr_mshtml_guid(riid), ppv);
4204 *ppv = NULL;
4205 return E_NOINTERFACE;
4208 void EventTarget_init_dispex_info(dispex_data_t *dispex_info, compat_mode_t compat_mode)
4210 static const dispex_hook_t IEventTarget_hooks[] = {
4211 {DISPID_IEVENTTARGET_ADDEVENTLISTENER, IEventTarget_addEventListener_hook},
4212 {DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, IEventTarget_removeEventListener_hook},
4213 {DISPID_UNKNOWN}
4216 if(compat_mode >= COMPAT_MODE_IE9)
4217 dispex_info_add_interface(dispex_info, IEventTarget_tid, IEventTarget_hooks);
4220 static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
4222 return wcscmp(key, WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry)->type);
4225 void EventTarget_Init(EventTarget *event_target, IUnknown *outer, dispex_static_data_t *dispex_data,
4226 compat_mode_t compat_mode)
4228 init_dispatch(&event_target->dispex, outer, dispex_data, compat_mode);
4229 event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
4230 wine_rb_init(&event_target->handler_map, event_id_cmp);
4233 void release_event_target(EventTarget *event_target)
4235 listener_container_t *iter, *iter2;
4237 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, listener_container_t, entry) {
4238 while(!list_empty(&iter->listeners)) {
4239 event_listener_t *listener = LIST_ENTRY(list_head(&iter->listeners), event_listener_t, entry);
4240 if(listener->function)
4241 IDispatch_Release(listener->function);
4242 list_remove(&listener->entry);
4243 heap_free(listener);
4245 heap_free(iter);