imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / mshtml / htmlevent.c
blob87039167281b72da37aef2b73ef847de42c1e97b
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 /* Keep inherited event types after the inheritor (e.g. DragEvent->MouseEvent->UIEvent) */
63 typedef enum {
64 EVENT_TYPE_EVENT,
65 EVENT_TYPE_CUSTOM,
66 EVENT_TYPE_DRAG,
67 EVENT_TYPE_KEYBOARD,
68 EVENT_TYPE_MOUSE,
69 EVENT_TYPE_FOCUS,
70 EVENT_TYPE_UIEVENT,
71 EVENT_TYPE_PAGETRANSITION,
72 EVENT_TYPE_MESSAGE,
73 EVENT_TYPE_PROGRESS,
74 EVENT_TYPE_STORAGE,
75 EVENT_TYPE_CLIPBOARD
76 } event_type_t;
78 static const WCHAR *event_types[] = {
79 L"Event",
80 L"CustomEvent",
81 L"Event", /* FIXME */
82 L"KeyboardEvent",
83 L"MouseEvent",
84 L"Event", /* FIXME */
85 L"UIEvent",
86 L"PageTransitionEvent",
87 L"MessageEvent",
88 L"ProgressEvent",
89 L"StorageEvent",
90 L"Event" /* FIXME */
93 typedef struct {
94 const WCHAR *name;
95 event_type_t type;
96 DISPID dispid;
97 DWORD flags;
98 } event_info_t;
100 /* Use Gecko default listener (it's registered on window object for DOM nodes). */
101 #define EVENT_DEFAULTLISTENER 0x0001
102 /* Register Gecko listener on target itself (unlike EVENT_DEFAULTLISTENER). */
103 #define EVENT_BIND_TO_TARGET 0x0002
104 /* Event bubbles by default (unless explicitly specified otherwise). */
105 #define EVENT_BUBBLES 0x0004
106 /* Event is cancelable by default (unless explicitly specified otherwise). */
107 #define EVENT_CANCELABLE 0x0008
108 /* Event may have default handler (so we always have to register Gecko listener). */
109 #define EVENT_HASDEFAULTHANDLERS 0x0020
110 /* Ecent is not supported properly, print FIXME message when it's used. */
111 #define EVENT_FIXME 0x0040
113 /* mouse event flags for fromElement and toElement implementation */
114 #define EVENT_MOUSE_TO_RELATED 0x0100
115 #define EVENT_MOUSE_FROM_RELATED 0x0200
117 /* Keep these sorted case sensitively */
118 static const event_info_t event_info[] = {
119 {L"DOMContentLoaded", EVENT_TYPE_EVENT, 0,
120 EVENT_BUBBLES | EVENT_CANCELABLE},
121 {L"abort", EVENT_TYPE_EVENT, DISPID_EVMETH_ONABORT,
122 EVENT_BIND_TO_TARGET},
123 {L"afterprint", EVENT_TYPE_EVENT, DISPID_EVMETH_ONAFTERPRINT,
124 EVENT_DEFAULTLISTENER},
125 {L"animationend", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONEND,
126 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
127 {L"animationstart", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONSTART,
128 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
129 {L"beforeactivate", EVENT_TYPE_EVENT, DISPID_EVMETH_ONBEFOREACTIVATE,
130 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
131 {L"beforeprint", EVENT_TYPE_EVENT, DISPID_EVMETH_ONBEFOREPRINT,
132 EVENT_DEFAULTLISTENER},
133 {L"beforeunload", EVENT_TYPE_EVENT, DISPID_EVMETH_ONBEFOREUNLOAD,
134 EVENT_DEFAULTLISTENER | EVENT_CANCELABLE },
135 {L"blur", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONBLUR,
136 EVENT_DEFAULTLISTENER},
137 {L"change", EVENT_TYPE_EVENT, DISPID_EVMETH_ONCHANGE,
138 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
139 {L"click", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONCLICK,
140 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE },
141 {L"contextmenu", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONCONTEXTMENU,
142 EVENT_BUBBLES | EVENT_CANCELABLE},
143 {L"dataavailable", EVENT_TYPE_EVENT, DISPID_EVMETH_ONDATAAVAILABLE,
144 EVENT_FIXME | EVENT_BUBBLES},
145 {L"dblclick", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONDBLCLICK,
146 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
147 {L"drag", EVENT_TYPE_DRAG, DISPID_EVMETH_ONDRAG,
148 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
149 {L"dragstart", EVENT_TYPE_DRAG, DISPID_EVMETH_ONDRAGSTART,
150 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
151 {L"error", EVENT_TYPE_EVENT, DISPID_EVMETH_ONERROR,
152 EVENT_BIND_TO_TARGET},
153 {L"focus", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUS,
154 EVENT_DEFAULTLISTENER},
155 {L"focusin", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSIN,
156 EVENT_BUBBLES},
157 {L"focusout", EVENT_TYPE_FOCUS, DISPID_EVMETH_ONFOCUSOUT,
158 EVENT_BUBBLES},
159 {L"help", EVENT_TYPE_EVENT, DISPID_EVMETH_ONHELP,
160 EVENT_BUBBLES | EVENT_CANCELABLE},
161 {L"input", EVENT_TYPE_EVENT, DISPID_UNKNOWN,
162 EVENT_DEFAULTLISTENER | EVENT_BUBBLES},
163 {L"keydown", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYDOWN,
164 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE },
165 {L"keypress", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYPRESS,
166 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
167 {L"keyup", EVENT_TYPE_KEYBOARD, DISPID_EVMETH_ONKEYUP,
168 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
169 {L"load", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONLOAD,
170 EVENT_BIND_TO_TARGET},
171 {L"loadend", EVENT_TYPE_PROGRESS, DISPID_EVPROP_LOADEND,
172 EVENT_BIND_TO_TARGET},
173 {L"loadstart", EVENT_TYPE_PROGRESS, DISPID_EVPROP_LOADSTART,
174 EVENT_BIND_TO_TARGET},
175 {L"message", EVENT_TYPE_MESSAGE, DISPID_EVMETH_ONMESSAGE,
177 {L"mousedown", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEDOWN,
178 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
179 {L"mousemove", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEMOVE,
180 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_FROM_RELATED},
181 {L"mouseout", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEOUT,
182 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_TO_RELATED},
183 {L"mouseover", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEOVER,
184 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE | EVENT_MOUSE_FROM_RELATED},
185 {L"mouseup", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEUP,
186 EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE},
187 {L"mousewheel", EVENT_TYPE_MOUSE, DISPID_EVMETH_ONMOUSEWHEEL,
188 EVENT_FIXME},
189 {L"msthumbnailclick", EVENT_TYPE_MOUSE, DISPID_EVPROP_ONMSTHUMBNAILCLICK,
190 EVENT_FIXME},
191 {L"pagehide", EVENT_TYPE_PAGETRANSITION, DISPID_EVPROP_ONPAGEHIDE,
193 {L"pageshow", EVENT_TYPE_PAGETRANSITION, DISPID_EVPROP_ONPAGESHOW,
195 {L"paste", EVENT_TYPE_CLIPBOARD, DISPID_EVMETH_ONPASTE,
196 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
197 {L"progress", EVENT_TYPE_PROGRESS, DISPID_EVPROP_PROGRESS,
198 EVENT_BIND_TO_TARGET},
199 {L"readystatechange", EVENT_TYPE_EVENT, DISPID_EVMETH_ONREADYSTATECHANGE,
201 {L"resize", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONRESIZE,
202 EVENT_DEFAULTLISTENER},
203 {L"scroll", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONSCROLL,
204 EVENT_DEFAULTLISTENER | EVENT_BUBBLES /* FIXME: not for elements */},
205 {L"selectionchange", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSELECTIONCHANGE,
206 EVENT_FIXME},
207 {L"selectstart", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSELECTSTART,
208 EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
209 {L"storage", EVENT_TYPE_STORAGE, DISPID_EVMETH_ONSTORAGE,
211 {L"storagecommit", EVENT_TYPE_STORAGE, DISPID_EVMETH_ONSTORAGECOMMIT,
213 {L"submit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSUBMIT,
214 EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE},
215 {L"timeout", EVENT_TYPE_PROGRESS, DISPID_EVPROP_TIMEOUT,
216 EVENT_BIND_TO_TARGET},
217 {L"unload", EVENT_TYPE_UIEVENT, DISPID_EVMETH_ONUNLOAD,
218 EVENT_BIND_TO_TARGET},
219 {L"visibilitychange", EVENT_TYPE_EVENT, DISPID_EVPROP_VISIBILITYCHANGE,
220 EVENT_FIXME | EVENT_BUBBLES},
222 /* EVENTID_LAST special entry */
223 {NULL, EVENT_TYPE_EVENT, 0, 0}
226 C_ASSERT(ARRAY_SIZE(event_info) - 1 == EVENTID_LAST);
228 static eventid_t str_to_eid(const WCHAR *str)
230 unsigned i, a = 0, b = ARRAY_SIZE(event_info) - 1;
231 int c;
233 while(a < b) {
234 i = (a + b) / 2;
235 if(!(c = wcscmp(event_info[i].name, str)))
236 return i;
237 if(c > 0) b = i;
238 else a = i + 1;
241 return EVENTID_LAST;
244 static eventid_t attr_to_eid(const WCHAR *str)
246 unsigned i, a = 0, b = ARRAY_SIZE(event_info) - 1;
247 int c;
249 if((str[0] != 'o' && str[0] != 'O') || (str[1] != 'n' && str[1] != 'N'))
250 return EVENTID_LAST;
252 while(a < b) {
253 i = (a + b) / 2;
254 if(!(c = wcscmp(event_info[i].name, str+2)))
255 return event_info[i].dispid ? i : EVENTID_LAST;
256 if(c > 0) b = i;
257 else a = i + 1;
260 return EVENTID_LAST;
263 const WCHAR *get_event_name(eventid_t eid)
265 return event_info[eid].name;
268 static listener_container_t *get_listener_container(EventTarget *event_target, const WCHAR *type, BOOL alloc)
270 const event_target_vtbl_t *vtbl;
271 listener_container_t *container;
272 struct wine_rb_entry *entry;
273 size_t type_len;
274 eventid_t eid;
276 entry = wine_rb_get(&event_target->handler_map, type);
277 if(entry)
278 return WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry);
279 if(!alloc)
280 return NULL;
282 eid = str_to_eid(type);
283 if(event_info[eid].flags & EVENT_FIXME)
284 FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
286 type_len = lstrlenW(type);
287 container = malloc(FIELD_OFFSET(listener_container_t, type[type_len+1]));
288 if(!container)
289 return NULL;
290 memcpy(container->type, type, (type_len + 1) * sizeof(WCHAR));
291 list_init(&container->listeners);
292 vtbl = dispex_get_vtbl(&event_target->dispex);
293 if (!vtbl->bind_event)
294 FIXME("Unsupported event binding on target %p\n", event_target);
295 else if(eid != EVENTID_LAST)
296 vtbl->bind_event(&event_target->dispex, eid);
298 wine_rb_put(&event_target->handler_map, container->type, &container->entry);
299 return container;
302 static void remove_event_listener(EventTarget *event_target, const WCHAR *type_name, listener_type_t type, IDispatch *function)
304 listener_container_t *container;
305 event_listener_t *listener;
307 container = get_listener_container(event_target, type_name, FALSE);
308 if(!container)
309 return;
311 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
312 if(listener->function == function && listener->type == type) {
313 IDispatch_Release(listener->function);
314 list_remove(&listener->entry);
315 free(listener);
316 break;
321 static IEventTarget *get_event_target_iface(EventTarget *event_target)
323 const event_target_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
324 IEventTarget *ret;
326 if(vtbl->get_dispatch_this) {
327 IDispatch *disp = vtbl->get_dispatch_this(&event_target->dispex);
328 IDispatch_QueryInterface(disp, &IID_IEventTarget, (void**)&ret);
329 }else {
330 ret = &event_target->IEventTarget_iface;
331 IEventTarget_AddRef(ret);
333 return ret;
336 static HRESULT get_gecko_target(IEventTarget*,nsIDOMEventTarget**);
338 typedef struct {
339 DOMEvent event;
340 IDOMUIEvent IDOMUIEvent_iface;
341 nsIDOMUIEvent *nsevent;
342 } DOMUIEvent;
344 static DOMUIEvent *DOMUIEvent_from_DOMEvent(DOMEvent *event)
346 return CONTAINING_RECORD(event, DOMUIEvent, event);
349 typedef struct {
350 DispatchEx dispex;
351 IHTMLEventObj IHTMLEventObj_iface;
353 DOMEvent *event;
354 VARIANT return_value;
355 } HTMLEventObj;
357 static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
359 return CONTAINING_RECORD(iface, HTMLEventObj, IHTMLEventObj_iface);
362 static HRESULT WINAPI HTMLEventObj_QueryInterface(IHTMLEventObj *iface, REFIID riid, void **ppv)
364 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
365 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
368 static ULONG WINAPI HTMLEventObj_AddRef(IHTMLEventObj *iface)
370 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
371 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
374 static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface)
376 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
377 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
380 static HRESULT WINAPI HTMLEventObj_GetTypeInfoCount(IHTMLEventObj *iface, UINT *pctinfo)
382 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
383 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
386 static HRESULT WINAPI HTMLEventObj_GetTypeInfo(IHTMLEventObj *iface, UINT iTInfo,
387 LCID lcid, ITypeInfo **ppTInfo)
389 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
390 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
393 static HRESULT WINAPI HTMLEventObj_GetIDsOfNames(IHTMLEventObj *iface, REFIID riid,
394 LPOLESTR *rgszNames, UINT cNames,
395 LCID lcid, DISPID *rgDispId)
397 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
398 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
399 lcid, rgDispId);
402 static HRESULT WINAPI HTMLEventObj_Invoke(IHTMLEventObj *iface, DISPID dispIdMember,
403 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
404 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
406 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
407 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
408 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
411 static HRESULT WINAPI HTMLEventObj_get_srcElement(IHTMLEventObj *iface, IHTMLElement **p)
413 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
415 TRACE("(%p)->(%p)\n", This, p);
417 if(!This->event) {
418 *p = NULL;
419 return S_OK;
422 return IDOMEvent_get_srcElement(&This->event->IDOMEvent_iface, p);
425 static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
427 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
428 IDOMKeyboardEvent *keyboard_event;
429 IDOMMouseEvent *mouse_event;
430 cpp_bool ret = FALSE;
432 TRACE("(%p)->(%p)\n", This, p);
434 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
435 HRESULT hres = IDOMMouseEvent_get_altKey(mouse_event, p);
436 IDOMMouseEvent_Release(mouse_event);
437 return hres;
440 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
441 HRESULT hres = IDOMKeyboardEvent_get_altKey(keyboard_event, p);
442 IDOMKeyboardEvent_Release(keyboard_event);
443 return hres;
446 *p = variant_bool(ret);
447 return S_OK;
450 static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
452 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
453 IDOMKeyboardEvent *keyboard_event;
454 IDOMMouseEvent *mouse_event;
455 cpp_bool ret = FALSE;
457 TRACE("(%p)->(%p)\n", This, p);
459 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
460 HRESULT hres = IDOMMouseEvent_get_ctrlKey(mouse_event, p);
461 IDOMMouseEvent_Release(mouse_event);
462 return hres;
465 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
466 HRESULT hres = IDOMKeyboardEvent_get_ctrlKey(keyboard_event, p);
467 IDOMKeyboardEvent_Release(keyboard_event);
468 return hres;
471 *p = variant_bool(ret);
472 return S_OK;
475 static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
477 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
478 IDOMKeyboardEvent *keyboard_event;
479 IDOMMouseEvent *mouse_event;
480 cpp_bool ret = FALSE;
482 TRACE("(%p)->(%p)\n", This, p);
484 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
485 HRESULT hres = IDOMMouseEvent_get_shiftKey(mouse_event, p);
486 IDOMMouseEvent_Release(mouse_event);
487 return hres;
490 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
491 HRESULT hres = IDOMKeyboardEvent_get_shiftKey(keyboard_event, p);
492 IDOMKeyboardEvent_Release(keyboard_event);
493 return hres;
496 *p = variant_bool(ret);
497 return S_OK;
500 static HRESULT WINAPI HTMLEventObj_put_returnValue(IHTMLEventObj *iface, VARIANT v)
502 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
504 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
506 if(V_VT(&v) != VT_BOOL) {
507 FIXME("unsupported value %s\n", debugstr_variant(&v));
508 return DISP_E_BADVARTYPE;
511 This->return_value = v;
512 if(!V_BOOL(&v) && This->event)
513 IDOMEvent_preventDefault(&This->event->IDOMEvent_iface);
514 return S_OK;
517 static HRESULT WINAPI HTMLEventObj_get_returnValue(IHTMLEventObj *iface, VARIANT *p)
519 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
521 TRACE("(%p)->(%p)\n", This, p);
523 V_VT(p) = VT_EMPTY;
524 return VariantCopy(p, &This->return_value);
527 static HRESULT WINAPI HTMLEventObj_put_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL v)
529 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
531 TRACE("(%p)->(%x)\n", This, v);
533 if(This->event)
534 IDOMEvent_stopPropagation(&This->event->IDOMEvent_iface);
535 return S_OK;
538 static HRESULT WINAPI HTMLEventObj_get_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL *p)
540 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
542 TRACE("(%p)->(%p)\n", This, p);
544 *p = variant_bool(This->event && This->event->stop_propagation);
545 return S_OK;
548 static HRESULT WINAPI HTMLEventObj_get_fromElement(IHTMLEventObj *iface, IHTMLElement **p)
550 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
551 IDOMMouseEvent *mouse_event;
553 TRACE("(%p)->(%p)\n", This, p);
555 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
556 HRESULT hres = IDOMMouseEvent_get_fromElement(mouse_event, p);
557 IDOMMouseEvent_Release(mouse_event);
558 return hres;
561 *p = NULL;
562 return S_OK;
565 static HRESULT WINAPI HTMLEventObj_get_toElement(IHTMLEventObj *iface, IHTMLElement **p)
567 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
568 IDOMMouseEvent *mouse_event;
570 TRACE("(%p)->(%p)\n", This, p);
572 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
573 HRESULT hres = IDOMMouseEvent_get_toElement(mouse_event, p);
574 IDOMMouseEvent_Release(mouse_event);
575 return hres;
578 *p = NULL;
579 return S_OK;
582 static HRESULT WINAPI HTMLEventObj_put_keyCode(IHTMLEventObj *iface, LONG v)
584 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
585 FIXME("(%p)->(%ld)\n", This, v);
586 return E_NOTIMPL;
589 static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, LONG *p)
591 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
592 IDOMKeyboardEvent *keyboard_event;
594 TRACE("(%p)->(%p)\n", This, p);
596 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
597 HRESULT hres = IDOMKeyboardEvent_get_keyCode(keyboard_event, p);
598 IDOMKeyboardEvent_Release(keyboard_event);
599 return hres;
602 *p = 0;
603 return S_OK;
606 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p)
608 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
609 IDOMMouseEvent *mouse_event;
610 USHORT button = 0;
612 TRACE("(%p)->(%p)\n", This, p);
614 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
615 HRESULT hres = IDOMMouseEvent_get_button(mouse_event, &button);
616 IDOMMouseEvent_Release(mouse_event);
617 if(FAILED(hres))
618 return hres;
621 *p = button;
622 return S_OK;
625 static HRESULT WINAPI HTMLEventObj_get_type(IHTMLEventObj *iface, BSTR *p)
627 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
629 TRACE("(%p)->(%p)\n", This, p);
631 if(!This->event) {
632 *p = NULL;
633 return S_OK;
636 return IDOMEvent_get_type(&This->event->IDOMEvent_iface, p);
639 static HRESULT WINAPI HTMLEventObj_get_qualifier(IHTMLEventObj *iface, BSTR *p)
641 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
643 FIXME("(%p)->(%p)\n", This, p);
645 *p = NULL;
646 return S_OK;
649 static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, LONG *p)
651 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
653 FIXME("(%p)->(%p)\n", This, p);
655 *p = 0;
656 return S_OK;
659 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p)
661 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
662 LONG x = 0;
664 TRACE("(%p)->(%p)\n", This, p);
666 if(This->event) {
667 nsIDOMUIEvent *ui_event;
668 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
670 if(NS_SUCCEEDED(nsres)) {
671 /* NOTE: pageX is not exactly right here. */
672 nsres = nsIDOMUIEvent_GetPageX(ui_event, &x);
673 assert(nsres == NS_OK);
674 nsIDOMUIEvent_Release(ui_event);
678 *p = x;
679 return S_OK;
682 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p)
684 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
685 LONG y = 0;
687 TRACE("(%p)->(%p)\n", This, p);
689 if(This->event) {
690 nsIDOMUIEvent *ui_event;
691 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
693 if(NS_SUCCEEDED(nsres)) {
694 /* NOTE: pageY is not exactly right here. */
695 nsres = nsIDOMUIEvent_GetPageY(ui_event, &y);
696 assert(nsres == NS_OK);
697 nsIDOMUIEvent_Release(ui_event);
701 *p = y;
702 return S_OK;
705 static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, LONG *p)
707 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
708 IDOMMouseEvent *mouse_event;
710 TRACE("(%p)->(%p)\n", This, p);
712 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
713 HRESULT hres = IDOMMouseEvent_get_clientX(mouse_event, p);
714 IDOMMouseEvent_Release(mouse_event);
715 return hres;
718 *p = 0;
719 return S_OK;
722 static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, LONG *p)
724 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
725 IDOMMouseEvent *mouse_event;
727 TRACE("(%p)->(%p)\n", This, p);
729 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
730 HRESULT hres = IDOMMouseEvent_get_clientY(mouse_event, p);
731 IDOMMouseEvent_Release(mouse_event);
732 return hres;
735 *p = 0;
736 return S_OK;
739 static HRESULT WINAPI HTMLEventObj_get_offsetX(IHTMLEventObj *iface, LONG *p)
741 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
742 IDOMMouseEvent *mouse_event;
744 TRACE("(%p)->(%p)\n", This, p);
746 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
747 HRESULT hres = IDOMMouseEvent_get_offsetX(mouse_event, p);
748 IDOMMouseEvent_Release(mouse_event);
749 return hres;
752 *p = 0;
753 return S_OK;
756 static HRESULT WINAPI HTMLEventObj_get_offsetY(IHTMLEventObj *iface, LONG *p)
758 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
759 IDOMMouseEvent *mouse_event;
761 TRACE("(%p)->(%p)\n", This, p);
763 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
764 HRESULT hres = IDOMMouseEvent_get_offsetY(mouse_event, p);
765 IDOMMouseEvent_Release(mouse_event);
766 return hres;
769 *p = 0;
770 return S_OK;
773 static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, LONG *p)
775 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
776 IDOMMouseEvent *mouse_event;
778 TRACE("(%p)->(%p)\n", This, p);
780 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
781 HRESULT hres = IDOMMouseEvent_get_screenX(mouse_event, p);
782 IDOMMouseEvent_Release(mouse_event);
783 return hres;
786 *p = 0;
787 return S_OK;
790 static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, LONG *p)
792 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
793 IDOMMouseEvent *mouse_event;
795 TRACE("(%p)->(%p)\n", This, p);
797 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
798 HRESULT hres = IDOMMouseEvent_get_screenY(mouse_event, p);
799 IDOMMouseEvent_Release(mouse_event);
800 return hres;
803 *p = 0;
804 return S_OK;
807 static HRESULT WINAPI HTMLEventObj_get_srcFilter(IHTMLEventObj *iface, IDispatch **p)
809 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
811 FIXME("(%p)->(%p)\n", This, p);
813 *p = NULL;
814 return S_OK;
817 static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
818 HTMLEventObj_QueryInterface,
819 HTMLEventObj_AddRef,
820 HTMLEventObj_Release,
821 HTMLEventObj_GetTypeInfoCount,
822 HTMLEventObj_GetTypeInfo,
823 HTMLEventObj_GetIDsOfNames,
824 HTMLEventObj_Invoke,
825 HTMLEventObj_get_srcElement,
826 HTMLEventObj_get_altKey,
827 HTMLEventObj_get_ctrlKey,
828 HTMLEventObj_get_shiftKey,
829 HTMLEventObj_put_returnValue,
830 HTMLEventObj_get_returnValue,
831 HTMLEventObj_put_cancelBubble,
832 HTMLEventObj_get_cancelBubble,
833 HTMLEventObj_get_fromElement,
834 HTMLEventObj_get_toElement,
835 HTMLEventObj_put_keyCode,
836 HTMLEventObj_get_keyCode,
837 HTMLEventObj_get_button,
838 HTMLEventObj_get_type,
839 HTMLEventObj_get_qualifier,
840 HTMLEventObj_get_reason,
841 HTMLEventObj_get_x,
842 HTMLEventObj_get_y,
843 HTMLEventObj_get_clientX,
844 HTMLEventObj_get_clientY,
845 HTMLEventObj_get_offsetX,
846 HTMLEventObj_get_offsetY,
847 HTMLEventObj_get_screenX,
848 HTMLEventObj_get_screenY,
849 HTMLEventObj_get_srcFilter
852 static inline HTMLEventObj *unsafe_impl_from_IHTMLEventObj(IHTMLEventObj *iface)
854 return iface->lpVtbl == &HTMLEventObjVtbl ? impl_from_IHTMLEventObj(iface) : NULL;
857 static inline HTMLEventObj *HTMLEventObj_from_DispatchEx(DispatchEx *iface)
859 return CONTAINING_RECORD(iface, HTMLEventObj, dispex);
862 static void *HTMLEventObj_query_interface(DispatchEx *dispex, REFIID riid)
864 HTMLEventObj *This = HTMLEventObj_from_DispatchEx(dispex);
866 if(IsEqualGUID(&IID_IHTMLEventObj, riid))
867 return &This->IHTMLEventObj_iface;
869 return NULL;
872 static void HTMLEventObj_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
874 HTMLEventObj *This = HTMLEventObj_from_DispatchEx(dispex);
875 if(This->event)
876 note_cc_edge((nsISupports*)&This->event->IDOMEvent_iface, "event", cb);
879 static void HTMLEventObj_unlink(DispatchEx *dispex)
881 HTMLEventObj *This = HTMLEventObj_from_DispatchEx(dispex);
882 if(This->event) {
883 DOMEvent *event = This->event;
884 This->event = NULL;
885 IDOMEvent_Release(&event->IDOMEvent_iface);
889 static void HTMLEventObj_destructor(DispatchEx *dispex)
891 HTMLEventObj *This = HTMLEventObj_from_DispatchEx(dispex);
892 free(This);
895 static const dispex_static_data_vtbl_t HTMLEventObj_dispex_vtbl = {
896 .query_interface = HTMLEventObj_query_interface,
897 .destructor = HTMLEventObj_destructor,
898 .traverse = HTMLEventObj_traverse,
899 .unlink = HTMLEventObj_unlink
902 static const tid_t HTMLEventObj_iface_tids[] = {
903 IHTMLEventObj_tid,
907 static dispex_static_data_t HTMLEventObj_dispex = {
908 "MSEventObj",
909 &HTMLEventObj_dispex_vtbl,
910 DispCEventObj_tid,
911 HTMLEventObj_iface_tids
914 static HTMLEventObj *alloc_event_obj(DOMEvent *event, compat_mode_t compat_mode)
916 HTMLEventObj *event_obj;
918 event_obj = calloc(1, sizeof(*event_obj));
919 if(!event_obj)
920 return NULL;
922 event_obj->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
923 event_obj->event = event;
924 if(event)
925 IDOMEvent_AddRef(&event->IDOMEvent_iface);
927 init_dispatch(&event_obj->dispex, &HTMLEventObj_dispex, compat_mode);
928 return event_obj;
931 HRESULT create_event_obj(compat_mode_t compat_mode, IHTMLEventObj **ret)
933 HTMLEventObj *event_obj;
935 event_obj = alloc_event_obj(NULL, compat_mode);
936 if(!event_obj)
937 return E_OUTOFMEMORY;
939 *ret = &event_obj->IHTMLEventObj_iface;
940 return S_OK;
943 static inline DOMEvent *impl_from_IDOMEvent(IDOMEvent *iface)
945 return CONTAINING_RECORD(iface, DOMEvent, IDOMEvent_iface);
948 static const IDOMEventVtbl DOMEventVtbl;
950 static inline DOMEvent *unsafe_impl_from_IDOMEvent(IDOMEvent *iface)
952 return iface && iface->lpVtbl == &DOMEventVtbl ? impl_from_IDOMEvent(iface) : NULL;
955 static HRESULT WINAPI DOMEvent_QueryInterface(IDOMEvent *iface, REFIID riid, void **ppv)
957 DOMEvent *This = impl_from_IDOMEvent(iface);
958 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
961 static ULONG WINAPI DOMEvent_AddRef(IDOMEvent *iface)
963 DOMEvent *This = impl_from_IDOMEvent(iface);
964 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
967 static ULONG WINAPI DOMEvent_Release(IDOMEvent *iface)
969 DOMEvent *This = impl_from_IDOMEvent(iface);
970 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
973 static HRESULT WINAPI DOMEvent_GetTypeInfoCount(IDOMEvent *iface, UINT *pctinfo)
975 DOMEvent *This = impl_from_IDOMEvent(iface);
976 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
979 static HRESULT WINAPI DOMEvent_GetTypeInfo(IDOMEvent *iface, UINT iTInfo,
980 LCID lcid, ITypeInfo **ppTInfo)
982 DOMEvent *This = impl_from_IDOMEvent(iface);
983 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
986 static HRESULT WINAPI DOMEvent_GetIDsOfNames(IDOMEvent *iface, REFIID riid,
987 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
989 DOMEvent *This = impl_from_IDOMEvent(iface);
990 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
991 lcid, rgDispId);
994 static HRESULT WINAPI DOMEvent_Invoke(IDOMEvent *iface, DISPID dispIdMember,
995 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
996 EXCEPINFO *pExcepInfo, UINT *puArgErr)
998 DOMEvent *This = impl_from_IDOMEvent(iface);
999 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1000 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1003 static HRESULT WINAPI DOMEvent_get_bubbles(IDOMEvent *iface, VARIANT_BOOL *p)
1005 DOMEvent *This = impl_from_IDOMEvent(iface);
1007 TRACE("(%p)->(%p)\n", This, p);
1009 *p = variant_bool(This->bubbles);
1010 return S_OK;
1013 static HRESULT WINAPI DOMEvent_get_cancelable(IDOMEvent *iface, VARIANT_BOOL *p)
1015 DOMEvent *This = impl_from_IDOMEvent(iface);
1017 TRACE("(%p)->(%p)\n", This, p);
1019 *p = variant_bool(This->cancelable);
1020 return S_OK;
1023 static HRESULT WINAPI DOMEvent_get_currentTarget(IDOMEvent *iface, IEventTarget **p)
1025 DOMEvent *This = impl_from_IDOMEvent(iface);
1027 TRACE("(%p)->(%p)\n", This, p);
1029 if(This->current_target)
1030 *p = get_event_target_iface(This->current_target);
1031 else
1032 *p = NULL;
1033 return S_OK;
1036 static HRESULT WINAPI DOMEvent_get_defaultPrevented(IDOMEvent *iface, VARIANT_BOOL *p)
1038 DOMEvent *This = impl_from_IDOMEvent(iface);
1040 TRACE("(%p)->(%p)\n", This, p);
1042 *p = variant_bool(This->prevent_default);
1043 return S_OK;
1046 static HRESULT WINAPI DOMEvent_get_eventPhase(IDOMEvent *iface, USHORT *p)
1048 DOMEvent *This = impl_from_IDOMEvent(iface);
1050 TRACE("(%p)->(%p)\n", This, p);
1052 *p = This->phase;
1053 return S_OK;
1056 static HRESULT WINAPI DOMEvent_get_target(IDOMEvent *iface, IEventTarget **p)
1058 DOMEvent *This = impl_from_IDOMEvent(iface);
1060 TRACE("(%p)->(%p)\n", This, p);
1062 if(This->target)
1063 *p = get_event_target_iface(This->target);
1064 else
1065 *p = NULL;
1066 return S_OK;
1069 static HRESULT WINAPI DOMEvent_get_timeStamp(IDOMEvent *iface, ULONGLONG *p)
1071 DOMEvent *This = impl_from_IDOMEvent(iface);
1073 TRACE("(%p)->(%p)\n", This, p);
1075 *p = This->time_stamp;
1076 return S_OK;
1079 static HRESULT WINAPI DOMEvent_get_type(IDOMEvent *iface, BSTR *p)
1081 DOMEvent *This = impl_from_IDOMEvent(iface);
1083 TRACE("(%p)->(%p)\n", This, p);
1085 if(This->type) {
1086 *p = SysAllocString(This->type);
1087 if(!*p)
1088 return E_OUTOFMEMORY;
1089 }else {
1090 *p = NULL;
1092 return S_OK;
1095 #ifdef __i386__
1096 #define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \
1097 ((void (WINAPI*)(void*,nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \
1098 &call_thiscall_func)((_this)->lpVtbl->InitEvent,_this,type,bubbles,cancelable)
1100 #endif
1102 static HRESULT WINAPI DOMEvent_initEvent(IDOMEvent *iface, BSTR type, VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable)
1104 DOMEvent *This = impl_from_IDOMEvent(iface);
1105 nsAString nsstr;
1107 TRACE("(%p)->(%s %x %x)\n", This, debugstr_w(type), can_bubble, cancelable);
1109 if(This->target) {
1110 TRACE("called on already dispatched event\n");
1111 return S_OK;
1114 free(This->type);
1115 This->type = wcsdup(type);
1116 if(!This->type)
1117 return E_OUTOFMEMORY;
1118 This->event_id = str_to_eid(type);
1120 This->bubbles = !!can_bubble;
1121 This->cancelable = !!cancelable;
1123 nsAString_InitDepend(&nsstr, type);
1124 nsIDOMEvent_InitEvent(This->nsevent, &nsstr, This->bubbles, This->cancelable);
1125 nsAString_Finish(&nsstr);
1127 return S_OK;
1130 static HRESULT WINAPI DOMEvent_preventDefault(IDOMEvent *iface)
1132 DOMEvent *This = impl_from_IDOMEvent(iface);
1134 TRACE("(%p)\n", This);
1136 if(This->current_target && This->cancelable) {
1137 This->prevent_default = TRUE;
1138 nsIDOMEvent_PreventDefault(This->nsevent);
1140 return S_OK;
1143 static HRESULT WINAPI DOMEvent_stopPropagation(IDOMEvent *iface)
1145 DOMEvent *This = impl_from_IDOMEvent(iface);
1147 TRACE("(%p)\n", This);
1149 This->stop_propagation = TRUE;
1150 nsIDOMEvent_StopPropagation(This->nsevent);
1151 return S_OK;
1154 static HRESULT WINAPI DOMEvent_stopImmediatePropagation(IDOMEvent *iface)
1156 DOMEvent *This = impl_from_IDOMEvent(iface);
1158 TRACE("(%p)\n", This);
1160 This->stop_immediate_propagation = This->stop_propagation = TRUE;
1161 nsIDOMEvent_StopImmediatePropagation(This->nsevent);
1162 return S_OK;
1165 static HRESULT WINAPI DOMEvent_get_isTrusted(IDOMEvent *iface, VARIANT_BOOL *p)
1167 DOMEvent *This = impl_from_IDOMEvent(iface);
1169 TRACE("(%p)->(%p)\n", This, p);
1171 *p = variant_bool(This->trusted);
1172 return S_OK;
1175 static HRESULT WINAPI DOMEvent_put_cancelBubble(IDOMEvent *iface, VARIANT_BOOL v)
1177 DOMEvent *This = impl_from_IDOMEvent(iface);
1178 FIXME("(%p)->(%x)\n", This, v);
1179 return E_NOTIMPL;
1182 static HRESULT WINAPI DOMEvent_get_cancelBubble(IDOMEvent *iface, VARIANT_BOOL *p)
1184 DOMEvent *This = impl_from_IDOMEvent(iface);
1185 FIXME("(%p)->(%p)\n", This, p);
1186 return E_NOTIMPL;
1189 static HRESULT WINAPI DOMEvent_get_srcElement(IDOMEvent *iface, IHTMLElement **p)
1191 DOMEvent *This = impl_from_IDOMEvent(iface);
1193 TRACE("(%p)->(%p)\n", This, p);
1195 if(This->target)
1196 IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
1197 else
1198 *p = NULL;
1199 return S_OK;
1202 static const IDOMEventVtbl DOMEventVtbl = {
1203 DOMEvent_QueryInterface,
1204 DOMEvent_AddRef,
1205 DOMEvent_Release,
1206 DOMEvent_GetTypeInfoCount,
1207 DOMEvent_GetTypeInfo,
1208 DOMEvent_GetIDsOfNames,
1209 DOMEvent_Invoke,
1210 DOMEvent_get_bubbles,
1211 DOMEvent_get_cancelable,
1212 DOMEvent_get_currentTarget,
1213 DOMEvent_get_defaultPrevented,
1214 DOMEvent_get_eventPhase,
1215 DOMEvent_get_target,
1216 DOMEvent_get_timeStamp,
1217 DOMEvent_get_type,
1218 DOMEvent_initEvent,
1219 DOMEvent_preventDefault,
1220 DOMEvent_stopPropagation,
1221 DOMEvent_stopImmediatePropagation,
1222 DOMEvent_get_isTrusted,
1223 DOMEvent_put_cancelBubble,
1224 DOMEvent_get_cancelBubble,
1225 DOMEvent_get_srcElement
1228 static inline DOMEvent *DOMEvent_from_DispatchEx(DispatchEx *iface)
1230 return CONTAINING_RECORD(iface, DOMEvent, dispex);
1233 static void *DOMEvent_query_interface(DispatchEx *dispex, REFIID riid)
1235 DOMEvent *This = DOMEvent_from_DispatchEx(dispex);
1237 if(IsEqualGUID(&IID_IDOMEvent, riid))
1238 return &This->IDOMEvent_iface;
1240 return NULL;
1243 static void DOMEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
1245 DOMEvent *This = DOMEvent_from_DispatchEx(dispex);
1246 if(This->target)
1247 note_cc_edge((nsISupports*)&This->target->IEventTarget_iface, "target", cb);
1248 if(This->nsevent)
1249 note_cc_edge((nsISupports*)This->nsevent, "nsevent", cb);
1252 static void DOMEvent_unlink(DispatchEx *dispex)
1254 DOMEvent *This = DOMEvent_from_DispatchEx(dispex);
1255 if(This->target) {
1256 EventTarget *target = This->target;
1257 This->target = NULL;
1258 IEventTarget_Release(&target->IEventTarget_iface);
1260 unlink_ref(&This->nsevent);
1263 static void DOMEvent_destructor(DispatchEx *dispex)
1265 DOMEvent *This = DOMEvent_from_DispatchEx(dispex);
1266 free(This->type);
1267 free(This);
1270 static inline DOMUIEvent *impl_from_IDOMUIEvent(IDOMUIEvent *iface)
1272 return CONTAINING_RECORD(iface, DOMUIEvent, IDOMUIEvent_iface);
1275 static HRESULT WINAPI DOMUIEvent_QueryInterface(IDOMUIEvent *iface, REFIID riid, void **ppv)
1277 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1278 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
1281 static ULONG WINAPI DOMUIEvent_AddRef(IDOMUIEvent *iface)
1283 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1284 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
1287 static ULONG WINAPI DOMUIEvent_Release(IDOMUIEvent *iface)
1289 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1290 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
1293 static HRESULT WINAPI DOMUIEvent_GetTypeInfoCount(IDOMUIEvent *iface, UINT *pctinfo)
1295 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1296 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
1299 static HRESULT WINAPI DOMUIEvent_GetTypeInfo(IDOMUIEvent *iface, UINT iTInfo,
1300 LCID lcid, ITypeInfo **ppTInfo)
1302 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1303 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1306 static HRESULT WINAPI DOMUIEvent_GetIDsOfNames(IDOMUIEvent *iface, REFIID riid,
1307 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1309 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1310 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1311 lcid, rgDispId);
1314 static HRESULT WINAPI DOMUIEvent_Invoke(IDOMUIEvent *iface, DISPID dispIdMember,
1315 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1316 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1318 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1319 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1320 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1323 static HRESULT WINAPI DOMUIEvent_get_view(IDOMUIEvent *iface, IHTMLWindow2 **p)
1325 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1326 mozIDOMWindowProxy *moz_window;
1327 HTMLOuterWindow *view = NULL;
1328 nsresult nsres;
1330 TRACE("(%p)->(%p)\n", This, p);
1332 nsres = nsIDOMUIEvent_GetView(This->nsevent, &moz_window);
1333 if(NS_FAILED(nsres))
1334 return E_FAIL;
1336 if(moz_window) {
1337 view = mozwindow_to_window(moz_window);
1338 mozIDOMWindowProxy_Release(moz_window);
1340 if(view)
1341 IHTMLWindow2_AddRef((*p = &view->base.inner_window->base.IHTMLWindow2_iface));
1342 else
1343 *p = NULL;
1344 return S_OK;
1347 static HRESULT WINAPI DOMUIEvent_get_detail(IDOMUIEvent *iface, LONG *p)
1349 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1350 LONG detail;
1351 nsresult nsres;
1353 TRACE("(%p)->(%p)\n", This, p);
1355 nsres = nsIDOMUIEvent_GetDetail(This->nsevent, &detail);
1356 if(NS_FAILED(nsres))
1357 return E_FAIL;
1359 *p = detail;
1360 return S_OK;
1363 static HRESULT WINAPI DOMUIEvent_initUIEvent(IDOMUIEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
1364 VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail)
1366 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1367 nsAString type_str;
1368 nsresult nsres;
1369 HRESULT hres;
1371 TRACE("(%p)->(%s %x %x %p %lx)\n", This, debugstr_w(type), can_bubble, cancelable, view, detail);
1373 if(This->event.target) {
1374 TRACE("called on already dispatched event\n");
1375 return S_OK;
1378 if(view)
1379 FIXME("view argument is not supported\n");
1381 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
1382 if(FAILED(hres))
1383 return hres;
1385 nsAString_InitDepend(&type_str, type);
1386 nsres = nsIDOMUIEvent_InitUIEvent(This->nsevent, &type_str, !!can_bubble, !!cancelable,
1387 NULL /* FIXME */, detail);
1388 nsAString_Finish(&type_str);
1389 if(NS_FAILED(nsres)) {
1390 FIXME("InitUIEvent failed: %08lx\n", nsres);
1391 return E_FAIL;
1394 return S_OK;
1397 static const IDOMUIEventVtbl DOMUIEventVtbl = {
1398 DOMUIEvent_QueryInterface,
1399 DOMUIEvent_AddRef,
1400 DOMUIEvent_Release,
1401 DOMUIEvent_GetTypeInfoCount,
1402 DOMUIEvent_GetTypeInfo,
1403 DOMUIEvent_GetIDsOfNames,
1404 DOMUIEvent_Invoke,
1405 DOMUIEvent_get_view,
1406 DOMUIEvent_get_detail,
1407 DOMUIEvent_initUIEvent
1410 static void *DOMUIEvent_query_interface(DispatchEx *dispex, REFIID riid)
1412 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1414 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1415 return &This->IDOMUIEvent_iface;
1416 return DOMEvent_query_interface(&This->event.dispex, riid);
1419 static void DOMUIEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
1421 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1422 DOMEvent_traverse(&This->event.dispex, cb);
1423 if(This->nsevent)
1424 note_cc_edge((nsISupports*)This->nsevent, "UIEvent.nsevent", cb);
1427 static void DOMUIEvent_unlink(DispatchEx *dispex)
1429 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1430 DOMEvent_unlink(&This->event.dispex);
1431 unlink_ref(&This->nsevent);
1434 typedef struct {
1435 DOMUIEvent ui_event;
1436 IDOMMouseEvent IDOMMouseEvent_iface;
1437 nsIDOMMouseEvent *nsevent;
1438 } DOMMouseEvent;
1440 static inline DOMMouseEvent *impl_from_IDOMMouseEvent(IDOMMouseEvent *iface)
1442 return CONTAINING_RECORD(iface, DOMMouseEvent, IDOMMouseEvent_iface);
1445 static HRESULT WINAPI DOMMouseEvent_QueryInterface(IDOMMouseEvent *iface, REFIID riid, void **ppv)
1447 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1448 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1451 static ULONG WINAPI DOMMouseEvent_AddRef(IDOMMouseEvent *iface)
1453 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1454 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1457 static ULONG WINAPI DOMMouseEvent_Release(IDOMMouseEvent *iface)
1459 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1460 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
1463 static HRESULT WINAPI DOMMouseEvent_GetTypeInfoCount(IDOMMouseEvent *iface, UINT *pctinfo)
1465 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1466 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
1469 static HRESULT WINAPI DOMMouseEvent_GetTypeInfo(IDOMMouseEvent *iface, UINT iTInfo,
1470 LCID lcid, ITypeInfo **ppTInfo)
1472 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1473 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1476 static HRESULT WINAPI DOMMouseEvent_GetIDsOfNames(IDOMMouseEvent *iface, REFIID riid,
1477 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1479 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1480 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1481 lcid, rgDispId);
1484 static HRESULT WINAPI DOMMouseEvent_Invoke(IDOMMouseEvent *iface, DISPID dispIdMember,
1485 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1486 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1488 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1489 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1490 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1493 static HRESULT WINAPI DOMMouseEvent_get_screenX(IDOMMouseEvent *iface, LONG *p)
1495 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1496 LONG screen_x;
1497 nsresult nsres;
1499 TRACE("(%p)->(%p)\n", This, p);
1501 nsres = nsIDOMMouseEvent_GetScreenX(This->nsevent, &screen_x);
1502 if(NS_FAILED(nsres))
1503 return E_FAIL;
1505 *p = screen_x;
1506 return S_OK;
1509 static HRESULT WINAPI DOMMouseEvent_get_screenY(IDOMMouseEvent *iface, LONG *p)
1511 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1512 LONG screen_y;
1513 nsresult nsres;
1515 TRACE("(%p)->(%p)\n", This, p);
1517 nsres = nsIDOMMouseEvent_GetScreenY(This->nsevent, &screen_y);
1518 if(NS_FAILED(nsres))
1519 return E_FAIL;
1521 *p = screen_y;
1522 return S_OK;
1525 static HRESULT WINAPI DOMMouseEvent_get_clientX(IDOMMouseEvent *iface, LONG *p)
1527 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1528 LONG client_x;
1529 nsresult nsres;
1531 TRACE("(%p)->(%p)\n", This, p);
1533 nsres = nsIDOMMouseEvent_GetClientX(This->nsevent, &client_x);
1534 if(NS_FAILED(nsres))
1535 return E_FAIL;
1537 *p = client_x;
1538 return S_OK;
1541 static HRESULT WINAPI DOMMouseEvent_get_clientY(IDOMMouseEvent *iface, LONG *p)
1543 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1544 LONG client_y;
1545 nsresult nsres;
1547 TRACE("(%p)->(%p)\n", This, p);
1549 nsres = nsIDOMMouseEvent_GetClientY(This->nsevent, &client_y);
1550 if(NS_FAILED(nsres))
1551 return E_FAIL;
1553 *p = client_y;
1554 return S_OK;
1557 static HRESULT WINAPI DOMMouseEvent_get_ctrlKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1559 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1560 cpp_bool r;
1561 nsresult nsres;
1563 TRACE("(%p)->(%p)\n", This, p);
1565 nsres = nsIDOMMouseEvent_GetCtrlKey(This->nsevent, &r);
1566 if(NS_FAILED(nsres))
1567 return E_FAIL;
1569 *p = variant_bool(r);
1570 return S_OK;
1573 static HRESULT WINAPI DOMMouseEvent_get_shiftKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1575 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1576 cpp_bool r;
1577 nsresult nsres;
1579 TRACE("(%p)->(%p)\n", This, p);
1581 nsres = nsIDOMMouseEvent_GetShiftKey(This->nsevent, &r);
1582 if(NS_FAILED(nsres))
1583 return E_FAIL;
1585 *p = variant_bool(r);
1586 return S_OK;
1589 static HRESULT WINAPI DOMMouseEvent_get_altKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1591 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1592 cpp_bool r;
1593 nsresult nsres;
1595 TRACE("(%p)->(%p)\n", This, p);
1597 nsres = nsIDOMMouseEvent_GetAltKey(This->nsevent, &r);
1598 if(NS_FAILED(nsres))
1599 return E_FAIL;
1601 *p = variant_bool(r);
1602 return S_OK;
1605 static HRESULT WINAPI DOMMouseEvent_get_metaKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1607 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1608 cpp_bool r;
1609 nsresult nsres;
1611 TRACE("(%p)->(%p)\n", This, p);
1613 nsres = nsIDOMMouseEvent_GetMetaKey(This->nsevent, &r);
1614 if(NS_FAILED(nsres))
1615 return E_FAIL;
1617 *p = variant_bool(r);
1618 return S_OK;
1621 static HRESULT WINAPI DOMMouseEvent_get_button(IDOMMouseEvent *iface, USHORT *p)
1623 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1624 INT16 r;
1625 nsresult nsres;
1627 TRACE("(%p)->(%p)\n", This, p);
1629 nsres = nsIDOMMouseEvent_GetButton(This->nsevent, &r);
1630 if(NS_FAILED(nsres))
1631 return E_FAIL;
1633 *p = r;
1634 return S_OK;
1637 static HRESULT WINAPI DOMMouseEvent_get_relatedTarget(IDOMMouseEvent *iface, IEventTarget **p)
1639 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1640 nsIDOMEventTarget *related_target;
1641 nsIDOMNode *target_node;
1642 HTMLDOMNode *node;
1643 HRESULT hres;
1644 nsresult nsres;
1646 TRACE("(%p)->(%p)\n", This, p);
1648 nsres = nsIDOMMouseEvent_GetRelatedTarget(This->nsevent, &related_target);
1649 if(NS_FAILED(nsres))
1650 return E_FAIL;
1652 if(!related_target) {
1653 *p = NULL;
1654 return S_OK;
1657 nsres = nsIDOMEventTarget_QueryInterface(related_target, &IID_nsIDOMNode, (void**)&target_node);
1658 nsIDOMEventTarget_Release(related_target);
1659 if(NS_FAILED(nsres)) {
1660 FIXME("Only node targets supported\n");
1661 return E_NOTIMPL;
1664 hres = get_node(target_node, TRUE, &node);
1665 nsIDOMNode_Release(target_node);
1666 if(FAILED(hres))
1667 return hres;
1669 *p = &node->event_target.IEventTarget_iface;
1670 return S_OK;
1673 static HRESULT WINAPI DOMMouseEvent_initMouseEvent(IDOMMouseEvent *iface, BSTR type,
1674 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail,
1675 LONG screen_x, LONG screen_y, LONG client_x, LONG client_y, VARIANT_BOOL ctrl_key,
1676 VARIANT_BOOL alt_key, VARIANT_BOOL shift_key, VARIANT_BOOL meta_key, USHORT button,
1677 IEventTarget *related_target)
1679 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1680 nsIDOMEventTarget *nstarget = NULL;
1681 nsAString type_str;
1682 nsresult nsres;
1683 HRESULT hres;
1685 TRACE("(%p)->(%s %x %x %p %ld %ld %ld %ld %ld %x %x %x %x %u %p)\n", This, debugstr_w(type),
1686 can_bubble, cancelable, view, detail, screen_x, screen_y, client_x, client_y,
1687 ctrl_key, alt_key, shift_key, meta_key, button, related_target);
1689 if(This->ui_event.event.target) {
1690 TRACE("called on already dispatched event\n");
1691 return S_OK;
1694 if(view)
1695 FIXME("view argument is not supported\n");
1697 if(related_target) {
1698 hres = get_gecko_target(related_target, &nstarget);
1699 if(FAILED(hres))
1700 return hres;
1703 hres = IDOMEvent_initEvent(&This->ui_event.event.IDOMEvent_iface, type, can_bubble, cancelable);
1704 if(SUCCEEDED(hres)) {
1705 nsAString_InitDepend(&type_str, type);
1706 nsres = nsIDOMMouseEvent_InitMouseEvent(This->nsevent, &type_str, can_bubble, cancelable,
1707 NULL /* FIXME */, detail, screen_x, screen_y,
1708 client_x, client_y, !!ctrl_key, !!alt_key, !!shift_key,
1709 !!meta_key, button, nstarget);
1710 nsAString_Finish(&type_str);
1711 if(NS_FAILED(nsres)) {
1712 FIXME("InitMouseEvent failed: %08lx\n", nsres);
1713 return E_FAIL;
1717 if(nstarget)
1718 nsIDOMEventTarget_Release(nstarget);
1719 return S_OK;
1722 static HRESULT WINAPI DOMMouseEvent_getModifierState(IDOMMouseEvent *iface, BSTR key,
1723 VARIANT_BOOL *activated)
1725 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1726 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), activated);
1727 return E_NOTIMPL;
1730 static HRESULT WINAPI DOMMouseEvent_get_buttons(IDOMMouseEvent *iface, USHORT *p)
1732 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1733 UINT16 r;
1734 nsresult nsres;
1736 TRACE("(%p)->(%p)\n", This, p);
1738 nsres = nsIDOMMouseEvent_GetButtons(This->nsevent, &r);
1739 if(NS_FAILED(nsres))
1740 return E_FAIL;
1742 *p = r;
1743 return S_OK;
1746 static HRESULT WINAPI DOMMouseEvent_get_fromElement(IDOMMouseEvent *iface, IHTMLElement **p)
1748 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1749 eventid_t event_id = This->ui_event.event.event_id;
1750 IEventTarget *related_target = NULL;
1751 HRESULT hres = S_OK;
1753 TRACE("(%p)->(%p)\n", This, p);
1755 if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1756 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1757 else if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1758 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1759 if(FAILED(hres))
1760 return hres;
1762 if(!related_target) {
1763 *p = NULL;
1764 return S_OK;
1767 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1768 return S_OK;
1771 static HRESULT WINAPI DOMMouseEvent_get_toElement(IDOMMouseEvent *iface, IHTMLElement **p)
1773 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1774 eventid_t event_id = This->ui_event.event.event_id;
1775 IEventTarget *related_target = NULL;
1776 HRESULT hres = S_OK;
1778 TRACE("(%p)->(%p)\n", This, p);
1780 if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1781 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1782 else if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1783 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1784 if(FAILED(hres))
1785 return hres;
1787 if(!related_target) {
1788 *p = NULL;
1789 return S_OK;
1792 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1793 return S_OK;
1796 static HRESULT WINAPI DOMMouseEvent_get_x(IDOMMouseEvent *iface, LONG *p)
1798 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1799 FIXME("(%p)->(%p)\n", This, p);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI DOMMouseEvent_get_y(IDOMMouseEvent *iface, LONG *p)
1805 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1806 FIXME("(%p)->(%p)\n", This, p);
1807 return E_NOTIMPL;
1810 static HRESULT WINAPI DOMMouseEvent_get_offsetX(IDOMMouseEvent *iface, LONG *p)
1812 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1814 FIXME("(%p)->(%p) returning 0\n", This, p);
1816 *p = 0;
1817 return S_OK;
1820 static HRESULT WINAPI DOMMouseEvent_get_offsetY(IDOMMouseEvent *iface, LONG *p)
1822 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1824 FIXME("(%p)->(%p) returning 0\n", This, p);
1826 *p = 0;
1827 return S_OK;
1830 static HRESULT WINAPI DOMMouseEvent_get_pageX(IDOMMouseEvent *iface, LONG *p)
1832 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1833 LONG r;
1834 nsresult nsres;
1836 TRACE("(%p)->(%p)\n", This, p);
1838 nsres = nsIDOMMouseEvent_GetPageX(This->nsevent, &r);
1839 if(NS_FAILED(nsres))
1840 return E_FAIL;
1842 *p = r;
1843 return S_OK;
1846 static HRESULT WINAPI DOMMouseEvent_get_pageY(IDOMMouseEvent *iface, LONG *p)
1848 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1849 LONG r;
1850 nsresult nsres;
1852 TRACE("(%p)->(%p)\n", This, p);
1854 nsres = nsIDOMMouseEvent_GetPageY(This->nsevent, &r);
1855 if(NS_FAILED(nsres))
1856 return E_FAIL;
1858 *p = r;
1859 return S_OK;
1862 static HRESULT WINAPI DOMMouseEvent_get_layerX(IDOMMouseEvent *iface, LONG *p)
1864 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1865 nsresult nsres;
1866 LONG r;
1868 TRACE("(%p)->(%p)\n", This, p);
1870 nsres = nsIDOMMouseEvent_GetLayerX(This->nsevent, &r);
1871 if(NS_FAILED(nsres))
1872 return E_FAIL;
1874 *p = r;
1875 return S_OK;
1878 static HRESULT WINAPI DOMMouseEvent_get_layerY(IDOMMouseEvent *iface, LONG *p)
1880 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1881 nsresult nsres;
1882 LONG r;
1884 TRACE("(%p)->(%p)\n", This, p);
1886 nsres = nsIDOMMouseEvent_GetLayerY(This->nsevent, &r);
1887 if(NS_FAILED(nsres))
1888 return E_FAIL;
1890 *p = r;
1891 return S_OK;
1894 static HRESULT WINAPI DOMMouseEvent_get_which(IDOMMouseEvent *iface, USHORT *p)
1896 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1897 UINT32 r;
1898 nsresult nsres;
1900 TRACE("(%p)->(%p)\n", This, p);
1902 nsres = nsIDOMMouseEvent_GetWhich(This->nsevent, &r);
1903 if(NS_FAILED(nsres))
1904 return E_FAIL;
1906 *p = r;
1907 return S_OK;
1910 static const IDOMMouseEventVtbl DOMMouseEventVtbl = {
1911 DOMMouseEvent_QueryInterface,
1912 DOMMouseEvent_AddRef,
1913 DOMMouseEvent_Release,
1914 DOMMouseEvent_GetTypeInfoCount,
1915 DOMMouseEvent_GetTypeInfo,
1916 DOMMouseEvent_GetIDsOfNames,
1917 DOMMouseEvent_Invoke,
1918 DOMMouseEvent_get_screenX,
1919 DOMMouseEvent_get_screenY,
1920 DOMMouseEvent_get_clientX,
1921 DOMMouseEvent_get_clientY,
1922 DOMMouseEvent_get_ctrlKey,
1923 DOMMouseEvent_get_shiftKey,
1924 DOMMouseEvent_get_altKey,
1925 DOMMouseEvent_get_metaKey,
1926 DOMMouseEvent_get_button,
1927 DOMMouseEvent_get_relatedTarget,
1928 DOMMouseEvent_initMouseEvent,
1929 DOMMouseEvent_getModifierState,
1930 DOMMouseEvent_get_buttons,
1931 DOMMouseEvent_get_fromElement,
1932 DOMMouseEvent_get_toElement,
1933 DOMMouseEvent_get_x,
1934 DOMMouseEvent_get_y,
1935 DOMMouseEvent_get_offsetX,
1936 DOMMouseEvent_get_offsetY,
1937 DOMMouseEvent_get_pageX,
1938 DOMMouseEvent_get_pageY,
1939 DOMMouseEvent_get_layerX,
1940 DOMMouseEvent_get_layerY,
1941 DOMMouseEvent_get_which
1944 static DOMMouseEvent *DOMMouseEvent_from_DOMEvent(DOMEvent *event)
1946 return CONTAINING_RECORD(event, DOMMouseEvent, ui_event.event);
1949 static void *DOMMouseEvent_query_interface(DispatchEx *dispex, REFIID riid)
1951 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1953 if(IsEqualGUID(&IID_IDOMMouseEvent, riid))
1954 return &This->IDOMMouseEvent_iface;
1955 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1956 return &This->ui_event.IDOMUIEvent_iface;
1957 return DOMEvent_query_interface(&This->ui_event.event.dispex, riid);
1960 static void DOMMouseEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
1962 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1963 DOMUIEvent_traverse(&This->ui_event.event.dispex, cb);
1964 if(This->nsevent)
1965 note_cc_edge((nsISupports*)This->nsevent, "MouseEvent.nsevent", cb);
1968 static void DOMMouseEvent_unlink(DispatchEx *dispex)
1970 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
1971 DOMUIEvent_unlink(&This->ui_event.event.dispex);
1972 unlink_ref(&This->nsevent);
1975 typedef struct {
1976 DOMUIEvent ui_event;
1977 IDOMKeyboardEvent IDOMKeyboardEvent_iface;
1978 nsIDOMKeyEvent *nsevent;
1979 } DOMKeyboardEvent;
1981 static inline DOMKeyboardEvent *impl_from_IDOMKeyboardEvent(IDOMKeyboardEvent *iface)
1983 return CONTAINING_RECORD(iface, DOMKeyboardEvent, IDOMKeyboardEvent_iface);
1986 static HRESULT WINAPI DOMKeyboardEvent_QueryInterface(IDOMKeyboardEvent *iface, REFIID riid, void **ppv)
1988 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1989 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1992 static ULONG WINAPI DOMKeyboardEvent_AddRef(IDOMKeyboardEvent *iface)
1994 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1995 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1998 static ULONG WINAPI DOMKeyboardEvent_Release(IDOMKeyboardEvent *iface)
2000 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2001 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
2004 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfoCount(IDOMKeyboardEvent *iface, UINT *pctinfo)
2006 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2007 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
2010 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfo(IDOMKeyboardEvent *iface, UINT iTInfo,
2011 LCID lcid, ITypeInfo **ppTInfo)
2013 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2014 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2017 static HRESULT WINAPI DOMKeyboardEvent_GetIDsOfNames(IDOMKeyboardEvent *iface, REFIID riid,
2018 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2020 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2021 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2022 lcid, rgDispId);
2025 static HRESULT WINAPI DOMKeyboardEvent_Invoke(IDOMKeyboardEvent *iface, DISPID dispIdMember,
2026 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2027 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2029 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2030 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2031 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2034 static HRESULT WINAPI DOMKeyboardEvent_get_key(IDOMKeyboardEvent *iface, BSTR *p)
2036 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2037 nsAString key_str;
2038 nsresult nsres;
2040 TRACE("(%p)->(%p)\n", This, p);
2043 nsAString_Init(&key_str, NULL);
2044 nsres = nsIDOMKeyEvent_GetKey(This->nsevent, &key_str);
2045 return return_nsstr(nsres, &key_str, p);
2048 static HRESULT WINAPI DOMKeyboardEvent_get_location(IDOMKeyboardEvent *iface, ULONG *p)
2050 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2051 UINT32 r;
2052 nsresult nsres;
2054 TRACE("(%p)->(%p)\n", This, p);
2056 nsres = nsIDOMKeyEvent_GetLocation(This->nsevent, &r);
2057 if(NS_FAILED(nsres))
2058 return E_FAIL;
2060 *p = r;
2061 return S_OK;
2064 static HRESULT WINAPI DOMKeyboardEvent_get_ctrlKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2066 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2067 cpp_bool r;
2068 nsresult nsres;
2070 TRACE("(%p)->(%p)\n", This, p);
2072 nsres = nsIDOMKeyEvent_GetCtrlKey(This->nsevent, &r);
2073 if(NS_FAILED(nsres))
2074 return E_FAIL;
2076 *p = variant_bool(r);
2077 return S_OK;
2080 static HRESULT WINAPI DOMKeyboardEvent_get_shiftKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2082 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2083 cpp_bool r;
2084 nsresult nsres;
2086 TRACE("(%p)->(%p)\n", This, p);
2088 nsres = nsIDOMKeyEvent_GetShiftKey(This->nsevent, &r);
2089 if(NS_FAILED(nsres))
2090 return E_FAIL;
2092 *p = variant_bool(r);
2093 return S_OK;
2096 static HRESULT WINAPI DOMKeyboardEvent_get_altKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2098 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2099 cpp_bool r;
2100 nsresult nsres;
2102 TRACE("(%p)->(%p)\n", This, p);
2104 nsres = nsIDOMKeyEvent_GetAltKey(This->nsevent, &r);
2105 if(NS_FAILED(nsres))
2106 return E_FAIL;
2108 *p = variant_bool(r);
2109 return S_OK;
2112 static HRESULT WINAPI DOMKeyboardEvent_get_metaKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2114 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2115 cpp_bool r;
2116 nsresult nsres;
2118 TRACE("(%p)->(%p)\n", This, p);
2120 nsres = nsIDOMKeyEvent_GetMetaKey(This->nsevent, &r);
2121 if(NS_FAILED(nsres))
2122 return E_FAIL;
2124 *p = variant_bool(r);
2125 return S_OK;
2128 static HRESULT WINAPI DOMKeyboardEvent_get_repeat(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2130 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2131 cpp_bool r;
2132 nsresult nsres;
2134 TRACE("(%p)->(%p)\n", This, p);
2136 nsres = nsIDOMKeyEvent_GetRepeat(This->nsevent, &r);
2137 if(NS_FAILED(nsres))
2138 return E_FAIL;
2140 *p = variant_bool(r);
2141 return S_OK;
2144 static HRESULT WINAPI DOMKeyboardEvent_getModifierState(IDOMKeyboardEvent *iface, BSTR key,
2145 VARIANT_BOOL *state)
2147 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2148 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), state);
2149 return E_NOTIMPL;
2152 static HRESULT WINAPI DOMKeyboardEvent_initKeyboardEvent(IDOMKeyboardEvent *iface, BSTR type,
2153 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, BSTR key,
2154 ULONG location, BSTR modifiers_list, VARIANT_BOOL repeat, BSTR locale)
2156 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2157 FIXME("(%p)->(%s %x %x %p %s %lu %s %x %s)\n", This, debugstr_w(type), can_bubble,
2158 cancelable, view, debugstr_w(key), location, debugstr_w(modifiers_list),
2159 repeat, debugstr_w(locale));
2160 return E_NOTIMPL;
2163 static HRESULT WINAPI DOMKeyboardEvent_get_keyCode(IDOMKeyboardEvent *iface, LONG *p)
2165 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2166 UINT32 r;
2167 nsresult nsres;
2169 TRACE("(%p)->(%p)\n", This, p);
2171 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2172 if(NS_FAILED(nsres))
2173 return E_FAIL;
2175 *p = r;
2176 return S_OK;
2179 static HRESULT WINAPI DOMKeyboardEvent_get_charCode(IDOMKeyboardEvent *iface, LONG *p)
2181 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2182 UINT32 r;
2183 nsresult nsres;
2185 TRACE("(%p)->(%p)\n", This, p);
2187 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2188 if(NS_FAILED(nsres))
2189 return E_FAIL;
2191 *p = r;
2192 return S_OK;
2195 static HRESULT WINAPI DOMKeyboardEvent_get_which(IDOMKeyboardEvent *iface, LONG *p)
2197 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2198 UINT32 r;
2199 nsresult nsres;
2201 TRACE("(%p)->(%p)\n", This, p);
2203 nsres = nsIDOMKeyEvent_GetWhich(This->nsevent, &r);
2204 if(NS_FAILED(nsres))
2205 return E_FAIL;
2207 *p = r;
2208 return S_OK;
2211 static HRESULT WINAPI DOMKeyboardEvent_get_char(IDOMKeyboardEvent *iface, VARIANT *p)
2213 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2214 FIXME("(%p)->(%p)\n", This, p);
2215 return E_NOTIMPL;
2218 static HRESULT WINAPI DOMKeyboardEvent_get_locale(IDOMKeyboardEvent *iface, BSTR *p)
2220 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2222 FIXME("(%p)->(%p) semi-stub\n", This, p);
2224 *p = SysAllocString(L"");
2225 return *p ? S_OK : E_OUTOFMEMORY;
2228 static const IDOMKeyboardEventVtbl DOMKeyboardEventVtbl = {
2229 DOMKeyboardEvent_QueryInterface,
2230 DOMKeyboardEvent_AddRef,
2231 DOMKeyboardEvent_Release,
2232 DOMKeyboardEvent_GetTypeInfoCount,
2233 DOMKeyboardEvent_GetTypeInfo,
2234 DOMKeyboardEvent_GetIDsOfNames,
2235 DOMKeyboardEvent_Invoke,
2236 DOMKeyboardEvent_get_key,
2237 DOMKeyboardEvent_get_location,
2238 DOMKeyboardEvent_get_ctrlKey,
2239 DOMKeyboardEvent_get_shiftKey,
2240 DOMKeyboardEvent_get_altKey,
2241 DOMKeyboardEvent_get_metaKey,
2242 DOMKeyboardEvent_get_repeat,
2243 DOMKeyboardEvent_getModifierState,
2244 DOMKeyboardEvent_initKeyboardEvent,
2245 DOMKeyboardEvent_get_keyCode,
2246 DOMKeyboardEvent_get_charCode,
2247 DOMKeyboardEvent_get_which,
2248 DOMKeyboardEvent_get_char,
2249 DOMKeyboardEvent_get_locale
2252 static DOMKeyboardEvent *DOMKeyboardEvent_from_DOMEvent(DOMEvent *event)
2254 return CONTAINING_RECORD(event, DOMKeyboardEvent, ui_event.event);
2257 static void *DOMKeyboardEvent_query_interface(DispatchEx *dispex, REFIID riid)
2259 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2261 if(IsEqualGUID(&IID_IDOMKeyboardEvent, riid))
2262 return &This->IDOMKeyboardEvent_iface;
2263 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
2264 return &This->ui_event.IDOMUIEvent_iface;
2265 return DOMEvent_query_interface(&This->ui_event.event.dispex, riid);
2268 static void DOMKeyboardEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
2270 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2271 DOMUIEvent_traverse(&This->ui_event.event.dispex, cb);
2272 if(This->nsevent)
2273 note_cc_edge((nsISupports*)This->nsevent, "KeyboardEvent.nsevent", cb);
2276 static void DOMKeyboardEvent_unlink(DispatchEx *dispex)
2278 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2279 DOMUIEvent_unlink(&This->ui_event.event.dispex);
2280 unlink_ref(&This->nsevent);
2283 typedef struct {
2284 DOMEvent event;
2285 IWinePageTransitionEvent IWinePageTransitionEvent_iface;
2286 } DOMPageTransitionEvent;
2288 static inline DOMPageTransitionEvent *impl_from_IWinePageTransitionEvent(IWinePageTransitionEvent *iface)
2290 return CONTAINING_RECORD(iface, DOMPageTransitionEvent, IWinePageTransitionEvent_iface);
2293 static HRESULT WINAPI DOMPageTransitionEvent_QueryInterface(IWinePageTransitionEvent *iface, REFIID riid, void **ppv)
2295 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2296 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2299 static ULONG WINAPI DOMPageTransitionEvent_AddRef(IWinePageTransitionEvent *iface)
2301 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2302 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2305 static ULONG WINAPI DOMPageTransitionEvent_Release(IWinePageTransitionEvent *iface)
2307 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2308 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2311 static HRESULT WINAPI DOMPageTransitionEvent_GetTypeInfoCount(IWinePageTransitionEvent *iface, UINT *pctinfo)
2313 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2314 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2317 static HRESULT WINAPI DOMPageTransitionEvent_GetTypeInfo(IWinePageTransitionEvent *iface, UINT iTInfo,
2318 LCID lcid, ITypeInfo **ppTInfo)
2320 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2321 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2324 static HRESULT WINAPI DOMPageTransitionEvent_GetIDsOfNames(IWinePageTransitionEvent *iface, REFIID riid,
2325 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2327 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2328 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2329 lcid, rgDispId);
2332 static HRESULT WINAPI DOMPageTransitionEvent_Invoke(IWinePageTransitionEvent *iface, DISPID dispIdMember,
2333 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2334 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2336 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2337 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2338 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2341 static HRESULT WINAPI DOMPageTransitionEvent_get_persisted(IWinePageTransitionEvent *iface, VARIANT_BOOL *p)
2343 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2345 FIXME("(%p)->(%p): always returning FALSE\n", This, p);
2347 *p = VARIANT_FALSE;
2348 return S_OK;
2351 static const IWinePageTransitionEventVtbl DOMPageTransitionEventVtbl = {
2352 DOMPageTransitionEvent_QueryInterface,
2353 DOMPageTransitionEvent_AddRef,
2354 DOMPageTransitionEvent_Release,
2355 DOMPageTransitionEvent_GetTypeInfoCount,
2356 DOMPageTransitionEvent_GetTypeInfo,
2357 DOMPageTransitionEvent_GetIDsOfNames,
2358 DOMPageTransitionEvent_Invoke,
2359 DOMPageTransitionEvent_get_persisted
2362 static DOMPageTransitionEvent *DOMPageTransitionEvent_from_DOMEvent(DOMEvent *event)
2364 return CONTAINING_RECORD(event, DOMPageTransitionEvent, event);
2367 static void *DOMPageTransitionEvent_query_interface(DispatchEx *dispex, REFIID riid)
2369 DOMPageTransitionEvent *page_transition_event = DOMPageTransitionEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2371 if(IsEqualGUID(&IID_IWinePageTransitionEvent, riid))
2372 return &page_transition_event->IWinePageTransitionEvent_iface;
2373 return DOMEvent_query_interface(&page_transition_event->event.dispex, riid);
2376 typedef struct {
2377 DOMEvent event;
2378 IDOMCustomEvent IDOMCustomEvent_iface;
2379 VARIANT detail;
2380 } DOMCustomEvent;
2382 static inline DOMCustomEvent *impl_from_IDOMCustomEvent(IDOMCustomEvent *iface)
2384 return CONTAINING_RECORD(iface, DOMCustomEvent, IDOMCustomEvent_iface);
2387 static HRESULT WINAPI DOMCustomEvent_QueryInterface(IDOMCustomEvent *iface, REFIID riid, void **ppv)
2389 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2390 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2393 static ULONG WINAPI DOMCustomEvent_AddRef(IDOMCustomEvent *iface)
2395 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2396 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2399 static ULONG WINAPI DOMCustomEvent_Release(IDOMCustomEvent *iface)
2401 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2402 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2405 static HRESULT WINAPI DOMCustomEvent_GetTypeInfoCount(IDOMCustomEvent *iface, UINT *pctinfo)
2407 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2408 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2411 static HRESULT WINAPI DOMCustomEvent_GetTypeInfo(IDOMCustomEvent *iface, UINT iTInfo,
2412 LCID lcid, ITypeInfo **ppTInfo)
2414 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2415 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2418 static HRESULT WINAPI DOMCustomEvent_GetIDsOfNames(IDOMCustomEvent *iface, REFIID riid,
2419 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2421 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2422 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2423 lcid, rgDispId);
2426 static HRESULT WINAPI DOMCustomEvent_Invoke(IDOMCustomEvent *iface, DISPID dispIdMember,
2427 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2428 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2430 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2431 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2432 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2435 static HRESULT WINAPI DOMCustomEvent_get_detail(IDOMCustomEvent *iface, VARIANT *p)
2437 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2439 TRACE("(%p)->(%p)\n", This, p);
2441 V_VT(p) = VT_EMPTY;
2442 return VariantCopy(p, &This->detail);
2445 static HRESULT WINAPI DOMCustomEvent_initCustomEvent(IDOMCustomEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2446 VARIANT_BOOL cancelable, VARIANT *detail)
2448 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2449 HRESULT hres;
2451 TRACE("(%p)->(%s %x %x %s)\n", This, debugstr_w(type), can_bubble, cancelable, debugstr_variant(detail));
2453 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
2454 if(FAILED(hres))
2455 return hres;
2457 return VariantCopy(&This->detail, detail);
2460 static const IDOMCustomEventVtbl DOMCustomEventVtbl = {
2461 DOMCustomEvent_QueryInterface,
2462 DOMCustomEvent_AddRef,
2463 DOMCustomEvent_Release,
2464 DOMCustomEvent_GetTypeInfoCount,
2465 DOMCustomEvent_GetTypeInfo,
2466 DOMCustomEvent_GetIDsOfNames,
2467 DOMCustomEvent_Invoke,
2468 DOMCustomEvent_get_detail,
2469 DOMCustomEvent_initCustomEvent
2472 static DOMCustomEvent *DOMCustomEvent_from_DOMEvent(DOMEvent *event)
2474 return CONTAINING_RECORD(event, DOMCustomEvent, event);
2477 static void *DOMCustomEvent_query_interface(DispatchEx *dispex, REFIID riid)
2479 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2481 if(IsEqualGUID(&IID_IDOMCustomEvent, riid))
2482 return &custom_event->IDOMCustomEvent_iface;
2483 return DOMEvent_query_interface(&custom_event->event.dispex, riid);
2486 static void DOMCustomEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
2488 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2489 DOMEvent_traverse(&custom_event->event.dispex, cb);
2490 traverse_variant(&custom_event->detail, "detail", cb);
2493 static void DOMCustomEvent_unlink(DispatchEx *dispex)
2495 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2496 DOMEvent_unlink(&custom_event->event.dispex);
2497 unlink_variant(&custom_event->detail);
2500 static void DOMCustomEvent_destructor(DispatchEx *dispex)
2502 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2503 VariantClear(&custom_event->detail);
2504 DOMEvent_destructor(dispex);
2507 typedef struct {
2508 DOMEvent event;
2509 IDOMMessageEvent IDOMMessageEvent_iface;
2510 VARIANT data;
2511 } DOMMessageEvent;
2513 static inline DOMMessageEvent *impl_from_IDOMMessageEvent(IDOMMessageEvent *iface)
2515 return CONTAINING_RECORD(iface, DOMMessageEvent, IDOMMessageEvent_iface);
2518 static HRESULT WINAPI DOMMessageEvent_QueryInterface(IDOMMessageEvent *iface, REFIID riid, void **ppv)
2520 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2521 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2524 static ULONG WINAPI DOMMessageEvent_AddRef(IDOMMessageEvent *iface)
2526 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2527 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2530 static ULONG WINAPI DOMMessageEvent_Release(IDOMMessageEvent *iface)
2532 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2533 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2536 static HRESULT WINAPI DOMMessageEvent_GetTypeInfoCount(IDOMMessageEvent *iface, UINT *pctinfo)
2538 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2539 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2542 static HRESULT WINAPI DOMMessageEvent_GetTypeInfo(IDOMMessageEvent *iface, UINT iTInfo,
2543 LCID lcid, ITypeInfo **ppTInfo)
2545 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2546 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2549 static HRESULT WINAPI DOMMessageEvent_GetIDsOfNames(IDOMMessageEvent *iface, REFIID riid,
2550 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2552 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2553 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2554 lcid, rgDispId);
2557 static HRESULT WINAPI DOMMessageEvent_Invoke(IDOMMessageEvent *iface, DISPID dispIdMember,
2558 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2559 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2561 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2562 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2563 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2566 static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
2568 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2570 TRACE("(%p)->(%p)\n", This, p);
2572 if(V_VT(&This->data) != VT_BSTR) {
2573 FIXME("non-string data\n");
2574 return E_NOTIMPL;
2577 return (*p = SysAllocString(V_BSTR(&This->data))) ? S_OK : E_OUTOFMEMORY;
2580 static HRESULT DOMMessageEvent_get_data_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res,
2581 EXCEPINFO *ei, IServiceProvider *caller)
2583 DOMMessageEvent *This = CONTAINING_RECORD(dispex, DOMMessageEvent, event.dispex);
2585 if(!(flags & DISPATCH_PROPERTYGET) || !res)
2586 return S_FALSE;
2588 TRACE("(%p)->(%p)\n", This, res);
2590 V_VT(res) = VT_EMPTY;
2591 return VariantCopy(res, &This->data);
2594 static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR *p)
2596 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2597 FIXME("(%p)->(%p)\n", This, p);
2598 return E_NOTIMPL;
2601 static HRESULT WINAPI DOMMessageEvent_get_source(IDOMMessageEvent *iface, IHTMLWindow2 **p)
2603 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2604 FIXME("(%p)->(%p)\n", This, p);
2605 return E_NOTIMPL;
2608 static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2609 VARIANT_BOOL cancelable, BSTR data, BSTR origin,
2610 BSTR last_event_id, IHTMLWindow2 *source)
2612 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2613 FIXME("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2614 debugstr_w(data), debugstr_w(origin), debugstr_w(last_event_id), source);
2615 return E_NOTIMPL;
2618 static const IDOMMessageEventVtbl DOMMessageEventVtbl = {
2619 DOMMessageEvent_QueryInterface,
2620 DOMMessageEvent_AddRef,
2621 DOMMessageEvent_Release,
2622 DOMMessageEvent_GetTypeInfoCount,
2623 DOMMessageEvent_GetTypeInfo,
2624 DOMMessageEvent_GetIDsOfNames,
2625 DOMMessageEvent_Invoke,
2626 DOMMessageEvent_get_data,
2627 DOMMessageEvent_get_origin,
2628 DOMMessageEvent_get_source,
2629 DOMMessageEvent_initMessageEvent
2632 static DOMMessageEvent *DOMMessageEvent_from_DOMEvent(DOMEvent *event)
2634 return CONTAINING_RECORD(event, DOMMessageEvent, event);
2637 static void *DOMMessageEvent_query_interface(DispatchEx *dispex, REFIID riid)
2639 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2641 if(IsEqualGUID(&IID_IDOMMessageEvent, riid))
2642 return &message_event->IDOMMessageEvent_iface;
2643 return DOMEvent_query_interface(&message_event->event.dispex, riid);
2646 static void DOMMessageEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
2648 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2649 DOMEvent_traverse(&message_event->event.dispex, cb);
2650 traverse_variant(&message_event->data, "data", cb);
2653 static void DOMMessageEvent_unlink(DispatchEx *dispex)
2655 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2656 DOMEvent_unlink(&message_event->event.dispex);
2657 unlink_variant(&message_event->data);
2660 static void DOMMessageEvent_destructor(DispatchEx *dispex)
2662 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2663 VariantClear(&message_event->data);
2664 DOMEvent_destructor(dispex);
2667 static void DOMMessageEvent_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
2669 static const dispex_hook_t hooks[] = {
2670 {DISPID_IDOMMESSAGEEVENT_DATA, DOMMessageEvent_get_data_hook},
2671 {DISPID_UNKNOWN}
2673 dispex_info_add_interface(info, IDOMMessageEvent_tid, compat_mode >= COMPAT_MODE_IE10 ? hooks : NULL);
2676 typedef struct {
2677 DOMEvent event;
2678 IDOMProgressEvent IDOMProgressEvent_iface;
2679 nsIDOMProgressEvent *nsevent;
2680 BOOL manual_init;
2681 } DOMProgressEvent;
2683 static inline DOMProgressEvent *impl_from_IDOMProgressEvent(IDOMProgressEvent *iface)
2685 return CONTAINING_RECORD(iface, DOMProgressEvent, IDOMProgressEvent_iface);
2688 static HRESULT WINAPI DOMProgressEvent_QueryInterface(IDOMProgressEvent *iface, REFIID riid, void **ppv)
2690 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2691 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2694 static ULONG WINAPI DOMProgressEvent_AddRef(IDOMProgressEvent *iface)
2696 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2697 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2700 static ULONG WINAPI DOMProgressEvent_Release(IDOMProgressEvent *iface)
2702 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2703 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2706 static HRESULT WINAPI DOMProgressEvent_GetTypeInfoCount(IDOMProgressEvent *iface, UINT *pctinfo)
2708 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2709 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2712 static HRESULT WINAPI DOMProgressEvent_GetTypeInfo(IDOMProgressEvent *iface, UINT iTInfo,
2713 LCID lcid, ITypeInfo **ppTInfo)
2715 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2716 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2719 static HRESULT WINAPI DOMProgressEvent_GetIDsOfNames(IDOMProgressEvent *iface, REFIID riid,
2720 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2722 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2723 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2724 lcid, rgDispId);
2727 static HRESULT WINAPI DOMProgressEvent_Invoke(IDOMProgressEvent *iface, DISPID dispIdMember,
2728 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2729 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2731 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2732 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2733 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2736 static HRESULT WINAPI DOMProgressEvent_get_lengthComputable(IDOMProgressEvent *iface, VARIANT_BOOL *p)
2738 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2739 nsresult nsres;
2740 cpp_bool b;
2742 TRACE("(%p)->(%p)\n", This, p);
2744 nsres = nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b);
2745 if(NS_FAILED(nsres))
2746 return map_nsresult(nsres);
2748 *p = b ? VARIANT_TRUE : VARIANT_FALSE;
2749 return S_OK;
2752 static HRESULT WINAPI DOMProgressEvent_get_loaded(IDOMProgressEvent *iface, ULONGLONG *p)
2754 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2756 TRACE("(%p)->(%p)\n", This, p);
2758 return map_nsresult(nsIDOMProgressEvent_GetLoaded(This->nsevent, p));
2761 static HRESULT WINAPI DOMProgressEvent_get_total(IDOMProgressEvent *iface, ULONGLONG *p)
2763 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2764 cpp_bool b;
2766 TRACE("(%p)->(%p)\n", This, p);
2768 if(!This->manual_init && (NS_FAILED(nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b)) || !b)) {
2769 *p = ~0;
2770 return S_OK;
2773 return map_nsresult(nsIDOMProgressEvent_GetTotal(This->nsevent, p));
2776 static HRESULT WINAPI DOMProgressEvent_initProgressEvent(IDOMProgressEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2777 VARIANT_BOOL cancelable, VARIANT_BOOL lengthComputable,
2778 ULONGLONG loaded, ULONGLONG total)
2780 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2781 nsAString type_str;
2782 nsresult nsres;
2783 HRESULT hres;
2785 TRACE("(%p)->(%s %x %x %x %s %s)\n", This, debugstr_w(type), can_bubble, cancelable, lengthComputable,
2786 wine_dbgstr_longlong(loaded), wine_dbgstr_longlong(total));
2788 if(This->event.target) {
2789 TRACE("called on already dispatched event\n");
2790 return S_OK;
2793 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
2794 if(SUCCEEDED(hres)) {
2795 nsAString_InitDepend(&type_str, type);
2796 nsres = nsIDOMProgressEvent_InitProgressEvent(This->nsevent, &type_str, !!can_bubble, !!cancelable,
2797 !!lengthComputable, loaded, total);
2798 nsAString_Finish(&type_str);
2799 if(NS_FAILED(nsres))
2800 return map_nsresult(nsres);
2801 This->manual_init = TRUE;
2804 return hres;
2807 static const IDOMProgressEventVtbl DOMProgressEventVtbl = {
2808 DOMProgressEvent_QueryInterface,
2809 DOMProgressEvent_AddRef,
2810 DOMProgressEvent_Release,
2811 DOMProgressEvent_GetTypeInfoCount,
2812 DOMProgressEvent_GetTypeInfo,
2813 DOMProgressEvent_GetIDsOfNames,
2814 DOMProgressEvent_Invoke,
2815 DOMProgressEvent_get_lengthComputable,
2816 DOMProgressEvent_get_loaded,
2817 DOMProgressEvent_get_total,
2818 DOMProgressEvent_initProgressEvent
2821 static DOMProgressEvent *DOMProgressEvent_from_DOMEvent(DOMEvent *event)
2823 return CONTAINING_RECORD(event, DOMProgressEvent, event);
2826 static void *DOMProgressEvent_query_interface(DispatchEx *dispex, REFIID riid)
2828 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2830 if(IsEqualGUID(&IID_IDOMProgressEvent, riid))
2831 return &This->IDOMProgressEvent_iface;
2832 return DOMEvent_query_interface(&This->event.dispex, riid);
2835 static void DOMProgressEvent_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
2837 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2838 DOMEvent_traverse(&This->event.dispex, cb);
2839 if(This->nsevent)
2840 note_cc_edge((nsISupports*)This->nsevent, "ProgressEvent.nsevent", cb);
2843 static void DOMProgressEvent_unlink(DispatchEx *dispex)
2845 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
2846 DOMEvent_unlink(&This->event.dispex);
2847 unlink_ref(&This->nsevent);
2850 typedef struct {
2851 DOMEvent event;
2852 IDOMStorageEvent IDOMStorageEvent_iface;
2853 BSTR key;
2854 BSTR old_value;
2855 BSTR new_value;
2856 BSTR url;
2857 } DOMStorageEvent;
2859 static inline DOMStorageEvent *impl_from_IDOMStorageEvent(IDOMStorageEvent *iface)
2861 return CONTAINING_RECORD(iface, DOMStorageEvent, IDOMStorageEvent_iface);
2864 static HRESULT WINAPI DOMStorageEvent_QueryInterface(IDOMStorageEvent *iface, REFIID riid, void **ppv)
2866 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2867 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2870 static ULONG WINAPI DOMStorageEvent_AddRef(IDOMStorageEvent *iface)
2872 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2873 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2876 static ULONG WINAPI DOMStorageEvent_Release(IDOMStorageEvent *iface)
2878 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2879 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2882 static HRESULT WINAPI DOMStorageEvent_GetTypeInfoCount(IDOMStorageEvent *iface, UINT *pctinfo)
2884 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2885 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2888 static HRESULT WINAPI DOMStorageEvent_GetTypeInfo(IDOMStorageEvent *iface, UINT iTInfo,
2889 LCID lcid, ITypeInfo **ppTInfo)
2891 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2892 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2895 static HRESULT WINAPI DOMStorageEvent_GetIDsOfNames(IDOMStorageEvent *iface, REFIID riid,
2896 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2898 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2899 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2900 lcid, rgDispId);
2903 static HRESULT WINAPI DOMStorageEvent_Invoke(IDOMStorageEvent *iface, DISPID dispIdMember,
2904 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2905 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2907 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2908 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2909 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2912 static HRESULT WINAPI DOMStorageEvent_get_key(IDOMStorageEvent *iface, BSTR *p)
2914 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2916 TRACE("(%p)->(%p)\n", This, p);
2918 if(This->key)
2919 return (*p = SysAllocStringLen(This->key, SysStringLen(This->key))) ? S_OK : E_OUTOFMEMORY;
2920 *p = NULL;
2921 return S_OK;
2924 static HRESULT WINAPI DOMStorageEvent_get_oldValue(IDOMStorageEvent *iface, BSTR *p)
2926 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2928 TRACE("(%p)->(%p)\n", This, p);
2930 if(This->old_value)
2931 return (*p = SysAllocStringLen(This->old_value, SysStringLen(This->old_value))) ? S_OK : E_OUTOFMEMORY;
2932 *p = NULL;
2933 return S_OK;
2936 static HRESULT WINAPI DOMStorageEvent_get_newValue(IDOMStorageEvent *iface, BSTR *p)
2938 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2940 TRACE("(%p)->(%p)\n", This, p);
2942 if(This->new_value)
2943 return (*p = SysAllocStringLen(This->new_value, SysStringLen(This->new_value))) ? S_OK : E_OUTOFMEMORY;
2944 *p = NULL;
2945 return S_OK;
2948 static HRESULT WINAPI DOMStorageEvent_get_url(IDOMStorageEvent *iface, BSTR *p)
2950 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2952 TRACE("(%p)->(%p)\n", This, p);
2954 if(This->url)
2955 return (*p = SysAllocStringLen(This->url, SysStringLen(This->url))) ? S_OK : E_OUTOFMEMORY;
2956 *p = NULL;
2957 return S_OK;
2960 static HRESULT WINAPI DOMStorageEvent_get_storageArea(IDOMStorageEvent *iface, IHTMLStorage **p)
2962 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2963 FIXME("(%p)->(%p)\n", This, p);
2964 return E_NOTIMPL;
2967 static HRESULT WINAPI DOMStorageEvent_initStorageEvent(IDOMStorageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2968 VARIANT_BOOL cancelable, BSTR keyArg, BSTR oldValueArg,
2969 BSTR newValueArg, BSTR urlArg, IHTMLStorage *storageAreaArg)
2971 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2972 FIXME("(%p)->(%s %x %x %s %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2973 debugstr_w(keyArg), debugstr_w(oldValueArg), debugstr_w(newValueArg), debugstr_w(urlArg), storageAreaArg);
2974 return E_NOTIMPL;
2977 static const IDOMStorageEventVtbl DOMStorageEventVtbl = {
2978 DOMStorageEvent_QueryInterface,
2979 DOMStorageEvent_AddRef,
2980 DOMStorageEvent_Release,
2981 DOMStorageEvent_GetTypeInfoCount,
2982 DOMStorageEvent_GetTypeInfo,
2983 DOMStorageEvent_GetIDsOfNames,
2984 DOMStorageEvent_Invoke,
2985 DOMStorageEvent_get_key,
2986 DOMStorageEvent_get_oldValue,
2987 DOMStorageEvent_get_newValue,
2988 DOMStorageEvent_get_url,
2989 DOMStorageEvent_get_storageArea,
2990 DOMStorageEvent_initStorageEvent
2993 static DOMStorageEvent *DOMStorageEvent_from_DOMEvent(DOMEvent *event)
2995 return CONTAINING_RECORD(event, DOMStorageEvent, event);
2998 static void *DOMStorageEvent_query_interface(DispatchEx *dispex, REFIID riid)
3000 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
3002 if(IsEqualGUID(&IID_IDOMStorageEvent, riid))
3003 return &storage_event->IDOMStorageEvent_iface;
3004 return DOMEvent_query_interface(&storage_event->event.dispex, riid);
3007 static void DOMStorageEvent_destructor(DispatchEx *dispex)
3009 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(DOMEvent_from_DispatchEx(dispex));
3010 SysFreeString(storage_event->key);
3011 SysFreeString(storage_event->old_value);
3012 SysFreeString(storage_event->new_value);
3013 SysFreeString(storage_event->url);
3014 DOMEvent_destructor(dispex);
3017 static const dispex_static_data_vtbl_t DOMEvent_dispex_vtbl = {
3018 .query_interface = DOMEvent_query_interface,
3019 .destructor = DOMEvent_destructor,
3020 .traverse = DOMEvent_traverse,
3021 .unlink = DOMEvent_unlink
3024 static const tid_t DOMEvent_iface_tids[] = {
3025 IDOMEvent_tid,
3029 static dispex_static_data_t DOMEvent_dispex = {
3030 "Event",
3031 &DOMEvent_dispex_vtbl,
3032 DispDOMEvent_tid,
3033 DOMEvent_iface_tids
3036 static const dispex_static_data_vtbl_t DOMUIEvent_dispex_vtbl = {
3037 .query_interface = DOMUIEvent_query_interface,
3038 .destructor = DOMEvent_destructor,
3039 .traverse = DOMUIEvent_traverse,
3040 .unlink = DOMUIEvent_unlink
3043 static const tid_t DOMUIEvent_iface_tids[] = {
3044 IDOMEvent_tid,
3045 IDOMUIEvent_tid,
3049 static dispex_static_data_t DOMUIEvent_dispex = {
3050 "UIEvent",
3051 &DOMUIEvent_dispex_vtbl,
3052 DispDOMUIEvent_tid,
3053 DOMUIEvent_iface_tids
3056 static const dispex_static_data_vtbl_t DOMMouseEvent_dispex_vtbl = {
3057 .query_interface = DOMMouseEvent_query_interface,
3058 .destructor = DOMEvent_destructor,
3059 .traverse = DOMMouseEvent_traverse,
3060 .unlink = DOMMouseEvent_unlink
3063 static const tid_t DOMMouseEvent_iface_tids[] = {
3064 IDOMEvent_tid,
3065 IDOMUIEvent_tid,
3066 IDOMMouseEvent_tid,
3070 static dispex_static_data_t DOMMouseEvent_dispex = {
3071 "MouseEvent",
3072 &DOMMouseEvent_dispex_vtbl,
3073 DispDOMMouseEvent_tid,
3074 DOMMouseEvent_iface_tids
3077 static const dispex_static_data_vtbl_t DOMKeyboardEvent_dispex_vtbl = {
3078 .query_interface = DOMKeyboardEvent_query_interface,
3079 .destructor = DOMEvent_destructor,
3080 .traverse = DOMKeyboardEvent_traverse,
3081 .unlink = DOMKeyboardEvent_unlink
3084 static const tid_t DOMKeyboardEvent_iface_tids[] = {
3085 IDOMEvent_tid,
3086 IDOMUIEvent_tid,
3087 IDOMKeyboardEvent_tid,
3091 static dispex_static_data_t DOMKeyboardEvent_dispex = {
3092 "KeyboardEvent",
3093 &DOMKeyboardEvent_dispex_vtbl,
3094 DispDOMKeyboardEvent_tid,
3095 DOMKeyboardEvent_iface_tids
3098 static void DOMPageTransitionEvent_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
3100 if(mode >= COMPAT_MODE_IE11)
3101 dispex_info_add_interface(info, IWinePageTransitionEvent_tid, NULL);
3104 static const dispex_static_data_vtbl_t DOMPageTransitionEvent_dispex_vtbl = {
3105 .query_interface = DOMPageTransitionEvent_query_interface,
3106 .destructor = DOMEvent_destructor,
3107 .traverse = DOMEvent_traverse,
3108 .unlink = DOMEvent_unlink
3111 static dispex_static_data_t DOMPageTransitionEvent_dispex = {
3112 "PageTransitionEvent",
3113 &DOMPageTransitionEvent_dispex_vtbl,
3114 DispDOMEvent_tid,
3115 DOMEvent_iface_tids,
3116 DOMPageTransitionEvent_init_dispex_info
3119 static const dispex_static_data_vtbl_t DOMCustomEvent_dispex_vtbl = {
3120 .query_interface = DOMCustomEvent_query_interface,
3121 .destructor = DOMCustomEvent_destructor,
3122 .traverse = DOMCustomEvent_traverse,
3123 .unlink = DOMCustomEvent_unlink
3126 static const tid_t DOMCustomEvent_iface_tids[] = {
3127 IDOMEvent_tid,
3128 IDOMCustomEvent_tid,
3132 static dispex_static_data_t DOMCustomEvent_dispex = {
3133 "CustomEvent",
3134 &DOMCustomEvent_dispex_vtbl,
3135 DispDOMCustomEvent_tid,
3136 DOMCustomEvent_iface_tids
3139 static const dispex_static_data_vtbl_t DOMMessageEvent_dispex_vtbl = {
3140 .query_interface = DOMMessageEvent_query_interface,
3141 .destructor = DOMMessageEvent_destructor,
3142 .traverse = DOMMessageEvent_traverse,
3143 .unlink = DOMMessageEvent_unlink
3146 static const tid_t DOMMessageEvent_iface_tids[] = {
3147 IDOMEvent_tid,
3151 static dispex_static_data_t DOMMessageEvent_dispex = {
3152 "MessageEvent",
3153 &DOMMessageEvent_dispex_vtbl,
3154 DispDOMMessageEvent_tid,
3155 DOMMessageEvent_iface_tids,
3156 DOMMessageEvent_init_dispex_info
3159 static const dispex_static_data_vtbl_t DOMProgressEvent_dispex_vtbl = {
3160 .query_interface = DOMProgressEvent_query_interface,
3161 .destructor = DOMEvent_destructor,
3162 .traverse = DOMProgressEvent_traverse,
3163 .unlink = DOMProgressEvent_unlink
3166 static const tid_t DOMProgressEvent_iface_tids[] = {
3167 IDOMEvent_tid,
3168 IDOMProgressEvent_tid,
3172 static dispex_static_data_t DOMProgressEvent_dispex = {
3173 "ProgressEvent",
3174 &DOMProgressEvent_dispex_vtbl,
3175 DispDOMProgressEvent_tid,
3176 DOMProgressEvent_iface_tids
3179 static const dispex_static_data_vtbl_t DOMStorageEvent_dispex_vtbl = {
3180 .query_interface = DOMStorageEvent_query_interface,
3181 .destructor = DOMStorageEvent_destructor,
3182 .traverse = DOMEvent_traverse,
3183 .unlink = DOMEvent_unlink
3186 static const tid_t DOMStorageEvent_iface_tids[] = {
3187 IDOMEvent_tid,
3188 IDOMStorageEvent_tid,
3192 static dispex_static_data_t DOMStorageEvent_dispex = {
3193 "StorageEvent",
3194 &DOMStorageEvent_dispex_vtbl,
3195 DispDOMStorageEvent_tid,
3196 DOMStorageEvent_iface_tids
3199 static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, nsIDOMEvent *nsevent, eventid_t event_id,
3200 compat_mode_t compat_mode)
3202 DOMEvent *event = calloc(1, size);
3204 if(!event)
3205 return NULL;
3206 event->IDOMEvent_iface.lpVtbl = &DOMEventVtbl;
3207 event->event_id = event_id;
3208 if(event_id != EVENTID_LAST) {
3209 event->type = wcsdup(event_info[event_id].name);
3210 if(!event->type) {
3211 free(event);
3212 return NULL;
3214 event->bubbles = (event_info[event_id].flags & EVENT_BUBBLES) != 0;
3215 event->cancelable = (event_info[event_id].flags & EVENT_CANCELABLE) != 0;
3217 nsIDOMEvent_AddRef(event->nsevent = nsevent);
3219 event->time_stamp = get_time_stamp();
3221 init_dispatch(&event->dispex, dispex_data, compat_mode);
3222 return event;
3225 static void fill_parent_ui_event(nsIDOMEvent *nsevent, DOMUIEvent *ui_event)
3227 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
3228 nsIDOMEvent_QueryInterface(nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event->nsevent);
3231 static DOMEvent *generic_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3233 return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, nsevent, event_id, compat_mode);
3236 static DOMEvent *ui_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3238 DOMUIEvent *ui_event = event_ctor(sizeof(DOMUIEvent), &DOMUIEvent_dispex, nsevent, event_id, compat_mode);
3239 if(!ui_event) return NULL;
3240 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
3241 ui_event->nsevent = iface;
3242 return &ui_event->event;
3245 static DOMEvent *mouse_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3247 DOMMouseEvent *mouse_event = event_ctor(sizeof(DOMMouseEvent), &DOMMouseEvent_dispex, nsevent, event_id, compat_mode);
3248 if(!mouse_event) return NULL;
3249 mouse_event->IDOMMouseEvent_iface.lpVtbl = &DOMMouseEventVtbl;
3250 mouse_event->nsevent = iface;
3251 fill_parent_ui_event(nsevent, &mouse_event->ui_event);
3252 return &mouse_event->ui_event.event;
3255 static DOMEvent *keyboard_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3257 DOMKeyboardEvent *keyboard_event = event_ctor(sizeof(DOMKeyboardEvent), &DOMKeyboardEvent_dispex, nsevent, event_id, compat_mode);
3258 if(!keyboard_event) return NULL;
3259 keyboard_event->IDOMKeyboardEvent_iface.lpVtbl = &DOMKeyboardEventVtbl;
3260 keyboard_event->nsevent = iface;
3261 fill_parent_ui_event(nsevent, &keyboard_event->ui_event);
3262 return &keyboard_event->ui_event.event;
3265 static DOMEvent *page_transition_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3267 DOMPageTransitionEvent *page_transition_event = event_ctor(sizeof(DOMCustomEvent), &DOMPageTransitionEvent_dispex, nsevent, event_id, compat_mode);
3268 if(!page_transition_event) return NULL;
3269 page_transition_event->IWinePageTransitionEvent_iface.lpVtbl = &DOMPageTransitionEventVtbl;
3270 return &page_transition_event->event;
3273 static DOMEvent *custom_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3275 DOMCustomEvent *custom_event = event_ctor(sizeof(DOMCustomEvent), &DOMCustomEvent_dispex, nsevent, event_id, compat_mode);
3276 if(!custom_event) return NULL;
3277 custom_event->IDOMCustomEvent_iface.lpVtbl = &DOMCustomEventVtbl;
3278 nsIDOMCustomEvent_Release(iface);
3279 return &custom_event->event;
3282 static DOMEvent *progress_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3284 DOMProgressEvent *progress_event;
3286 if(!(progress_event = event_ctor(sizeof(DOMProgressEvent), &DOMProgressEvent_dispex, nsevent, event_id, compat_mode)))
3287 return NULL;
3288 progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
3289 progress_event->nsevent = iface;
3290 return &progress_event->event;
3293 static DOMEvent *message_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3295 DOMMessageEvent *message_event = event_ctor(sizeof(DOMMessageEvent), &DOMMessageEvent_dispex, nsevent, event_id, compat_mode);
3296 if(!message_event) return NULL;
3297 message_event->IDOMMessageEvent_iface.lpVtbl = &DOMMessageEventVtbl;
3298 return &message_event->event;
3301 static DOMEvent *storage_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3303 DOMStorageEvent *storage_event = event_ctor(sizeof(DOMStorageEvent), &DOMStorageEvent_dispex, nsevent, event_id, compat_mode);
3304 if(!storage_event) return NULL;
3305 storage_event->IDOMStorageEvent_iface.lpVtbl = &DOMStorageEventVtbl;
3306 return &storage_event->event;
3309 static const struct {
3310 REFIID iid;
3311 DOMEvent *(*ctor)(void *iface, nsIDOMEvent *nsevent, eventid_t, compat_mode_t);
3312 compat_mode_t min_compat_mode;
3313 } event_types_ctor_table[] = {
3314 [EVENT_TYPE_EVENT] = { NULL, generic_event_ctor },
3315 [EVENT_TYPE_UIEVENT] = { &IID_nsIDOMUIEvent, ui_event_ctor },
3316 [EVENT_TYPE_MOUSE] = { &IID_nsIDOMMouseEvent, mouse_event_ctor },
3317 [EVENT_TYPE_KEYBOARD] = { &IID_nsIDOMKeyEvent, keyboard_event_ctor },
3318 [EVENT_TYPE_CLIPBOARD] = { NULL, generic_event_ctor },
3319 [EVENT_TYPE_FOCUS] = { NULL, generic_event_ctor },
3320 [EVENT_TYPE_DRAG] = { NULL, generic_event_ctor },
3321 [EVENT_TYPE_PAGETRANSITION] = { NULL, page_transition_event_ctor },
3322 [EVENT_TYPE_CUSTOM] = { &IID_nsIDOMCustomEvent, custom_event_ctor },
3323 [EVENT_TYPE_PROGRESS] = { &IID_nsIDOMProgressEvent, progress_event_ctor, COMPAT_MODE_IE10 },
3324 [EVENT_TYPE_MESSAGE] = { NULL, message_event_ctor },
3325 [EVENT_TYPE_STORAGE] = { NULL, storage_event_ctor },
3328 static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, event_type_t event_type,
3329 eventid_t event_id)
3331 void *iface = NULL;
3332 DOMEvent *event;
3334 if(compat_mode < event_types_ctor_table[event_type].min_compat_mode)
3335 event_type = EVENT_TYPE_EVENT;
3337 if(event_types_ctor_table[event_type].iid)
3338 nsIDOMEvent_QueryInterface(nsevent, event_types_ctor_table[event_type].iid, &iface);
3340 /* Transfer the iface ownership to the ctor on success */
3341 if(!(event = event_types_ctor_table[event_type].ctor(iface, nsevent, event_id, compat_mode)) && iface)
3342 nsISupports_Release(iface);
3343 return event;
3346 HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, compat_mode_t compat_mode, DOMEvent **ret_event)
3348 event_type_t event_type = EVENT_TYPE_EVENT;
3349 eventid_t event_id = EVENTID_LAST;
3350 DOMEvent *event;
3351 nsAString nsstr;
3352 nsresult nsres;
3353 unsigned i;
3355 nsAString_Init(&nsstr, NULL);
3356 nsres = nsIDOMEvent_GetType(nsevent, &nsstr);
3357 if(NS_SUCCEEDED(nsres)) {
3358 const WCHAR *type;
3359 nsAString_GetData(&nsstr, &type);
3360 event_id = str_to_eid(type);
3361 if(event_id == EVENTID_LAST)
3362 FIXME("unknown event type %s\n", debugstr_w(type));
3363 }else {
3364 ERR("GetType failed: %08lx\n", nsres);
3366 nsAString_Finish(&nsstr);
3368 for(i = 0; i < ARRAY_SIZE(event_types_ctor_table); i++) {
3369 void *iface;
3370 if(event_types_ctor_table[i].iid &&
3371 nsIDOMEvent_QueryInterface(nsevent, event_types_ctor_table[i].iid, &iface) == NS_OK) {
3372 nsISupports_Release(iface);
3373 event_type = i;
3374 break;
3378 event = alloc_event(nsevent, compat_mode, event_type, event_id);
3379 if(!event)
3380 return E_OUTOFMEMORY;
3382 event->trusted = TRUE;
3383 *ret_event = event;
3384 return S_OK;
3387 HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOMEvent **ret_event)
3389 event_type_t event_type = EVENT_TYPE_EVENT;
3390 nsIDOMEvent *nsevent;
3391 DOMEvent *event;
3392 nsAString nsstr;
3393 nsresult nsres;
3394 unsigned i;
3396 nsAString_InitDepend(&nsstr, type);
3397 nsres = nsIDOMDocument_CreateEvent(doc->dom_document, &nsstr, &nsevent);
3398 nsAString_Finish(&nsstr);
3399 if(NS_FAILED(nsres)) {
3400 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(type), nsres);
3401 return E_FAIL;
3404 for(i = 0; i < ARRAY_SIZE(event_types); i++) {
3405 if(!wcsicmp(type, event_types[i])) {
3406 event_type = i;
3407 break;
3411 event = alloc_event(nsevent, dispex_compat_mode(&doc->node.event_target.dispex),
3412 event_type, EVENTID_LAST);
3413 nsIDOMEvent_Release(nsevent);
3414 if(!event)
3415 return E_OUTOFMEMORY;
3417 *ret_event = &event->IDOMEvent_iface;
3418 return S_OK;
3421 HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEvent **ret_event)
3423 nsIDOMEvent *nsevent;
3424 DOMEvent *event;
3425 nsAString nsstr;
3426 nsresult nsres;
3428 nsAString_InitDepend(&nsstr, event_types[event_info[event_id].type]);
3429 nsres = nsIDOMDocument_CreateEvent(doc->dom_document, &nsstr, &nsevent);
3430 nsAString_Finish(&nsstr);
3431 if(NS_FAILED(nsres)) {
3432 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(event_types[event_info[event_id].type]), nsres);
3433 return E_FAIL;
3436 event = alloc_event(nsevent, doc->document_mode, event_info[event_id].type, event_id);
3437 nsIDOMEvent_Release(nsevent);
3438 if(!event)
3439 return E_OUTOFMEMORY;
3441 event->event_id = event_id;
3442 event->trusted = TRUE;
3443 *ret_event = event;
3444 return S_OK;
3447 HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **ret)
3449 DOMMessageEvent *message_event;
3450 DOMEvent *event;
3451 HRESULT hres;
3453 hres = create_document_event(doc, EVENTID_MESSAGE, &event);
3454 if(FAILED(hres))
3455 return hres;
3456 message_event = DOMMessageEvent_from_DOMEvent(event);
3458 V_VT(&message_event->data) = VT_EMPTY;
3459 hres = VariantCopy(&message_event->data, data);
3460 if(FAILED(hres)) {
3461 IDOMEvent_Release(&event->IDOMEvent_iface);
3462 return hres;
3465 *ret = event;
3466 return S_OK;
3469 HRESULT create_storage_event(HTMLDocumentNode *doc, BSTR key, BSTR old_value, BSTR new_value,
3470 const WCHAR *url, BOOL commit, DOMEvent **ret)
3472 DOMStorageEvent *storage_event;
3473 DOMEvent *event;
3474 HRESULT hres;
3476 hres = create_document_event(doc, commit ? EVENTID_STORAGECOMMIT : EVENTID_STORAGE, &event);
3477 if(FAILED(hres))
3478 return hres;
3479 storage_event = DOMStorageEvent_from_DOMEvent(event);
3481 if(!commit) {
3482 if((key && !(storage_event->key = SysAllocString(key))) ||
3483 (old_value && !(storage_event->old_value = SysAllocString(old_value))) ||
3484 (new_value && !(storage_event->new_value = SysAllocString(new_value)))) {
3485 IDOMEvent_Release(&event->IDOMEvent_iface);
3486 return E_OUTOFMEMORY;
3490 if(url && !(storage_event->url = SysAllocString(url))) {
3491 IDOMEvent_Release(&event->IDOMEvent_iface);
3492 return E_OUTOFMEMORY;
3495 *ret = event;
3496 return S_OK;
3499 HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
3501 IDispatchEx *dispex;
3502 EXCEPINFO ei;
3503 HRESULT hres;
3505 memset(&ei, 0, sizeof(ei));
3507 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
3508 if(SUCCEEDED(hres)) {
3509 hres = IDispatchEx_InvokeEx(dispex, 0, GetUserDefaultLCID(), DISPATCH_METHOD, dp, retv, &ei, NULL);
3510 IDispatchEx_Release(dispex);
3511 }else {
3512 TRACE("Could not get IDispatchEx interface: %08lx\n", hres);
3513 hres = IDispatch_Invoke(disp, 0, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD,
3514 dp, retv, &ei, NULL);
3517 return hres;
3520 static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, IHTMLEventObj *event_obj, VARIANT *retv)
3522 DISPPARAMS dp = {NULL,NULL,0,0};
3523 VARIANT event_arg;
3524 UINT argerr;
3525 EXCEPINFO ei;
3527 TRACE("%p,%ld,%p,%p\n", disp, dispid, event_obj, retv);
3529 if(event_obj) {
3530 V_VT(&event_arg) = VT_DISPATCH;
3531 V_DISPATCH(&event_arg) = (IDispatch*)event_obj;
3532 dp.rgvarg = &event_arg;
3533 dp.cArgs = 1;
3536 memset(&ei, 0, sizeof(ei));
3537 return IDispatch_Invoke(disp, dispid, &IID_NULL, 0, DISPATCH_METHOD, &dp, retv, &ei, &argerr);
3540 static BOOL use_event_quirks(EventTarget *event_target)
3542 return dispex_compat_mode(&event_target->dispex) < COMPAT_MODE_IE9;
3545 static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
3547 int min, max, i;
3548 HRESULT hres;
3550 if(!data || dispid == DISPID_UNKNOWN)
3551 return FALSE;
3553 if(!data->ids) {
3554 hres = get_dispids(data->tid, &data->id_cnt, &data->ids);
3555 if(FAILED(hres))
3556 return FALSE;
3559 min = 0;
3560 max = data->id_cnt-1;
3561 while(min <= max) {
3562 i = (min+max)/2;
3563 if(data->ids[i] == dispid)
3564 return TRUE;
3566 if(data->ids[i] < dispid)
3567 min = i+1;
3568 else
3569 max = i-1;
3572 return FALSE;
3575 static void call_event_handlers(EventTarget *event_target, DOMEvent *event, dispatch_mode_t dispatch_mode)
3577 const listener_container_t *container = get_listener_container(event_target, event->type, FALSE);
3578 const event_target_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
3579 event_listener_t *listener, listeners_buf[8], *listeners = listeners_buf;
3580 unsigned listeners_cnt, listeners_size;
3581 ConnectionPointContainer *cp_container = NULL;
3582 BOOL skip_onevent_listener = FALSE;
3583 VARIANT v;
3584 HRESULT hres;
3586 assert(!event->current_target);
3587 event->current_target = event_target;
3589 if(container && !list_empty(&container->listeners) && event->phase != DEP_CAPTURING_PHASE) {
3590 listener = LIST_ENTRY(list_tail(&container->listeners), event_listener_t, entry);
3591 if(listener && listener->function && listener->type == LISTENER_TYPE_ONEVENT
3592 && use_event_quirks(event_target)) {
3593 DISPID named_arg = DISPID_THIS;
3594 VARIANTARG arg;
3595 DISPPARAMS dp = {&arg, &named_arg, 1, 1};
3597 skip_onevent_listener = TRUE;
3599 V_VT(&arg) = VT_DISPATCH;
3600 V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3601 V_VT(&v) = VT_EMPTY;
3602 if(vtbl->get_dispatch_this)
3603 V_DISPATCH(&arg) = vtbl->get_dispatch_this(&event_target->dispex);
3604 IDispatch_AddRef(V_DISPATCH(&arg));
3606 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3607 hres = call_disp_func(listener->function, &dp, &v);
3608 IDispatch_Release(V_DISPATCH(&arg));
3610 if(hres == S_OK) {
3611 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type), debugstr_variant(&v));
3613 if(event->cancelable) {
3614 if(V_VT(&v) == VT_BOOL) {
3615 if(!V_BOOL(&v))
3616 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3617 }else if(V_VT(&v) != VT_EMPTY) {
3618 FIXME("unhandled result %s\n", debugstr_variant(&v));
3621 VariantClear(&v);
3622 }else {
3623 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3628 listeners_cnt = 0;
3629 listeners_size = ARRAY_SIZE(listeners_buf);
3631 if(container) {
3632 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
3633 if(!listener->function)
3634 continue;
3635 switch(listener->type) {
3636 case LISTENER_TYPE_ONEVENT:
3637 if(skip_onevent_listener || event->phase == DEP_CAPTURING_PHASE)
3638 continue;
3639 break;
3640 case LISTENER_TYPE_CAPTURE:
3641 if(event->phase == DEP_BUBBLING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3642 continue;
3643 break;
3644 case LISTENER_TYPE_BUBBLE:
3645 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3646 continue;
3647 break;
3648 case LISTENER_TYPE_ATTACHED:
3649 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_STANDARD)
3650 continue;
3651 break;
3654 if(listeners_cnt == listeners_size) {
3655 event_listener_t *new_listeners;
3656 if(listeners == listeners_buf) {
3657 new_listeners = malloc(listeners_size * 2 * sizeof(*new_listeners));
3658 if(!new_listeners)
3659 break;
3660 memcpy(new_listeners, listeners, listeners_cnt * sizeof(*listeners));
3661 }else {
3662 new_listeners = realloc(listeners, listeners_size * 2 * sizeof(*new_listeners));
3664 listeners = new_listeners;
3665 listeners_size *= 2;
3668 listeners[listeners_cnt].type = listener->type;
3669 IDispatch_AddRef(listeners[listeners_cnt].function = listener->function);
3670 listeners_cnt++;
3674 for(listener = listeners; !event->stop_immediate_propagation
3675 && listener < listeners + listeners_cnt; listener++) {
3676 if(listener->type != LISTENER_TYPE_ATTACHED) {
3677 DISPID named_arg = DISPID_THIS;
3678 VARIANTARG args[2];
3679 DISPPARAMS dp = {args, &named_arg, 2, 1};
3681 V_VT(args) = VT_DISPATCH;
3682 V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3683 if(vtbl->get_dispatch_this)
3684 V_DISPATCH(args) = vtbl->get_dispatch_this(&event_target->dispex);
3685 IDispatch_AddRef(V_DISPATCH(args));
3687 V_VT(args+1) = VT_DISPATCH;
3688 V_DISPATCH(args+1) = dispatch_mode == DISPATCH_LEGACY
3689 ? (IDispatch*)event->event_obj : (IDispatch*)&event->IDOMEvent_iface;
3690 V_VT(&v) = VT_EMPTY;
3692 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3693 hres = call_disp_func(listener->function, &dp, &v);
3694 IDispatch_Release(V_DISPATCH(args));
3696 if(hres == S_OK) {
3697 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type),
3698 debugstr_variant(&v));
3700 if(event->cancelable) {
3701 if(V_VT(&v) == VT_BOOL) {
3702 if(!V_BOOL(&v))
3703 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3704 }else if(V_VT(&v) != VT_EMPTY) {
3705 FIXME("unhandled result %s\n", debugstr_variant(&v));
3708 VariantClear(&v);
3709 }else {
3710 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3712 }else {
3713 VARIANTARG arg;
3714 DISPPARAMS dp = {&arg, NULL, 1, 0};
3716 V_VT(&arg) = VT_DISPATCH;
3717 V_DISPATCH(&arg) = (IDispatch*)event->event_obj;
3718 V_VT(&v) = VT_EMPTY;
3720 TRACE("%p %s attached >>>\n", event_target, debugstr_w(event->type));
3721 hres = call_disp_func(listener->function, &dp, &v);
3722 if(hres == S_OK) {
3723 TRACE("%p %s attached <<<\n", event_target, debugstr_w(event->type));
3725 if(event->cancelable) {
3726 if(V_VT(&v) == VT_BOOL) {
3727 if(!V_BOOL(&v))
3728 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3729 }else if(V_VT(&v) != VT_EMPTY) {
3730 FIXME("unhandled result %s\n", debugstr_variant(&v));
3733 VariantClear(&v);
3734 }else {
3735 WARN("%p %s attached <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3740 for(listener = listeners; listener < listeners + listeners_cnt; listener++)
3741 IDispatch_Release(listener->function);
3742 if(listeners != listeners_buf)
3743 free(listeners);
3745 if(event->phase != DEP_CAPTURING_PHASE && event_info[event->event_id].dispid && vtbl->get_cp_container)
3746 cp_container = vtbl->get_cp_container(&event_target->dispex);
3747 if(cp_container) {
3748 if(cp_container->cps) {
3749 ConnectionPoint *cp;
3750 unsigned i, j;
3752 for(j=0; cp_container->cp_entries[j].riid; j++) {
3753 cp = cp_container->cps + j;
3754 if(!cp->sinks_size || !is_cp_event(cp->data, event_info[event->event_id].dispid))
3755 continue;
3757 for(i=0; i < cp->sinks_size; i++) {
3758 if(!cp->sinks[i].disp)
3759 continue;
3761 V_VT(&v) = VT_EMPTY;
3763 TRACE("%p cp %s [%u] >>>\n", event_target, debugstr_w(event->type), i);
3764 hres = call_cp_func(cp->sinks[i].disp, event_info[event->event_id].dispid,
3765 cp->data->pass_event_arg ? event->event_obj : NULL, &v);
3766 if(hres == S_OK) {
3767 TRACE("%p cp %s [%u] <<<\n", event_target, debugstr_w(event->type), i);
3769 if(event->cancelable) {
3770 if(V_VT(&v) == VT_BOOL) {
3771 if(!V_BOOL(&v))
3772 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3773 }else if(V_VT(&v) != VT_EMPTY) {
3774 FIXME("unhandled result %s\n", debugstr_variant(&v));
3777 VariantClear(&v);
3778 }else {
3779 WARN("%p cp %s [%u] <<< %08lx\n", event_target, debugstr_w(event->type), i, hres);
3784 IConnectionPointContainer_Release(&cp_container->IConnectionPointContainer_iface);
3787 event->current_target = NULL;
3790 static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event,
3791 dispatch_mode_t dispatch_mode, VARIANT_BOOL *r)
3793 EventTarget *target_chain_buf[8], **target_chain = target_chain_buf;
3794 unsigned chain_cnt, chain_buf_size, i;
3795 const event_target_vtbl_t *vtbl, *target_vtbl;
3796 HTMLEventObj *event_obj_ref = NULL;
3797 IHTMLEventObj *prev_event = NULL;
3798 EventTarget *iter;
3799 HRESULT hres;
3801 TRACE("(%p) %s\n", event_target, debugstr_w(event->type));
3803 if(!event->type) {
3804 FIXME("Uninitialized event.\n");
3805 return E_FAIL;
3808 if(event->current_target) {
3809 FIXME("event is being dispatched.\n");
3810 return E_FAIL;
3813 iter = event_target;
3814 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3816 chain_cnt = 0;
3817 chain_buf_size = ARRAY_SIZE(target_chain_buf);
3819 do {
3820 if(chain_cnt == chain_buf_size) {
3821 EventTarget **new_chain;
3822 if(target_chain == target_chain_buf) {
3823 new_chain = malloc(chain_buf_size * 2 * sizeof(*new_chain));
3824 if(!new_chain)
3825 break;
3826 memcpy(new_chain, target_chain, chain_buf_size * sizeof(*new_chain));
3827 }else {
3828 new_chain = realloc(target_chain, chain_buf_size * 2 * sizeof(*new_chain));
3829 if(!new_chain)
3830 break;
3832 chain_buf_size *= 2;
3833 target_chain = new_chain;
3836 target_chain[chain_cnt++] = iter;
3838 if(!(vtbl = dispex_get_vtbl(&iter->dispex))->get_parent_event_target)
3839 break;
3840 iter = vtbl->get_parent_event_target(&iter->dispex);
3841 } while(iter);
3843 if(!event->event_obj && !event->no_event_obj) {
3844 event_obj_ref = alloc_event_obj(event, dispex_compat_mode(&event->dispex));
3845 if(event_obj_ref)
3846 event->event_obj = &event_obj_ref->IHTMLEventObj_iface;
3849 target_vtbl = dispex_get_vtbl(&event_target->dispex);
3850 if(target_vtbl->set_current_event)
3851 prev_event = target_vtbl->set_current_event(&event_target->dispex, event->event_obj);
3853 if(event->target)
3854 IEventTarget_Release(&event->target->IEventTarget_iface);
3855 event->target = event_target;
3856 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3858 event->phase = DEP_CAPTURING_PHASE;
3859 i = chain_cnt-1;
3860 while(!event->stop_propagation && i)
3861 call_event_handlers(target_chain[i--], event, dispatch_mode);
3863 if(!event->stop_propagation) {
3864 event->phase = DEP_AT_TARGET;
3865 call_event_handlers(target_chain[0], event, dispatch_mode);
3868 if(event->bubbles) {
3869 event->phase = DEP_BUBBLING_PHASE;
3870 for(i = 1; !event->stop_propagation && i < chain_cnt; i++)
3871 call_event_handlers(target_chain[i], event, dispatch_mode);
3874 if(r)
3875 *r = variant_bool(!event->prevent_default);
3877 if(target_vtbl->set_current_event) {
3878 IHTMLEventObj *prev = target_vtbl->set_current_event(&event_target->dispex, prev_event);
3879 if(prev)
3880 IHTMLEventObj_Release(prev);
3883 if(prev_event)
3884 IHTMLEventObj_Release(prev_event);
3886 if(event_info[event->event_id].flags & EVENT_HASDEFAULTHANDLERS) {
3887 BOOL prevent_default = event->prevent_default;
3888 for(i = 0; !prevent_default && i < chain_cnt; i++) {
3889 vtbl = dispex_get_vtbl(&target_chain[i]->dispex);
3890 if(!vtbl->handle_event)
3891 continue;
3892 hres = vtbl->handle_event(&event_target->dispex, event->event_id, event->nsevent, &prevent_default);
3893 if(FAILED(hres) || event->stop_propagation)
3894 break;
3895 if(prevent_default)
3896 nsIDOMEvent_PreventDefault(event->nsevent);
3900 event->prevent_default = FALSE;
3901 if(event_obj_ref) {
3902 event->event_obj = NULL;
3903 IHTMLEventObj_Release(&event_obj_ref->IHTMLEventObj_iface);
3906 for(i = 0; i < chain_cnt; i++)
3907 IEventTarget_Release(&target_chain[i]->IEventTarget_iface);
3908 if(target_chain != target_chain_buf)
3909 free(target_chain);
3911 return S_OK;
3914 void dispatch_event(EventTarget *event_target, DOMEvent *event)
3916 dispatch_event_object(event_target, event, DISPATCH_BOTH, NULL);
3919 * We may have registered multiple Gecko listeners for the same event type,
3920 * but we already dispatched event to all relevant targets. Stop event
3921 * propagation here to avoid events being dispatched multiple times.
3923 if(event_info[event->event_id].flags & EVENT_BIND_TO_TARGET)
3924 nsIDOMEvent_StopPropagation(event->nsevent);
3927 HRESULT fire_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_var, VARIANT_BOOL *cancelled)
3929 HTMLEventObj *event_obj = NULL;
3930 eventid_t eid;
3931 HRESULT hres = S_OK;
3933 eid = attr_to_eid(event_name);
3934 if(eid == EVENTID_LAST) {
3935 WARN("unknown event %s\n", debugstr_w(event_name));
3936 return E_INVALIDARG;
3939 if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
3940 if(V_VT(event_var) != VT_DISPATCH) {
3941 FIXME("event_var %s not supported\n", debugstr_variant(event_var));
3942 return E_NOTIMPL;
3945 if(V_DISPATCH(event_var)) {
3946 IHTMLEventObj *event_iface;
3948 hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
3949 if(FAILED(hres)) {
3950 FIXME("No IHTMLEventObj iface\n");
3951 return hres;
3954 event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
3955 if(!event_obj) {
3956 ERR("Not our IHTMLEventObj?\n");
3957 IHTMLEventObj_Release(event_iface);
3958 return E_FAIL;
3963 if(!event_obj) {
3964 event_obj = alloc_event_obj(NULL, dispex_compat_mode(&node->event_target.dispex));
3965 if(!event_obj)
3966 return E_OUTOFMEMORY;
3969 if(!event_obj->event)
3970 hres = create_document_event(node->doc, eid, &event_obj->event);
3972 if(SUCCEEDED(hres)) {
3973 event_obj->event->event_obj = &event_obj->IHTMLEventObj_iface;
3974 dispatch_event_object(&node->event_target, event_obj->event, DISPATCH_LEGACY, NULL);
3975 event_obj->event->event_obj = NULL;
3978 IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
3979 if(FAILED(hres))
3980 return hres;
3982 *cancelled = VARIANT_TRUE; /* FIXME */
3983 return S_OK;
3986 HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, nsIDOMNode *nsnode, eventid_t eid)
3988 TRACE("%s\n", debugstr_w(event_info[eid].name));
3990 if(!doc->dom_document)
3991 return S_OK;
3993 switch(eid) {
3994 case EVENTID_FOCUSIN:
3995 doc->event_vector[eid] = TRUE;
3996 eid = EVENTID_FOCUS;
3997 break;
3998 case EVENTID_FOCUSOUT:
3999 doc->event_vector[eid] = TRUE;
4000 eid = EVENTID_BLUR;
4001 break;
4002 default:
4003 break;
4006 if(event_info[eid].flags & EVENT_DEFAULTLISTENER) {
4007 nsnode = NULL;
4008 }else if(!(event_info[eid].flags & EVENT_BIND_TO_TARGET)) {
4009 return S_OK;
4012 if(!nsnode || nsnode == doc->node.nsnode) {
4013 if(doc->event_vector[eid])
4014 return S_OK;
4015 doc->event_vector[eid] = TRUE;
4018 add_nsevent_listener(doc, nsnode, event_info[eid].name);
4019 return S_OK;
4022 void detach_events(HTMLDocumentNode *doc)
4024 if(doc->event_vector) {
4025 int i;
4027 for(i=0; i < EVENTID_LAST; i++) {
4028 if(doc->event_vector[i]) {
4029 detach_nsevent(doc, event_info[i].name);
4030 doc->event_vector[i] = FALSE;
4035 release_nsevents(doc);
4038 static HRESULT get_event_dispex_ref(EventTarget *event_target, eventid_t eid, BOOL alloc, VARIANT **ret)
4040 WCHAR buf[64];
4041 buf[0] = 'o';
4042 buf[1] = 'n';
4043 lstrcpyW(buf+2, event_info[eid].name);
4044 return dispex_get_dprop_ref(&event_target->dispex, buf, alloc, ret);
4047 static event_listener_t *get_onevent_listener(EventTarget *event_target, eventid_t eid, BOOL alloc)
4049 listener_container_t *container;
4050 event_listener_t *listener;
4052 container = get_listener_container(event_target, event_info[eid].name, alloc);
4053 if(!container)
4054 return NULL;
4056 LIST_FOR_EACH_ENTRY_REV(listener, &container->listeners, event_listener_t, entry) {
4057 if(listener->type == LISTENER_TYPE_ONEVENT)
4058 return listener;
4061 if(!alloc)
4062 return NULL;
4064 listener = malloc(sizeof(*listener));
4065 if(!listener)
4066 return NULL;
4068 listener->type = LISTENER_TYPE_ONEVENT;
4069 listener->function = NULL;
4070 list_add_tail(&container->listeners, &listener->entry);
4071 return listener;
4074 static void remove_event_handler(EventTarget *event_target, eventid_t eid)
4076 event_listener_t *listener;
4077 VARIANT *store;
4078 HRESULT hres;
4080 hres = get_event_dispex_ref(event_target, eid, FALSE, &store);
4081 if(SUCCEEDED(hres))
4082 VariantClear(store);
4084 listener = get_onevent_listener(event_target, eid, FALSE);
4085 if(listener && listener->function) {
4086 IDispatch_Release(listener->function);
4087 listener->function = NULL;
4091 static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp)
4093 event_listener_t *listener;
4095 if(event_info[eid].flags & EVENT_FIXME)
4096 FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
4098 remove_event_handler(event_target, eid);
4099 if(!disp)
4100 return S_OK;
4102 listener = get_onevent_listener(event_target, eid, TRUE);
4103 if(!listener)
4104 return E_OUTOFMEMORY;
4106 if(listener->function)
4107 IDispatch_Release(listener->function);
4109 IDispatch_AddRef(listener->function = disp);
4110 return S_OK;
4113 HRESULT set_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
4115 switch(V_VT(var)) {
4116 case VT_EMPTY:
4117 if(use_event_quirks(event_target)) {
4118 WARN("attempt to set to VT_EMPTY in quirks mode\n");
4119 return E_NOTIMPL;
4121 /* fall through */
4122 case VT_NULL:
4123 remove_event_handler(event_target, eid);
4124 return S_OK;
4126 case VT_DISPATCH:
4127 return set_event_handler_disp(event_target, eid, V_DISPATCH(var));
4129 case VT_BSTR: {
4130 VARIANT *v;
4131 HRESULT hres;
4133 if(!use_event_quirks(event_target))
4134 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var)));
4137 * Setting event handler to string is a rare case and we don't want to
4138 * complicate nor increase memory of listener_container_t for that. Instead,
4139 * we store the value in DispatchEx, which can already handle custom
4140 * properties.
4142 remove_event_handler(event_target, eid);
4144 hres = get_event_dispex_ref(event_target, eid, TRUE, &v);
4145 if(FAILED(hres))
4146 return hres;
4148 V_BSTR(v) = SysAllocString(V_BSTR(var));
4149 if(!V_BSTR(v))
4150 return E_OUTOFMEMORY;
4151 V_VT(v) = VT_BSTR;
4152 return S_OK;
4155 default:
4156 FIXME("not handler %s\n", debugstr_variant(var));
4157 return E_NOTIMPL;
4160 return S_OK;
4163 HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
4165 event_listener_t *listener;
4166 VARIANT *v;
4167 HRESULT hres;
4169 hres = get_event_dispex_ref(event_target, eid, FALSE, &v);
4170 if(SUCCEEDED(hres) && V_VT(v) != VT_EMPTY) {
4171 V_VT(var) = VT_EMPTY;
4172 return VariantCopy(var, v);
4175 listener = get_onevent_listener(event_target, eid, FALSE);
4176 if(listener && listener->function) {
4177 V_VT(var) = VT_DISPATCH;
4178 V_DISPATCH(var) = listener->function;
4179 IDispatch_AddRef(V_DISPATCH(var));
4180 }else {
4181 V_VT(var) = VT_NULL;
4184 return S_OK;
4187 HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
4189 listener_container_t *container;
4190 event_listener_t *listener;
4191 eventid_t eid;
4193 if(!disp) {
4194 *res = VARIANT_FALSE;
4195 return S_OK;
4198 eid = attr_to_eid(name);
4199 if(eid == EVENTID_LAST) {
4200 WARN("Unknown event\n");
4201 *res = VARIANT_TRUE;
4202 return S_OK;
4205 container = get_listener_container(event_target, event_info[eid].name, TRUE);
4206 if(!container)
4207 return E_OUTOFMEMORY;
4209 listener = malloc(sizeof(*listener));
4210 if(!listener)
4211 return E_OUTOFMEMORY;
4213 listener->type = LISTENER_TYPE_ATTACHED;
4214 IDispatch_AddRef(listener->function = disp);
4215 if(use_event_quirks(event_target))
4216 list_add_head(&container->listeners, &listener->entry);
4217 else
4218 list_add_tail(&container->listeners, &listener->entry);
4220 *res = VARIANT_TRUE;
4221 return S_OK;
4224 HRESULT detach_event(EventTarget *event_target, BSTR name, IDispatch *disp)
4226 eventid_t eid;
4228 eid = attr_to_eid(name);
4229 if(eid == EVENTID_LAST) {
4230 WARN("Unknown event\n");
4231 return S_OK;
4234 remove_event_listener(event_target, event_info[eid].name, LISTENER_TYPE_ATTACHED, disp);
4235 return S_OK;
4238 void bind_target_event(HTMLDocumentNode *doc, EventTarget *event_target, const WCHAR *event, IDispatch *disp)
4240 eventid_t eid;
4242 TRACE("(%p %p %s %p)\n", doc, event_target, debugstr_w(event), disp);
4244 eid = attr_to_eid(event);
4245 if(eid == EVENTID_LAST) {
4246 WARN("Unsupported event %s\n", debugstr_w(event));
4247 return;
4250 set_event_handler_disp(event_target, eid, disp);
4253 void update_doc_cp_events(HTMLDocumentNode *doc, cp_static_data_t *cp)
4255 int i;
4257 for(i=0; i < EVENTID_LAST; i++) {
4258 if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid))
4259 ensure_doc_nsevent_handler(doc, NULL, i);
4263 void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem)
4265 nsIDOMMozNamedAttrMap *attr_map;
4266 const PRUnichar *name, *value;
4267 nsAString name_str, value_str;
4268 HTMLDOMNode *node = NULL;
4269 cpp_bool has_attrs;
4270 nsIDOMAttr *attr;
4271 IDispatch *disp;
4272 UINT32 length, i;
4273 eventid_t eid;
4274 nsresult nsres;
4275 HRESULT hres;
4277 nsres = nsIDOMElement_HasAttributes(nselem, &has_attrs);
4278 if(NS_FAILED(nsres) || !has_attrs)
4279 return;
4281 nsres = nsIDOMElement_GetAttributes(nselem, &attr_map);
4282 if(NS_FAILED(nsres))
4283 return;
4285 nsres = nsIDOMMozNamedAttrMap_GetLength(attr_map, &length);
4286 assert(nsres == NS_OK);
4288 nsAString_Init(&name_str, NULL);
4289 nsAString_Init(&value_str, NULL);
4291 for(i = 0; i < length; i++) {
4292 nsres = nsIDOMMozNamedAttrMap_Item(attr_map, i, &attr);
4293 if(NS_FAILED(nsres))
4294 continue;
4296 nsres = nsIDOMAttr_GetName(attr, &name_str);
4297 if(NS_FAILED(nsres)) {
4298 nsIDOMAttr_Release(attr);
4299 continue;
4302 nsAString_GetData(&name_str, &name);
4303 eid = attr_to_eid(name);
4304 if(eid == EVENTID_LAST) {
4305 nsIDOMAttr_Release(attr);
4306 continue;
4309 nsres = nsIDOMAttr_GetValue(attr, &value_str);
4310 nsIDOMAttr_Release(attr);
4311 if(NS_FAILED(nsres))
4312 continue;
4314 nsAString_GetData(&value_str, &value);
4315 if(!*value)
4316 continue;
4318 TRACE("%p.%s = %s\n", nselem, debugstr_w(name), debugstr_w(value));
4320 disp = script_parse_event(doc->window, value);
4321 if(!disp)
4322 continue;
4324 if(!node) {
4325 hres = get_node((nsIDOMNode*)nselem, TRUE, &node);
4326 if(FAILED(hres)) {
4327 IDispatch_Release(disp);
4328 break;
4332 set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp);
4333 IDispatch_Release(disp);
4336 if(node)
4337 node_release(node);
4338 nsAString_Finish(&name_str);
4339 nsAString_Finish(&value_str);
4340 nsIDOMMozNamedAttrMap_Release(attr_map);
4343 HRESULT doc_init_events(HTMLDocumentNode *doc)
4345 unsigned i;
4346 HRESULT hres;
4348 doc->event_vector = calloc(EVENTID_LAST, sizeof(BOOL));
4349 if(!doc->event_vector)
4350 return E_OUTOFMEMORY;
4352 init_nsevents(doc);
4354 for(i=0; i < EVENTID_LAST; i++) {
4355 if(event_info[i].flags & EVENT_HASDEFAULTHANDLERS) {
4356 hres = ensure_doc_nsevent_handler(doc, NULL, i);
4357 if(FAILED(hres))
4358 return hres;
4362 return S_OK;
4365 static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
4367 return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
4370 static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
4372 EventTarget *This = impl_from_IEventTarget(iface);
4373 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
4376 static ULONG WINAPI EventTarget_AddRef(IEventTarget *iface)
4378 EventTarget *This = impl_from_IEventTarget(iface);
4379 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
4382 static ULONG WINAPI EventTarget_Release(IEventTarget *iface)
4384 EventTarget *This = impl_from_IEventTarget(iface);
4385 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
4388 static HRESULT WINAPI EventTarget_GetTypeInfoCount(IEventTarget *iface, UINT *pctinfo)
4390 EventTarget *This = impl_from_IEventTarget(iface);
4391 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
4394 static HRESULT WINAPI EventTarget_GetTypeInfo(IEventTarget *iface, UINT iTInfo,
4395 LCID lcid, ITypeInfo **ppTInfo)
4397 EventTarget *This = impl_from_IEventTarget(iface);
4398 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
4401 static HRESULT WINAPI EventTarget_GetIDsOfNames(IEventTarget *iface, REFIID riid, LPOLESTR *rgszNames,
4402 UINT cNames, LCID lcid, DISPID *rgDispId)
4404 EventTarget *This = impl_from_IEventTarget(iface);
4405 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid,
4406 rgszNames, cNames, lcid, rgDispId);
4409 static HRESULT WINAPI EventTarget_Invoke(IEventTarget *iface, DISPID dispIdMember,
4410 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
4411 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
4413 EventTarget *This = impl_from_IEventTarget(iface);
4414 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember,
4415 riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4418 static HRESULT WINAPI EventTarget_addEventListener(IEventTarget *iface, BSTR type,
4419 IDispatch *function, VARIANT_BOOL capture)
4421 EventTarget *This = impl_from_IEventTarget(iface);
4422 listener_type_t listener_type = capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE;
4423 listener_container_t *container;
4424 event_listener_t *listener;
4426 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), function, capture);
4428 if(!function)
4429 return S_OK;
4431 container = get_listener_container(This, type, TRUE);
4432 if(!container)
4433 return E_OUTOFMEMORY;
4435 /* check for duplicates */
4436 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
4437 if(listener->type == listener_type && listener->function == function)
4438 return S_OK;
4441 listener = malloc(sizeof(*listener));
4442 if(!listener)
4443 return E_OUTOFMEMORY;
4445 listener->type = listener_type;
4446 IDispatch_AddRef(listener->function = function);
4447 list_add_tail(&container->listeners, &listener->entry);
4448 return S_OK;
4451 static HRESULT WINAPI EventTarget_removeEventListener(IEventTarget *iface, BSTR type,
4452 IDispatch *listener, VARIANT_BOOL capture)
4454 EventTarget *This = impl_from_IEventTarget(iface);
4456 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
4458 remove_event_listener(This, type, capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE, listener);
4459 return S_OK;
4462 static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event_iface, VARIANT_BOOL *result)
4464 EventTarget *This = impl_from_IEventTarget(iface);
4465 DOMEvent *event = unsafe_impl_from_IDOMEvent(event_iface);
4467 TRACE("(%p)->(%p %p)\n", This, event, result);
4469 if(!event) {
4470 WARN("Invalid event\n");
4471 return E_INVALIDARG;
4474 return dispatch_event_object(This, event, DISPATCH_STANDARD, result);
4477 static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, WORD flags,
4478 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4480 /* If only two arguments were given, implicitly set capture to false */
4481 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4482 VARIANT args[3];
4483 DISPPARAMS new_dp = {args, NULL, 3, 0};
4484 V_VT(args) = VT_BOOL;
4485 V_BOOL(args) = VARIANT_FALSE;
4486 args[1] = dp->rgvarg[0];
4487 args[2] = dp->rgvarg[1];
4489 TRACE("implicit capture\n");
4491 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_ADDEVENTLISTENER, &new_dp, res, ei, caller);
4494 return S_FALSE; /* fallback to default */
4497 static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, WORD flags,
4498 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4500 /* If only two arguments were given, implicitly set capture to false */
4501 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4502 VARIANT args[3];
4503 DISPPARAMS new_dp = {args, NULL, 3, 0};
4504 V_VT(args) = VT_BOOL;
4505 V_BOOL(args) = VARIANT_FALSE;
4506 args[1] = dp->rgvarg[0];
4507 args[2] = dp->rgvarg[1];
4509 TRACE("implicit capture\n");
4511 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, &new_dp, res, ei, caller);
4514 return S_FALSE; /* fallback to default */
4517 static const IEventTargetVtbl EventTargetVtbl = {
4518 EventTarget_QueryInterface,
4519 EventTarget_AddRef,
4520 EventTarget_Release,
4521 EventTarget_GetTypeInfoCount,
4522 EventTarget_GetTypeInfo,
4523 EventTarget_GetIDsOfNames,
4524 EventTarget_Invoke,
4525 EventTarget_addEventListener,
4526 EventTarget_removeEventListener,
4527 EventTarget_dispatchEvent
4530 static EventTarget *unsafe_impl_from_IEventTarget(IEventTarget *iface)
4532 return iface && iface->lpVtbl == &EventTargetVtbl ? impl_from_IEventTarget(iface) : NULL;
4535 static HRESULT get_gecko_target(IEventTarget *target, nsIDOMEventTarget **ret)
4537 EventTarget *event_target = unsafe_impl_from_IEventTarget(target);
4538 const event_target_vtbl_t *vtbl;
4539 nsresult nsres;
4541 if(!event_target) {
4542 WARN("Not our IEventTarget implementation\n");
4543 return E_INVALIDARG;
4546 vtbl = (const event_target_vtbl_t*)dispex_get_vtbl(&event_target->dispex);
4547 nsres = nsISupports_QueryInterface(vtbl->get_gecko_target(&event_target->dispex),
4548 &IID_nsIDOMEventTarget, (void**)ret);
4549 assert(nsres == NS_OK);
4550 return S_OK;
4553 void *EventTarget_query_interface(EventTarget *event_target, REFIID riid)
4555 if(IsEqualGUID(riid, &IID_IEventTarget)) {
4556 if(use_event_quirks(event_target)) {
4557 WARN("IEventTarget queried, but not supported by in document mode\n");
4558 return NULL;
4560 return &event_target->IEventTarget_iface;
4563 return NULL;
4566 void EventTarget_init_dispex_info(dispex_data_t *dispex_info, compat_mode_t compat_mode)
4568 static const dispex_hook_t IEventTarget_hooks[] = {
4569 {DISPID_IEVENTTARGET_ADDEVENTLISTENER, IEventTarget_addEventListener_hook},
4570 {DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, IEventTarget_removeEventListener_hook},
4571 {DISPID_UNKNOWN}
4574 if(compat_mode >= COMPAT_MODE_IE9)
4575 dispex_info_add_interface(dispex_info, IEventTarget_tid, IEventTarget_hooks);
4578 static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
4580 return wcscmp(key, WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry)->type);
4583 void EventTarget_Init(EventTarget *event_target, dispex_static_data_t *dispex_data, compat_mode_t compat_mode)
4585 init_dispatch(&event_target->dispex, dispex_data, compat_mode);
4586 event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
4587 wine_rb_init(&event_target->handler_map, event_id_cmp);
4590 void release_event_target(EventTarget *event_target)
4592 listener_container_t *iter, *iter2;
4594 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, listener_container_t, entry) {
4595 while(!list_empty(&iter->listeners)) {
4596 event_listener_t *listener = LIST_ENTRY(list_head(&iter->listeners), event_listener_t, entry);
4597 list_remove(&listener->entry);
4598 if(listener->function)
4599 IDispatch_Release(listener->function);
4600 free(listener);
4602 free(iter);
4604 rb_destroy(&event_target->handler_map, NULL, NULL);