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

This commit is contained in:
Jacek Caban 2008-06-23 09:54:33 -05:00 committed by Alexandre Julliard
parent 97298e66ec
commit cf51da73f6
3 changed files with 104 additions and 5 deletions

View file

@ -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);
}
}
}

View file

@ -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*);

View file

@ -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)) {