Gabriel Ivăncescu : mshtml: Use a table to construct the different event types by their interface.

Alexandre Julliard julliard at winehq.org
Tue Jul 26 15:35:15 CDT 2022


Module: wine
Branch: master
Commit: 79c46d470daa8e3c55707da4f20688acced7b81f
URL:    https://gitlab.winehq.org/wine/wine/-/commit/79c46d470daa8e3c55707da4f20688acced7b81f

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Mon Jul 25 21:54:04 2022 +0300

mshtml: Use a table to construct the different event types by their interface.

Avoids hardcoding as the amount of events grows to become more manageable,
which will also be used for the existing hardcoded "special" events (UI,
Mouse, Keyboard).

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>

---

 dlls/mshtml/htmlevent.c | 125 ++++++++++++++++++++++++++++--------------------
 dlls/mshtml/nsiface.idl |  14 ++++++
 2 files changed, 88 insertions(+), 51 deletions(-)

diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 0f6525af86a..f5e889712c0 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -2299,6 +2299,7 @@ static void DOMMessageEvent_destroy(DOMEvent *event)
 typedef struct {
     DOMEvent event;
     IDOMProgressEvent IDOMProgressEvent_iface;
+    nsIDOMProgressEvent *nsevent;
 } DOMProgressEvent;
 
 static inline DOMProgressEvent *impl_from_IDOMProgressEvent(IDOMProgressEvent *iface)
@@ -2412,6 +2413,12 @@ static void *DOMProgressEvent_query_interface(DOMEvent *event, REFIID riid)
     return NULL;
 }
 
