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
|
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 = {
|
||||||
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
|
||||||
|
|
||||||
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;
|
|
||||||
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);
|
init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
|
||||||
|
|
||||||
return ret;
|
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)
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue