Commit 3de3d070 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

mshtml: Added support for event object in HTMLElement::fireEvent.

parent fffb717b
...@@ -788,6 +788,11 @@ static const IHTMLEventObjVtbl HTMLEventObjVtbl = { ...@@ -788,6 +788,11 @@ static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
HTMLEventObj_get_srcFilter 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[] = { static const tid_t HTMLEventObj_iface_tids[] = {
IHTMLEventObj_tid, IHTMLEventObj_tid,
0 0
...@@ -800,7 +805,7 @@ static dispex_static_data_t HTMLEventObj_dispex = { ...@@ -800,7 +805,7 @@ static dispex_static_data_t HTMLEventObj_dispex = {
HTMLEventObj_iface_tids HTMLEventObj_iface_tids
}; };
static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent) static HTMLEventObj *create_event(void)
{ {
HTMLEventObj *ret; HTMLEventObj *ret;
...@@ -810,39 +815,43 @@ static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEven ...@@ -810,39 +815,43 @@ static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEven
ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl; ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
ret->ref = 1; 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) { if(nsevent) {
nsIDOMEvent_AddRef(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; nsAString type_str;
nsresult nsres; nsresult nsres;
nsAString_InitDepend(&type_str, event_types[event_info[eid].type]); 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); nsAString_Finish(&type_str);
if(NS_FAILED(nsres)) { if(NS_FAILED(nsres)) {
ERR("Could not create event: %08x\n", nsres); ERR("Could not create event: %08x\n", nsres);
IHTMLEventObj_Release(&ret->IHTMLEventObj_iface); return E_FAIL;
return NULL;
} }
} }
ret->target = target; event->target = target;
if(target) if(target)
IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface); IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface);
return S_OK;
init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
return ret;
} }
HRESULT create_event_obj(IHTMLEventObj **ret) HRESULT create_event_obj(IHTMLEventObj **ret)
{ {
HTMLEventObj *event; HTMLEventObj *event;
event = create_event(NULL, EVENTID_LAST, NULL); event = create_event();
if(!event) if(!event)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
...@@ -1021,9 +1030,8 @@ static void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, ...@@ -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; IHTMLEventObj *prev_event;
nsIDOMNode *parent, *nsnode; nsIDOMNode *parent, *nsnode;
BOOL prevent_default = FALSE; BOOL prevent_default = FALSE;
...@@ -1037,17 +1045,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode ...@@ -1037,17 +1045,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
window = doc->window; window = doc->window;
prev_event = window->event; prev_event = window->event;
if(set_event) { window->event = &event_obj->IHTMLEventObj_iface;
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;
}
nsIDOMNode_GetNodeType(target, &node_type); nsIDOMNode_GetNodeType(target, &node_type);
nsnode = target; nsnode = target;
...@@ -1111,8 +1109,6 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode ...@@ -1111,8 +1109,6 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
if(event_obj && event_obj->prevent_default) if(event_obj && event_obj->prevent_default)
prevent_default = TRUE; prevent_default = TRUE;
window->event = prev_event; window->event = prev_event;
if(event_obj)
IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) { if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) {
nsIDOMNode_AddRef(target); nsIDOMNode_AddRef(target);
...@@ -1125,7 +1121,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode ...@@ -1125,7 +1121,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
if(node) { if(node) {
if(node->vtbl->handle_event) 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); node_release(node);
if(FAILED(hres) || prevent_default || (event_obj && event_obj->cancel_bubble)) if(FAILED(hres) || prevent_default || (event_obj && event_obj->cancel_bubble))
break; break;
...@@ -1143,15 +1139,46 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode ...@@ -1143,15 +1139,46 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
nsIDOMNode_Release(nsnode); nsIDOMNode_Release(nsnode);
} }
if(prevent_default && nsevent) { if(prevent_default && event_obj && event_obj->nsevent) {
TRACE("calling PreventDefault\n"); 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; eventid_t eid;
HRESULT hres;
eid = attr_to_eid(event_name); eid = attr_to_eid(event_name);
if(eid == EVENTID_LAST) { if(eid == EVENTID_LAST) {
...@@ -1159,15 +1186,46 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even ...@@ -1159,15 +1186,46 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even
return E_INVALIDARG; return E_INVALIDARG;
} }
if(event_obj && V_VT(event_obj) != VT_EMPTY && V_VT(event_obj) != VT_ERROR) if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
FIXME("event_obj not implemented\n"); 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)) { if(V_DISPATCH(event_var)) {
FIXME("not EVENT_DEFAULTEVENTHANDLER\n"); IHTMLEventObj *event_iface;
return E_NOTIMPL;
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 */ *cancelled = VARIANT_TRUE; /* FIXME */
return S_OK; return S_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment