mshtml: Store event handlers in rb tree.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-02-13 21:12:33 +01:00 committed by Alexandre Julliard
parent 357bf1b569
commit c4e9787e86
6 changed files with 51 additions and 49 deletions

View File

@ -36,15 +36,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
typedef struct {
struct wine_rb_entry entry;
eventid_t event_id;
IDispatch *handler_prop;
DWORD handler_cnt;
IDispatch **handlers;
} handler_vector_t;
struct event_target_t {
handler_vector_t *event_table[EVENTID_LAST];
};
static const WCHAR abortW[] = {'a','b','o','r','t',0};
static const WCHAR onabortW[] = {'o','n','a','b','o','r','t',0};
@ -899,37 +897,35 @@ HRESULT create_event_obj(IHTMLEventObj **ret)
return S_OK;
}
static inline event_target_t *get_event_target_data(EventTarget *event_target, BOOL alloc)
{
const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl && vtbl->get_event_target)
event_target = vtbl->get_event_target(&event_target->dispex);
if(event_target->ptr || !alloc)
return event_target->ptr;
return event_target->ptr = heap_alloc_zero(sizeof(event_target_t));
}
static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
{
event_target_t *data;
const dispex_static_data_vtbl_t *vtbl;
handler_vector_t *handler_vector;
struct wine_rb_entry *entry;
data = get_event_target_data(event_target, alloc);
if(!data)
vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->get_event_target)
event_target = vtbl->get_event_target(&event_target->dispex);
entry = wine_rb_get(&event_target->handler_map, (const void*)eid);
if(entry)
return WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry);
if(!alloc)
return NULL;
if(alloc && !data->event_table[eid]) {
data->event_table[eid] = heap_alloc_zero(sizeof(*data->event_table[eid]));
if(data->event_table[eid]) {
const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->bind_event)
vtbl->bind_event(&event_target->dispex, eid);
else
FIXME("Unsupported event binding on target %p\n", event_target);
}
}
return data->event_table[eid];
handler_vector = heap_alloc_zero(sizeof(*handler_vector));
if(!handler_vector)
return NULL;
handler_vector->event_id = eid;
vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->bind_event)
vtbl->bind_event(&event_target->dispex, eid);
else
FIXME("Unsupported event binding on target %p\n", event_target);
wine_rb_put(&event_target->handler_map, (const void*)eid, &handler_vector->entry);
return handler_vector;
}
static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
@ -1642,25 +1638,28 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
return S_OK;
}
static int event_id_cmp(const void *key, const struct wine_rb_entry *entry)
{
return (INT_PTR)key - WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry)->event_id;
}
void init_event_target(EventTarget *event_target)
{
wine_rb_init(&event_target->handler_map, event_id_cmp);
}
void release_event_target(EventTarget *event_target)
{
int i;
unsigned int j;
handler_vector_t *iter, *iter2;
unsigned i;
if(!event_target->ptr)
return;
for(i=0; i < EVENTID_LAST; i++) {
if(event_target->ptr->event_table[i]) {
if(event_target->ptr->event_table[i]->handler_prop)
IDispatch_Release(event_target->ptr->event_table[i]->handler_prop);
for(j=0; j < event_target->ptr->event_table[i]->handler_cnt; j++)
if(event_target->ptr->event_table[i]->handlers[j])
IDispatch_Release(event_target->ptr->event_table[i]->handlers[j]);
heap_free(event_target->ptr->event_table[i]->handlers);
heap_free(event_target->ptr->event_table[i]);
}
WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &event_target->handler_map, handler_vector_t, entry) {
if(iter->handler_prop)
IDispatch_Release(iter->handler_prop);
for(i = 0; i < iter->handler_cnt; i++)
if(iter->handlers[i])
IDispatch_Release(iter->handlers[i]);
heap_free(iter->handlers);
heap_free(iter);
}
heap_free(event_target->ptr);
}

View File

@ -55,6 +55,7 @@ typedef enum {
eventid_t str_to_eid(LPCWSTR) DECLSPEC_HIDDEN;
void check_event_attr(HTMLDocumentNode*,nsIDOMHTMLElement*) DECLSPEC_HIDDEN;
void init_event_target(EventTarget*) DECLSPEC_HIDDEN;
void release_event_target(EventTarget*) DECLSPEC_HIDDEN;
void fire_event(HTMLDocumentNode*,eventid_t,BOOL,HTMLDOMNode*,nsIDOMEvent*,IDispatch*) DECLSPEC_HIDDEN;
HRESULT set_event_handler(EventTarget*,eventid_t,VARIANT*) DECLSPEC_HIDDEN;

View File

@ -1214,6 +1214,7 @@ void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsno
node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
ccref_init(&node->ccref, 1);
init_event_target(&node->event_target);
if(&doc->node != node)
htmldoc_addref(&doc->basedoc);

View File

@ -3020,6 +3020,7 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon,
window->base.outer_window = outer_window;
window->base.inner_window = window;
init_event_target(&window->event_target);
init_dispex(&window->event_target.dispex, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex);
window->task_magic = get_task_target_magic();

View File

@ -72,7 +72,6 @@
typedef struct HTMLDOMNode HTMLDOMNode;
typedef struct ConnectionPoint ConnectionPoint;
typedef struct BSCallback BSCallback;
typedef struct event_target_t event_target_t;
typedef struct EventTarget EventTarget;
#define TID_LIST \
@ -366,7 +365,7 @@ typedef struct {
struct EventTarget {
DispatchEx dispex;
event_target_t *ptr;
struct wine_rb_tree handler_map;
};
typedef struct {

View File

@ -851,6 +851,7 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor
ret->nsxhr = nsxhr;
ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
init_event_target(&ret->event_target);
init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
&HTMLXMLHttpRequest_dispex);
ret->ref = 1;