Jacek Caban : mshtml: Added generic HTML event listener and use it for click event.

Alexandre Julliard julliard at winehq.org
Mon Jun 23 16:04:03 CDT 2008


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Jun 23 09:54:33 2008 -0500

mshtml: Added generic HTML event listener and use it for click  event.

---

 dlls/mshtml/htmlevent.c      |   43 ++++++++++++++++++++++++++---
 dlls/mshtml/mshtml_private.h |    5 +++
 dlls/mshtml/nsevents.c       |   61 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 6583716..d155ed5 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -44,13 +44,29 @@ static const WCHAR onloadW[] = {'o','n','l','o','a','d',0};
 typedef struct {
     LPCWSTR name;
     LPCWSTR attr_name;
+    DWORD flags;
 } event_info_t;
 
+#define EVENT_DEFAULTLISTENER    0x0001
+
 static const event_info_t event_info[] = {
-    {clickW, onclickW},
-    {loadW, onloadW}
+    {clickW,    onclickW,    EVENT_DEFAULTLISTENER},
+    {loadW,     onloadW,     0}
 };
 
+eventid_t str_to_eid(LPCWSTR str)
+{
+    int i;
+
+    for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) {
+        if(!strcmpW(event_info[i].name, str))
+            return i;
+    }
+
+    ERR("unknown type %s\n", debugstr_w(str));
+    return EVENTID_LAST;
+}
+
 typedef struct {
     const IHTMLEventObjVtbl  *lpIHTMLEventObjVtbl;
     LONG ref;
@@ -385,6 +401,24 @@ void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target)
     }
 }
 