+static void DOMProgressEvent_destroy(DOMEvent *event)
+{
+    DOMProgressEvent *This = DOMProgressEvent_from_DOMEvent(event);
+    nsIDOMProgressEvent_Release(This->nsevent);
+}
+
 static const tid_t DOMEvent_iface_tids[] = {
     IDOMEvent_tid,
     0
@@ -2504,64 +2511,20 @@ dispex_static_data_t DOMProgressEvent_dispex = {
     DOMProgressEvent_iface_tids
 };
 
-static BOOL check_event_iface(nsIDOMEvent *event, REFIID riid)
-{
-    nsISupports *iface;
-    nsresult nsres;
-
-    nsres = nsIDOMEvent_QueryInterface(event, riid, (void**)&iface);
-    if(NS_FAILED(nsres))
-        return FALSE;
-
-    nsISupports_Release(iface);
-    return TRUE;
-}
-
-static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, eventid_t event_id)
+static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, void *(*query_interface)(DOMEvent*,REFIID),
+        void (*destroy)(DOMEvent*), nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
 {
-    dispex_static_data_t *dispex_data = &DOMEvent_dispex;
-    DOMEvent *event = NULL;
+    DOMEvent *event = heap_alloc_zero(size);
     nsresult nsres;
 
-    if(check_event_iface(nsevent, &IID_nsIDOMCustomEvent)) {
-        DOMCustomEvent *custom_event = heap_alloc_zero(sizeof(*custom_event));
-        if(!custom_event)
-            return NULL;
-
-        custom_event->IDOMCustomEvent_iface.lpVtbl = &DOMCustomEventVtbl;
-        custom_event->event.query_interface = DOMCustomEvent_query_interface;
-        custom_event->event.destroy = DOMCustomEvent_destroy;
-        event = &custom_event->event;
-        dispex_data = &DOMCustomEvent_dispex;
-    }else if(event_id == EVENTID_MESSAGE) {
-        DOMMessageEvent *message_event = heap_alloc_zero(sizeof(*message_event));
-        if(!message_event)
-            return NULL;
-
-        message_event->IDOMMessageEvent_iface.lpVtbl = &DOMMessageEventVtbl;
-        message_event->event.query_interface = DOMMessageEvent_query_interface;
-        message_event->event.destroy = DOMMessageEvent_destroy;
-        event = &message_event->event;
-        dispex_data = &DOMMessageEvent_dispex;
-    }else if(event_info[event_id].type == EVENT_TYPE_PROGRESS && compat_mode >= COMPAT_MODE_IE10) {
-        DOMProgressEvent *progress_event = heap_alloc_zero(sizeof(*progress_event));
-        if(!progress_event)
-            return NULL;
-
-        progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
-        progress_event->event.query_interface = DOMProgressEvent_query_interface;
-        event = &progress_event->event;
-        dispex_data = &DOMProgressEvent_dispex;
-    }else {
-        event = heap_alloc_zero(sizeof(*event));
-        if(!event)
-            return NULL;
-    }
-
+    if(!event)
+        return NULL;
     event->IDOMEvent_iface.lpVtbl = &DOMEventVtbl;
     event->IDOMUIEvent_iface.lpVtbl = &DOMUIEventVtbl;
     event->IDOMMouseEvent_iface.lpVtbl = &DOMMouseEventVtbl;
     event->IDOMKeyboardEvent_iface.lpVtbl = &DOMKeyboardEventVtbl;
+    event->query_interface = query_interface;
+    event->destroy = destroy;
     event->ref = 1;
     event->event_id = event_id;
     if(event_id != EVENTID_LAST) {
@@ -2599,6 +2562,66 @@ static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, ev
     return event;
 }
 
+static DOMEvent *custom_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
+{
+    DOMCustomEvent *custom_event = event_ctor(sizeof(DOMCustomEvent), &DOMCustomEvent_dispex,
+            DOMCustomEvent_query_interface, DOMCustomEvent_destroy, nsevent, event_id, compat_mode);
+    if(!custom_event) return NULL;
+    custom_event->IDOMCustomEvent_iface.lpVtbl = &DOMCustomEventVtbl;
+    nsIDOMCustomEvent_Release(iface);
+    return &custom_event->event;
+}
+
+static DOMEvent *progress_event_ctor(void *iface, nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
+{
+    DOMProgressEvent *progress_event;
+
+    if(compat_mode < COMPAT_MODE_IE10)
+        return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, NULL, NULL, nsevent, event_id, compat_mode);
+
+    if(!(progress_event = event_ctor(sizeof(DOMProgressEvent), &DOMProgressEvent_dispex,
+            DOMProgressEvent_query_interface, DOMProgressEvent_destroy, nsevent, event_id, compat_mode)))
+        return NULL;
+    progress_event->IDOMProgressEvent_iface.lpVtbl = &DOMProgressEventVtbl;
+    progress_event->nsevent = iface;
+    return &progress_event->event;
+}
+
+static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, eventid_t event_id)
+{
+    static const struct {
+        REFIID iid;
+        DOMEvent *(*ctor)(void *iface, nsIDOMEvent *nsevent, eventid_t, compat_mode_t);
+    } types_table[] = {
+        { &IID_nsIDOMCustomEvent,       custom_event_ctor },
+        { &IID_nsIDOMProgressEvent,     progress_event_ctor },
+    };
+    DOMEvent *event;
+    unsigned i;
+
+    if(event_id == EVENTID_MESSAGE) {
+        DOMMessageEvent *message_event = event_ctor(sizeof(DOMMessageEvent), &DOMMessageEvent_dispex,
+                DOMMessageEvent_query_interface, DOMMessageEvent_destroy, nsevent, event_id, compat_mode);
+        if(!message_event)
+            return NULL;
+        message_event->IDOMMessageEvent_iface.lpVtbl = &DOMMessageEventVtbl;
+        return &message_event->event;
+    }
+
+    for(i = 0; i < ARRAY_SIZE(types_table); i++) {
+        void *iface;
+        nsresult nsres = nsIDOMEvent_QueryInterface(nsevent, types_table[i].iid, &iface);
+        if(NS_SUCCEEDED(nsres)) {
+            /* Transfer the iface ownership to the ctor on success */
+            if(!(event = types_table[i].ctor(iface, nsevent, event_id, compat_mode)))
+                nsISupports_Release(iface);
+            return event;
+        }
+    }
+
+    return event_ctor(sizeof(DOMEvent), &DOMEvent_dispex, NULL, NULL, nsevent, event_id, compat_mode);
+}
+
 HRESULT create_event_from_nsevent(nsIDOMEvent *nsevent, compat_mode_t compat_mode, DOMEvent **ret_event)
 {
     eventid_t event_id = EVENTID_LAST;
diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl
index cad48f725c6..c4b479b16e3 100644
--- a/dlls/mshtml/nsiface.idl
+++ b/dlls/mshtml/nsiface.idl
@@ -3304,6 +3304,20 @@ interface nsIDOMKeyEvent : nsIDOMUIEvent
     nsresult GetKey(nsAString *aKey);
 }
 
+[
+    object,
+    uuid(e0682338-4c3f-4d3a-9487-d7492ea76335),
+    local
+]
+interface nsIDOMProgressEvent : nsISupports
+{
+    nsresult GetLengthComputable(bool *aLengthComputable);
+    nsresult GetLoaded(uint64_t *aLoaded);
+    nsresult GetTotal(uint64_t *aTotal);
+    nsresult InitProgressEvent(const nsAString *typeArg, bool canBubbleArg, bool cancelableArg,
+             bool lengthComputableArg, uint64_t loadedArg, uint64_t totalArg);
+}
+
 [
     object,
     uuid(5be16b03-36f9-4ca8-b2c5-0daadf3cd1b3),




More information about the wine-cvs mailing list