windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / mshtml / htmlevent.c
blobccea4e16567e16fe99ed731c4d7741b4175f57c0
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 HRESULT get_gecko_target(IEventTarget*,nsIDOMEventTarget**);
323 typedef struct {
324 DOMEvent event;
325 IDOMUIEvent IDOMUIEvent_iface;
326 nsIDOMUIEvent *nsevent;
327 } DOMUIEvent;
329 static DOMUIEvent *DOMUIEvent_from_DOMEvent(DOMEvent *event)
331 return CONTAINING_RECORD(event, DOMUIEvent, event);
334 typedef struct {
335 DispatchEx dispex;
336 IHTMLEventObj IHTMLEventObj_iface;
338 LONG ref;
340 DOMEvent *event;
341 VARIANT return_value;
342 } HTMLEventObj;
344 static inline HTMLEventObj *impl_from_IHTMLEventObj(IHTMLEventObj *iface)
346 return CONTAINING_RECORD(iface, HTMLEventObj, IHTMLEventObj_iface);
349 static HRESULT WINAPI HTMLEventObj_QueryInterface(IHTMLEventObj *iface, REFIID riid, void **ppv)
351 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
353 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
355 if(IsEqualGUID(&IID_IUnknown, riid)) {
356 *ppv = &This->IHTMLEventObj_iface;
357 }else if(IsEqualGUID(&IID_IHTMLEventObj, riid)) {
358 *ppv = &This->IHTMLEventObj_iface;
359 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
360 return *ppv ? S_OK : E_NOINTERFACE;
361 }else {
362 *ppv = NULL;
363 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
364 return E_NOINTERFACE;
367 IUnknown_AddRef((IUnknown*)*ppv);
368 return S_OK;
371 static ULONG WINAPI HTMLEventObj_AddRef(IHTMLEventObj *iface)
373 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
374 LONG ref = InterlockedIncrement(&This->ref);
376 TRACE("(%p) ref=%ld\n", This, ref);
378 return ref;
381 static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface)
383 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
384 LONG ref = InterlockedDecrement(&This->ref);
386 TRACE("(%p) ref=%ld\n", This, ref);
388 if(!ref) {
389 if(This->event)
390 IDOMEvent_Release(&This->event->IDOMEvent_iface);
391 release_dispex(&This->dispex);
392 free(This);
395 return ref;
398 static HRESULT WINAPI HTMLEventObj_GetTypeInfoCount(IHTMLEventObj *iface, UINT *pctinfo)
400 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
401 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
404 static HRESULT WINAPI HTMLEventObj_GetTypeInfo(IHTMLEventObj *iface, UINT iTInfo,
405 LCID lcid, ITypeInfo **ppTInfo)
407 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
408 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
411 static HRESULT WINAPI HTMLEventObj_GetIDsOfNames(IHTMLEventObj *iface, REFIID riid,
412 LPOLESTR *rgszNames, UINT cNames,
413 LCID lcid, DISPID *rgDispId)
415 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
416 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
417 lcid, rgDispId);
420 static HRESULT WINAPI HTMLEventObj_Invoke(IHTMLEventObj *iface, DISPID dispIdMember,
421 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
422 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
424 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
425 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
426 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
429 static HRESULT WINAPI HTMLEventObj_get_srcElement(IHTMLEventObj *iface, IHTMLElement **p)
431 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
433 TRACE("(%p)->(%p)\n", This, p);
435 if(!This->event) {
436 *p = NULL;
437 return S_OK;
440 return IDOMEvent_get_srcElement(&This->event->IDOMEvent_iface, p);
443 static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
445 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
446 IDOMKeyboardEvent *keyboard_event;
447 IDOMMouseEvent *mouse_event;
448 cpp_bool ret = FALSE;
450 TRACE("(%p)->(%p)\n", This, p);
452 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
453 HRESULT hres = IDOMMouseEvent_get_altKey(mouse_event, p);
454 IDOMMouseEvent_Release(mouse_event);
455 return hres;
458 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
459 HRESULT hres = IDOMKeyboardEvent_get_altKey(keyboard_event, p);
460 IDOMKeyboardEvent_Release(keyboard_event);
461 return hres;
464 *p = variant_bool(ret);
465 return S_OK;
468 static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
470 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
471 IDOMKeyboardEvent *keyboard_event;
472 IDOMMouseEvent *mouse_event;
473 cpp_bool ret = FALSE;
475 TRACE("(%p)->(%p)\n", This, p);
477 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
478 HRESULT hres = IDOMMouseEvent_get_ctrlKey(mouse_event, p);
479 IDOMMouseEvent_Release(mouse_event);
480 return hres;
483 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
484 HRESULT hres = IDOMKeyboardEvent_get_ctrlKey(keyboard_event, p);
485 IDOMKeyboardEvent_Release(keyboard_event);
486 return hres;
489 *p = variant_bool(ret);
490 return S_OK;
493 static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BOOL *p)
495 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
496 IDOMKeyboardEvent *keyboard_event;
497 IDOMMouseEvent *mouse_event;
498 cpp_bool ret = FALSE;
500 TRACE("(%p)->(%p)\n", This, p);
502 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
503 HRESULT hres = IDOMMouseEvent_get_shiftKey(mouse_event, p);
504 IDOMMouseEvent_Release(mouse_event);
505 return hres;
508 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
509 HRESULT hres = IDOMKeyboardEvent_get_shiftKey(keyboard_event, p);
510 IDOMKeyboardEvent_Release(keyboard_event);
511 return hres;
514 *p = variant_bool(ret);
515 return S_OK;
518 static HRESULT WINAPI HTMLEventObj_put_returnValue(IHTMLEventObj *iface, VARIANT v)
520 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
522 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
524 if(V_VT(&v) != VT_BOOL) {
525 FIXME("unsupported value %s\n", debugstr_variant(&v));
526 return DISP_E_BADVARTYPE;
529 This->return_value = v;
530 if(!V_BOOL(&v) && This->event)
531 IDOMEvent_preventDefault(&This->event->IDOMEvent_iface);
532 return S_OK;
535 static HRESULT WINAPI HTMLEventObj_get_returnValue(IHTMLEventObj *iface, VARIANT *p)
537 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
539 TRACE("(%p)->(%p)\n", This, p);
541 V_VT(p) = VT_EMPTY;
542 return VariantCopy(p, &This->return_value);
545 static HRESULT WINAPI HTMLEventObj_put_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL v)
547 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
549 TRACE("(%p)->(%x)\n", This, v);
551 if(This->event)
552 IDOMEvent_stopPropagation(&This->event->IDOMEvent_iface);
553 return S_OK;
556 static HRESULT WINAPI HTMLEventObj_get_cancelBubble(IHTMLEventObj *iface, VARIANT_BOOL *p)
558 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
560 TRACE("(%p)->(%p)\n", This, p);
562 *p = variant_bool(This->event && This->event->stop_propagation);
563 return S_OK;
566 static HRESULT WINAPI HTMLEventObj_get_fromElement(IHTMLEventObj *iface, IHTMLElement **p)
568 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
569 IDOMMouseEvent *mouse_event;
571 TRACE("(%p)->(%p)\n", This, p);
573 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
574 HRESULT hres = IDOMMouseEvent_get_fromElement(mouse_event, p);
575 IDOMMouseEvent_Release(mouse_event);
576 return hres;
579 *p = NULL;
580 return S_OK;
583 static HRESULT WINAPI HTMLEventObj_get_toElement(IHTMLEventObj *iface, IHTMLElement **p)
585 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
586 IDOMMouseEvent *mouse_event;
588 TRACE("(%p)->(%p)\n", This, p);
590 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
591 HRESULT hres = IDOMMouseEvent_get_toElement(mouse_event, p);
592 IDOMMouseEvent_Release(mouse_event);
593 return hres;
596 *p = NULL;
597 return S_OK;
600 static HRESULT WINAPI HTMLEventObj_put_keyCode(IHTMLEventObj *iface, LONG v)
602 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
603 FIXME("(%p)->(%ld)\n", This, v);
604 return E_NOTIMPL;
607 static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, LONG *p)
609 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
610 IDOMKeyboardEvent *keyboard_event;
612 TRACE("(%p)->(%p)\n", This, p);
614 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMKeyboardEvent, (void**)&keyboard_event))) {
615 HRESULT hres = IDOMKeyboardEvent_get_keyCode(keyboard_event, p);
616 IDOMKeyboardEvent_Release(keyboard_event);
617 return hres;
620 *p = 0;
621 return S_OK;
624 static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p)
626 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
627 IDOMMouseEvent *mouse_event;
628 USHORT button = 0;
630 TRACE("(%p)->(%p)\n", This, p);
632 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
633 HRESULT hres = IDOMMouseEvent_get_button(mouse_event, &button);
634 IDOMMouseEvent_Release(mouse_event);
635 if(FAILED(hres))
636 return hres;
639 *p = button;
640 return S_OK;
643 static HRESULT WINAPI HTMLEventObj_get_type(IHTMLEventObj *iface, BSTR *p)
645 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
647 TRACE("(%p)->(%p)\n", This, p);
649 if(!This->event) {
650 *p = NULL;
651 return S_OK;
654 return IDOMEvent_get_type(&This->event->IDOMEvent_iface, p);
657 static HRESULT WINAPI HTMLEventObj_get_qualifier(IHTMLEventObj *iface, BSTR *p)
659 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
661 FIXME("(%p)->(%p)\n", This, p);
663 *p = NULL;
664 return S_OK;
667 static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, LONG *p)
669 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
671 FIXME("(%p)->(%p)\n", This, p);
673 *p = 0;
674 return S_OK;
677 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p)
679 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
680 LONG x = 0;
682 TRACE("(%p)->(%p)\n", This, p);
684 if(This->event) {
685 nsIDOMUIEvent *ui_event;
686 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
688 if(NS_SUCCEEDED(nsres)) {
689 /* NOTE: pageX is not exactly right here. */
690 nsres = nsIDOMUIEvent_GetPageX(ui_event, &x);
691 assert(nsres == NS_OK);
692 nsIDOMUIEvent_Release(ui_event);
696 *p = x;
697 return S_OK;
700 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p)
702 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
703 LONG y = 0;
705 TRACE("(%p)->(%p)\n", This, p);
707 if(This->event) {
708 nsIDOMUIEvent *ui_event;
709 nsresult nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
711 if(NS_SUCCEEDED(nsres)) {
712 /* NOTE: pageY is not exactly right here. */
713 nsres = nsIDOMUIEvent_GetPageY(ui_event, &y);
714 assert(nsres == NS_OK);
715 nsIDOMUIEvent_Release(ui_event);
719 *p = y;
720 return S_OK;
723 static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, LONG *p)
725 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
726 IDOMMouseEvent *mouse_event;
728 TRACE("(%p)->(%p)\n", This, p);
730 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
731 HRESULT hres = IDOMMouseEvent_get_clientX(mouse_event, p);
732 IDOMMouseEvent_Release(mouse_event);
733 return hres;
736 *p = 0;
737 return S_OK;
740 static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, LONG *p)
742 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
743 IDOMMouseEvent *mouse_event;
745 TRACE("(%p)->(%p)\n", This, p);
747 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
748 HRESULT hres = IDOMMouseEvent_get_clientY(mouse_event, p);
749 IDOMMouseEvent_Release(mouse_event);
750 return hres;
753 *p = 0;
754 return S_OK;
757 static HRESULT WINAPI HTMLEventObj_get_offsetX(IHTMLEventObj *iface, LONG *p)
759 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
760 IDOMMouseEvent *mouse_event;
762 TRACE("(%p)->(%p)\n", This, p);
764 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
765 HRESULT hres = IDOMMouseEvent_get_offsetX(mouse_event, p);
766 IDOMMouseEvent_Release(mouse_event);
767 return hres;
770 *p = 0;
771 return S_OK;
774 static HRESULT WINAPI HTMLEventObj_get_offsetY(IHTMLEventObj *iface, LONG *p)
776 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
777 IDOMMouseEvent *mouse_event;
779 TRACE("(%p)->(%p)\n", This, p);
781 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
782 HRESULT hres = IDOMMouseEvent_get_offsetY(mouse_event, p);
783 IDOMMouseEvent_Release(mouse_event);
784 return hres;
787 *p = 0;
788 return S_OK;
791 static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, LONG *p)
793 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
794 IDOMMouseEvent *mouse_event;
796 TRACE("(%p)->(%p)\n", This, p);
798 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
799 HRESULT hres = IDOMMouseEvent_get_screenX(mouse_event, p);
800 IDOMMouseEvent_Release(mouse_event);
801 return hres;
804 *p = 0;
805 return S_OK;
808 static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, LONG *p)
810 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
811 IDOMMouseEvent *mouse_event;
813 TRACE("(%p)->(%p)\n", This, p);
815 if(This->event && SUCCEEDED(IDOMEvent_QueryInterface(&This->event->IDOMEvent_iface, &IID_IDOMMouseEvent, (void**)&mouse_event))) {
816 HRESULT hres = IDOMMouseEvent_get_screenY(mouse_event, p);
817 IDOMMouseEvent_Release(mouse_event);
818 return hres;
821 *p = 0;
822 return S_OK;
825 static HRESULT WINAPI HTMLEventObj_get_srcFilter(IHTMLEventObj *iface, IDispatch **p)
827 HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
829 FIXME("(%p)->(%p)\n", This, p);
831 *p = NULL;
832 return S_OK;
835 static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
836 HTMLEventObj_QueryInterface,
837 HTMLEventObj_AddRef,
838 HTMLEventObj_Release,
839 HTMLEventObj_GetTypeInfoCount,
840 HTMLEventObj_GetTypeInfo,
841 HTMLEventObj_GetIDsOfNames,
842 HTMLEventObj_Invoke,
843 HTMLEventObj_get_srcElement,
844 HTMLEventObj_get_altKey,
845 HTMLEventObj_get_ctrlKey,
846 HTMLEventObj_get_shiftKey,
847 HTMLEventObj_put_returnValue,
848 HTMLEventObj_get_returnValue,
849 HTMLEventObj_put_cancelBubble,
850 HTMLEventObj_get_cancelBubble,
851 HTMLEventObj_get_fromElement,
852 HTMLEventObj_get_toElement,
853 HTMLEventObj_put_keyCode,
854 HTMLEventObj_get_keyCode,
855 HTMLEventObj_get_button,
856 HTMLEventObj_get_type,
857 HTMLEventObj_get_qualifier,
858 HTMLEventObj_get_reason,
859 HTMLEventObj_get_x,
860 HTMLEventObj_get_y,
861 HTMLEventObj_get_clientX,
862 HTMLEventObj_get_clientY,
863 HTMLEventObj_get_offsetX,
864 HTMLEventObj_get_offsetY,
865 HTMLEventObj_get_screenX,
866 HTMLEventObj_get_screenY,
867 HTMLEventObj_get_srcFilter
870 static inline HTMLEventObj *unsafe_impl_from_IHTMLEventObj(IHTMLEventObj *iface)
872 return iface->lpVtbl == &HTMLEventObjVtbl ? impl_from_IHTMLEventObj(iface) : NULL;
875 static const tid_t HTMLEventObj_iface_tids[] = {
876 IHTMLEventObj_tid,
880 static dispex_static_data_t HTMLEventObj_dispex = {
881 L"MSEventObj",
882 NULL,
883 DispCEventObj_tid,
884 HTMLEventObj_iface_tids
887 static HTMLEventObj *alloc_event_obj(DOMEvent *event, compat_mode_t compat_mode)
889 HTMLEventObj *event_obj;
891 event_obj = calloc(1, sizeof(*event_obj));
892 if(!event_obj)
893 return NULL;
895 event_obj->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
896 event_obj->ref = 1;
897 event_obj->event = event;
898 if(event)
899 IDOMEvent_AddRef(&event->IDOMEvent_iface);
901 init_dispatch(&event_obj->dispex, (IUnknown*)&event_obj->IHTMLEventObj_iface, &HTMLEventObj_dispex, compat_mode);
902 return event_obj;
905 HRESULT create_event_obj(compat_mode_t compat_mode, IHTMLEventObj **ret)
907 HTMLEventObj *event_obj;
909 event_obj = alloc_event_obj(NULL, compat_mode);
910 if(!event_obj)
911 return E_OUTOFMEMORY;
913 *ret = &event_obj->IHTMLEventObj_iface;
914 return S_OK;
917 static inline DOMEvent *impl_from_IDOMEvent(IDOMEvent *iface)
919 return CONTAINING_RECORD(iface, DOMEvent, IDOMEvent_iface);
922 static const IDOMEventVtbl DOMEventVtbl;
924 static inline DOMEvent *unsafe_impl_from_IDOMEvent(IDOMEvent *iface)
926 return iface && iface->lpVtbl == &DOMEventVtbl ? impl_from_IDOMEvent(iface) : NULL;
929 static HRESULT WINAPI DOMEvent_QueryInterface(IDOMEvent *iface, REFIID riid, void **ppv)
931 DOMEvent *This = impl_from_IDOMEvent(iface);
933 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
935 if(IsEqualGUID(&IID_IUnknown, riid))
936 *ppv = &This->IDOMEvent_iface;
937 else if(IsEqualGUID(&IID_IDOMEvent, riid))
938 *ppv = &This->IDOMEvent_iface;
939 else if(dispex_query_interface(&This->dispex, riid, ppv))
940 return *ppv ? S_OK : E_NOINTERFACE;
941 else if(!This->query_interface || !(*ppv = This->query_interface(This, riid))) {
942 *ppv = NULL;
943 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
944 return E_NOINTERFACE;
947 IUnknown_AddRef((IUnknown*)*ppv);
948 return S_OK;
951 static ULONG WINAPI DOMEvent_AddRef(IDOMEvent *iface)
953 DOMEvent *This = impl_from_IDOMEvent(iface);
954 LONG ref = InterlockedIncrement(&This->ref);
956 TRACE("(%p) ref=%lu\n", This, ref);
958 return ref;
961 static ULONG WINAPI DOMEvent_Release(IDOMEvent *iface)
963 DOMEvent *This = impl_from_IDOMEvent(iface);
964 LONG ref = InterlockedDecrement(&This->ref);
966 TRACE("(%p) ref=%lu\n", This, ref);
968 if(!ref) {
969 if(This->destroy)
970 This->destroy(This);
971 if(This->target)
972 IEventTarget_Release(&This->target->IEventTarget_iface);
973 nsIDOMEvent_Release(This->nsevent);
974 release_dispex(&This->dispex);
975 free(This->type);
976 free(This);
979 return ref;
982 static HRESULT WINAPI DOMEvent_GetTypeInfoCount(IDOMEvent *iface, UINT *pctinfo)
984 DOMEvent *This = impl_from_IDOMEvent(iface);
985 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
988 static HRESULT WINAPI DOMEvent_GetTypeInfo(IDOMEvent *iface, UINT iTInfo,
989 LCID lcid, ITypeInfo **ppTInfo)
991 DOMEvent *This = impl_from_IDOMEvent(iface);
992 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
995 static HRESULT WINAPI DOMEvent_GetIDsOfNames(IDOMEvent *iface, REFIID riid,
996 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
998 DOMEvent *This = impl_from_IDOMEvent(iface);
999 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1000 lcid, rgDispId);
1003 static HRESULT WINAPI DOMEvent_Invoke(IDOMEvent *iface, DISPID dispIdMember,
1004 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1005 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1007 DOMEvent *This = impl_from_IDOMEvent(iface);
1008 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1009 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1012 static HRESULT WINAPI DOMEvent_get_bubbles(IDOMEvent *iface, VARIANT_BOOL *p)
1014 DOMEvent *This = impl_from_IDOMEvent(iface);
1016 TRACE("(%p)->(%p)\n", This, p);
1018 *p = variant_bool(This->bubbles);
1019 return S_OK;
1022 static HRESULT WINAPI DOMEvent_get_cancelable(IDOMEvent *iface, VARIANT_BOOL *p)
1024 DOMEvent *This = impl_from_IDOMEvent(iface);
1026 TRACE("(%p)->(%p)\n", This, p);
1028 *p = variant_bool(This->cancelable);
1029 return S_OK;
1032 static HRESULT WINAPI DOMEvent_get_currentTarget(IDOMEvent *iface, IEventTarget **p)
1034 DOMEvent *This = impl_from_IDOMEvent(iface);
1036 TRACE("(%p)->(%p)\n", This, p);
1038 if(This->current_target)
1039 IEventTarget_AddRef(*p = &This->current_target->IEventTarget_iface);
1040 else
1041 *p = NULL;
1042 return S_OK;
1045 static HRESULT WINAPI DOMEvent_get_defaultPrevented(IDOMEvent *iface, VARIANT_BOOL *p)
1047 DOMEvent *This = impl_from_IDOMEvent(iface);
1049 TRACE("(%p)->(%p)\n", This, p);
1051 *p = variant_bool(This->prevent_default);
1052 return S_OK;
1055 static HRESULT WINAPI DOMEvent_get_eventPhase(IDOMEvent *iface, USHORT *p)
1057 DOMEvent *This = impl_from_IDOMEvent(iface);
1059 TRACE("(%p)->(%p)\n", This, p);
1061 *p = This->phase;
1062 return S_OK;
1065 static HRESULT WINAPI DOMEvent_get_target(IDOMEvent *iface, IEventTarget **p)
1067 DOMEvent *This = impl_from_IDOMEvent(iface);
1069 TRACE("(%p)->(%p)\n", This, p);
1071 if(This->target)
1072 IEventTarget_AddRef(*p = &This->target->IEventTarget_iface);
1073 else
1074 *p = NULL;
1075 return S_OK;
1078 static HRESULT WINAPI DOMEvent_get_timeStamp(IDOMEvent *iface, ULONGLONG *p)
1080 DOMEvent *This = impl_from_IDOMEvent(iface);
1082 TRACE("(%p)->(%p)\n", This, p);
1084 *p = This->time_stamp;
1085 return S_OK;
1088 static HRESULT WINAPI DOMEvent_get_type(IDOMEvent *iface, BSTR *p)
1090 DOMEvent *This = impl_from_IDOMEvent(iface);
1092 TRACE("(%p)->(%p)\n", This, p);
1094 if(This->type) {
1095 *p = SysAllocString(This->type);
1096 if(!*p)
1097 return E_OUTOFMEMORY;
1098 }else {
1099 *p = NULL;
1101 return S_OK;
1104 #ifdef __i386__
1105 #define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \
1106 ((void (WINAPI*)(void*,nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \
1107 &call_thiscall_func)((_this)->lpVtbl->InitEvent,_this,type,bubbles,cancelable)
1109 #endif
1111 static HRESULT WINAPI DOMEvent_initEvent(IDOMEvent *iface, BSTR type, VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable)
1113 DOMEvent *This = impl_from_IDOMEvent(iface);
1114 nsAString nsstr;
1116 TRACE("(%p)->(%s %x %x)\n", This, debugstr_w(type), can_bubble, cancelable);
1118 if(This->target) {
1119 TRACE("called on already dispatched event\n");
1120 return S_OK;
1123 free(This->type);
1124 This->type = wcsdup(type);
1125 if(!This->type)
1126 return E_OUTOFMEMORY;
1127 This->event_id = str_to_eid(type);
1129 This->bubbles = !!can_bubble;
1130 This->cancelable = !!cancelable;
1132 nsAString_InitDepend(&nsstr, type);
1133 nsIDOMEvent_InitEvent(This->nsevent, &nsstr, This->bubbles, This->cancelable);
1134 nsAString_Finish(&nsstr);
1136 return S_OK;
1139 static HRESULT WINAPI DOMEvent_preventDefault(IDOMEvent *iface)
1141 DOMEvent *This = impl_from_IDOMEvent(iface);
1143 TRACE("(%p)\n", This);
1145 if(This->current_target && This->cancelable) {
1146 This->prevent_default = TRUE;
1147 nsIDOMEvent_PreventDefault(This->nsevent);
1149 return S_OK;
1152 static HRESULT WINAPI DOMEvent_stopPropagation(IDOMEvent *iface)
1154 DOMEvent *This = impl_from_IDOMEvent(iface);
1156 TRACE("(%p)\n", This);
1158 This->stop_propagation = TRUE;
1159 nsIDOMEvent_StopPropagation(This->nsevent);
1160 return S_OK;
1163 static HRESULT WINAPI DOMEvent_stopImmediatePropagation(IDOMEvent *iface)
1165 DOMEvent *This = impl_from_IDOMEvent(iface);
1167 TRACE("(%p)\n", This);
1169 This->stop_immediate_propagation = This->stop_propagation = TRUE;
1170 nsIDOMEvent_StopImmediatePropagation(This->nsevent);
1171 return S_OK;
1174 static HRESULT WINAPI DOMEvent_get_isTrusted(IDOMEvent *iface, VARIANT_BOOL *p)
1176 DOMEvent *This = impl_from_IDOMEvent(iface);
1178 TRACE("(%p)->(%p)\n", This, p);
1180 *p = variant_bool(This->trusted);
1181 return S_OK;
1184 static HRESULT WINAPI DOMEvent_put_cancelBubble(IDOMEvent *iface, VARIANT_BOOL v)
1186 DOMEvent *This = impl_from_IDOMEvent(iface);
1187 FIXME("(%p)->(%x)\n", This, v);
1188 return E_NOTIMPL;
1191 static HRESULT WINAPI DOMEvent_get_cancelBubble(IDOMEvent *iface, VARIANT_BOOL *p)
1193 DOMEvent *This = impl_from_IDOMEvent(iface);
1194 FIXME("(%p)->(%p)\n", This, p);
1195 return E_NOTIMPL;
1198 static HRESULT WINAPI DOMEvent_get_srcElement(IDOMEvent *iface, IHTMLElement **p)
1200 DOMEvent *This = impl_from_IDOMEvent(iface);
1202 TRACE("(%p)->(%p)\n", This, p);
1204 if(This->target)
1205 IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
1206 else
1207 *p = NULL;
1208 return S_OK;
1211 static const IDOMEventVtbl DOMEventVtbl = {
1212 DOMEvent_QueryInterface,
1213 DOMEvent_AddRef,
1214 DOMEvent_Release,
1215 DOMEvent_GetTypeInfoCount,
1216 DOMEvent_GetTypeInfo,
1217 DOMEvent_GetIDsOfNames,
1218 DOMEvent_Invoke,
1219 DOMEvent_get_bubbles,
1220 DOMEvent_get_cancelable,
1221 DOMEvent_get_currentTarget,
1222 DOMEvent_get_defaultPrevented,
1223 DOMEvent_get_eventPhase,
1224 DOMEvent_get_target,
1225 DOMEvent_get_timeStamp,
1226 DOMEvent_get_type,
1227 DOMEvent_initEvent,
1228 DOMEvent_preventDefault,
1229 DOMEvent_stopPropagation,
1230 DOMEvent_stopImmediatePropagation,
1231 DOMEvent_get_isTrusted,
1232 DOMEvent_put_cancelBubble,
1233 DOMEvent_get_cancelBubble,
1234 DOMEvent_get_srcElement
1237 static inline DOMUIEvent *impl_from_IDOMUIEvent(IDOMUIEvent *iface)
1239 return CONTAINING_RECORD(iface, DOMUIEvent, IDOMUIEvent_iface);
1242 static HRESULT WINAPI DOMUIEvent_QueryInterface(IDOMUIEvent *iface, REFIID riid, void **ppv)
1244 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1245 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
1248 static ULONG WINAPI DOMUIEvent_AddRef(IDOMUIEvent *iface)
1250 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1251 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
1254 static ULONG WINAPI DOMUIEvent_Release(IDOMUIEvent *iface)
1256 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1257 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
1260 static HRESULT WINAPI DOMUIEvent_GetTypeInfoCount(IDOMUIEvent *iface, UINT *pctinfo)
1262 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1263 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
1266 static HRESULT WINAPI DOMUIEvent_GetTypeInfo(IDOMUIEvent *iface, UINT iTInfo,
1267 LCID lcid, ITypeInfo **ppTInfo)
1269 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1270 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1273 static HRESULT WINAPI DOMUIEvent_GetIDsOfNames(IDOMUIEvent *iface, REFIID riid,
1274 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1276 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1277 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1278 lcid, rgDispId);
1281 static HRESULT WINAPI DOMUIEvent_Invoke(IDOMUIEvent *iface, DISPID dispIdMember,
1282 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1283 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1285 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1286 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1287 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1290 static HRESULT WINAPI DOMUIEvent_get_view(IDOMUIEvent *iface, IHTMLWindow2 **p)
1292 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1293 mozIDOMWindowProxy *moz_window;
1294 HTMLOuterWindow *view = NULL;
1295 nsresult nsres;
1297 TRACE("(%p)->(%p)\n", This, p);
1299 nsres = nsIDOMUIEvent_GetView(This->nsevent, &moz_window);
1300 if(NS_FAILED(nsres))
1301 return E_FAIL;
1303 if(moz_window) {
1304 view = mozwindow_to_window(moz_window);
1305 mozIDOMWindowProxy_Release(moz_window);
1307 if(view)
1308 IHTMLWindow2_AddRef((*p = &view->base.inner_window->base.IHTMLWindow2_iface));
1309 else
1310 *p = NULL;
1311 return S_OK;
1314 static HRESULT WINAPI DOMUIEvent_get_detail(IDOMUIEvent *iface, LONG *p)
1316 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1317 LONG detail;
1318 nsresult nsres;
1320 TRACE("(%p)->(%p)\n", This, p);
1322 nsres = nsIDOMUIEvent_GetDetail(This->nsevent, &detail);
1323 if(NS_FAILED(nsres))
1324 return E_FAIL;
1326 *p = detail;
1327 return S_OK;
1330 static HRESULT WINAPI DOMUIEvent_initUIEvent(IDOMUIEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
1331 VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail)
1333 DOMUIEvent *This = impl_from_IDOMUIEvent(iface);
1334 nsAString type_str;
1335 nsresult nsres;
1336 HRESULT hres;
1338 TRACE("(%p)->(%s %x %x %p %lx)\n", This, debugstr_w(type), can_bubble, cancelable, view, detail);
1340 if(This->event.target) {
1341 TRACE("called on already dispatched event\n");
1342 return S_OK;
1345 if(view)
1346 FIXME("view argument is not supported\n");
1348 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
1349 if(FAILED(hres))
1350 return hres;
1352 nsAString_InitDepend(&type_str, type);
1353 nsres = nsIDOMUIEvent_InitUIEvent(This->nsevent, &type_str, !!can_bubble, !!cancelable,
1354 NULL /* FIXME */, detail);
1355 nsAString_Finish(&type_str);
1356 if(NS_FAILED(nsres)) {
1357 FIXME("InitUIEvent failed: %08lx\n", nsres);
1358 return E_FAIL;
1361 return S_OK;
1364 static const IDOMUIEventVtbl DOMUIEventVtbl = {
1365 DOMUIEvent_QueryInterface,
1366 DOMUIEvent_AddRef,
1367 DOMUIEvent_Release,
1368 DOMUIEvent_GetTypeInfoCount,
1369 DOMUIEvent_GetTypeInfo,
1370 DOMUIEvent_GetIDsOfNames,
1371 DOMUIEvent_Invoke,
1372 DOMUIEvent_get_view,
1373 DOMUIEvent_get_detail,
1374 DOMUIEvent_initUIEvent
1377 static void *DOMUIEvent_query_interface(DOMEvent *event, REFIID riid)
1379 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(event);
1380 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1381 return &This->IDOMUIEvent_iface;
1382 return NULL;
1385 static void DOMUIEvent_destroy(DOMEvent *event)
1387 DOMUIEvent *This = DOMUIEvent_from_DOMEvent(event);
1388 nsIDOMUIEvent_Release(This->nsevent);
1391 typedef struct {
1392 DOMUIEvent ui_event;
1393 IDOMMouseEvent IDOMMouseEvent_iface;
1394 nsIDOMMouseEvent *nsevent;
1395 } DOMMouseEvent;
1397 static inline DOMMouseEvent *impl_from_IDOMMouseEvent(IDOMMouseEvent *iface)
1399 return CONTAINING_RECORD(iface, DOMMouseEvent, IDOMMouseEvent_iface);
1402 static HRESULT WINAPI DOMMouseEvent_QueryInterface(IDOMMouseEvent *iface, REFIID riid, void **ppv)
1404 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1405 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1408 static ULONG WINAPI DOMMouseEvent_AddRef(IDOMMouseEvent *iface)
1410 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1411 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1414 static ULONG WINAPI DOMMouseEvent_Release(IDOMMouseEvent *iface)
1416 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1417 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
1420 static HRESULT WINAPI DOMMouseEvent_GetTypeInfoCount(IDOMMouseEvent *iface, UINT *pctinfo)
1422 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1423 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
1426 static HRESULT WINAPI DOMMouseEvent_GetTypeInfo(IDOMMouseEvent *iface, UINT iTInfo,
1427 LCID lcid, ITypeInfo **ppTInfo)
1429 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1430 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1433 static HRESULT WINAPI DOMMouseEvent_GetIDsOfNames(IDOMMouseEvent *iface, REFIID riid,
1434 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1436 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1437 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1438 lcid, rgDispId);
1441 static HRESULT WINAPI DOMMouseEvent_Invoke(IDOMMouseEvent *iface, DISPID dispIdMember,
1442 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1443 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1445 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1446 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1447 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1450 static HRESULT WINAPI DOMMouseEvent_get_screenX(IDOMMouseEvent *iface, LONG *p)
1452 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1453 LONG screen_x;
1454 nsresult nsres;
1456 TRACE("(%p)->(%p)\n", This, p);
1458 nsres = nsIDOMMouseEvent_GetScreenX(This->nsevent, &screen_x);
1459 if(NS_FAILED(nsres))
1460 return E_FAIL;
1462 *p = screen_x;
1463 return S_OK;
1466 static HRESULT WINAPI DOMMouseEvent_get_screenY(IDOMMouseEvent *iface, LONG *p)
1468 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1469 LONG screen_y;
1470 nsresult nsres;
1472 TRACE("(%p)->(%p)\n", This, p);
1474 nsres = nsIDOMMouseEvent_GetScreenY(This->nsevent, &screen_y);
1475 if(NS_FAILED(nsres))
1476 return E_FAIL;
1478 *p = screen_y;
1479 return S_OK;
1482 static HRESULT WINAPI DOMMouseEvent_get_clientX(IDOMMouseEvent *iface, LONG *p)
1484 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1485 LONG client_x;
1486 nsresult nsres;
1488 TRACE("(%p)->(%p)\n", This, p);
1490 nsres = nsIDOMMouseEvent_GetClientX(This->nsevent, &client_x);
1491 if(NS_FAILED(nsres))
1492 return E_FAIL;
1494 *p = client_x;
1495 return S_OK;
1498 static HRESULT WINAPI DOMMouseEvent_get_clientY(IDOMMouseEvent *iface, LONG *p)
1500 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1501 LONG client_y;
1502 nsresult nsres;
1504 TRACE("(%p)->(%p)\n", This, p);
1506 nsres = nsIDOMMouseEvent_GetClientY(This->nsevent, &client_y);
1507 if(NS_FAILED(nsres))
1508 return E_FAIL;
1510 *p = client_y;
1511 return S_OK;
1514 static HRESULT WINAPI DOMMouseEvent_get_ctrlKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1516 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1517 cpp_bool r;
1518 nsresult nsres;
1520 TRACE("(%p)->(%p)\n", This, p);
1522 nsres = nsIDOMMouseEvent_GetCtrlKey(This->nsevent, &r);
1523 if(NS_FAILED(nsres))
1524 return E_FAIL;
1526 *p = variant_bool(r);
1527 return S_OK;
1530 static HRESULT WINAPI DOMMouseEvent_get_shiftKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1532 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1533 cpp_bool r;
1534 nsresult nsres;
1536 TRACE("(%p)->(%p)\n", This, p);
1538 nsres = nsIDOMMouseEvent_GetShiftKey(This->nsevent, &r);
1539 if(NS_FAILED(nsres))
1540 return E_FAIL;
1542 *p = variant_bool(r);
1543 return S_OK;
1546 static HRESULT WINAPI DOMMouseEvent_get_altKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1548 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1549 cpp_bool r;
1550 nsresult nsres;
1552 TRACE("(%p)->(%p)\n", This, p);
1554 nsres = nsIDOMMouseEvent_GetAltKey(This->nsevent, &r);
1555 if(NS_FAILED(nsres))
1556 return E_FAIL;
1558 *p = variant_bool(r);
1559 return S_OK;
1562 static HRESULT WINAPI DOMMouseEvent_get_metaKey(IDOMMouseEvent *iface, VARIANT_BOOL *p)
1564 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1565 cpp_bool r;
1566 nsresult nsres;
1568 TRACE("(%p)->(%p)\n", This, p);
1570 nsres = nsIDOMMouseEvent_GetMetaKey(This->nsevent, &r);
1571 if(NS_FAILED(nsres))
1572 return E_FAIL;
1574 *p = variant_bool(r);
1575 return S_OK;
1578 static HRESULT WINAPI DOMMouseEvent_get_button(IDOMMouseEvent *iface, USHORT *p)
1580 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1581 INT16 r;
1582 nsresult nsres;
1584 TRACE("(%p)->(%p)\n", This, p);
1586 nsres = nsIDOMMouseEvent_GetButton(This->nsevent, &r);
1587 if(NS_FAILED(nsres))
1588 return E_FAIL;
1590 *p = r;
1591 return S_OK;
1594 static HRESULT WINAPI DOMMouseEvent_get_relatedTarget(IDOMMouseEvent *iface, IEventTarget **p)
1596 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1597 nsIDOMEventTarget *related_target;
1598 nsIDOMNode *target_node;
1599 HTMLDOMNode *node;
1600 HRESULT hres;
1601 nsresult nsres;
1603 TRACE("(%p)->(%p)\n", This, p);
1605 nsres = nsIDOMMouseEvent_GetRelatedTarget(This->nsevent, &related_target);
1606 if(NS_FAILED(nsres))
1607 return E_FAIL;
1609 if(!related_target) {
1610 *p = NULL;
1611 return S_OK;
1614 nsres = nsIDOMEventTarget_QueryInterface(related_target, &IID_nsIDOMNode, (void**)&target_node);
1615 nsIDOMEventTarget_Release(related_target);
1616 if(NS_FAILED(nsres)) {
1617 FIXME("Only node targets supported\n");
1618 return E_NOTIMPL;
1621 hres = get_node(target_node, TRUE, &node);
1622 nsIDOMNode_Release(target_node);
1623 if(FAILED(hres))
1624 return hres;
1626 *p = &node->event_target.IEventTarget_iface;
1627 return S_OK;
1630 static HRESULT WINAPI DOMMouseEvent_initMouseEvent(IDOMMouseEvent *iface, BSTR type,
1631 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, LONG detail,
1632 LONG screen_x, LONG screen_y, LONG client_x, LONG client_y, VARIANT_BOOL ctrl_key,
1633 VARIANT_BOOL alt_key, VARIANT_BOOL shift_key, VARIANT_BOOL meta_key, USHORT button,
1634 IEventTarget *related_target)
1636 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1637 nsIDOMEventTarget *nstarget = NULL;
1638 nsAString type_str;
1639 nsresult nsres;
1640 HRESULT hres;
1642 TRACE("(%p)->(%s %x %x %p %ld %ld %ld %ld %ld %x %x %x %x %u %p)\n", This, debugstr_w(type),
1643 can_bubble, cancelable, view, detail, screen_x, screen_y, client_x, client_y,
1644 ctrl_key, alt_key, shift_key, meta_key, button, related_target);
1646 if(This->ui_event.event.target) {
1647 TRACE("called on already dispatched event\n");
1648 return S_OK;
1651 if(view)
1652 FIXME("view argument is not supported\n");
1654 if(related_target) {
1655 hres = get_gecko_target(related_target, &nstarget);
1656 if(FAILED(hres))
1657 return hres;
1660 hres = IDOMEvent_initEvent(&This->ui_event.event.IDOMEvent_iface, type, can_bubble, cancelable);
1661 if(SUCCEEDED(hres)) {
1662 nsAString_InitDepend(&type_str, type);
1663 nsres = nsIDOMMouseEvent_InitMouseEvent(This->nsevent, &type_str, can_bubble, cancelable,
1664 NULL /* FIXME */, detail, screen_x, screen_y,
1665 client_x, client_y, !!ctrl_key, !!alt_key, !!shift_key,
1666 !!meta_key, button, nstarget);
1667 nsAString_Finish(&type_str);
1668 if(NS_FAILED(nsres)) {
1669 FIXME("InitMouseEvent failed: %08lx\n", nsres);
1670 return E_FAIL;
1674 if(nstarget)
1675 nsIDOMEventTarget_Release(nstarget);
1676 return S_OK;
1679 static HRESULT WINAPI DOMMouseEvent_getModifierState(IDOMMouseEvent *iface, BSTR key,
1680 VARIANT_BOOL *activated)
1682 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1683 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), activated);
1684 return E_NOTIMPL;
1687 static HRESULT WINAPI DOMMouseEvent_get_buttons(IDOMMouseEvent *iface, USHORT *p)
1689 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1690 UINT16 r;
1691 nsresult nsres;
1693 TRACE("(%p)->(%p)\n", This, p);
1695 nsres = nsIDOMMouseEvent_GetButtons(This->nsevent, &r);
1696 if(NS_FAILED(nsres))
1697 return E_FAIL;
1699 *p = r;
1700 return S_OK;
1703 static HRESULT WINAPI DOMMouseEvent_get_fromElement(IDOMMouseEvent *iface, IHTMLElement **p)
1705 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1706 eventid_t event_id = This->ui_event.event.event_id;
1707 IEventTarget *related_target = NULL;
1708 HRESULT hres = S_OK;
1710 TRACE("(%p)->(%p)\n", This, p);
1712 if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1713 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1714 else if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1715 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1716 if(FAILED(hres))
1717 return hres;
1719 if(!related_target) {
1720 *p = NULL;
1721 return S_OK;
1724 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1725 return S_OK;
1728 static HRESULT WINAPI DOMMouseEvent_get_toElement(IDOMMouseEvent *iface, IHTMLElement **p)
1730 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1731 eventid_t event_id = This->ui_event.event.event_id;
1732 IEventTarget *related_target = NULL;
1733 HRESULT hres = S_OK;
1735 TRACE("(%p)->(%p)\n", This, p);
1737 if(event_info[event_id].flags & EVENT_MOUSE_TO_RELATED)
1738 hres = IDOMMouseEvent_get_relatedTarget(&This->IDOMMouseEvent_iface, &related_target);
1739 else if(event_info[event_id].flags & EVENT_MOUSE_FROM_RELATED)
1740 hres = IDOMEvent_get_target(&This->ui_event.event.IDOMEvent_iface, &related_target);
1741 if(FAILED(hres))
1742 return hres;
1744 if(!related_target) {
1745 *p = NULL;
1746 return S_OK;
1749 IEventTarget_QueryInterface(related_target, &IID_IHTMLElement, (void**)p);
1750 return S_OK;
1753 static HRESULT WINAPI DOMMouseEvent_get_x(IDOMMouseEvent *iface, LONG *p)
1755 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1756 FIXME("(%p)->(%p)\n", This, p);
1757 return E_NOTIMPL;
1760 static HRESULT WINAPI DOMMouseEvent_get_y(IDOMMouseEvent *iface, LONG *p)
1762 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1763 FIXME("(%p)->(%p)\n", This, p);
1764 return E_NOTIMPL;
1767 static HRESULT WINAPI DOMMouseEvent_get_offsetX(IDOMMouseEvent *iface, LONG *p)
1769 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1771 FIXME("(%p)->(%p) returning 0\n", This, p);
1773 *p = 0;
1774 return S_OK;
1777 static HRESULT WINAPI DOMMouseEvent_get_offsetY(IDOMMouseEvent *iface, LONG *p)
1779 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1781 FIXME("(%p)->(%p) returning 0\n", This, p);
1783 *p = 0;
1784 return S_OK;
1787 static HRESULT WINAPI DOMMouseEvent_get_pageX(IDOMMouseEvent *iface, LONG *p)
1789 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1790 LONG r;
1791 nsresult nsres;
1793 TRACE("(%p)->(%p)\n", This, p);
1795 nsres = nsIDOMMouseEvent_GetPageX(This->nsevent, &r);
1796 if(NS_FAILED(nsres))
1797 return E_FAIL;
1799 *p = r;
1800 return S_OK;
1803 static HRESULT WINAPI DOMMouseEvent_get_pageY(IDOMMouseEvent *iface, LONG *p)
1805 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1806 LONG r;
1807 nsresult nsres;
1809 TRACE("(%p)->(%p)\n", This, p);
1811 nsres = nsIDOMMouseEvent_GetPageY(This->nsevent, &r);
1812 if(NS_FAILED(nsres))
1813 return E_FAIL;
1815 *p = r;
1816 return S_OK;
1819 static HRESULT WINAPI DOMMouseEvent_get_layerX(IDOMMouseEvent *iface, LONG *p)
1821 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1822 nsresult nsres;
1823 LONG r;
1825 TRACE("(%p)->(%p)\n", This, p);
1827 nsres = nsIDOMMouseEvent_GetLayerX(This->nsevent, &r);
1828 if(NS_FAILED(nsres))
1829 return E_FAIL;
1831 *p = r;
1832 return S_OK;
1835 static HRESULT WINAPI DOMMouseEvent_get_layerY(IDOMMouseEvent *iface, LONG *p)
1837 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1838 nsresult nsres;
1839 LONG r;
1841 TRACE("(%p)->(%p)\n", This, p);
1843 nsres = nsIDOMMouseEvent_GetLayerY(This->nsevent, &r);
1844 if(NS_FAILED(nsres))
1845 return E_FAIL;
1847 *p = r;
1848 return S_OK;
1851 static HRESULT WINAPI DOMMouseEvent_get_which(IDOMMouseEvent *iface, USHORT *p)
1853 DOMMouseEvent *This = impl_from_IDOMMouseEvent(iface);
1854 UINT32 r;
1855 nsresult nsres;
1857 TRACE("(%p)->(%p)\n", This, p);
1859 nsres = nsIDOMMouseEvent_GetWhich(This->nsevent, &r);
1860 if(NS_FAILED(nsres))
1861 return E_FAIL;
1863 *p = r;
1864 return S_OK;
1867 static const IDOMMouseEventVtbl DOMMouseEventVtbl = {
1868 DOMMouseEvent_QueryInterface,
1869 DOMMouseEvent_AddRef,
1870 DOMMouseEvent_Release,
1871 DOMMouseEvent_GetTypeInfoCount,
1872 DOMMouseEvent_GetTypeInfo,
1873 DOMMouseEvent_GetIDsOfNames,
1874 DOMMouseEvent_Invoke,
1875 DOMMouseEvent_get_screenX,
1876 DOMMouseEvent_get_screenY,
1877 DOMMouseEvent_get_clientX,
1878 DOMMouseEvent_get_clientY,
1879 DOMMouseEvent_get_ctrlKey,
1880 DOMMouseEvent_get_shiftKey,
1881 DOMMouseEvent_get_altKey,
1882 DOMMouseEvent_get_metaKey,
1883 DOMMouseEvent_get_button,
1884 DOMMouseEvent_get_relatedTarget,
1885 DOMMouseEvent_initMouseEvent,
1886 DOMMouseEvent_getModifierState,
1887 DOMMouseEvent_get_buttons,
1888 DOMMouseEvent_get_fromElement,
1889 DOMMouseEvent_get_toElement,
1890 DOMMouseEvent_get_x,
1891 DOMMouseEvent_get_y,
1892 DOMMouseEvent_get_offsetX,
1893 DOMMouseEvent_get_offsetY,
1894 DOMMouseEvent_get_pageX,
1895 DOMMouseEvent_get_pageY,
1896 DOMMouseEvent_get_layerX,
1897 DOMMouseEvent_get_layerY,
1898 DOMMouseEvent_get_which
1901 static DOMMouseEvent *DOMMouseEvent_from_DOMEvent(DOMEvent *event)
1903 return CONTAINING_RECORD(event, DOMMouseEvent, ui_event.event);
1906 static void *DOMMouseEvent_query_interface(DOMEvent *event, REFIID riid)
1908 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(event);
1909 if(IsEqualGUID(&IID_IDOMMouseEvent, riid))
1910 return &This->IDOMMouseEvent_iface;
1911 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
1912 return &This->ui_event.IDOMUIEvent_iface;
1913 return NULL;
1916 static void DOMMouseEvent_destroy(DOMEvent *event)
1918 DOMMouseEvent *This = DOMMouseEvent_from_DOMEvent(event);
1919 DOMUIEvent_destroy(&This->ui_event.event);
1920 nsIDOMMouseEvent_Release(This->nsevent);
1923 typedef struct {
1924 DOMUIEvent ui_event;
1925 IDOMKeyboardEvent IDOMKeyboardEvent_iface;
1926 nsIDOMKeyEvent *nsevent;
1927 } DOMKeyboardEvent;
1929 static inline DOMKeyboardEvent *impl_from_IDOMKeyboardEvent(IDOMKeyboardEvent *iface)
1931 return CONTAINING_RECORD(iface, DOMKeyboardEvent, IDOMKeyboardEvent_iface);
1934 static HRESULT WINAPI DOMKeyboardEvent_QueryInterface(IDOMKeyboardEvent *iface, REFIID riid, void **ppv)
1936 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1937 return IDOMEvent_QueryInterface(&This->ui_event.event.IDOMEvent_iface, riid, ppv);
1940 static ULONG WINAPI DOMKeyboardEvent_AddRef(IDOMKeyboardEvent *iface)
1942 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1943 return IDOMEvent_AddRef(&This->ui_event.event.IDOMEvent_iface);
1946 static ULONG WINAPI DOMKeyboardEvent_Release(IDOMKeyboardEvent *iface)
1948 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1949 return IDOMEvent_Release(&This->ui_event.event.IDOMEvent_iface);
1952 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfoCount(IDOMKeyboardEvent *iface, UINT *pctinfo)
1954 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1955 return IDispatchEx_GetTypeInfoCount(&This->ui_event.event.dispex.IDispatchEx_iface, pctinfo);
1958 static HRESULT WINAPI DOMKeyboardEvent_GetTypeInfo(IDOMKeyboardEvent *iface, UINT iTInfo,
1959 LCID lcid, ITypeInfo **ppTInfo)
1961 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1962 return IDispatchEx_GetTypeInfo(&This->ui_event.event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1965 static HRESULT WINAPI DOMKeyboardEvent_GetIDsOfNames(IDOMKeyboardEvent *iface, REFIID riid,
1966 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1968 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1969 return IDispatchEx_GetIDsOfNames(&This->ui_event.event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1970 lcid, rgDispId);
1973 static HRESULT WINAPI DOMKeyboardEvent_Invoke(IDOMKeyboardEvent *iface, DISPID dispIdMember,
1974 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1975 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1977 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1978 return IDispatchEx_Invoke(&This->ui_event.event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1979 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1982 static HRESULT WINAPI DOMKeyboardEvent_get_key(IDOMKeyboardEvent *iface, BSTR *p)
1984 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1985 nsAString key_str;
1986 nsresult nsres;
1988 TRACE("(%p)->(%p)\n", This, p);
1991 nsAString_Init(&key_str, NULL);
1992 nsres = nsIDOMKeyEvent_GetKey(This->nsevent, &key_str);
1993 return return_nsstr(nsres, &key_str, p);
1996 static HRESULT WINAPI DOMKeyboardEvent_get_location(IDOMKeyboardEvent *iface, ULONG *p)
1998 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
1999 UINT32 r;
2000 nsresult nsres;
2002 TRACE("(%p)->(%p)\n", This, p);
2004 nsres = nsIDOMKeyEvent_GetLocation(This->nsevent, &r);
2005 if(NS_FAILED(nsres))
2006 return E_FAIL;
2008 *p = r;
2009 return S_OK;
2012 static HRESULT WINAPI DOMKeyboardEvent_get_ctrlKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2014 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2015 cpp_bool r;
2016 nsresult nsres;
2018 TRACE("(%p)->(%p)\n", This, p);
2020 nsres = nsIDOMKeyEvent_GetCtrlKey(This->nsevent, &r);
2021 if(NS_FAILED(nsres))
2022 return E_FAIL;
2024 *p = variant_bool(r);
2025 return S_OK;
2028 static HRESULT WINAPI DOMKeyboardEvent_get_shiftKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2030 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2031 cpp_bool r;
2032 nsresult nsres;
2034 TRACE("(%p)->(%p)\n", This, p);
2036 nsres = nsIDOMKeyEvent_GetShiftKey(This->nsevent, &r);
2037 if(NS_FAILED(nsres))
2038 return E_FAIL;
2040 *p = variant_bool(r);
2041 return S_OK;
2044 static HRESULT WINAPI DOMKeyboardEvent_get_altKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2046 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2047 cpp_bool r;
2048 nsresult nsres;
2050 TRACE("(%p)->(%p)\n", This, p);
2052 nsres = nsIDOMKeyEvent_GetAltKey(This->nsevent, &r);
2053 if(NS_FAILED(nsres))
2054 return E_FAIL;
2056 *p = variant_bool(r);
2057 return S_OK;
2060 static HRESULT WINAPI DOMKeyboardEvent_get_metaKey(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2062 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2063 cpp_bool r;
2064 nsresult nsres;
2066 TRACE("(%p)->(%p)\n", This, p);
2068 nsres = nsIDOMKeyEvent_GetMetaKey(This->nsevent, &r);
2069 if(NS_FAILED(nsres))
2070 return E_FAIL;
2072 *p = variant_bool(r);
2073 return S_OK;
2076 static HRESULT WINAPI DOMKeyboardEvent_get_repeat(IDOMKeyboardEvent *iface, VARIANT_BOOL *p)
2078 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2079 cpp_bool r;
2080 nsresult nsres;
2082 TRACE("(%p)->(%p)\n", This, p);
2084 nsres = nsIDOMKeyEvent_GetRepeat(This->nsevent, &r);
2085 if(NS_FAILED(nsres))
2086 return E_FAIL;
2088 *p = variant_bool(r);
2089 return S_OK;
2092 static HRESULT WINAPI DOMKeyboardEvent_getModifierState(IDOMKeyboardEvent *iface, BSTR key,
2093 VARIANT_BOOL *state)
2095 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2096 FIXME("(%p)->(%s %p)\n", This, debugstr_w(key), state);
2097 return E_NOTIMPL;
2100 static HRESULT WINAPI DOMKeyboardEvent_initKeyboardEvent(IDOMKeyboardEvent *iface, BSTR type,
2101 VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable, IHTMLWindow2 *view, BSTR key,
2102 ULONG location, BSTR modifiers_list, VARIANT_BOOL repeat, BSTR locale)
2104 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2105 FIXME("(%p)->(%s %x %x %p %s %lu %s %x %s)\n", This, debugstr_w(type), can_bubble,
2106 cancelable, view, debugstr_w(key), location, debugstr_w(modifiers_list),
2107 repeat, debugstr_w(locale));
2108 return E_NOTIMPL;
2111 static HRESULT WINAPI DOMKeyboardEvent_get_keyCode(IDOMKeyboardEvent *iface, LONG *p)
2113 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2114 UINT32 r;
2115 nsresult nsres;
2117 TRACE("(%p)->(%p)\n", This, p);
2119 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2120 if(NS_FAILED(nsres))
2121 return E_FAIL;
2123 *p = r;
2124 return S_OK;
2127 static HRESULT WINAPI DOMKeyboardEvent_get_charCode(IDOMKeyboardEvent *iface, LONG *p)
2129 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2130 UINT32 r;
2131 nsresult nsres;
2133 TRACE("(%p)->(%p)\n", This, p);
2135 nsres = nsIDOMKeyEvent_GetKeyCode(This->nsevent, &r);
2136 if(NS_FAILED(nsres))
2137 return E_FAIL;
2139 *p = r;
2140 return S_OK;
2143 static HRESULT WINAPI DOMKeyboardEvent_get_which(IDOMKeyboardEvent *iface, LONG *p)
2145 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2146 UINT32 r;
2147 nsresult nsres;
2149 TRACE("(%p)->(%p)\n", This, p);
2151 nsres = nsIDOMKeyEvent_GetWhich(This->nsevent, &r);
2152 if(NS_FAILED(nsres))
2153 return E_FAIL;
2155 *p = r;
2156 return S_OK;
2159 static HRESULT WINAPI DOMKeyboardEvent_get_char(IDOMKeyboardEvent *iface, VARIANT *p)
2161 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2162 FIXME("(%p)->(%p)\n", This, p);
2163 return E_NOTIMPL;
2166 static HRESULT WINAPI DOMKeyboardEvent_get_locale(IDOMKeyboardEvent *iface, BSTR *p)
2168 DOMKeyboardEvent *This = impl_from_IDOMKeyboardEvent(iface);
2170 FIXME("(%p)->(%p) semi-stub\n", This, p);
2172 *p = SysAllocString(L"");
2173 return *p ? S_OK : E_OUTOFMEMORY;
2176 static const IDOMKeyboardEventVtbl DOMKeyboardEventVtbl = {
2177 DOMKeyboardEvent_QueryInterface,
2178 DOMKeyboardEvent_AddRef,
2179 DOMKeyboardEvent_Release,
2180 DOMKeyboardEvent_GetTypeInfoCount,
2181 DOMKeyboardEvent_GetTypeInfo,
2182 DOMKeyboardEvent_GetIDsOfNames,
2183 DOMKeyboardEvent_Invoke,
2184 DOMKeyboardEvent_get_key,
2185 DOMKeyboardEvent_get_location,
2186 DOMKeyboardEvent_get_ctrlKey,
2187 DOMKeyboardEvent_get_shiftKey,
2188 DOMKeyboardEvent_get_altKey,
2189 DOMKeyboardEvent_get_metaKey,
2190 DOMKeyboardEvent_get_repeat,
2191 DOMKeyboardEvent_getModifierState,
2192 DOMKeyboardEvent_initKeyboardEvent,
2193 DOMKeyboardEvent_get_keyCode,
2194 DOMKeyboardEvent_get_charCode,
2195 DOMKeyboardEvent_get_which,
2196 DOMKeyboardEvent_get_char,
2197 DOMKeyboardEvent_get_locale
2200 static DOMKeyboardEvent *DOMKeyboardEvent_from_DOMEvent(DOMEvent *event)
2202 return CONTAINING_RECORD(event, DOMKeyboardEvent, ui_event.event);
2205 static void *DOMKeyboardEvent_query_interface(DOMEvent *event, REFIID riid)
2207 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(event);
2208 if(IsEqualGUID(&IID_IDOMKeyboardEvent, riid))
2209 return &This->IDOMKeyboardEvent_iface;
2210 if(IsEqualGUID(&IID_IDOMUIEvent, riid))
2211 return &This->ui_event.IDOMUIEvent_iface;
2212 return NULL;
2215 static void DOMKeyboardEvent_destroy(DOMEvent *event)
2217 DOMKeyboardEvent *This = DOMKeyboardEvent_from_DOMEvent(event);
2218 DOMUIEvent_destroy(&This->ui_event.event);
2219 nsIDOMKeyEvent_Release(This->nsevent);
2222 typedef struct {
2223 DOMEvent event;
2224 IWinePageTransitionEvent IWinePageTransitionEvent_iface;
2225 } DOMPageTransitionEvent;
2227 static inline DOMPageTransitionEvent *impl_from_IWinePageTransitionEvent(IWinePageTransitionEvent *iface)
2229 return CONTAINING_RECORD(iface, DOMPageTransitionEvent, IWinePageTransitionEvent_iface);
2232 static HRESULT WINAPI DOMPageTransitionEvent_QueryInterface(IWinePageTransitionEvent *iface, REFIID riid, void **ppv)
2234 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2235 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2238 static ULONG WINAPI DOMPageTransitionEvent_AddRef(IWinePageTransitionEvent *iface)
2240 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2241 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2244 static ULONG WINAPI DOMPageTransitionEvent_Release(IWinePageTransitionEvent *iface)
2246 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2247 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2250 static HRESULT WINAPI DOMPageTransitionEvent_GetTypeInfoCount(IWinePageTransitionEvent *iface, UINT *pctinfo)
2252 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2253 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2256 static HRESULT WINAPI DOMPageTransitionEvent_GetTypeInfo(IWinePageTransitionEvent *iface, UINT iTInfo,
2257 LCID lcid, ITypeInfo **ppTInfo)
2259 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2260 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2263 static HRESULT WINAPI DOMPageTransitionEvent_GetIDsOfNames(IWinePageTransitionEvent *iface, REFIID riid,
2264 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2266 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2267 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2268 lcid, rgDispId);
2271 static HRESULT WINAPI DOMPageTransitionEvent_Invoke(IWinePageTransitionEvent *iface, DISPID dispIdMember,
2272 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2273 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2275 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2276 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2277 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2280 static HRESULT WINAPI DOMPageTransitionEvent_get_persisted(IWinePageTransitionEvent *iface, VARIANT_BOOL *p)
2282 DOMPageTransitionEvent *This = impl_from_IWinePageTransitionEvent(iface);
2284 FIXME("(%p)->(%p): always returning FALSE\n", This, p);
2286 *p = VARIANT_FALSE;
2287 return S_OK;
2290 static const IWinePageTransitionEventVtbl DOMPageTransitionEventVtbl = {
2291 DOMPageTransitionEvent_QueryInterface,
2292 DOMPageTransitionEvent_AddRef,
2293 DOMPageTransitionEvent_Release,
2294 DOMPageTransitionEvent_GetTypeInfoCount,
2295 DOMPageTransitionEvent_GetTypeInfo,
2296 DOMPageTransitionEvent_GetIDsOfNames,
2297 DOMPageTransitionEvent_Invoke,
2298 DOMPageTransitionEvent_get_persisted
2301 static DOMPageTransitionEvent *DOMPageTransitionEvent_from_DOMEvent(DOMEvent *event)
2303 return CONTAINING_RECORD(event, DOMPageTransitionEvent, event);
2306 static void *DOMPageTransitionEvent_query_interface(DOMEvent *event, REFIID riid)
2308 DOMPageTransitionEvent *page_transition_event = DOMPageTransitionEvent_from_DOMEvent(event);
2309 if(IsEqualGUID(&IID_IWinePageTransitionEvent, riid))
2310 return &page_transition_event->IWinePageTransitionEvent_iface;
2311 return NULL;
2314 typedef struct {
2315 DOMEvent event;
2316 IDOMCustomEvent IDOMCustomEvent_iface;
2317 VARIANT detail;
2318 } DOMCustomEvent;
2320 static inline DOMCustomEvent *impl_from_IDOMCustomEvent(IDOMCustomEvent *iface)
2322 return CONTAINING_RECORD(iface, DOMCustomEvent, IDOMCustomEvent_iface);
2325 static HRESULT WINAPI DOMCustomEvent_QueryInterface(IDOMCustomEvent *iface, REFIID riid, void **ppv)
2327 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2328 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2331 static ULONG WINAPI DOMCustomEvent_AddRef(IDOMCustomEvent *iface)
2333 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2334 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2337 static ULONG WINAPI DOMCustomEvent_Release(IDOMCustomEvent *iface)
2339 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2340 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2343 static HRESULT WINAPI DOMCustomEvent_GetTypeInfoCount(IDOMCustomEvent *iface, UINT *pctinfo)
2345 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2346 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2349 static HRESULT WINAPI DOMCustomEvent_GetTypeInfo(IDOMCustomEvent *iface, UINT iTInfo,
2350 LCID lcid, ITypeInfo **ppTInfo)
2352 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2353 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2356 static HRESULT WINAPI DOMCustomEvent_GetIDsOfNames(IDOMCustomEvent *iface, REFIID riid,
2357 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2359 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2360 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2361 lcid, rgDispId);
2364 static HRESULT WINAPI DOMCustomEvent_Invoke(IDOMCustomEvent *iface, DISPID dispIdMember,
2365 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2366 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2368 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2369 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2370 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2373 static HRESULT WINAPI DOMCustomEvent_get_detail(IDOMCustomEvent *iface, VARIANT *p)
2375 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2377 TRACE("(%p)->(%p)\n", This, p);
2379 V_VT(p) = VT_EMPTY;
2380 return VariantCopy(p, &This->detail);
2383 static HRESULT WINAPI DOMCustomEvent_initCustomEvent(IDOMCustomEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2384 VARIANT_BOOL cancelable, VARIANT *detail)
2386 DOMCustomEvent *This = impl_from_IDOMCustomEvent(iface);
2387 HRESULT hres;
2389 TRACE("(%p)->(%s %x %x %s)\n", This, debugstr_w(type), can_bubble, cancelable, debugstr_variant(detail));
2391 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
2392 if(FAILED(hres))
2393 return hres;
2395 return VariantCopy(&This->detail, detail);
2398 static const IDOMCustomEventVtbl DOMCustomEventVtbl = {
2399 DOMCustomEvent_QueryInterface,
2400 DOMCustomEvent_AddRef,
2401 DOMCustomEvent_Release,
2402 DOMCustomEvent_GetTypeInfoCount,
2403 DOMCustomEvent_GetTypeInfo,
2404 DOMCustomEvent_GetIDsOfNames,
2405 DOMCustomEvent_Invoke,
2406 DOMCustomEvent_get_detail,
2407 DOMCustomEvent_initCustomEvent
2410 static DOMCustomEvent *DOMCustomEvent_from_DOMEvent(DOMEvent *event)
2412 return CONTAINING_RECORD(event, DOMCustomEvent, event);
2415 static void *DOMCustomEvent_query_interface(DOMEvent *event, REFIID riid)
2417 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(event);
2418 if(IsEqualGUID(&IID_IDOMCustomEvent, riid))
2419 return &custom_event->IDOMCustomEvent_iface;
2420 return NULL;
2423 static void DOMCustomEvent_destroy(DOMEvent *event)
2425 DOMCustomEvent *custom_event = DOMCustomEvent_from_DOMEvent(event);
2426 VariantClear(&custom_event->detail);
2429 typedef struct {
2430 DOMEvent event;
2431 IDOMMessageEvent IDOMMessageEvent_iface;
2432 VARIANT data;
2433 } DOMMessageEvent;
2435 static inline DOMMessageEvent *impl_from_IDOMMessageEvent(IDOMMessageEvent *iface)
2437 return CONTAINING_RECORD(iface, DOMMessageEvent, IDOMMessageEvent_iface);
2440 static HRESULT WINAPI DOMMessageEvent_QueryInterface(IDOMMessageEvent *iface, REFIID riid, void **ppv)
2442 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2443 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2446 static ULONG WINAPI DOMMessageEvent_AddRef(IDOMMessageEvent *iface)
2448 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2449 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2452 static ULONG WINAPI DOMMessageEvent_Release(IDOMMessageEvent *iface)
2454 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2455 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2458 static HRESULT WINAPI DOMMessageEvent_GetTypeInfoCount(IDOMMessageEvent *iface, UINT *pctinfo)
2460 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2461 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2464 static HRESULT WINAPI DOMMessageEvent_GetTypeInfo(IDOMMessageEvent *iface, UINT iTInfo,
2465 LCID lcid, ITypeInfo **ppTInfo)
2467 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2468 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2471 static HRESULT WINAPI DOMMessageEvent_GetIDsOfNames(IDOMMessageEvent *iface, REFIID riid,
2472 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2474 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2475 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2476 lcid, rgDispId);
2479 static HRESULT WINAPI DOMMessageEvent_Invoke(IDOMMessageEvent *iface, DISPID dispIdMember,
2480 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2481 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2483 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2484 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2485 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2488 static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
2490 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2492 TRACE("(%p)->(%p)\n", This, p);
2494 if(V_VT(&This->data) != VT_BSTR) {
2495 FIXME("non-string data\n");
2496 return E_NOTIMPL;
2499 return (*p = SysAllocString(V_BSTR(&This->data))) ? S_OK : E_OUTOFMEMORY;
2502 static HRESULT DOMMessageEvent_get_data_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res,
2503 EXCEPINFO *ei, IServiceProvider *caller)
2505 DOMMessageEvent *This = CONTAINING_RECORD(dispex, DOMMessageEvent, event.dispex);
2507 if(!(flags & DISPATCH_PROPERTYGET) || !res)
2508 return S_FALSE;
2510 TRACE("(%p)->(%p)\n", This, res);
2512 V_VT(res) = VT_EMPTY;
2513 return VariantCopy(res, &This->data);
2516 static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR *p)
2518 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2519 FIXME("(%p)->(%p)\n", This, p);
2520 return E_NOTIMPL;
2523 static HRESULT WINAPI DOMMessageEvent_get_source(IDOMMessageEvent *iface, IHTMLWindow2 **p)
2525 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2526 FIXME("(%p)->(%p)\n", This, p);
2527 return E_NOTIMPL;
2530 static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2531 VARIANT_BOOL cancelable, BSTR data, BSTR origin,
2532 BSTR last_event_id, IHTMLWindow2 *source)
2534 DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
2535 FIXME("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2536 debugstr_w(data), debugstr_w(origin), debugstr_w(last_event_id), source);
2537 return E_NOTIMPL;
2540 static const IDOMMessageEventVtbl DOMMessageEventVtbl = {
2541 DOMMessageEvent_QueryInterface,
2542 DOMMessageEvent_AddRef,
2543 DOMMessageEvent_Release,
2544 DOMMessageEvent_GetTypeInfoCount,
2545 DOMMessageEvent_GetTypeInfo,
2546 DOMMessageEvent_GetIDsOfNames,
2547 DOMMessageEvent_Invoke,
2548 DOMMessageEvent_get_data,
2549 DOMMessageEvent_get_origin,
2550 DOMMessageEvent_get_source,
2551 DOMMessageEvent_initMessageEvent
2554 static DOMMessageEvent *DOMMessageEvent_from_DOMEvent(DOMEvent *event)
2556 return CONTAINING_RECORD(event, DOMMessageEvent, event);
2559 static void *DOMMessageEvent_query_interface(DOMEvent *event, REFIID riid)
2561 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(event);
2562 if(IsEqualGUID(&IID_IDOMMessageEvent, riid))
2563 return &message_event->IDOMMessageEvent_iface;
2564 return NULL;
2567 static void DOMMessageEvent_destroy(DOMEvent *event)
2569 DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(event);
2570 VariantClear(&message_event->data);
2573 static void DOMMessageEvent_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
2575 static const dispex_hook_t hooks[] = {
2576 {DISPID_IDOMMESSAGEEVENT_DATA, DOMMessageEvent_get_data_hook},
2577 {DISPID_UNKNOWN}
2579 dispex_info_add_interface(info, IDOMMessageEvent_tid, compat_mode >= COMPAT_MODE_IE10 ? hooks : NULL);
2582 typedef struct {
2583 DOMEvent event;
2584 IDOMProgressEvent IDOMProgressEvent_iface;
2585 nsIDOMProgressEvent *nsevent;
2586 BOOL manual_init;
2587 } DOMProgressEvent;
2589 static inline DOMProgressEvent *impl_from_IDOMProgressEvent(IDOMProgressEvent *iface)
2591 return CONTAINING_RECORD(iface, DOMProgressEvent, IDOMProgressEvent_iface);
2594 static HRESULT WINAPI DOMProgressEvent_QueryInterface(IDOMProgressEvent *iface, REFIID riid, void **ppv)
2596 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2597 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2600 static ULONG WINAPI DOMProgressEvent_AddRef(IDOMProgressEvent *iface)
2602 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2603 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2606 static ULONG WINAPI DOMProgressEvent_Release(IDOMProgressEvent *iface)
2608 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2609 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2612 static HRESULT WINAPI DOMProgressEvent_GetTypeInfoCount(IDOMProgressEvent *iface, UINT *pctinfo)
2614 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2615 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2618 static HRESULT WINAPI DOMProgressEvent_GetTypeInfo(IDOMProgressEvent *iface, UINT iTInfo,
2619 LCID lcid, ITypeInfo **ppTInfo)
2621 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2622 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2625 static HRESULT WINAPI DOMProgressEvent_GetIDsOfNames(IDOMProgressEvent *iface, REFIID riid,
2626 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2628 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2629 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2630 lcid, rgDispId);
2633 static HRESULT WINAPI DOMProgressEvent_Invoke(IDOMProgressEvent *iface, DISPID dispIdMember,
2634 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2635 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2637 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2638 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2639 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2642 static HRESULT WINAPI DOMProgressEvent_get_lengthComputable(IDOMProgressEvent *iface, VARIANT_BOOL *p)
2644 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2645 nsresult nsres;
2646 cpp_bool b;
2648 TRACE("(%p)->(%p)\n", This, p);
2650 nsres = nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b);
2651 if(NS_FAILED(nsres))
2652 return map_nsresult(nsres);
2654 *p = b ? VARIANT_TRUE : VARIANT_FALSE;
2655 return S_OK;
2658 static HRESULT WINAPI DOMProgressEvent_get_loaded(IDOMProgressEvent *iface, ULONGLONG *p)
2660 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2662 TRACE("(%p)->(%p)\n", This, p);
2664 return map_nsresult(nsIDOMProgressEvent_GetLoaded(This->nsevent, p));
2667 static HRESULT WINAPI DOMProgressEvent_get_total(IDOMProgressEvent *iface, ULONGLONG *p)
2669 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2670 cpp_bool b;
2672 TRACE("(%p)->(%p)\n", This, p);
2674 if(!This->manual_init && (NS_FAILED(nsIDOMProgressEvent_GetLengthComputable(This->nsevent, &b)) || !b)) {
2675 *p = ~0;
2676 return S_OK;
2679 return map_nsresult(nsIDOMProgressEvent_GetTotal(This->nsevent, p));
2682 static HRESULT WINAPI DOMProgressEvent_initProgressEvent(IDOMProgressEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2683 VARIANT_BOOL cancelable, VARIANT_BOOL lengthComputable,
2684 ULONGLONG loaded, ULONGLONG total)
2686 DOMProgressEvent *This = impl_from_IDOMProgressEvent(iface);
2687 nsAString type_str;
2688 nsresult nsres;
2689 HRESULT hres;
2691 TRACE("(%p)->(%s %x %x %x %s %s)\n", This, debugstr_w(type), can_bubble, cancelable, lengthComputable,
2692 wine_dbgstr_longlong(loaded), wine_dbgstr_longlong(total));
2694 if(This->event.target) {
2695 TRACE("called on already dispatched event\n");
2696 return S_OK;
2699 hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
2700 if(SUCCEEDED(hres)) {
2701 nsAString_InitDepend(&type_str, type);
2702 nsres = nsIDOMProgressEvent_InitProgressEvent(This->nsevent, &type_str, !!can_bubble, !!cancelable,
2703 !!lengthComputable, loaded, total);
2704 nsAString_Finish(&type_str);
2705 if(NS_FAILED(nsres))
2706 return map_nsresult(nsres);
2707 This->manual_init = TRUE;
2710 return hres;
2713 static const IDOMProgressEventVtbl DOMProgressEventVtbl = {
2714 DOMProgressEvent_QueryInterface,
2715 DOMProgressEvent_AddRef,
2716 DOMProgressEvent_Release,
2717 DOMProgressEvent_GetTypeInfoCount,
2718 DOMProgressEvent_GetTypeInfo,
2719 DOMProgressEvent_GetIDsOfNames,
2720 DOMProgressEvent_Invoke,
2721 DOMProgressEvent_get_lengthComputable,
2722 DOMProgressEvent_get_loaded,
2723 DOMProgressEvent_get_total,
2724 DOMProgressEvent_initProgressEvent
2727 static DOMProgressEvent *DOMProgressEvent_from_DOMEvent(DOMEvent *event)
2729 return CONTAINING_RECORD(event, DOMProgressEvent, event);
2732 static void *DOMProgressEvent_query_interface(DOMEvent *event, REFIID riid)
2734 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
2735 if(IsEqualGUID(&IID_IDOMProgressEvent, riid))
2736 return &This->IDOMProgressEvent_iface;
2737 return NULL;
2740 static void DOMProgressEvent_destroy(DOMEvent *event)
2742 DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
2743 nsIDOMProgressEvent_Release(This->nsevent);
2746 typedef struct {
2747 DOMEvent event;
2748 IDOMStorageEvent IDOMStorageEvent_iface;
2749 BSTR key;
2750 BSTR old_value;
2751 BSTR new_value;
2752 BSTR url;
2753 } DOMStorageEvent;
2755 static inline DOMStorageEvent *impl_from_IDOMStorageEvent(IDOMStorageEvent *iface)
2757 return CONTAINING_RECORD(iface, DOMStorageEvent, IDOMStorageEvent_iface);
2760 static HRESULT WINAPI DOMStorageEvent_QueryInterface(IDOMStorageEvent *iface, REFIID riid, void **ppv)
2762 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2763 return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
2766 static ULONG WINAPI DOMStorageEvent_AddRef(IDOMStorageEvent *iface)
2768 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2769 return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
2772 static ULONG WINAPI DOMStorageEvent_Release(IDOMStorageEvent *iface)
2774 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2775 return IDOMEvent_Release(&This->event.IDOMEvent_iface);
2778 static HRESULT WINAPI DOMStorageEvent_GetTypeInfoCount(IDOMStorageEvent *iface, UINT *pctinfo)
2780 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2781 return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
2784 static HRESULT WINAPI DOMStorageEvent_GetTypeInfo(IDOMStorageEvent *iface, UINT iTInfo,
2785 LCID lcid, ITypeInfo **ppTInfo)
2787 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2788 return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2791 static HRESULT WINAPI DOMStorageEvent_GetIDsOfNames(IDOMStorageEvent *iface, REFIID riid,
2792 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2794 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2795 return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2796 lcid, rgDispId);
2799 static HRESULT WINAPI DOMStorageEvent_Invoke(IDOMStorageEvent *iface, DISPID dispIdMember,
2800 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2801 EXCEPINFO *pExcepInfo, UINT *puArgErr)
2803 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2804 return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2805 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2808 static HRESULT WINAPI DOMStorageEvent_get_key(IDOMStorageEvent *iface, BSTR *p)
2810 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2812 TRACE("(%p)->(%p)\n", This, p);
2814 if(This->key)
2815 return (*p = SysAllocStringLen(This->key, SysStringLen(This->key))) ? S_OK : E_OUTOFMEMORY;
2816 *p = NULL;
2817 return S_OK;
2820 static HRESULT WINAPI DOMStorageEvent_get_oldValue(IDOMStorageEvent *iface, BSTR *p)
2822 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2824 TRACE("(%p)->(%p)\n", This, p);
2826 if(This->old_value)
2827 return (*p = SysAllocStringLen(This->old_value, SysStringLen(This->old_value))) ? S_OK : E_OUTOFMEMORY;
2828 *p = NULL;
2829 return S_OK;
2832 static HRESULT WINAPI DOMStorageEvent_get_newValue(IDOMStorageEvent *iface, BSTR *p)
2834 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2836 TRACE("(%p)->(%p)\n", This, p);
2838 if(This->new_value)
2839 return (*p = SysAllocStringLen(This->new_value, SysStringLen(This->new_value))) ? S_OK : E_OUTOFMEMORY;
2840 *p = NULL;
2841 return S_OK;
2844 static HRESULT WINAPI DOMStorageEvent_get_url(IDOMStorageEvent *iface, BSTR *p)
2846 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2848 TRACE("(%p)->(%p)\n", This, p);
2850 if(This->url)
2851 return (*p = SysAllocStringLen(This->url, SysStringLen(This->url))) ? S_OK : E_OUTOFMEMORY;
2852 *p = NULL;
2853 return S_OK;
2856 static HRESULT WINAPI DOMStorageEvent_get_storageArea(IDOMStorageEvent *iface, IHTMLStorage **p)
2858 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2859 FIXME("(%p)->(%p)\n", This, p);
2860 return E_NOTIMPL;
2863 static HRESULT WINAPI DOMStorageEvent_initStorageEvent(IDOMStorageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
2864 VARIANT_BOOL cancelable, BSTR keyArg, BSTR oldValueArg,
2865 BSTR newValueArg, BSTR urlArg, IHTMLStorage *storageAreaArg)
2867 DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
2868 FIXME("(%p)->(%s %x %x %s %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
2869 debugstr_w(keyArg), debugstr_w(oldValueArg), debugstr_w(newValueArg), debugstr_w(urlArg), storageAreaArg);
2870 return E_NOTIMPL;
2873 static const IDOMStorageEventVtbl DOMStorageEventVtbl = {
2874 DOMStorageEvent_QueryInterface,
2875 DOMStorageEvent_AddRef,
2876 DOMStorageEvent_Release,
2877 DOMStorageEvent_GetTypeInfoCount,
2878 DOMStorageEvent_GetTypeInfo,
2879 DOMStorageEvent_GetIDsOfNames,
2880 DOMStorageEvent_Invoke,
2881 DOMStorageEvent_get_key,
2882 DOMStorageEvent_get_oldValue,
2883 DOMStorageEvent_get_newValue,
2884 DOMStorageEvent_get_url,
2885 DOMStorageEvent_get_storageArea,
2886 DOMStorageEvent_initStorageEvent
2889 static DOMStorageEvent *DOMStorageEvent_from_DOMEvent(DOMEvent *event)
2891 return CONTAINING_RECORD(event, DOMStorageEvent, event);
2894 static void *DOMStorageEvent_query_interface(DOMEvent *event, REFIID riid)
2896 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
2897 if(IsEqualGUID(&IID_IDOMStorageEvent, riid))
2898 return &storage_event->IDOMStorageEvent_iface;
2899 return NULL;
2902 static void DOMStorageEvent_destroy(DOMEvent *event)
2904 DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
2905 SysFreeString(storage_event->key);
2906 SysFreeString(storage_event->old_value);
2907 SysFreeString(storage_event->new_value);
2908 SysFreeString(storage_event->url);
2911 static const tid_t DOMEvent_iface_tids[] = {
2912 IDOMEvent_tid,
2916 static dispex_static_data_t DOMEvent_dispex = {
2917 L"Event",
2918 NULL,
2919 DispDOMEvent_tid,
2920 DOMEvent_iface_tids
2923 static const tid_t DOMUIEvent_iface_tids[] = {
2924 IDOMEvent_tid,
2925 IDOMUIEvent_tid,
2929 static dispex_static_data_t DOMUIEvent_dispex = {
2930 L"UIEvent",
2931 NULL,
2932 DispDOMUIEvent_tid,
2933 DOMUIEvent_iface_tids
2936 static const tid_t DOMMouseEvent_iface_tids[] = {
2937 IDOMEvent_tid,
2938 IDOMUIEvent_tid,
2939 IDOMMouseEvent_tid,
2943 static dispex_static_data_t DOMMouseEvent_dispex = {
2944 L"MouseEvent",
2945 NULL,
2946 DispDOMMouseEvent_tid,
2947 DOMMouseEvent_iface_tids
2950 static const tid_t DOMKeyboardEvent_iface_tids[] = {
2951 IDOMEvent_tid,
2952 IDOMUIEvent_tid,
2953 IDOMKeyboardEvent_tid,
2957 static dispex_static_data_t DOMKeyboardEvent_dispex = {
2958 L"KeyboardEvent",
2959 NULL,
2960 DispDOMKeyboardEvent_tid,
2961 DOMKeyboardEvent_iface_tids
2964 static void DOMPageTransitionEvent_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
2966 if(mode >= COMPAT_MODE_IE11)
2967 dispex_info_add_interface(info, IWinePageTransitionEvent_tid, NULL);
2970 dispex_static_data_t DOMPageTransitionEvent_dispex = {
2971 L"PageTransitionEvent",
2972 NULL,
2973 DispDOMEvent_tid,
2974 DOMEvent_iface_tids,
2975 DOMPageTransitionEvent_init_dispex_info
2978 static const tid_t DOMCustomEvent_iface_tids[] = {
2979 IDOMEvent_tid,
2980 IDOMCustomEvent_tid,
2984 static dispex_static_data_t DOMCustomEvent_dispex = {
2985 L"CustomEvent",
2986 NULL,
2987 DispDOMCustomEvent_tid,
2988 DOMCustomEvent_iface_tids
2991 static const tid_t DOMMessageEvent_iface_tids[] = {
2992 IDOMEvent_tid,
2996 dispex_static_data_t DOMMessageEvent_dispex = {
2997 L"MessageEvent",
2998 NULL,
2999 DispDOMMessageEvent_tid,
3000 DOMMessageEvent_iface_tids,
3001 DOMMessageEvent_init_dispex_info
3004 static const tid_t DOMProgressEvent_iface_tids[] = {
3005 IDOMEvent_tid,
3006 IDOMProgressEvent_tid,
3010 dispex_static_data_t DOMProgressEvent_dispex = {
3011 L"ProgressEvent",
3012 NULL,
3013 DispDOMProgressEvent_tid,
3014 DOMProgressEvent_iface_tids
3017 static const tid_t DOMStorageEvent_iface_tids[] = {
3018 IDOMEvent_tid,
3019 IDOMStorageEvent_tid,
3023 dispex_static_data_t DOMStorageEvent_dispex = {
3024 L"StorageEvent",
3025 NULL,
3026 DispDOMStorageEvent_tid,
3027 DOMStorageEvent_iface_tids
3030 static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, void *(*query_interface)(DOMEvent*,REFIID),
3031 void (*destroy)(DOMEvent*), nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3033 DOMEvent *event = calloc(1, size);
3035 if(!event)
3036 return NULL;
3037 event->IDOMEvent_iface.lpVtbl = &DOMEventVtbl;
3038 event->query_interface = query_interface;
3039 event->destroy = destroy;
3040 event->ref = 1;
3041 event->event_id = event_id;
3042 if(event_id != EVENTID_LAST) {
3043 event->type = wcsdup(event_info[event_id].name);
3044 if(!event->type) {
3045 free(event);
3046 return NULL;
3048 event->bubbles = (event_info[event_id].flags & EVENT_BUBBLES) != 0;
3049 event->cancelable = (event_info[event_id].flags & EVENT_CANCELABLE) != 0;
3051 nsIDOMEvent_AddRef(event->nsevent = nsevent);
3053 event->time_stamp = get_time_stamp();
3055 init_dispatch(&event->dispex, (IUnknown*)&event->IDOMEvent_iface, dispex_data, compat_mode);
3056 return event;
3059 static void fill_parent_ui_event(nsIDOMEvent *nsevent, DOMUIEvent *ui_event)
3061 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
3062 nsIDOMEvent_QueryInterface(nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event->nsevent);
3065 static DOMEvent *generic_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3067 return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, NULL, NULL, nsevent, event_id, compat_mode);
3070 static DOMEvent *ui_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3072 DOMUIEvent *ui_event = event_ctor(sizeof(DOMUIEvent), &DOMUIEvent_dispex,
3073 DOMUIEvent_query_interface, DOMUIEvent_destroy, nsevent, event_id, compat_mode);
3074 if(!ui_event) return NULL;
3075 ui_event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
3076 ui_event->nsevent = iface;
3077 return &ui_event->event;
3080 static DOMEvent *mouse_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3082 DOMMouseEvent *mouse_event = event_ctor(sizeof(DOMMouseEvent), &DOMMouseEvent_dispex,
3083 DOMMouseEvent_query_interface, DOMMouseEvent_destroy, nsevent, event_id, compat_mode);
3084 if(!mouse_event) return NULL;
3085 mouse_event->IDOMMouseEvent_iface.lpVtbl = &DOMMouseEventVtbl;
3086 mouse_event->nsevent = iface;
3087 fill_parent_ui_event(nsevent, &mouse_event->ui_event);
3088 return &mouse_event->ui_event.event;
3091 static DOMEvent *keyboard_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3093 DOMKeyboardEvent *keyboard_event = event_ctor(sizeof(DOMKeyboardEvent), &DOMKeyboardEvent_dispex,
3094 DOMKeyboardEvent_query_interface, DOMKeyboardEvent_destroy, nsevent, event_id, compat_mode);
3095 if(!keyboard_event) return NULL;
3096 keyboard_event->IDOMKeyboardEvent_iface.lpVtbl = &DOMKeyboardEventVtbl;
3097 keyboard_event->nsevent = iface;
3098 fill_parent_ui_event(nsevent, &keyboard_event->ui_event);
3099 return &keyboard_event->ui_event.event;
3102 static DOMEvent *page_transition_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3104 DOMPageTransitionEvent *page_transition_event = event_ctor(sizeof(DOMCustomEvent), &DOMPageTransitionEvent_dispex,
3105 DOMPageTransitionEvent_query_interface, NULL, nsevent, event_id, compat_mode);
3106 if(!page_transition_event) return NULL;
3107 page_transition_event->IWinePageTransitionEvent_iface.lpVtbl = &DOMPageTransitionEventVtbl;
3108 return &page_transition_event->event;
3111 static DOMEvent *custom_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3113 DOMCustomEvent *custom_event = event_ctor(sizeof(DOMCustomEvent), &DOMCustomEvent_dispex,
3114 DOMCustomEvent_query_interface, DOMCustomEvent_destroy, nsevent, event_id, compat_mode);
3115 if(!custom_event) return NULL;
3116 custom_event->IDOMCustomEvent_iface.lpVtbl = &DOMCustomEventVtbl;
3117 nsIDOMCustomEvent_Release(iface);
3118 return &custom_event->event;
3121 static DOMEvent *progress_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3123 DOMProgressEvent *progress_event;
3125 if(!(progress_event = event_ctor(sizeof(DOMProgressEvent), &DOMProgressEvent_dispex,
3126 DOMProgressEvent_query_interface, DOMProgressEvent_destroy, nsevent, event_id, compat_mode)))
3127 return NULL;
3128 progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
3129 progress_event->nsevent = iface;
3130 return &progress_event->event;
3133 static DOMEvent *message_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3135 DOMMessageEvent *message_event = event_ctor(sizeof(DOMMessageEvent), &DOMMessageEvent_dispex,
3136 DOMMessageEvent_query_interface, DOMMessageEvent_destroy, nsevent, event_id, compat_mode);
3137 if(!message_event) return NULL;
3138 message_event->IDOMMessageEvent_iface.lpVtbl = &DOMMessageEventVtbl;
3139 return &message_event->event;
3142 static DOMEvent *storage_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
3144 DOMStorageEvent *storage_event = event_ctor(sizeof(DOMStorageEvent), &DOMStorageEvent_dispex,
3145 DOMStorageEvent_query_interface, DOMStorageEvent_destroy, nsevent, event_id, compat_mode);
3146 if(!storage_event) return NULL;
3147 storage_event->IDOMStorageEvent_iface.lpVtbl = &DOMStorageEventVtbl;
3148 return &storage_event->event;
3151 static const struct {
3152 REFIID iid;
3153 DOMEvent *(*ctor)(void *iface, nsIDOMEvent *nsevent, eventid_t, compat_mode_t);
3154 compat_mode_t min_compat_mode;
3155 } event_types_ctor_table[] = {
3156 [EVENT_TYPE_EVENT] = { NULL, generic_event_ctor },
3157 [EVENT_TYPE_UIEVENT] = { &IID_nsIDOMUIEvent, ui_event_ctor },
3158 [EVENT_TYPE_MOUSE] = { &IID_nsIDOMMouseEvent, mouse_event_ctor },
3159 [EVENT_TYPE_KEYBOARD] = { &IID_nsIDOMKeyEvent, keyboard_event_ctor },
3160 [EVENT_TYPE_CLIPBOARD] = { NULL, generic_event_ctor },
3161 [EVENT_TYPE_FOCUS] = { NULL, generic_event_ctor },
3162 [EVENT_TYPE_DRAG] = { NULL, generic_event_ctor },
3163 [EVENT_TYPE_PAGETRANSITION] = { NULL, page_transition_event_ctor },
3164 [EVENT_TYPE_CUSTOM] = { &IID_nsIDOMCustomEvent, custom_event_ctor },
3165 [EVENT_TYPE_PROGRESS] = { &IID_nsIDOMProgressEvent, progress_event_ctor, COMPAT_MODE_IE10 },
3166 [EVENT_TYPE_MESSAGE] = { NULL, message_event_ctor },
3167 [EVENT_TYPE_STORAGE] = { NULL, storage_event_ctor },
3170 static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, event_type_t event_type,
3171 eventid_t event_id)
3173 void *iface = NULL;
3174 DOMEvent *event;
3176 if(compat_mode < event_types_ctor_table[event_type].min_compat_mode)
3177 event_type = EVENT_TYPE_EVENT;
3179 if(event_types_ctor_table[event_type].iid)
3180 nsIDOMEvent_QueryInterface(nsevent, event_types_ctor_table[event_type].iid, &iface);
3182 /* Transfer the iface ownership to the ctor on success */
3183 if(!(event = event_types_ctor_table[event_type].ctor(iface, nsevent, event_id, compat_mode)) && iface)
3184 nsISupports_Release(iface);
3185 return event;
3188 HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, compat_mode_t compat_mode, DOMEvent **ret_event)
3190 event_type_t event_type = EVENT_TYPE_EVENT;
3191 eventid_t event_id = EVENTID_LAST;
3192 DOMEvent *event;
3193 nsAString nsstr;
3194 nsresult nsres;
3195 unsigned i;
3197 nsAString_Init(&nsstr, NULL);
3198 nsres = nsIDOMEvent_GetType(nsevent, &nsstr);
3199 if(NS_SUCCEEDED(nsres)) {
3200 const WCHAR *type;
3201 nsAString_GetData(&nsstr, &type);
3202 event_id = str_to_eid(type);
3203 if(event_id == EVENTID_LAST)
3204 FIXME("unknown event type %s\n", debugstr_w(type));
3205 }else {
3206 ERR("GetType failed: %08lx\n", nsres);
3208 nsAString_Finish(&nsstr);
3210 for(i = 0; i < ARRAY_SIZE(event_types_ctor_table); i++) {
3211 void *iface;
3212 if(event_types_ctor_table[i].iid &&
3213 nsIDOMEvent_QueryInterface(nsevent, event_types_ctor_table[i].iid, &iface) == NS_OK) {
3214 nsISupports_Release(iface);
3215 event_type = i;
3216 break;
3220 event = alloc_event(nsevent, compat_mode, event_type, event_id);
3221 if(!event)
3222 return E_OUTOFMEMORY;
3224 event->trusted = TRUE;
3225 *ret_event = event;
3226 return S_OK;
3229 HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOMEvent **ret_event)
3231 event_type_t event_type = EVENT_TYPE_EVENT;
3232 nsIDOMEvent *nsevent;
3233 DOMEvent *event;
3234 nsAString nsstr;
3235 nsresult nsres;
3236 unsigned i;
3238 nsAString_InitDepend(&nsstr, type);
3239 nsres = nsIDOMDocument_CreateEvent(doc->dom_document, &nsstr, &nsevent);
3240 nsAString_Finish(&nsstr);
3241 if(NS_FAILED(nsres)) {
3242 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(type), nsres);
3243 return E_FAIL;
3246 for(i = 0; i < ARRAY_SIZE(event_types); i++) {
3247 if(!wcsicmp(type, event_types[i])) {
3248 event_type = i;
3249 break;
3253 event = alloc_event(nsevent, dispex_compat_mode(&doc->node.event_target.dispex),
3254 event_type, EVENTID_LAST);
3255 nsIDOMEvent_Release(nsevent);
3256 if(!event)
3257 return E_OUTOFMEMORY;
3259 *ret_event = &event->IDOMEvent_iface;
3260 return S_OK;
3263 HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEvent **ret_event)
3265 nsIDOMEvent *nsevent;
3266 DOMEvent *event;
3267 nsAString nsstr;
3268 nsresult nsres;
3270 nsAString_InitDepend(&nsstr, event_types[event_info[event_id].type]);
3271 nsres = nsIDOMDocument_CreateEvent(doc->dom_document, &nsstr, &nsevent);
3272 nsAString_Finish(&nsstr);
3273 if(NS_FAILED(nsres)) {
3274 FIXME("CreateEvent(%s) failed: %08lx\n", debugstr_w(event_types[event_info[event_id].type]), nsres);
3275 return E_FAIL;
3278 event = alloc_event(nsevent, doc->document_mode, event_info[event_id].type, event_id);
3279 nsIDOMEvent_Release(nsevent);
3280 if(!event)
3281 return E_OUTOFMEMORY;
3283 event->event_id = event_id;
3284 event->trusted = TRUE;
3285 *ret_event = event;
3286 return S_OK;
3289 HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **ret)
3291 DOMMessageEvent *message_event;
3292 DOMEvent *event;
3293 HRESULT hres;
3295 hres = create_document_event(doc, EVENTID_MESSAGE, &event);
3296 if(FAILED(hres))
3297 return hres;
3298 message_event = DOMMessageEvent_from_DOMEvent(event);
3300 V_VT(&message_event->data) = VT_EMPTY;
3301 hres = VariantCopy(&message_event->data, data);
3302 if(FAILED(hres)) {
3303 IDOMEvent_Release(&event->IDOMEvent_iface);
3304 return hres;
3307 *ret = event;
3308 return S_OK;
3311 HRESULT create_storage_event(HTMLDocumentNode *doc, BSTR key, BSTR old_value, BSTR new_value,
3312 const WCHAR *url, BOOL commit, DOMEvent **ret)
3314 DOMStorageEvent *storage_event;
3315 DOMEvent *event;
3316 HRESULT hres;
3318 hres = create_document_event(doc, commit ? EVENTID_STORAGECOMMIT : EVENTID_STORAGE, &event);
3319 if(FAILED(hres))
3320 return hres;
3321 storage_event = DOMStorageEvent_from_DOMEvent(event);
3323 if(!commit) {
3324 if((key && !(storage_event->key = SysAllocString(key))) ||
3325 (old_value && !(storage_event->old_value = SysAllocString(old_value))) ||
3326 (new_value && !(storage_event->new_value = SysAllocString(new_value)))) {
3327 IDOMEvent_Release(&event->IDOMEvent_iface);
3328 return E_OUTOFMEMORY;
3332 if(url && !(storage_event->url = SysAllocString(url))) {
3333 IDOMEvent_Release(&event->IDOMEvent_iface);
3334 return E_OUTOFMEMORY;
3337 *ret = event;
3338 return S_OK;
3341 HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
3343 IDispatchEx *dispex;
3344 EXCEPINFO ei;
3345 HRESULT hres;
3347 memset(&ei, 0, sizeof(ei));
3349 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
3350 if(SUCCEEDED(hres)) {
3351 hres = IDispatchEx_InvokeEx(dispex, 0, GetUserDefaultLCID(), DISPATCH_METHOD, dp, retv, &ei, NULL);
3352 IDispatchEx_Release(dispex);
3353 }else {
3354 TRACE("Could not get IDispatchEx interface: %08lx\n", hres);
3355 hres = IDispatch_Invoke(disp, 0, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD,
3356 dp, retv, &ei, NULL);
3359 return hres;
3362 static HRESULT call_cp_func(IDispatch *disp, DISPID dispid, IHTMLEventObj *event_obj, VARIANT *retv)
3364 DISPPARAMS dp = {NULL,NULL,0,0};
3365 VARIANT event_arg;
3366 UINT argerr;
3367 EXCEPINFO ei;
3369 TRACE("%p,%ld,%p,%p\n", disp, dispid, event_obj, retv);
3371 if(event_obj) {
3372 V_VT(&event_arg) = VT_DISPATCH;
3373 V_DISPATCH(&event_arg) = (IDispatch*)event_obj;
3374 dp.rgvarg = &event_arg;
3375 dp.cArgs = 1;
3378 memset(&ei, 0, sizeof(ei));
3379 return IDispatch_Invoke(disp, dispid, &IID_NULL, 0, DISPATCH_METHOD, &dp, retv, &ei, &argerr);
3382 static BOOL use_event_quirks(EventTarget *event_target)
3384 return dispex_compat_mode(&event_target->dispex) < COMPAT_MODE_IE9;
3387 static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
3389 int min, max, i;
3390 HRESULT hres;
3392 if(!data || dispid == DISPID_UNKNOWN)
3393 return FALSE;
3395 if(!data->ids) {
3396 hres = get_dispids(data->tid, &data->id_cnt, &data->ids);
3397 if(FAILED(hres))
3398 return FALSE;
3401 min = 0;
3402 max = data->id_cnt-1;
3403 while(min <= max) {
3404 i = (min+max)/2;
3405 if(data->ids[i] == dispid)
3406 return TRUE;
3408 if(data->ids[i] < dispid)
3409 min = i+1;
3410 else
3411 max = i-1;
3414 return FALSE;
3417 static void call_event_handlers(EventTarget *event_target, DOMEvent *event, dispatch_mode_t dispatch_mode)
3419 const listener_container_t *container = get_listener_container(event_target, event->type, FALSE);
3420 event_listener_t *listener, listeners_buf[8], *listeners = listeners_buf;
3421 unsigned listeners_cnt, listeners_size;
3422 ConnectionPointContainer *cp_container = NULL;
3423 const event_target_vtbl_t *vtbl = NULL;
3424 BOOL skip_onevent_listener = FALSE;
3425 VARIANT v;
3426 HRESULT hres;
3428 assert(!event->current_target);
3429 event->current_target = event_target;
3431 if(container && !list_empty(&container->listeners) && event->phase != DEP_CAPTURING_PHASE) {
3432 listener = LIST_ENTRY(list_tail(&container->listeners), event_listener_t, entry);
3433 if(listener && listener->function && listener->type == LISTENER_TYPE_ONEVENT
3434 && use_event_quirks(event_target)) {
3435 DISPID named_arg = DISPID_THIS;
3436 VARIANTARG arg;
3437 DISPPARAMS dp = {&arg, &named_arg, 1, 1};
3439 skip_onevent_listener = TRUE;
3441 V_VT(&arg) = VT_DISPATCH;
3442 V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3443 V_VT(&v) = VT_EMPTY;
3445 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3446 hres = call_disp_func(listener->function, &dp, &v);
3447 if(hres == S_OK) {
3448 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type), debugstr_variant(&v));
3450 if(event->cancelable) {
3451 if(V_VT(&v) == VT_BOOL) {
3452 if(!V_BOOL(&v))
3453 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3454 }else if(V_VT(&v) != VT_EMPTY) {
3455 FIXME("unhandled result %s\n", debugstr_variant(&v));
3458 VariantClear(&v);
3459 }else {
3460 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3465 listeners_cnt = 0;
3466 listeners_size = ARRAY_SIZE(listeners_buf);
3468 if(container) {
3469 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
3470 if(!listener->function)
3471 continue;
3472 switch(listener->type) {
3473 case LISTENER_TYPE_ONEVENT:
3474 if(skip_onevent_listener || event->phase == DEP_CAPTURING_PHASE)
3475 continue;
3476 break;
3477 case LISTENER_TYPE_CAPTURE:
3478 if(event->phase == DEP_BUBBLING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3479 continue;
3480 break;
3481 case LISTENER_TYPE_BUBBLE:
3482 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_LEGACY)
3483 continue;
3484 break;
3485 case LISTENER_TYPE_ATTACHED:
3486 if(event->phase == DEP_CAPTURING_PHASE || dispatch_mode == DISPATCH_STANDARD)
3487 continue;
3488 break;
3491 if(listeners_cnt == listeners_size) {
3492 event_listener_t *new_listeners;
3493 if(listeners == listeners_buf) {
3494 new_listeners = malloc(listeners_size * 2 * sizeof(*new_listeners));
3495 if(!new_listeners)
3496 break;
3497 memcpy(new_listeners, listeners, listeners_cnt * sizeof(*listeners));
3498 }else {
3499 new_listeners = realloc(listeners, listeners_size * 2 * sizeof(*new_listeners));
3501 listeners = new_listeners;
3502 listeners_size *= 2;
3505 listeners[listeners_cnt].type = listener->type;
3506 IDispatch_AddRef(listeners[listeners_cnt].function = listener->function);
3507 listeners_cnt++;
3511 for(listener = listeners; !event->stop_immediate_propagation
3512 && listener < listeners + listeners_cnt; listener++) {
3513 if(listener->type != LISTENER_TYPE_ATTACHED) {
3514 DISPID named_arg = DISPID_THIS;
3515 VARIANTARG args[2];
3516 DISPPARAMS dp = {args, &named_arg, 2, 1};
3518 V_VT(args) = VT_DISPATCH;
3519 V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
3520 V_VT(args+1) = VT_DISPATCH;
3521 V_DISPATCH(args+1) = dispatch_mode == DISPATCH_LEGACY
3522 ? (IDispatch*)event->event_obj : (IDispatch*)&event->IDOMEvent_iface;
3523 V_VT(&v) = VT_EMPTY;
3525 TRACE("%p %s >>>\n", event_target, debugstr_w(event->type));
3526 hres = call_disp_func(listener->function, &dp, &v);
3527 if(hres == S_OK) {
3528 TRACE("%p %s <<< %s\n", event_target, debugstr_w(event->type),
3529 debugstr_variant(&v));
3531 if(event->cancelable) {
3532 if(V_VT(&v) == VT_BOOL) {
3533 if(!V_BOOL(&v))
3534 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3535 }else if(V_VT(&v) != VT_EMPTY) {
3536 FIXME("unhandled result %s\n", debugstr_variant(&v));
3539 VariantClear(&v);
3540 }else {
3541 WARN("%p %s <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3543 }else {
3544 VARIANTARG arg;
3545 DISPPARAMS dp = {&arg, NULL, 1, 0};
3547 V_VT(&arg) = VT_DISPATCH;
3548 V_DISPATCH(&arg) = (IDispatch*)event->event_obj;
3549 V_VT(&v) = VT_EMPTY;
3551 TRACE("%p %s attached >>>\n", event_target, debugstr_w(event->type));
3552 hres = call_disp_func(listener->function, &dp, &v);
3553 if(hres == S_OK) {
3554 TRACE("%p %s attached <<<\n", event_target, debugstr_w(event->type));
3556 if(event->cancelable) {
3557 if(V_VT(&v) == VT_BOOL) {
3558 if(!V_BOOL(&v))
3559 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3560 }else if(V_VT(&v) != VT_EMPTY) {
3561 FIXME("unhandled result %s\n", debugstr_variant(&v));
3564 VariantClear(&v);
3565 }else {
3566 WARN("%p %s attached <<< %08lx\n", event_target, debugstr_w(event->type), hres);
3571 for(listener = listeners; listener < listeners + listeners_cnt; listener++)
3572 IDispatch_Release(listener->function);
3573 if(listeners != listeners_buf)
3574 free(listeners);
3576 if(event->phase != DEP_CAPTURING_PHASE && event_info[event->event_id].dispid
3577 && (vtbl = dispex_get_vtbl(&event_target->dispex)) && vtbl->get_cp_container)
3578 cp_container = vtbl->get_cp_container(&event_target->dispex);
3579 if(cp_container) {
3580 if(cp_container->cps) {
3581 ConnectionPoint *cp;
3582 unsigned i, j;
3584 for(j=0; cp_container->cp_entries[j].riid; j++) {
3585 cp = cp_container->cps + j;
3586 if(!cp->sinks_size || !is_cp_event(cp->data, event_info[event->event_id].dispid))
3587 continue;
3589 for(i=0; i < cp->sinks_size; i++) {
3590 if(!cp->sinks[i].disp)
3591 continue;
3593 V_VT(&v) = VT_EMPTY;
3595 TRACE("%p cp %s [%u] >>>\n", event_target, debugstr_w(event->type), i);
3596 hres = call_cp_func(cp->sinks[i].disp, event_info[event->event_id].dispid,
3597 cp->data->pass_event_arg ? event->event_obj : NULL, &v);
3598 if(hres == S_OK) {
3599 TRACE("%p cp %s [%u] <<<\n", event_target, debugstr_w(event->type), i);
3601 if(event->cancelable) {
3602 if(V_VT(&v) == VT_BOOL) {
3603 if(!V_BOOL(&v))
3604 IDOMEvent_preventDefault(&event->IDOMEvent_iface);
3605 }else if(V_VT(&v) != VT_EMPTY) {
3606 FIXME("unhandled result %s\n", debugstr_variant(&v));
3609 VariantClear(&v);
3610 }else {
3611 WARN("%p cp %s [%u] <<< %08lx\n", event_target, debugstr_w(event->type), i, hres);
3616 IConnectionPointContainer_Release(&cp_container->IConnectionPointContainer_iface);
3619 event->current_target = NULL;
3622 static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event,
3623 dispatch_mode_t dispatch_mode, VARIANT_BOOL *r)
3625 EventTarget *target_chain_buf[8], **target_chain = target_chain_buf;
3626 unsigned chain_cnt, chain_buf_size, i;
3627 const event_target_vtbl_t *vtbl, *target_vtbl;
3628 HTMLEventObj *event_obj_ref = NULL;
3629 IHTMLEventObj *prev_event = NULL;
3630 EventTarget *iter;
3631 HRESULT hres;
3633 TRACE("(%p) %s\n", event_target, debugstr_w(event->type));
3635 if(!event->type) {
3636 FIXME("Uninitialized event.\n");
3637 return E_FAIL;
3640 if(event->current_target) {
3641 FIXME("event is being dispatched.\n");
3642 return E_FAIL;
3645 iter = event_target;
3646 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3648 chain_cnt = 0;
3649 chain_buf_size = ARRAY_SIZE(target_chain_buf);
3651 do {
3652 if(chain_cnt == chain_buf_size) {
3653 EventTarget **new_chain;
3654 if(target_chain == target_chain_buf) {
3655 new_chain = malloc(chain_buf_size * 2 * sizeof(*new_chain));
3656 if(!new_chain)
3657 break;
3658 memcpy(new_chain, target_chain, chain_buf_size * sizeof(*new_chain));
3659 }else {
3660 new_chain = realloc(target_chain, chain_buf_size * 2 * sizeof(*new_chain));
3661 if(!new_chain)
3662 break;
3664 chain_buf_size *= 2;
3665 target_chain = new_chain;
3668 target_chain[chain_cnt++] = iter;
3670 if(!(vtbl = dispex_get_vtbl(&iter->dispex)) || !vtbl->get_parent_event_target)
3671 break;
3672 iter = vtbl->get_parent_event_target(&iter->dispex);
3673 } while(iter);
3675 if(!event->event_obj && !event->no_event_obj) {
3676 event_obj_ref = alloc_event_obj(event, dispex_compat_mode(&event->dispex));
3677 if(event_obj_ref)
3678 event->event_obj = &event_obj_ref->IHTMLEventObj_iface;
3681 target_vtbl = dispex_get_vtbl(&event_target->dispex);
3682 if(target_vtbl && target_vtbl->set_current_event)
3683 prev_event = target_vtbl->set_current_event(&event_target->dispex, event->event_obj);
3685 if(event->target)
3686 IEventTarget_Release(&event->target->IEventTarget_iface);
3687 event->target = event_target;
3688 IEventTarget_AddRef(&event_target->IEventTarget_iface);
3690 event->phase = DEP_CAPTURING_PHASE;
3691 i = chain_cnt-1;
3692 while(!event->stop_propagation && i)
3693 call_event_handlers(target_chain[i--], event, dispatch_mode);
3695 if(!event->stop_propagation) {
3696 event->phase = DEP_AT_TARGET;
3697 call_event_handlers(target_chain[0], event, dispatch_mode);
3700 if(event->bubbles) {
3701 event->phase = DEP_BUBBLING_PHASE;
3702 for(i = 1; !event->stop_propagation && i < chain_cnt; i++)
3703 call_event_handlers(target_chain[i], event, dispatch_mode);
3706 if(r)
3707 *r = variant_bool(!event->prevent_default);
3709 if(target_vtbl && target_vtbl->set_current_event) {
3710 IHTMLEventObj *prev = target_vtbl->set_current_event(&event_target->dispex, prev_event);
3711 if(prev)
3712 IHTMLEventObj_Release(prev);
3715 if(prev_event)
3716 IHTMLEventObj_Release(prev_event);
3718 if(event_info[event->event_id].flags & EVENT_HASDEFAULTHANDLERS) {
3719 BOOL prevent_default = event->prevent_default;
3720 for(i = 0; !prevent_default && i < chain_cnt; i++) {
3721 vtbl = dispex_get_vtbl(&target_chain[i]->dispex);
3722 if(!vtbl || !vtbl->handle_event_default)
3723 continue;
3724 hres = vtbl->handle_event_default(&event_target->dispex, event->event_id,
3725 event->nsevent, &prevent_default);
3726 if(FAILED(hres) || event->stop_propagation)
3727 break;
3728 if(prevent_default)
3729 nsIDOMEvent_PreventDefault(event->nsevent);
3733 event->prevent_default = FALSE;
3734 if(event_obj_ref) {
3735 event->event_obj = NULL;
3736 IHTMLEventObj_Release(&event_obj_ref->IHTMLEventObj_iface);
3739 for(i = 0; i < chain_cnt; i++)
3740 IEventTarget_Release(&target_chain[i]->IEventTarget_iface);
3741 if(target_chain != target_chain_buf)
3742 free(target_chain);
3744 return S_OK;
3747 void dispatch_event(EventTarget *event_target, DOMEvent *event)
3749 dispatch_event_object(event_target, event, DISPATCH_BOTH, NULL);
3752 * We may have registered multiple Gecko listeners for the same event type,
3753 * but we already dispatched event to all relevant targets. Stop event
3754 * propagation here to avoid events being dispatched multiple times.
3756 if(event_info[event->event_id].flags & EVENT_BIND_TO_TARGET)
3757 nsIDOMEvent_StopPropagation(event->nsevent);
3760 HRESULT fire_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_var, VARIANT_BOOL *cancelled)
3762 HTMLEventObj *event_obj = NULL;
3763 eventid_t eid;
3764 HRESULT hres = S_OK;
3766 eid = attr_to_eid(event_name);
3767 if(eid == EVENTID_LAST) {
3768 WARN("unknown event %s\n", debugstr_w(event_name));
3769 return E_INVALIDARG;
3772 if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
3773 if(V_VT(event_var) != VT_DISPATCH) {
3774 FIXME("event_var %s not supported\n", debugstr_variant(event_var));
3775 return E_NOTIMPL;
3778 if(V_DISPATCH(event_var)) {
3779 IHTMLEventObj *event_iface;
3781 hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
3782 if(FAILED(hres)) {
3783 FIXME("No IHTMLEventObj iface\n");
3784 return hres;
3787 event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
3788 if(!event_obj) {
3789 ERR("Not our IHTMLEventObj?\n");
3790 IHTMLEventObj_Release(event_iface);
3791 return E_FAIL;
3796 if(!event_obj) {
3797 event_obj = alloc_event_obj(NULL, dispex_compat_mode(&node->event_target.dispex));
3798 if(!event_obj)
3799 return E_OUTOFMEMORY;
3802 if(!event_obj->event)
3803 hres = create_document_event(node->doc, eid, &event_obj->event);
3805 if(SUCCEEDED(hres)) {
3806 event_obj->event->event_obj = &event_obj->IHTMLEventObj_iface;
3807 dispatch_event_object(&node->event_target, event_obj->event, DISPATCH_LEGACY, NULL);
3808 event_obj->event->event_obj = NULL;
3811 IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
3812 if(FAILED(hres))
3813 return hres;
3815 *cancelled = VARIANT_TRUE; /* FIXME */
3816 return S_OK;
3819 HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, nsIDOMNode *nsnode, eventid_t eid)
3821 TRACE("%s\n", debugstr_w(event_info[eid].name));
3823 if(!doc->dom_document)
3824 return S_OK;
3826 switch(eid) {
3827 case EVENTID_FOCUSIN:
3828 doc->event_vector[eid] = TRUE;
3829 eid = EVENTID_FOCUS;
3830 break;
3831 case EVENTID_FOCUSOUT:
3832 doc->event_vector[eid] = TRUE;
3833 eid = EVENTID_BLUR;
3834 break;
3835 default:
3836 break;
3839 if(event_info[eid].flags & EVENT_DEFAULTLISTENER) {
3840 nsnode = NULL;
3841 }else if(!(event_info[eid].flags & EVENT_BIND_TO_TARGET)) {
3842 return S_OK;
3845 if(!nsnode || nsnode == doc->node.nsnode) {
3846 if(doc->event_vector[eid])
3847 return S_OK;
3848 doc->event_vector[eid] = TRUE;
3851 add_nsevent_listener(doc, nsnode, event_info[eid].name);
3852 return S_OK;
3855 void detach_events(HTMLDocumentNode *doc)
3857 if(doc->event_vector) {
3858 int i;
3860 for(i=0; i < EVENTID_LAST; i++) {
3861 if(doc->event_vector[i]) {
3862 detach_nsevent(doc, event_info[i].name);
3863 doc->event_vector[i] = FALSE;
3868 release_nsevents(doc);
3871 static HRESULT get_event_dispex_ref(EventTarget *event_target, eventid_t eid, BOOL alloc, VARIANT **ret)
3873 WCHAR buf[64];
3874 buf[0] = 'o';
3875 buf[1] = 'n';
3876 lstrcpyW(buf+2, event_info[eid].name);
3877 return dispex_get_dprop_ref(&event_target->dispex, buf, alloc, ret);
3880 static event_listener_t *get_onevent_listener(EventTarget *event_target, eventid_t eid, BOOL alloc)
3882 listener_container_t *container;
3883 event_listener_t *listener;
3885 container = get_listener_container(event_target, event_info[eid].name, alloc);
3886 if(!container)
3887 return NULL;
3889 LIST_FOR_EACH_ENTRY_REV(listener, &container->listeners, event_listener_t, entry) {
3890 if(listener->type == LISTENER_TYPE_ONEVENT)
3891 return listener;
3894 if(!alloc)
3895 return NULL;
3897 listener = malloc(sizeof(*listener));
3898 if(!listener)
3899 return NULL;
3901 listener->type = LISTENER_TYPE_ONEVENT;
3902 listener->function = NULL;
3903 list_add_tail(&container->listeners, &listener->entry);
3904 return listener;
3907 static void remove_event_handler(EventTarget *event_target, eventid_t eid)
3909 event_listener_t *listener;
3910 VARIANT *store;
3911 HRESULT hres;
3913 hres = get_event_dispex_ref(event_target, eid, FALSE, &store);
3914 if(SUCCEEDED(hres))
3915 VariantClear(store);
3917 listener = get_onevent_listener(event_target, eid, FALSE);
3918 if(listener && listener->function) {
3919 IDispatch_Release(listener->function);
3920 listener->function = NULL;
3924 static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp)
3926 event_listener_t *listener;
3928 if(event_info[eid].flags & EVENT_FIXME)
3929 FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
3931 remove_event_handler(event_target, eid);
3932 if(!disp)
3933 return S_OK;
3935 listener = get_onevent_listener(event_target, eid, TRUE);
3936 if(!listener)
3937 return E_OUTOFMEMORY;
3939 if(listener->function)
3940 IDispatch_Release(listener->function);
3942 IDispatch_AddRef(listener->function = disp);
3943 return S_OK;
3946 HRESULT set_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
3948 switch(V_VT(var)) {
3949 case VT_EMPTY:
3950 if(use_event_quirks(event_target)) {
3951 WARN("attempt to set to VT_EMPTY in quirks mode\n");
3952 return E_NOTIMPL;
3954 /* fall through */
3955 case VT_NULL:
3956 remove_event_handler(event_target, eid);
3957 return S_OK;
3959 case VT_DISPATCH:
3960 return set_event_handler_disp(event_target, eid, V_DISPATCH(var));
3962 case VT_BSTR: {
3963 VARIANT *v;
3964 HRESULT hres;
3966 if(!use_event_quirks(event_target))
3967 FIXME("Setting to string %s not supported\n", debugstr_w(V_BSTR(var)));
3970 * Setting event handler to string is a rare case and we don't want to
3971 * complicate nor increase memory of listener_container_t for that. Instead,
3972 * we store the value in DispatchEx, which can already handle custom
3973 * properties.
3975 remove_event_handler(event_target, eid);
3977 hres = get_event_dispex_ref(event_target, eid, TRUE, &v);
3978 if(FAILED(hres))
3979 return hres;
3981 V_BSTR(v) = SysAllocString(V_BSTR(var));
3982 if(!V_BSTR(v))
3983 return E_OUTOFMEMORY;
3984 V_VT(v) = VT_BSTR;
3985 return S_OK;
3988 default:
3989 FIXME("not handler %s\n", debugstr_variant(var));
3990 return E_NOTIMPL;
3993 return S_OK;
3996 HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var)
3998 event_listener_t *listener;
3999 VARIANT *v;
4000 HRESULT hres;
4002 hres = get_event_dispex_ref(event_target, eid, FALSE, &v);
4003 if(SUCCEEDED(hres) && V_VT(v) != VT_EMPTY) {
4004 V_VT(var) = VT_EMPTY;
4005 return VariantCopy(var, v);
4008 listener = get_onevent_listener(event_target, eid, FALSE);
4009 if(listener && listener->function) {
4010 V_VT(var) = VT_DISPATCH;
4011 V_DISPATCH(var) = listener->function;
4012 IDispatch_AddRef(V_DISPATCH(var));
4013 }else {
4014 V_VT(var) = VT_NULL;
4017 return S_OK;
4020 HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
4022 listener_container_t *container;
4023 event_listener_t *listener;
4024 eventid_t eid;
4026 if(!disp) {
4027 *res = VARIANT_FALSE;
4028 return S_OK;
4031 eid = attr_to_eid(name);
4032 if(eid == EVENTID_LAST) {
4033 WARN("Unknown event\n");
4034 *res = VARIANT_TRUE;
4035 return S_OK;
4038 container = get_listener_container(event_target, event_info[eid].name, TRUE);
4039 if(!container)
4040 return E_OUTOFMEMORY;
4042 listener = malloc(sizeof(*listener));
4043 if(!listener)
4044 return E_OUTOFMEMORY;
4046 listener->type = LISTENER_TYPE_ATTACHED;
4047 IDispatch_AddRef(listener->function = disp);
4048 if(use_event_quirks(event_target))
4049 list_add_head(&container->listeners, &listener->entry);
4050 else
4051 list_add_tail(&container->listeners, &listener->entry);
4053 *res = VARIANT_TRUE;
4054 return S_OK;
4057 HRESULT detach_event(EventTarget *event_target, BSTR name, IDispatch *disp)
4059 eventid_t eid;
4061 eid = attr_to_eid(name);
4062 if(eid == EVENTID_LAST) {
4063 WARN("Unknown event\n");
4064 return S_OK;
4067 remove_event_listener(event_target, event_info[eid].name, LISTENER_TYPE_ATTACHED, disp);
4068 return S_OK;
4071 void bind_target_event(HTMLDocumentNode *doc, EventTarget *event_target, const WCHAR *event, IDispatch *disp)
4073 eventid_t eid;
4075 TRACE("(%p %p %s %p)\n", doc, event_target, debugstr_w(event), disp);
4077 eid = attr_to_eid(event);
4078 if(eid == EVENTID_LAST) {
4079 WARN("Unsupported event %s\n", debugstr_w(event));
4080 return;
4083 set_event_handler_disp(event_target, eid, disp);
4086 void update_doc_cp_events(HTMLDocumentNode *doc, cp_static_data_t *cp)
4088 int i;
4090 for(i=0; i < EVENTID_LAST; i++) {
4091 if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid))
4092 ensure_doc_nsevent_handler(doc, NULL, i);
4096 void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem)
4098 nsIDOMMozNamedAttrMap *attr_map;
4099 const PRUnichar *name, *value;
4100 nsAString name_str, value_str;
4101 HTMLDOMNode *node = NULL;
4102 cpp_bool has_attrs;
4103 nsIDOMAttr *attr;
4104 IDispatch *disp;
4105 UINT32 length, i;
4106 eventid_t eid;
4107 nsresult nsres;
4108 HRESULT hres;
4110 nsres = nsIDOMElement_HasAttributes(nselem, &has_attrs);
4111 if(NS_FAILED(nsres) || !has_attrs)
4112 return;
4114 nsres = nsIDOMElement_GetAttributes(nselem, &attr_map);
4115 if(NS_FAILED(nsres))
4116 return;
4118 nsres = nsIDOMMozNamedAttrMap_GetLength(attr_map, &length);
4119 assert(nsres == NS_OK);
4121 nsAString_Init(&name_str, NULL);
4122 nsAString_Init(&value_str, NULL);
4124 for(i = 0; i < length; i++) {
4125 nsres = nsIDOMMozNamedAttrMap_Item(attr_map, i, &attr);
4126 if(NS_FAILED(nsres))
4127 continue;
4129 nsres = nsIDOMAttr_GetName(attr, &name_str);
4130 if(NS_FAILED(nsres)) {
4131 nsIDOMAttr_Release(attr);
4132 continue;
4135 nsAString_GetData(&name_str, &name);
4136 eid = attr_to_eid(name);
4137 if(eid == EVENTID_LAST) {
4138 nsIDOMAttr_Release(attr);
4139 continue;
4142 nsres = nsIDOMAttr_GetValue(attr, &value_str);
4143 nsIDOMAttr_Release(attr);
4144 if(NS_FAILED(nsres))
4145 continue;
4147 nsAString_GetData(&value_str, &value);
4148 if(!*value)
4149 continue;
4151 TRACE("%p.%s = %s\n", nselem, debugstr_w(name), debugstr_w(value));
4153 disp = script_parse_event(doc->window, value);
4154 if(!disp)
4155 continue;
4157 if(!node) {
4158 hres = get_node((nsIDOMNode*)nselem, TRUE, &node);
4159 if(FAILED(hres)) {
4160 IDispatch_Release(disp);
4161 break;
4165 set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp);
4166 IDispatch_Release(disp);
4169 if(node)
4170 node_release(node);
4171 nsAString_Finish(&name_str);
4172 nsAString_Finish(&value_str);
4173 nsIDOMMozNamedAttrMap_Release(attr_map);
4176 HRESULT doc_init_events(HTMLDocumentNode *doc)
4178 unsigned i;
4179 HRESULT hres;
4181 doc->event_vector = calloc(EVENTID_LAST, sizeof(BOOL));
4182 if(!doc->event_vector)
4183 return E_OUTOFMEMORY;
4185 init_nsevents(doc);
4187 for(i=0; i < EVENTID_LAST; i++) {
4188 if(event_info[i].flags & EVENT_HASDEFAULTHANDLERS) {
4189 hres = ensure_doc_nsevent_handler(doc, NULL, i);
4190 if(FAILED(hres))
4191 return hres;
4195 return S_OK;
4198 static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
4200 return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
4203 static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
4205 EventTarget *This = impl_from_IEventTarget(iface);
4206 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
4209 static ULONG WINAPI EventTarget_AddRef(IEventTarget *iface)
4211 EventTarget *This = impl_from_IEventTarget(iface);
4212 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
4215 static ULONG WINAPI EventTarget_Release(IEventTarget *iface)
4217 EventTarget *This = impl_from_IEventTarget(iface);
4218 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
4221 static HRESULT WINAPI EventTarget_GetTypeInfoCount(IEventTarget *iface, UINT *pctinfo)
4223 EventTarget *This = impl_from_IEventTarget(iface);
4224 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
4227 static HRESULT WINAPI EventTarget_GetTypeInfo(IEventTarget *iface, UINT iTInfo,
4228 LCID lcid, ITypeInfo **ppTInfo)
4230 EventTarget *This = impl_from_IEventTarget(iface);
4231 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
4234 static HRESULT WINAPI EventTarget_GetIDsOfNames(IEventTarget *iface, REFIID riid, LPOLESTR *rgszNames,
4235 UINT cNames, LCID lcid, DISPID *rgDispId)
4237 EventTarget *This = impl_from_IEventTarget(iface);
4238 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid,
4239 rgszNames, cNames, lcid, rgDispId);
4242 static HRESULT WINAPI EventTarget_Invoke(IEventTarget *iface, DISPID dispIdMember,
4243 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
4244 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
4246 EventTarget *This = impl_from_IEventTarget(iface);
4247 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember,
4248 riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4251 static HRESULT WINAPI EventTarget_addEventListener(IEventTarget *iface, BSTR type,
4252 IDispatch *function, VARIANT_BOOL capture)
4254 EventTarget *This = impl_from_IEventTarget(iface);
4255 listener_type_t listener_type = capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE;
4256 listener_container_t *container;
4257 event_listener_t *listener;
4259 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), function, capture);
4261 if(!function)
4262 return S_OK;
4264 container = get_listener_container(This, type, TRUE);
4265 if(!container)
4266 return E_OUTOFMEMORY;
4268 /* check for duplicates */
4269 LIST_FOR_EACH_ENTRY(listener, &container->listeners, event_listener_t, entry) {
4270 if(listener->type == listener_type && listener->function == function)
4271 return S_OK;
4274 listener = malloc(sizeof(*listener));
4275 if(!listener)
4276 return E_OUTOFMEMORY;
4278 listener->type = listener_type;
4279 IDispatch_AddRef(listener->function = function);
4280 list_add_tail(&container->listeners, &listener->entry);
4281 return S_OK;
4284 static HRESULT WINAPI EventTarget_removeEventListener(IEventTarget *iface, BSTR type,
4285 IDispatch *listener, VARIANT_BOOL capture)
4287 EventTarget *This = impl_from_IEventTarget(iface);
4289 TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
4291 remove_event_listener(This, type, capture ? LISTENER_TYPE_CAPTURE : LISTENER_TYPE_BUBBLE, listener);
4292 return S_OK;
4295 static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event_iface, VARIANT_BOOL *result)
4297 EventTarget *This = impl_from_IEventTarget(iface);
4298 DOMEvent *event = unsafe_impl_from_IDOMEvent(event_iface);
4300 TRACE("(%p)->(%p %p)\n", This, event, result);
4302 if(!event) {
4303 WARN("Invalid event\n");
4304 return E_INVALIDARG;
4307 return dispatch_event_object(This, event, DISPATCH_STANDARD, result);
4310 static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, WORD flags,
4311 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4313 /* If only two arguments were given, implicitly set capture to false */
4314 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4315 VARIANT args[3];
4316 DISPPARAMS new_dp = {args, NULL, 3, 0};
4317 V_VT(args) = VT_BOOL;
4318 V_BOOL(args) = VARIANT_FALSE;
4319 args[1] = dp->rgvarg[0];
4320 args[2] = dp->rgvarg[1];
4322 TRACE("implicit capture\n");
4324 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_ADDEVENTLISTENER, &new_dp, res, ei, caller);
4327 return S_FALSE; /* fallback to default */
4330 static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, WORD flags,
4331 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
4333 /* If only two arguments were given, implicitly set capture to false */
4334 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
4335 VARIANT args[3];
4336 DISPPARAMS new_dp = {args, NULL, 3, 0};
4337 V_VT(args) = VT_BOOL;
4338 V_BOOL(args) = VARIANT_FALSE;
4339 args[1] = dp->rgvarg[0];
4340 args[2] = dp->rgvarg[1];
4342 TRACE("implicit capture\n");
4344 return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, &new_dp, res, ei, caller);
4347 return S_FALSE; /* fallback to default */
4350 static const IEventTargetVtbl EventTargetVtbl = {
4351 EventTarget_QueryInterface,
4352 EventTarget_AddRef,
4353 EventTarget_Release,
4354 EventTarget_GetTypeInfoCount,
4355 EventTarget_GetTypeInfo,
4356 EventTarget_GetIDsOfNames,
4357 EventTarget_Invoke,
4358 EventTarget_addEventListener,
4359 EventTarget_removeEventListener,
4360 EventTarget_dispatchEvent
4363 static EventTarget *unsafe_impl_from_IEventTarget(IEventTarget *iface)
4365 return iface && iface->lpVtbl == &EventTargetVtbl ? impl_from_IEventTarget(iface) : NULL;
4368 static HRESULT get_gecko_target(IEventTarget *target, nsIDOMEventTarget **ret)
4370 EventTarget *event_target = unsafe_impl_from_IEventTarget(target);
4371 const event_target_vtbl_t *vtbl;
4372 nsresult nsres;
4374 if(!event_target) {
4375 WARN("Not our IEventTarget implementation\n");
4376 return E_INVALIDARG;
4379 vtbl = (const event_target_vtbl_t*)dispex_get_vtbl(&event_target->dispex);
4380 nsres = nsISupports_QueryInterface(vtbl->get_gecko_target(&event_target->dispex),
4381 &IID_nsIDOMEventTarget, (void**)ret);
4382 assert(nsres == NS_OK);
4383 return S_OK;
4386 HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
4388 if(IsEqualGUID(riid, &IID_IEventTarget)) {
4389 if(use_event_quirks(event_target)) {
4390 WARN("IEventTarget queried, but not supported by in document mode\n");
4391 *ppv = NULL;
4392 return E_NOINTERFACE;
4394 IEventTarget_AddRef(&event_target->IEventTarget_iface);
4395 *ppv = &event_target->IEventTarget_iface;
4396 return S_OK;
4399 if(dispex_query_interface(&event_target->dispex, riid, ppv))
4400 return *ppv ? S_OK : E_NOINTERFACE;
4402 WARN("(%p)->(%s %p)\n", event_target, debugstr_mshtml_guid(riid), ppv);
4403 *ppv = NULL;
4404 return E_NOINTERFACE;
4407 void EventTarget_init_dispex_info(dispex_data_t *dispex_info, compat_mode_t compat_mode)
4409 static const dispex_hook_t IEventTarget_hooks[] = {
4410 {DISPID_IEVENTTARGET_ADDEVENTLISTENER, IEventTarget_addEventListener_hook},
4411 {DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, IEventTarget_removeEventListener_hook},
4412 {DISPID_UNKNOWN}
4415 if(compat_mode >= COMPAT_MODE_IE9)
4416 dispex_info_add_interface(dispex_info, IEventTarget_tid, IEventTarget_hooks);
4419 static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
4421 return wcscmp(key, WINE_RB_ENTRY_VALUE(entry, listener_container_t, entry)->type);
4424 void EventTarget_Init(EventTarget *event_target, IUnknown *outer, dispex_static_data_t *dispex_data,
4425 compat_mode_t compat_mode)
4427 init_dispatch(&event_target->dispex, outer, dispex_data, compat_mode);
4428 event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
4429 wine_rb_init(&event_target->handler_map, event_id_cmp);
4432 void release_event_target(EventTarget *event_target)
4434 listener_container_t *iter, *iter2;
4436 WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, listener_container_t, entry) {
4437 while(!list_empty(&iter->listeners)) {
4438 event_listener_t *listener = LIST_ENTRY(list_head(&iter->listeners), event_listener_t, entry);
4439 if(listener->function)
4440 IDispatch_Release(listener->function);
4441 list_remove(&listener->entry);
4442 free(listener);
4444 free(iter);