Jacek Caban : mshtml: Added event bubbling implementation.

Alexandre Julliard julliard at winehq.org
Mon Oct 13 06:37:19 CDT 2008


Module: wine
Branch: master
Commit: a0c162cc4aa1cff4a7a38260735c0e26ddfae16e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a0c162cc4aa1cff4a7a38260735c0e26ddfae16e

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Oct 10 15:46:47 2008 -0500

mshtml: Added event bubbling implementation.

---

 dlls/mshtml/htmlevent.c |   68 ++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 4c8e2a2..5942990 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;
     }
 }
 




More information about the wine-cvs mailing list