Jacek Caban : mshtml: Added support for event object in HTMLElement:: fireEvent.

Alexandre Julliard julliard at winehq.org
Thu Sep 13 14:39:21 CDT 2012


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Sep 13 12:28:09 2012 +0200

mshtml: Added support for event object in HTMLElement::fireEvent.

---

 dlls/mshtml/htmlevent.c |  134 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 96 insertions(+), 38 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index eecff1c..6f1260a 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -788,6 +788,11 @@ static const IHTMLEventObjVtbl HTMLEventObjVtbl = {
     HTMLEventObj_get_srcFilter
 };
 
+static inline HTMLEventObj *unsafe_impl_from_IHTMLEventObj(IHTMLEventObj *iface)
+{
+    return iface->lpVtbl == &HTMLEventObjVtbl ? impl_from_IHTMLEventObj(iface) : NULL;
+}
+
 static const tid_t HTMLEventObj_iface_tids[] = {
     IHTMLEventObj_tid,
     0
@@ -800,7 +805,7 @@ static dispex_static_data_t HTMLEventObj_dispex = {
     HTMLEventObj_iface_tids
 };
 
-static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent)
+static HTMLEventObj *create_event(void)
 {
     HTMLEventObj *ret;
 
@@ -810,39 +815,43 @@ static HTMLEventObj *create_event(HTMLDOMNode *target, eventid_t eid, nsIDOMEven
 
     ret->IHTMLEventObj_iface.lpVtbl = &HTMLEventObjVtbl;
     ret->ref = 1;
-    ret->type = eid != EVENTID_LAST ? event_info+eid : NULL;
 
-    ret->nsevent = nsevent;
+    init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
+
+    return ret;
+}
+
+static HRESULT set_event_info(HTMLEventObj *event, HTMLDOMNode *target, eventid_t eid, nsIDOMEvent *nsevent)
+{
+    event->type = event_info+eid;
+    event->nsevent = nsevent;
+
     if(nsevent) {
         nsIDOMEvent_AddRef(nsevent);
-    }else if(eid != EVENTID_LAST && event_types[event_info[eid].type]) {
+    }else if(event_types[event_info[eid].type]) {
         nsAString type_str;
         nsresult nsres;
 
         nsAString_InitDepend(&type_str, event_types[event_info[eid].type]);
-        nsres = nsIDOMHTMLDocument_CreateEvent(target->doc->nsdoc, &type_str, &ret->nsevent);
+        nsres = nsIDOMHTMLDocument_CreateEvent(target->doc->nsdoc, &type_str, &event->nsevent);
         nsAString_Finish(&type_str);
         if(NS_FAILED(nsres)) {
             ERR("Could not create event: %08x\n", nsres);
-            IHTMLEventObj_Release(&ret->IHTMLEventObj_iface);
-            return NULL;
+            return E_FAIL;
         }
     }
 
-    ret->target = target;
+    event->target = target;
     if(target)
         IHTMLDOMNode_AddRef(&target->IHTMLDOMNode_iface);
-
-    init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLEventObj_iface, &HTMLEventObj_dispex);
-
-    return ret;
+    return S_OK;
 }
 
 HRESULT create_event_obj(IHTMLEventObj **ret)
 {
     HTMLEventObj *event;
 
-    event = create_event(NULL, EVENTID_LAST, NULL);
+    event = create_event();
     if(!event)
         return E_OUTOFMEMORY;
 
@@ -1021,9 +1030,8 @@ static void call_event_handlers(HTMLDocumentNode *doc, HTMLEventObj *event_obj,
     }
 }
 
