mshtml: Use event target vtbl to set current window event in fire_event_obj.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-10-19 17:01:43 +02:00 committed by Alexandre Julliard
parent 57b830526b
commit 6dc67c4234
5 changed files with 60 additions and 24 deletions

View file

@ -5048,6 +5048,12 @@ static ConnectionPointContainer *HTMLDocumentNode_get_cp_container(DispatchEx *d
return container;
}
static IHTMLEventObj *HTMLDocumentNode_set_current_event(DispatchEx *dispex, IHTMLEventObj *event)
{
HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
return default_set_current_event(This->window, event);
}
static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
{
NULL,
@ -5059,7 +5065,8 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = {
HTMLDocumentNode_bind_event,
HTMLDocumentNode_get_parent_event_target,
NULL,
HTMLDocumentNode_get_cp_container
HTMLDocumentNode_get_cp_container,
HTMLDocumentNode_set_current_event
};
static const NodeImplVtbl HTMLDocumentFragmentImplVtbl = {

View file

@ -5384,6 +5384,12 @@ static ConnectionPointContainer *HTMLElement_get_cp_container(DispatchEx *dispex
return &This->cp_container;
}
static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEventObj *event)
{
HTMLElement *This = impl_from_DispatchEx(dispex);
return default_set_current_event(This->node.doc->window, event);
}
void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
{
static const DISPID elem2_ie11_blacklist[] = {DISPID_IHTMLELEMENT2_DOSCROLL, DISPID_UNKNOWN};
@ -5417,7 +5423,8 @@ static event_target_vtbl_t HTMLElement_event_target_vtbl = {
HTMLElement_bind_event,
HTMLElement_get_parent_event_target,
HTMLElement_handle_event_default,
HTMLElement_get_cp_container
HTMLElement_get_cp_container,
HTMLElement_set_current_event
};
static dispex_static_data_t HTMLElement_dispex = {

View file

@ -1063,29 +1063,17 @@ void call_event_handlers(HTMLEventObj *event_obj, EventTarget *event_target, eve
}
}
static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *event_obj, EventTarget *event_target)
static void fire_event_obj(EventTarget *event_target, eventid_t eid, HTMLEventObj *event_obj)
{
EventTarget *target_chain_buf[8], **target_chain = target_chain_buf;
unsigned chain_cnt, chain_buf_size, i;
IHTMLEventObj *prev_event;
const event_target_vtbl_t *vtbl;
const event_target_vtbl_t *vtbl, *target_vtbl;
IHTMLEventObj *prev_event = NULL;
BOOL prevent_default = FALSE;
HTMLInnerWindow *window;
EventTarget *iter;
HRESULT hres;
TRACE("(%p) %s\n", doc, debugstr_w(event_info[eid].name));
window = doc->window;
if(!window) {
WARN("NULL window\n");
return;
}
htmldoc_addref(&doc->basedoc);
prev_event = window->event;
window->event = event_obj ? &event_obj->IHTMLEventObj_iface : NULL;
TRACE("(%p) %s\n", event_target, debugstr_w(event_info[eid].name));
iter = event_target;
IDispatchEx_AddRef(&event_target->dispex.IDispatchEx_iface);
@ -1117,15 +1105,24 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
iter = vtbl->get_parent_event_target(&iter->dispex);
} while(iter);
target_vtbl = dispex_get_vtbl(&event_target->dispex);
if(target_vtbl && target_vtbl->set_current_event)
prev_event = target_vtbl->set_current_event(&event_target->dispex, event_obj ? &event_obj->IHTMLEventObj_iface : NULL);
for(i = 0; i < chain_cnt; i++) {
call_event_handlers(event_obj, target_chain[i], eid);
if(!(event_info[eid].flags & EVENT_BUBBLES) || (event_obj && event_obj->cancel_bubble))
break;
}
if(target_vtbl && target_vtbl->set_current_event) {
prev_event = target_vtbl->set_current_event(&event_target->dispex, prev_event);
if(prev_event)
IHTMLEventObj_Release(prev_event);
}
if(event_obj && event_obj->prevent_default)
prevent_default = TRUE;
window->event = prev_event;
if(event_info[eid].flags & EVENT_HASDEFAULTHANDLERS) {
for(i = 0; !prevent_default && i < chain_cnt; i++) {
@ -1147,8 +1144,6 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
TRACE("calling PreventDefault\n");
nsIDOMEvent_PreventDefault(event_obj->nsevent);
}
htmldoc_release(&doc->basedoc);
}
void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, EventTarget *target, nsIDOMEvent *nsevent)
@ -1168,7 +1163,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, EventTarge
}
}
fire_event_obj(doc, eid, event_obj, target);
fire_event_obj(target, eid, event_obj);
if(event_obj)
IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
@ -1213,7 +1208,7 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even
if(event_obj) {
hres = set_event_info(event_obj, &node->event_target, eid, node->doc, NULL);
if(SUCCEEDED(hres))
fire_event_obj(node->doc, eid, event_obj, &node->event_target);
fire_event_obj(&node->event_target, eid, event_obj);
IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
if(FAILED(hres))

View file

@ -86,8 +86,11 @@ typedef struct {
EventTarget *(*get_parent_event_target)(DispatchEx*);
HRESULT (*handle_event_default)(DispatchEx*,eventid_t,nsIDOMEvent*,BOOL*);
ConnectionPointContainer *(*get_cp_container)(DispatchEx*);
IHTMLEventObj *(*set_current_event)(DispatchEx*,IHTMLEventObj*);
} event_target_vtbl_t;
IHTMLEventObj *default_set_current_event(HTMLInnerWindow*,IHTMLEventObj*) DECLSPEC_HIDDEN;
static inline EventTarget *get_node_event_prop_target(HTMLDOMNode *node, eventid_t eid)
{
return node->vtbl->get_event_prop_target ? node->vtbl->get_event_prop_target(node, eid) : &node->event_target;

View file

@ -1241,6 +1241,20 @@ static HRESULT WINAPI HTMLWindow2_get_document(IHTMLWindow2 *iface, IHTMLDocumen
return S_OK;
}
IHTMLEventObj *default_set_current_event(HTMLInnerWindow *window, IHTMLEventObj *event_obj)
{
IHTMLEventObj *prev_event = NULL;
if(window) {
if(event_obj)
IHTMLEventObj_AddRef(event_obj);
prev_event = window->event;
window->event = event_obj;
}
return prev_event;
}
static HRESULT WINAPI HTMLWindow2_get_event(IHTMLWindow2 *iface, IHTMLEventObj **p)
{
HTMLWindow *This = impl_from_IHTMLWindow2(iface);
@ -3006,6 +3020,12 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa
dispex_info_add_interface(info, IHTMLWindow5_tid, NULL);
}
static IHTMLEventObj *HTMLWindow_set_current_event(DispatchEx *dispex, IHTMLEventObj *event)
{
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
return default_set_current_event(This, event);
}
static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
{
NULL,
@ -3014,7 +3034,11 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
NULL,
NULL
},
HTMLWindow_bind_event
HTMLWindow_bind_event,
NULL,
NULL,
NULL,
HTMLWindow_set_current_event
};
static const tid_t HTMLWindow_iface_tids[] = {