Module: wine Branch: master Commit: cf51da73f6cfe5bae5f042feacdb5e93b5713835 URL: http://source.winehq.org/git/wine.git/?a=commit;h=cf51da73f6cfe5bae5f042feac...
Author: Jacek Caban jacek@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)) {