diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index aee9d39026c..9e6bed5aab8 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -223,15 +223,6 @@ static eventid_t attr_to_eid(const WCHAR *str) return EVENTID_LAST; } -typedef struct { - DispatchEx dispex; - IDOMEvent IDOMEvent_iface; - - LONG ref; - - nsIDOMEvent *nsevent; -} DOMEvent; - struct HTMLEventObj { DispatchEx dispex; IHTMLEventObj IHTMLEventObj_iface; @@ -240,7 +231,7 @@ struct HTMLEventObj { EventTarget *target; const event_info_t *type; - nsIDOMEvent *nsevent; + DOMEvent *event; VARIANT return_value; BOOL prevent_default; BOOL cancel_bubble; @@ -293,8 +284,8 @@ static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface) if(!ref) { if(This->target) IDispatchEx_Release(&This->target->dispex.IDispatchEx_iface); - if(This->nsevent) - nsIDOMEvent_Release(This->nsevent); + if(This->event) + IDOMEvent_Release(&This->event->IDOMEvent_iface); release_dispex(&This->dispex); heap_free(This); } @@ -352,18 +343,18 @@ static HRESULT WINAPI HTMLEventObj_get_altKey(IHTMLEventObj *iface, VARIANT_BOOL TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMKeyEvent *key_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); if(NS_SUCCEEDED(nsres)) { nsIDOMKeyEvent_GetAltKey(key_event, &ret); nsIDOMKeyEvent_Release(key_event); }else { nsIDOMMouseEvent *mouse_event; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetAltKey(mouse_event, &ret); nsIDOMMouseEvent_Release(mouse_event); @@ -382,18 +373,18 @@ static HRESULT WINAPI HTMLEventObj_get_ctrlKey(IHTMLEventObj *iface, VARIANT_BOO TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMKeyEvent *key_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); if(NS_SUCCEEDED(nsres)) { nsIDOMKeyEvent_GetCtrlKey(key_event, &ret); nsIDOMKeyEvent_Release(key_event); }else { nsIDOMMouseEvent *mouse_event; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetCtrlKey(mouse_event, &ret); nsIDOMMouseEvent_Release(mouse_event); @@ -412,18 +403,18 @@ static HRESULT WINAPI HTMLEventObj_get_shiftKey(IHTMLEventObj *iface, VARIANT_BO TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMKeyEvent *key_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); if(NS_SUCCEEDED(nsres)) { nsIDOMKeyEvent_GetShiftKey(key_event, &ret); nsIDOMKeyEvent_Release(key_event); }else { nsIDOMMouseEvent *mouse_event; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetShiftKey(mouse_event, &ret); nsIDOMMouseEvent_Release(mouse_event); @@ -516,11 +507,11 @@ static HRESULT WINAPI HTMLEventObj_get_keyCode(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMKeyEvent *key_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMKeyEvent, (void**)&key_event); if(NS_SUCCEEDED(nsres)) { nsIDOMKeyEvent_GetKeyCode(key_event, &key_code); nsIDOMKeyEvent_Release(key_event); @@ -538,11 +529,11 @@ static HRESULT WINAPI HTMLEventObj_get_button(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMMouseEvent *mouse_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetButton(mouse_event, &button); nsIDOMMouseEvent_Release(mouse_event); @@ -595,11 +586,11 @@ static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMUIEvent *ui_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event); if(NS_SUCCEEDED(nsres)) { /* NOTE: pageX is not exactly right here. */ nsres = nsIDOMUIEvent_GetPageX(ui_event, &x); @@ -619,11 +610,11 @@ static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMUIEvent *ui_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event); if(NS_SUCCEEDED(nsres)) { /* NOTE: pageY is not exactly right here. */ nsres = nsIDOMUIEvent_GetPageY(ui_event, &y); @@ -643,11 +634,11 @@ static HRESULT WINAPI HTMLEventObj_get_clientX(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMMouseEvent *mouse_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetClientX(mouse_event, &x); nsIDOMMouseEvent_Release(mouse_event); @@ -665,11 +656,11 @@ static HRESULT WINAPI HTMLEventObj_get_clientY(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMMouseEvent *mouse_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetClientY(mouse_event, &y); nsIDOMMouseEvent_Release(mouse_event); @@ -707,11 +698,11 @@ static HRESULT WINAPI HTMLEventObj_get_screenX(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMMouseEvent *mouse_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetScreenX(mouse_event, &x); nsIDOMMouseEvent_Release(mouse_event); @@ -729,11 +720,11 @@ static HRESULT WINAPI HTMLEventObj_get_screenY(IHTMLEventObj *iface, LONG *p) TRACE("(%p)->(%p)\n", This, p); - if(This->nsevent) { + if(This->event) { nsIDOMMouseEvent *mouse_event; nsresult nsres; - nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + nsres = nsIDOMEvent_QueryInterface(This->event->nsevent, &IID_nsIDOMMouseEvent, (void**)&mouse_event); if(NS_SUCCEEDED(nsres)) { nsIDOMMouseEvent_GetScreenY(mouse_event, &y); nsIDOMMouseEvent_Release(mouse_event); @@ -805,20 +796,34 @@ static dispex_static_data_t HTMLEventObj_dispex = { HTMLEventObj_iface_tids }; -static HTMLEventObj *create_event(void) +static HTMLEventObj *alloc_event_obj(DOMEvent *event) { - HTMLEventObj *ret; + HTMLEventObj *event_obj; - ret = heap_alloc_zero(sizeof(*ret)); - if(!ret) + event_obj = heap_alloc_zero(sizeof(*event_obj)); + if(!event_obj) return NULL; - ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl; - ret->ref = 1; + event_obj->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl; + event_obj->ref = 1; + event_obj->event = event; + if(event) + IDOMEvent_AddRef(&event->IDOMEvent_iface); - init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex); + init_dispex(&event_obj->dispex, (IUnknown*)&event_obj->IHTMLEventObj_iface, &HTMLEventObj_dispex); + return event_obj; +} - return ret; +HRESULT create_event_obj(IHTMLEventObj **ret) +{ + HTMLEventObj *event_obj; + + event_obj = alloc_event_obj(NULL); + if(!event_obj) + return E_OUTOFMEMORY; + + *ret = &event_obj->IHTMLEventObj_iface; + return S_OK; } static inline DOMEvent *impl_from_IDOMEvent(IDOMEvent *iface) @@ -1053,7 +1058,7 @@ static dispex_static_data_t DOMEvent_dispex = { DOMEvent_iface_tids }; -static HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, IDOMEvent **ret_event) +static HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, DOMEvent **ret_event) { DOMEvent *event; @@ -1067,13 +1072,14 @@ static HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, IDOMEvent **ret_e nsIDOMEvent_AddRef(event->nsevent = nsevent); - *ret_event = &event->IDOMEvent_iface; + *ret_event = event; return S_OK; } HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOMEvent **ret_event) { nsIDOMEvent *nsevent; + DOMEvent *event; nsAString nsstr; nsresult nsres; HRESULT hres; @@ -1082,48 +1088,34 @@ HRESULT create_document_event_str(HTMLDocumentNode *doc, const WCHAR *type, IDOM nsres = nsIDOMHTMLDocument_CreateEvent(doc->nsdoc, &nsstr, &nsevent); nsAString_Finish(&nsstr); if(NS_FAILED(nsres)) { - FIXME("CreateEvent failed: %08x\n", nsres); + FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(type), nsres); return E_FAIL; } - hres = create_event_from_nsevent(nsevent, ret_event); + hres = create_event_from_nsevent(nsevent, &event); nsIDOMEvent_Release(nsevent); - return hres; + if(FAILED(hres)) + return hres; + + *ret_event = &event->IDOMEvent_iface; + return S_OK; } -static HRESULT set_event_info(HTMLEventObj *event, eventid_t eid, HTMLDocumentNode *doc, nsIDOMEvent *nsevent) +static HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEvent **ret_event) { - event->type = event_info+eid; - event->nsevent = nsevent; + nsIDOMEvent *nsevent; + nsAString nsstr; + nsresult nsres; - if(nsevent) { - nsIDOMEvent_AddRef(nsevent); - }else if(event_types[event_info[eid].type]) { - nsAString type_str; - nsresult nsres; - - nsAString_InitDepend(&type_str, event_types[event_info[eid].type]); - nsres = nsIDOMHTMLDocument_CreateEvent(doc->nsdoc, &type_str, &event->nsevent); - nsAString_Finish(&type_str); - if(NS_FAILED(nsres)) { - ERR("Could not create event: %08x\n", nsres); - return E_FAIL; - } + nsAString_InitDepend(&nsstr, event_types[event_info[event_id].type]); + nsres = nsIDOMHTMLDocument_CreateEvent(doc->nsdoc, &nsstr, &nsevent); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) { + FIXME("CreateEvent(%s) failed: %08x\n", debugstr_w(event_types[event_info[event_id].type]), nsres); + return E_FAIL; } - return S_OK; -} - -HRESULT create_event_obj(IHTMLEventObj **ret) -{ - HTMLEventObj *event; - - event = create_event(); - if(!event) - return E_OUTOFMEMORY; - - *ret = &event->IHTMLEventObj_iface; - return S_OK; + return create_event_from_nsevent(nsevent, ret_event); } static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc) @@ -1410,7 +1402,8 @@ static void fire_event_obj(EventTarget *event_target, eventid_t eid, HTMLEventOb vtbl = dispex_get_vtbl(&target_chain[i]->dispex); if(!vtbl || !vtbl->handle_event_default) continue; - hres = vtbl->handle_event_default(&event_target->dispex, eid, event_obj ? event_obj->nsevent : NULL, &prevent_default); + hres = vtbl->handle_event_default(&event_target->dispex, eid, + event_obj && event_obj->event ? event_obj->event->nsevent : NULL, &prevent_default); if(FAILED(hres) || (event_obj && event_obj->cancel_bubble)) break; } @@ -1421,40 +1414,46 @@ static void fire_event_obj(EventTarget *event_target, eventid_t eid, HTMLEventOb if(target_chain != target_chain_buf) heap_free(target_chain); - if(prevent_default && event_obj && event_obj->nsevent) { + if(prevent_default && event_obj && event_obj->event && event_obj->event->nsevent) { TRACE("calling PreventDefault\n"); - nsIDOMEvent_PreventDefault(event_obj->nsevent); + nsIDOMEvent_PreventDefault(event_obj->event->nsevent); } } void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, EventTarget *target, nsIDOMEvent *nsevent) { HTMLEventObj *event_obj = NULL; + DOMEvent *event; HRESULT hres; - if(set_event) { - event_obj = create_event(); - if(!event_obj) - return; + if(nsevent) + hres = create_event_from_nsevent(nsevent, &event); + else + hres = create_document_event(doc, eid, &event); + if(FAILED(hres)) + return; - hres = set_event_info(event_obj, eid, doc, nsevent); - if(FAILED(hres)) { - IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface); + if(set_event) { + event_obj = alloc_event_obj(event); + if(!event_obj) { + IDOMEvent_Release(&event->IDOMEvent_iface); return; } + event_obj->type = event_info + eid; } fire_event_obj(target, eid, event_obj); if(event_obj) IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface); + IDOMEvent_Release(&event->IDOMEvent_iface); } HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_var, VARIANT_BOOL *cancelled) { HTMLEventObj *event_obj = NULL; eventid_t eid; - HRESULT hres; + HRESULT hres = S_OK; eid = attr_to_eid(event_name); if(eid == EVENTID_LAST) { @@ -1486,18 +1485,24 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even } } - if(event_obj) { - hres = set_event_info(event_obj, eid, node->doc, NULL); - if(SUCCEEDED(hres)) - fire_event_obj(&node->event_target, eid, event_obj); - - IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface); - if(FAILED(hres)) - return hres; - }else { - fire_event(node->doc, eid, TRUE, &node->event_target, NULL); + if(!event_obj) { + event_obj = alloc_event_obj(NULL); + if(!event_obj) + return E_OUTOFMEMORY; } + event_obj->type = event_info + eid; + if(!event_obj->event) + hres = create_document_event(node->doc, eid, &event_obj->event); + + if(SUCCEEDED(hres)) + fire_event_obj(&node->event_target, eid, event_obj); + + if(event_obj) + IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface); + if(FAILED(hres)) + return hres; + *cancelled = VARIANT_TRUE; /* FIXME */ return S_OK; } diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index f604003c9b1..daf436861f0 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -55,6 +55,15 @@ typedef enum { EVENTID_LAST } eventid_t; +typedef struct { + DispatchEx dispex; + IDOMEvent IDOMEvent_iface; + + LONG ref; + + nsIDOMEvent *nsevent; +} DOMEvent; + eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN; void check_event_attr(HTMLDocumentNode*,nsIDOMHTMLElement*) DECLSPEC_HIDDEN; void release_event_target(EventTarget*) DECLSPEC_HIDDEN;