-void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent)
+static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *event_obj, nsIDOMNode *target)
 {
-    HTMLEventObj *event_obj = NULL;
     IHTMLEventObj *prev_event;
     nsIDOMNode *parent, *nsnode;
     BOOL prevent_default = FALSE;
@@ -1037,17 +1045,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
 
     window = doc->window;
     prev_event = window->event;
-    if(set_event) {
-        hres = get_node(doc, target, TRUE, &node);
-        if(FAILED(hres))
-            return;
-
-        event_obj = create_event(node, eid, nsevent);
-        node_release(node);
-        window->event = &event_obj->IHTMLEventObj_iface;
-    }else {
-        window->event = NULL;
-    }
+    window->event = &event_obj->IHTMLEventObj_iface;
 
     nsIDOMNode_GetNodeType(target, &node_type);
     nsnode = target;
@@ -1111,8 +1109,6 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
     if(event_obj && event_obj->prevent_default)
         prevent_default = TRUE;
     window->event = prev_event;
-    if(event_obj)
-        IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
 
     if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) {
         nsIDOMNode_AddRef(target);
@@ -1125,7 +1121,7 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
 
             if(node) {
                 if(node->vtbl->handle_event)
-                    hres = node->vtbl->handle_event(node, eid, nsevent, &prevent_default);
+                    hres = node->vtbl->handle_event(node, eid, event_obj ? event_obj->nsevent : NULL, &prevent_default);
                 node_release(node);
                 if(FAILED(hres) || prevent_default || (event_obj && event_obj->cancel_bubble))
                     break;
@@ -1143,15 +1139,46 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode
             nsIDOMNode_Release(nsnode);
     }
 
-    if(prevent_default && nsevent) {
+    if(prevent_default && event_obj && event_obj->nsevent) {
         TRACE("calling PreventDefault\n");
-        nsIDOMEvent_PreventDefault(nsevent);
+        nsIDOMEvent_PreventDefault(event_obj->nsevent);
     }
 }
 
-HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_obj, VARIANT_BOOL *cancelled)
+void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent)
 {
+    HTMLEventObj *event_obj = NULL;
+    HTMLDOMNode *node;
+    HRESULT hres;
+
+    if(set_event) {
+        hres = get_node(doc, target, TRUE, &node);
+        if(FAILED(hres))
+            return;
+
+        event_obj = create_event();
+        node_release(node);
+        if(!event_obj)
+            return;
+
+        hres = set_event_info(event_obj, node, eid, nsevent);
+        if(FAILED(hres)) {
+            IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+            return;
+        }
+    }
+
+    fire_event_obj(doc, eid, event_obj, target);
+
+    if(event_obj)
+        IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+}
+
+HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *event_var, VARIANT_BOOL *cancelled)
+{
+    HTMLEventObj *event_obj = NULL;
     eventid_t eid;
+    HRESULT hres;
 
     eid = attr_to_eid(event_name);
     if(eid == EVENTID_LAST) {
@@ -1159,15 +1186,46 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even
         return E_INVALIDARG;
     }
 
-    if(event_obj && V_VT(event_obj) != VT_EMPTY && V_VT(event_obj) != VT_ERROR)
-        FIXME("event_obj not implemented\n");
+    if(event_var && V_VT(event_var) != VT_EMPTY && V_VT(event_var) != VT_ERROR) {
+        if(V_VT(event_var) != VT_DISPATCH) {
+            FIXME("event_var %s not supported\n", debugstr_variant(event_var));
+            return E_NOTIMPL;
+        }
 
-    if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) {
-        FIXME("not EVENT_DEFAULTEVENTHANDLER\n");
-        return E_NOTIMPL;
+        if(V_DISPATCH(event_var)) {
+            IHTMLEventObj *event_iface;
+
+            hres = IDispatch_QueryInterface(V_DISPATCH(event_var), &IID_IHTMLEventObj, (void**)&event_iface);
+            if(FAILED(hres)) {
+                FIXME("No IHTMLEventObj iface\n");
+                return hres;
+            }
+
+            event_obj = unsafe_impl_from_IHTMLEventObj(event_iface);
+            if(!event_obj) {
+                ERR("Not our IHTMLEventObj?\n");
+                IHTMLEventObj_Release(event_iface);
+                return E_FAIL;
+            }
+        }
     }
 
-    fire_event(node->doc, eid, TRUE, node->nsnode, NULL);
+    if(event_obj) {
+        hres = set_event_info(event_obj, node, eid, NULL);
+        if(SUCCEEDED(hres))
+            fire_event_obj(node->doc, eid, event_obj, node->nsnode);
+
+        IHTMLEventObj_Release(&event_obj->IHTMLEventObj_iface);
+        if(FAILED(hres))
+            return hres;
+    }else {
+        if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) {
+            FIXME("not EVENT_DEFAULTEVENTHANDLER\n");
+            return E_NOTIMPL;
+        }
+
+        fire_event(node->doc, eid, TRUE, node->nsnode, NULL);
+    }
 
     *cancelled = VARIANT_TRUE; /* FIXME */
     return S_OK;




More information about the wine-cvs mailing list