+static HRESULT set_node_event_disp(HTMLDOMNode *node, eventid_t eid, IDispatch *disp)
+{
+    if(!node->event_target)
+        node->event_target = heap_alloc_zero(sizeof(event_target_t));
+    else if(node->event_target->event_table[eid])
+        IDispatch_Release(node->event_target->event_table[eid]);
+
+    IDispatch_AddRef(disp);
+    node->event_target->event_table[eid] = disp;
+
+    if((event_info[eid].flags & EVENT_DEFAULTLISTENER) && !node->doc->nscontainer->event_vector[eid]) {
+        node->doc->nscontainer->event_vector[eid] = TRUE;
+        add_nsevent_listener(node->doc->nscontainer, event_info[eid].name);
+    }
+
+    return S_OK;
+}
+
 void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
 {
     const PRUnichar *attr_value;
@@ -410,9 +444,8 @@ void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
             disp = script_parse_event(doc, attr_value);
             if(disp) {
                 node = get_node(doc, (nsIDOMNode*)nselem, TRUE);
-                if(!node->event_target)
-                    node->event_target = heap_alloc_zero(sizeof(event_target_t));
-                node->event_target->event_table[i] = disp;
+                set_node_event_disp(node, i, disp);
+                IDispatch_Release(disp);
             }
         }
     }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 2522125..38dc715 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -289,6 +289,7 @@ struct NSContainer {
     nsEventListener keypress_listener;
     nsEventListener load_listener;
     nsEventListener node_insert_listener;
+    nsEventListener htmlevent_listener;
 
     nsIWebBrowser *webbrowser;
     nsIWebNavigation *navigation;
@@ -309,6 +310,8 @@ struct NSContainer {
 
     nsChannelBSC *bscallback; /* hack */
     HWND reset_focus; /* hack */
+
+    BOOL event_vector[EVENTID_LAST];
 };
 
 typedef struct {
@@ -496,11 +499,13 @@ nsIWritableVariant *create_nsvariant(void);
 void nsnode_to_nsstring(nsIDOMNode*,nsAString*);
 void get_editor_controller(NSContainer*);
 void init_nsevents(NSContainer*);
+void add_nsevent_listener(NSContainer*,LPCWSTR);
 nsresult get_nsinterface(nsISupports*,REFIID,void**);
 
 void check_event_attr(HTMLDocument*,nsIDOMElement*);
 void release_event_target(event_target_t*);
 void fire_event(HTMLDocument*,eventid_t,nsIDOMNode*);
+eventid_t str_to_eid(LPCWSTR);
 
 void set_document_bscallback(HTMLDocument*,nsChannelBSC*);
 void set_current_mon(HTMLDocument*,IMoniker*);
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c
index 5b72a2d..d0f5079 100644
--- a/dlls/mshtml/nsevents.c
+++ b/dlls/mshtml/nsevents.c
@@ -211,6 +211,42 @@ static nsresult NSAPI handle_node_insert(nsIDOMEventListener *iface, nsIDOMEvent
     return NS_OK;
 }
 
+static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event)
+{
+    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    const PRUnichar *type;
+    nsIDOMEventTarget *event_target;
+    nsIDOMNode *nsnode;
+    nsAString type_str;
+    eventid_t eid;
+    nsresult nsres;
+
+    nsAString_Init(&type_str, NULL);
+    nsIDOMEvent_GetType(event, &type_str);
+    nsAString_GetData(&type_str, &type);
+    eid = str_to_eid(type);
+    nsAString_Finish(&type_str);
+
+    nsres = nsIDOMEvent_GetTarget(event, &event_target);
+    if(NS_FAILED(nsres) || !event_target) {
+        ERR("GetEventTarget failed: %08x\n", nsres);
+        return NS_OK;
+    }
+
+    nsres = nsIDOMEventTarget_QueryInterface(event_target, &IID_nsIDOMNode, (void**)&nsnode);
+    nsIDOMEventTarget_Release(event_target);
+    if(NS_FAILED(nsres)) {
+        ERR("Could not get nsIDOMNode: %08x\n", nsres);
+        return NS_OK;
+    }
+
+    fire_event(This->doc, eid, nsnode);
+
+    nsIDOMNode_Release(nsnode);
+
+    return NS_OK;
+}
+
 #undef NSEVENTLIST_THIS
 
 #define EVENTLISTENER_VTBL(handler) \
@@ -226,6 +262,7 @@ static const nsIDOMEventListenerVtbl focus_vtbl =     EVENTLISTENER_VTBL(handle_
 static const nsIDOMEventListenerVtbl keypress_vtbl =  EVENTLISTENER_VTBL(handle_keypress);
 static const nsIDOMEventListenerVtbl load_vtbl =      EVENTLISTENER_VTBL(handle_load);
 static const nsIDOMEventListenerVtbl node_insert_vtbl = EVENTLISTENER_VTBL(handle_node_insert);
+static const nsIDOMEventListenerVtbl htmlevent_vtbl = EVENTLISTENER_VTBL(handle_htmlevent);
 
 static void init_event(nsIDOMEventTarget *target, const PRUnichar *type,
         nsIDOMEventListener *listener, BOOL capture)
@@ -248,6 +285,29 @@ static void init_listener(nsEventListener *This, NSContainer *container,
     This->This = container;
 }
 
+void add_nsevent_listener(NSContainer *container, LPCWSTR type)
+{
+    nsIDOMWindow *dom_window;
+    nsIDOMEventTarget *target;
+    nsresult nsres;
+
+    nsres = nsIWebBrowser_GetContentDOMWindow(container->webbrowser, &dom_window);
+    if(NS_FAILED(nsres)) {
+        ERR("GetContentDOMWindow failed: %08x\n", nsres);
+        return;
+    }
+
+    nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target);
+    nsIDOMWindow_Release(dom_window);
+    if(NS_FAILED(nsres)) {
+        ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
+        return;
+    }
+
+    init_event(target, type, NSEVENTLIST(&container->htmlevent_listener), TRUE);
+    nsIDOMEventTarget_Release(target);
+}
+
 void init_nsevents(NSContainer *This)
 {
     nsIDOMWindow *dom_window;
@@ -266,6 +326,7 @@ void init_nsevents(NSContainer *This)
     init_listener(&This->keypress_listener,    This, &keypress_vtbl);
     init_listener(&This->load_listener,        This, &load_vtbl);
     init_listener(&This->node_insert_listener, This, &node_insert_vtbl);
+    init_listener(&This->htmlevent_listener,   This, &htmlevent_vtbl);
 
     nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
     if(NS_FAILED(nsres)) {




More information about the wine-cvs mailing list