void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent, IDispatch *script_this) { 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, script_this); 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) { WARN("unknown event %s\n", debugstr_w(event_name)); return E_INVALIDARG; } 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(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; } } } 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, NULL); 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, NULL); } *cancelled = VARIANT_TRUE; /* FIXME */ return S_OK; }
static IHTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent) { HTMLEventObj *ret; ret = heap_alloc(sizeof(*ret)); if(!ret) return NULL; ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl; ret->ref = 1; ret->type = event_info+eid; ret->nsevent = nsevent; if(nsevent) { nsIDOMEvent_AddRef(nsevent); }else if(event_types[event_info[eid].type]) { nsIDOMDocumentEvent *doc_event; nsresult nsres; nsres = nsIDOMHTMLDocument_QueryInterface(target->doc->nsdoc, &IID_nsIDOMDocumentEvent, (void**)&doc_event); if(NS_SUCCEEDED(nsres)) { nsAString type_str; nsAString_InitDepend(&type_str, event_types[event_info[eid].type]); nsres = nsIDOMDocumentEvent_CreateEvent(doc_event, &type_str, &ret->nsevent); nsAString_Finish(&type_str); nsIDOMDocumentEvent_Release(doc_event); } if(NS_FAILED(nsres)) { ERR("Could not create event: %08x\n", nsres); IHTMLEventObj_Release(&ret->IHTMLEventObj_iface); return NULL; } } ret->target = target; IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface); init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex); return &ret->IHTMLEventObj_iface; }
void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent) { IHTMLEventObj *prev_event, *event_obj = NULL; nsIDOMNode *parent, *nsnode; HTMLDOMNode *node; PRUint16 node_type; HRESULT hres; TRACE("(%p) %s\n", doc, debugstr_w(event_info[eid].name)); prev_event = doc->basedoc.window->event; if(set_event) { hres = get_node(doc, target, TRUE, &node); if(FAILED(hres)) return; event_obj = create_event(node, eid, nsevent); } doc->basedoc.window->event = event_obj; nsIDOMNode_GetNodeType(target, &node_type); nsnode = target; nsIDOMNode_AddRef(nsnode); switch(node_type) { case ELEMENT_NODE: do { hres = get_node(doc, nsnode, FALSE, &node); if(SUCCEEDED(hres) && node) call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, (IDispatch*)&node->IHTMLDOMNode_iface); if(!(event_info[eid].flags & EVENT_BUBBLE)) break; nsIDOMNode_GetParentNode(nsnode, &parent); nsIDOMNode_Release(nsnode); nsnode = parent; if(!nsnode) break; nsIDOMNode_GetNodeType(nsnode, &node_type); }while(node_type == ELEMENT_NODE); if(!(event_info[eid].flags & EVENT_BUBBLE)) break; case DOCUMENT_NODE: if(event_info[eid].flags & EVENT_FORWARDBODY) { nsIDOMHTMLElement *nsbody; nsresult nsres; nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); if(NS_SUCCEEDED(nsres) && nsbody) { hres = get_node(doc, (nsIDOMNode*)nsbody, FALSE, &node); if(SUCCEEDED(hres) && node) call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, (IDispatch*)&node->IHTMLDOMNode_iface); nsIDOMHTMLElement_Release(nsbody); }else { ERR("Could not get body: %08x\n", nsres); } } call_event_handlers(doc, event_obj, doc->node.event_target, &doc->basedoc.cp_container, eid, (IDispatch*)&doc->basedoc.IHTMLDocument2_iface); break; default: FIXME("unimplemented node type %d\n", node_type); } if(nsnode) nsIDOMNode_Release(nsnode); if(event_obj) IHTMLEventObj_Release(event_obj); doc->basedoc.window->event = prev_event; }