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