Jacek Caban : mshtml: Added support for event object in HTMLElement:: fireEvent.
Alexandre Julliard
julliard at winehq.org
Thu Sep 13 14:39:21 CDT 2012
Module: wine
Branch: master
Commit: 3de3d07054d586d60be9d36f6c5725c3f28134fb
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3de3d07054d586d60be9d36f6c5725c3f28134fb
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Sep 13 12:28:09 2012 +0200
mshtml: Added support for event object in HTMLElement::fireEvent.
---
dlls/mshtml/htmlevent.c | 134 +++++++++++++++++++++++++++++++++-------------
1 files changed, 96 insertions(+), 38 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index eecff1c..6f1260a 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -788,6 +788,11 @@ static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
HTMLEventObj_get_srcFilter
};
+static inline HTMLEventObj *unsafe_impl_from_IHTMLEventObj(IHTMLEventObj *iface)
+{
+ return iface->lpVtbl == &HTMLEventObjVtbl ? impl_from_IHTMLEventObj(iface) : NULL;
+}
+
static const tid_t HTMLEventObj_iface_tids[] = {
IHTMLEventObj_tid,
0
@@ -800,7 +805,7 @@ static dispex_static_data_t HTMLEventObj_dispex = {
HTMLEventObj_iface_tids
};
-static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent)
+static HTMLEventObj *create_event(void)
{
HTMLEventObj *ret;
@@ -810,39 +815,43 @@ static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEven
ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
ret->ref = 1;
- ret->type = eid != EVENTID_LAST ? event_info+eid : NULL;
- ret->nsevent = nsevent;
+ init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
+
+ return ret;
+}
+
+static HRESULT set_event_info(HTMLEventObj *event, HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent)
+{
+ event->type = event_info+eid;
+ event->nsevent = nsevent;
+
if(nsevent) {
nsIDOMEvent_AddRef(nsevent);
- }else if(eid != EVENTID_LAST && event_types[event_info[eid].type]) {
+ }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(target->doc->nsdoc, &type_str, &ret->nsevent);
+ nsres = nsIDOMHTMLDocument_CreateEvent(target->doc->nsdoc, &type_str, &event->nsevent);
nsAString_Finish(&type_str);
if(NS_FAILED(nsres)) {
ERR("Could not create event: %08x\n", nsres);
- IHTMLEventObj_Release(&ret->IHTMLEventObj_iface);
- return NULL;
+ return E_FAIL;
}
}
- ret->target = target;
+ event->target = target;
if(target)
IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface);
-
- init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
-
- return ret;
+ return S_OK;
}
HRESULT create_event_obj(IHTMLEventObj **ret)
{
HTMLEventObj *event;
- event = create_event(NULL, EVENTID_LAST, NULL);
+ event = create_event();
if(!event)
return E_OUTOFMEMORY;
@@ -1021,9 +1030,8 @@ static void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj,
}
}
-void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent)
+static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *event_obj, nsIDOMNode *target)
{
- HTMLEventObj *event_obj = NULL;
IHTMLEventObj *prev_event;
nsIDOMNode *parent, *nsnode;
BOOL prevent_default = FALSE;
@@ -1037,17 +1045,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
window = doc->window;
prev_event = window->event;
- if(set_event) {
- hres = get_node(doc, target, TRUE, &node);
- if(FAILED(hres))
- return;
-
- event_obj = create_event(node, eid, nsevent);
- node_release(node);
- window->event = &event_obj->IHTMLEventObj_iface;
- }else {
- window->event = NULL;
- }
+ window->event = &event_obj->IHTMLEventObj_iface;
nsIDOMNode_GetNodeType(target, &node_type);
nsnode = target;
@@ -1111,8 +1109,6 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
if(event_obj && event_obj->prevent_default)
prevent_default = TRUE;
window->event = prev_event;
- if(event_obj)
- IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) {
nsIDOMNode_AddRef(target);
@@ -1125,7 +1121,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
if(node) {
if(node->vtbl->handle_event)
- hres = node->vtbl->handle_event(node, eid, nsevent, &prevent_default);
+ hres = node->vtbl->handle_event(node, eid, event_obj ? event_obj->nsevent : NULL, &prevent_default);
node_release(node);
if(FAILED(hres) || prevent_default || (event_obj && event_obj->cancel_bubble))
break;
@@ -1143,15 +1139,46 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
nsIDOMNode_Release(nsnode);
}
- if(prevent_default && nsevent) {
+ if(prevent_default && event_obj && event_obj->nsevent) {
TRACE("calling PreventDefault\n");
- nsIDOMEvent_PreventDefault(nsevent);
+ nsIDOMEvent_PreventDefault(event_obj->nsevent);
}
}
-HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_obj, VARIANT_BOOL *cancelled)
+void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent)
{
+ HTMLEventObj *event_obj = NULL;
+ HTMLDOMNode *node;
+ HRESULT hres;
+
+ if(set_event) {
+ hres = get_node(doc, target, TRUE, &node);
+ if(FAILED(hres))
+ return;
+
+ event_obj = create_event();
+ node_release(node);
+ if(!event_obj)
+ return;
+
+ hres = set_event_info(event_obj, node, eid, nsevent);
+ if(FAILED(hres)) {
+ IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+ return;
+ }
+ }
+
+ fire_event_obj(doc, eid, event_obj, target);
+
+ if(event_obj)
+ IHTMLEventObj_Release(&event_obj->IHTMLEventObj_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;
eid = attr_to_eid(event_name);
if(eid == EVENTID_LAST) {
@@ -1159,15 +1186,46 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even
return E_INVALIDARG;
}
- if(event_obj && V_VT(event_obj) != VT_EMPTY && V_VT(event_obj) != VT_ERROR)
- FIXME("event_obj not implemented\n");
+ if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
+ if(V_VT(event_var) != VT_DISPATCH) {
+ FIXME("event_var %s not supported\n", debugstr_variant(event_var));
+ return E_NOTIMPL;
+ }
- if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) {
- FIXME("not EVENT_DEFAULTEVENTHANDLER\n");
- return E_NOTIMPL;
+ if(V_DISPATCH(event_var)) {
+ IHTMLEventObj *event_iface;
+
+ hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
+ if(FAILED(hres)) {
+ FIXME("No IHTMLEventObj iface\n");
+ return hres;
+ }
+
+ event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
+ if(!event_obj) {
+ ERR("Not our IHTMLEventObj?\n");
+ IHTMLEventObj_Release(event_iface);
+ return E_FAIL;
+ }
+ }
}
- fire_event(node->doc, eid, TRUE, node->nsnode, NULL);
+ if(event_obj) {
+ hres = set_event_info(event_obj, node, eid, NULL);
+ if(SUCCEEDED(hres))
+ fire_event_obj(node->doc, eid, event_obj, node->nsnode);
+
+ IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) {
+ FIXME("not EVENT_DEFAULTEVENTHANDLER\n");
+ return E_NOTIMPL;
+ }
+
+ fire_event(node->doc, eid, TRUE, node->nsnode, NULL);
+ }
*cancelled = VARIANT_TRUE; /* FIXME */
return S_OK;
More information about the wine-cvs
mailing list