From a0c162cc4aa1cff4a7a38260735c0e26ddfae16e Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 10 Oct 2008 15:46:47 -0500 Subject: [PATCH] mshtml: Added event bubbling implementation. --- dlls/mshtml/htmlevent.c | 68 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 4c8e2a2e161..5942990b864 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -58,13 +58,14 @@ typedef struct { } event_info_t; #define EVENT_DEFAULTLISTENER 0x0001 +#define EVENT_BUBBLE 0x0002 static const event_info_t event_info[] = { - {changeW, onchangeW, EVENT_DEFAULTLISTENER}, - {clickW, onclickW, EVENT_DEFAULTLISTENER}, - {keyupW, onkeyupW, EVENT_DEFAULTLISTENER}, + {changeW, onchangeW, EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, + {clickW, onclickW, EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, + {keyupW, onkeyupW, EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, {loadW, onloadW, 0}, - {mouseoverW, onmouseoverW, EVENT_DEFAULTLISTENER} + {mouseoverW, onmouseoverW, EVENT_DEFAULTLISTENER|EVENT_BUBBLE} }; eventid_t str_to_eid(LPCWSTR str) @@ -412,21 +413,62 @@ static IHTMLEventObj *create_event(void) void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target) { + IHTMLEventObj *prev_event, *event_obj = NULL; + nsIDOMNode *parent, *nsnode; HTMLDOMNode *node; + PRUint16 node_type; - node = get_node(doc, target, FALSE); - if(!node) + nsIDOMNode_GetNodeType(target, &node_type); + if(node_type != ELEMENT_NODE) { + FIXME("node type %d node supported\n", node_type); return; + } + + prev_event = doc->window->event; + nsnode = target; + nsIDOMNode_AddRef(nsnode); + + while(1) { + node = get_node(doc, nsnode, FALSE); + + if(node && node->event_target && node->event_target->event_table[eid]) { + if(!event_obj) + event_obj = doc->window->event = create_event(); + + TRACE("%s >>>\n", debugstr_w(event_info[eid].name)); + call_disp_func(doc, node->event_target->event_table[eid]); + TRACE("%s <<<\n", debugstr_w(event_info[eid].name)); + } - if(node->event_target && node->event_target->event_table[eid]) { - doc->window->event = create_event(); + if(!(event_info[eid].flags & EVENT_BUBBLE)) + break; - TRACE("%s >>>\n", debugstr_w(event_info[eid].name)); - call_disp_func(doc, node->event_target->event_table[eid]); - TRACE("%s <<<\n", debugstr_w(event_info[eid].name)); + nsIDOMNode_GetParentNode(nsnode, &parent); + nsIDOMNode_Release(nsnode); + nsnode = parent; + if(!nsnode) + break; + + nsIDOMNode_GetNodeType(nsnode, &node_type); + if(node_type != ELEMENT_NODE) + break; + } + + if(nsnode) + nsIDOMNode_Release(nsnode); + + if((event_info[eid].flags & EVENT_BUBBLE) && doc->event_target && doc->event_target->event_table[eid]) { + if(!event_obj) + event_obj = doc->window->event = create_event(); + + TRACE("doc %s >>>\n", debugstr_w(event_info[eid].name)); + call_disp_func(doc, doc->event_target->event_table[eid]); + TRACE("doc %s <<<\n", debugstr_w(event_info[eid].name)); + } - IHTMLEventObj_Release(doc->window->event); - doc->window->event = NULL; + if(event_obj) { + IHTMLEventObj_Release(event_obj); + doc->window->event = prev_event; } } -- 2.11.4.GIT