mshtml: Use vtbl to get ConnectionPointContainer from event target.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e5c0759c0c
commit
0c35bf7c8e
|
@ -5030,6 +5030,15 @@ static void HTMLDocumentNode_bind_event(DispatchEx *dispex, eventid_t eid)
|
|||
ensure_doc_nsevent_handler(This, eid);
|
||||
}
|
||||
|
||||
static ConnectionPointContainer *HTMLDocumentNode_get_cp_container(DispatchEx *dispex)
|
||||
{
|
||||
HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
|
||||
ConnectionPointContainer *container = This->basedoc.doc_obj
|
||||
? &This->basedoc.doc_obj->basedoc.cp_container : &This->basedoc.cp_container;
|
||||
IConnectionPointContainer_AddRef(&container->IConnectionPointContainer_iface);
|
||||
return container;
|
||||
}
|
||||
|
||||
static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
|
||||
{
|
||||
NULL,
|
||||
|
@ -5038,7 +5047,8 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
|
|||
HTMLDocumentNode_get_compat_mode,
|
||||
NULL
|
||||
},
|
||||
HTMLDocumentNode_bind_event
|
||||
HTMLDocumentNode_bind_event,
|
||||
HTMLDocumentNode_get_cp_container
|
||||
};
|
||||
|
||||
static const NodeImplVtbl HTMLDocumentFragmentImplVtbl = {
|
||||
|
@ -5138,7 +5148,6 @@ HRESULT create_doc_from_nsdoc(nsIDOMHTMLDocument *nsdoc, HTMLDocumentObj *doc_ob
|
|||
doc_init_events(doc);
|
||||
|
||||
doc->node.vtbl = &HTMLDocumentNodeImplVtbl;
|
||||
doc->node.cp_container = &doc->basedoc.cp_container;
|
||||
|
||||
*ret = doc;
|
||||
return S_OK;
|
||||
|
@ -5156,7 +5165,6 @@ static HRESULT create_document_fragment(nsIDOMNode *nsnode, HTMLDocumentNode *do
|
|||
|
||||
HTMLDOMNode_Init(doc_node, &doc_frag->node, nsnode, &HTMLDocumentNode_dispex);
|
||||
doc_frag->node.vtbl = &HTMLDocumentFragmentImplVtbl;
|
||||
doc_frag->node.cp_container = &doc_frag->basedoc.cp_container;
|
||||
|
||||
*ret = doc_frag;
|
||||
return S_OK;
|
||||
|
|
|
@ -5347,6 +5347,13 @@ static void HTMLElement_bind_event(DispatchEx *dispex, eventid_t eid)
|
|||
}
|
||||
}
|
||||
|
||||
static ConnectionPointContainer *HTMLElement_get_cp_container(DispatchEx *dispex)
|
||||
{
|
||||
HTMLElement *This = impl_from_DispatchEx(dispex);
|
||||
IConnectionPointContainer_AddRef(&This->cp_container.IConnectionPointContainer_iface);
|
||||
return &This->cp_container;
|
||||
}
|
||||
|
||||
void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
|
||||
{
|
||||
static const DISPID elem2_ie11_blacklist[] = {DISPID_IHTMLELEMENT2_DOSCROLL, DISPID_UNKNOWN};
|
||||
|
@ -5377,7 +5384,8 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = {
|
|||
NULL,
|
||||
HTMLElement_populate_props
|
||||
},
|
||||
HTMLElement_bind_event
|
||||
HTMLElement_bind_event,
|
||||
HTMLElement_get_cp_container
|
||||
};
|
||||
|
||||
static dispex_static_data_t HTMLElement_dispex = {
|
||||
|
@ -5410,7 +5418,6 @@ void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElemen
|
|||
This->nselem = nselem;
|
||||
}
|
||||
|
||||
This->node.cp_container = &This->cp_container;
|
||||
ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface, This->node.vtbl->cpc_entries);
|
||||
}
|
||||
|
||||
|
|
|
@ -937,11 +937,12 @@ static BOOL is_cp_event(cp_static_data_t *data, DISPID dispid)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTarget *event_target,
|
||||
ConnectionPointContainer *cp_container, eventid_t eid, IDispatch *this_obj)
|
||||
void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, eventid_t eid, IDispatch *this_obj)
|
||||
{
|
||||
handler_vector_t *handler_vector = get_handler_vector(event_target, eid, FALSE);
|
||||
const BOOL cancelable = event_info[eid].flags & EVENT_CANCELABLE;
|
||||
ConnectionPointContainer *cp_container = NULL;
|
||||
const event_target_vtbl_t *vtbl;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1010,51 +1011,46 @@ void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj, EventTa
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: CP events may require doc_obj reference, which we don't own. We make sure that
|
||||
* it's safe to call event handler by checking nsevent_listener, which is NULL for
|
||||
* detached documents.
|
||||
*/
|
||||
if(cp_container && cp_container->forward_container)
|
||||
cp_container = cp_container->forward_container;
|
||||
if(cp_container && cp_container->cps && doc->nsevent_listener) {
|
||||
ConnectionPoint *cp;
|
||||
unsigned i, j;
|
||||
if((vtbl = dispex_get_vtbl(&event_target->dispex)) && vtbl->get_cp_container)
|
||||
cp_container = vtbl->get_cp_container(&event_target->dispex);
|
||||
if(cp_container) {
|
||||
if(cp_container->cps) {
|
||||
ConnectionPoint *cp;
|
||||
unsigned i, j;
|
||||
|
||||
for(j=0; cp_container->cp_entries[j].riid; j++) {
|
||||
cp = cp_container->cps + j;
|
||||
if(!cp->sinks_size || !is_cp_event(cp->data, event_info[eid].dispid))
|
||||
continue;
|
||||
|
||||
for(i=0; doc->nsevent_listener && i < cp->sinks_size; i++) {
|
||||
if(!cp->sinks[i].disp)
|
||||
for(j=0; cp_container->cp_entries[j].riid; j++) {
|
||||
cp = cp_container->cps + j;
|
||||
if(!cp->sinks_size || !is_cp_event(cp->data, event_info[eid].dispid))
|
||||
continue;
|
||||
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
for(i=0; i < cp->sinks_size; i++) {
|
||||
if(!cp->sinks[i].disp)
|
||||
continue;
|
||||
|
||||
TRACE("cp %s [%u] >>>\n", debugstr_w(event_info[eid].name), i);
|
||||
hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid,
|
||||
cp->data->pass_event_arg ? event_obj : NULL, &v);
|
||||
if(hres == S_OK) {
|
||||
TRACE("cp %s [%u] <<<\n", debugstr_w(event_info[eid].name), i);
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
|
||||
if(cancelable) {
|
||||
if(V_VT(&v) == VT_BOOL) {
|
||||
if(!V_BOOL(&v))
|
||||
event_obj->prevent_default = TRUE;
|
||||
}else if(V_VT(&v) != VT_EMPTY) {
|
||||
FIXME("unhandled result %s\n", debugstr_variant(&v));
|
||||
TRACE("cp %s [%u] >>>\n", debugstr_w(event_info[eid].name), i);
|
||||
hres = call_cp_func(cp->sinks[i].disp, event_info[eid].dispid,
|
||||
cp->data->pass_event_arg ? event_obj : NULL, &v);
|
||||
if(hres == S_OK) {
|
||||
TRACE("cp %s [%u] <<<\n", debugstr_w(event_info[eid].name), i);
|
||||
|
||||
if(cancelable) {
|
||||
if(V_VT(&v) == VT_BOOL) {
|
||||
if(!V_BOOL(&v))
|
||||
event_obj->prevent_default = TRUE;
|
||||
}else if(V_VT(&v) != VT_EMPTY) {
|
||||
FIXME("unhandled result %s\n", debugstr_variant(&v));
|
||||
}
|
||||
}
|
||||
VariantClear(&v);
|
||||
}else {
|
||||
WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres);
|
||||
}
|
||||
VariantClear(&v);
|
||||
}else {
|
||||
WARN("cp %s [%u] <<< %08x\n", debugstr_w(event_info[eid].name), i, hres);
|
||||
}
|
||||
}
|
||||
|
||||
if(!doc->nsevent_listener)
|
||||
break;
|
||||
}
|
||||
IConnectionPointContainer_Release(&cp_container->IConnectionPointContainer_iface);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1094,7 +1090,7 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
|
|||
do {
|
||||
hres = get_node(doc, nsnode, FALSE, &node);
|
||||
if(SUCCEEDED(hres) && node) {
|
||||
call_event_handlers(doc, event_obj, &node->event_target, node->cp_container, eid,
|
||||
call_event_handlers(event_obj, &node->event_target, eid,
|
||||
script_this ? script_this : (IDispatch*)&node->IHTMLDOMNode_iface);
|
||||
node_release(node);
|
||||
}
|
||||
|
@ -1116,14 +1112,14 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
|
|||
/* fallthrough */
|
||||
|
||||
case DOCUMENT_NODE:
|
||||
call_event_handlers(doc, event_obj, &doc->node.event_target, &doc->basedoc.cp_container, eid,
|
||||
call_event_handlers(event_obj, &doc->node.event_target, eid,
|
||||
script_this ? script_this : (IDispatch*)&doc->basedoc.IHTMLDocument2_iface);
|
||||
if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble))
|
||||
break;
|
||||
/* fallthrough */
|
||||
|
||||
default: /* window object */
|
||||
call_event_handlers(doc, event_obj, &doc->window->event_target, NULL, eid,
|
||||
call_event_handlers(event_obj, &doc->window->event_target, eid,
|
||||
script_this ? script_this : (IDispatch*)&doc->window->base.IHTMLWindow2_iface);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ void bind_target_event(HTMLDocumentNode*,EventTarget*,const WCHAR*,IDispatch*) D
|
|||
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode*,eventid_t) DECLSPEC_HIDDEN;
|
||||
|
||||
typedef struct HTMLEventObj HTMLEventObj;
|
||||
void call_event_handlers(HTMLDocumentNode*,HTMLEventObj*,EventTarget*,ConnectionPointContainer*,eventid_t,IDispatch*);
|
||||
void call_event_handlers(HTMLEventObj*,EventTarget*,eventid_t,IDispatch*);
|
||||
|
||||
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
|
||||
|
@ -83,6 +83,7 @@ void detach_nsevent(HTMLDocumentNode*,const WCHAR*) DECLSPEC_HIDDEN;
|
|||
typedef struct {
|
||||
dispex_static_data_vtbl_t dispex_vtbl;
|
||||
void (*bind_event)(DispatchEx*,eventid_t);
|
||||
ConnectionPointContainer *(*get_cp_container)(DispatchEx*);
|
||||
} event_target_vtbl_t;
|
||||
|
||||
static inline EventTarget *get_node_event_prop_target(HTMLDOMNode *node, eventid_t eid)
|
||||
|
|
|
@ -736,7 +736,6 @@ struct HTMLDOMNode {
|
|||
|
||||
nsIDOMNode *nsnode;
|
||||
HTMLDocumentNode *doc;
|
||||
ConnectionPointContainer *cp_container;
|
||||
};
|
||||
|
||||
static inline void node_addref(HTMLDOMNode *node)
|
||||
|
|
|
@ -190,7 +190,7 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
|
|||
if(!This->xhr)
|
||||
return NS_OK;
|
||||
|
||||
call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
|
||||
call_event_handlers(NULL, &This->xhr->event_target, EVENTID_READYSTATECHANGE,
|
||||
(IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue