mshtml: Added support for event object in HTMLElement::fireEvent.
This commit is contained in:
parent
fffb717b1b
commit
3de3d07054
|
@ -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;
|
||||
if(nsevent) {
|
||||
nsIDOMEvent_AddRef(nsevent);
|
||||
}else if(eid != EVENTID_LAST && 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);
|
||||
nsAString_Finish(&type_str);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not create event: %08x\n", nsres);
|
||||
IHTMLEventObj_Release(&ret->IHTMLEventObj_iface);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret->target = target;
|
||||
if(target)
|
||||
IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface);
|
||||
|
||||
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(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, &event->nsevent);
|
||||
nsAString_Finish(&type_str);
|
||||
if(NS_FAILED(nsres)) {
|
||||
ERR("Could not create event: %08x\n", nsres);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
event->target = target;
|
||||
if(target)
|
||||
IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface);
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue