mshtml: Added generic HTML event listener and use it for click event.
This commit is contained in:
parent
97298e66ec
commit
cf51da73f6
|
@ -44,13 +44,29 @@ static const WCHAR onloadW[] = {'o','n','l','o','a','d',0};
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LPCWSTR name;
|
LPCWSTR name;
|
||||||
LPCWSTR attr_name;
|
LPCWSTR attr_name;
|
||||||
|
DWORD flags;
|
||||||
} event_info_t;
|
} event_info_t;
|
||||||
|
|
||||||
|
#define EVENT_DEFAULTLISTENER 0x0001
|
||||||
|
|
||||||
static const event_info_t event_info[] = {
|
static const event_info_t event_info[] = {
|
||||||
{clickW, onclickW},
|
{clickW, onclickW, EVENT_DEFAULTLISTENER},
|
||||||
{loadW, onloadW}
|
{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 {
|
typedef struct {
|
||||||
const IHTMLEventObjVtbl *lpIHTMLEventObjVtbl;
|
const IHTMLEventObjVtbl *lpIHTMLEventObjVtbl;
|
||||||
LONG ref;
|
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)
|
void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
|
||||||
{
|
{
|
||||||
const PRUnichar *attr_value;
|
const PRUnichar *attr_value;
|
||||||
|
@ -410,9 +444,8 @@ void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem)
|
||||||
disp = script_parse_event(doc, attr_value);
|
disp = script_parse_event(doc, attr_value);
|
||||||
if(disp) {
|
if(disp) {
|
||||||
node = get_node(doc, (nsIDOMNode*)nselem, TRUE);
|
node = get_node(doc, (nsIDOMNode*)nselem, TRUE);
|
||||||
if(!node->event_target)
|
set_node_event_disp(node, i, disp);
|
||||||
node->event_target = heap_alloc_zero(sizeof(event_target_t));
|
IDispatch_Release(disp);
|
||||||
node->event_target->event_table[i] = disp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,6 +289,7 @@ struct NSContainer {
|
||||||
nsEventListener keypress_listener;
|
nsEventListener keypress_listener;
|
||||||
nsEventListener load_listener;
|
nsEventListener load_listener;
|
||||||
nsEventListener node_insert_listener;
|
nsEventListener node_insert_listener;
|
||||||
|
nsEventListener htmlevent_listener;
|
||||||
|
|
||||||
nsIWebBrowser *webbrowser;
|
nsIWebBrowser *webbrowser;
|
||||||
nsIWebNavigation *navigation;
|
nsIWebNavigation *navigation;
|
||||||
|
@ -309,6 +310,8 @@ struct NSContainer {
|
||||||
|
|
||||||
nsChannelBSC *bscallback; /* hack */
|
nsChannelBSC *bscallback; /* hack */
|
||||||
HWND reset_focus; /* hack */
|
HWND reset_focus; /* hack */
|
||||||
|
|
||||||
|
BOOL event_vector[EVENTID_LAST];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -496,11 +499,13 @@ nsIWritableVariant *create_nsvariant(void);
|
||||||
void nsnode_to_nsstring(nsIDOMNode*,nsAString*);
|
void nsnode_to_nsstring(nsIDOMNode*,nsAString*);
|
||||||
void get_editor_controller(NSContainer*);
|
void get_editor_controller(NSContainer*);
|
||||||
void init_nsevents(NSContainer*);
|
void init_nsevents(NSContainer*);
|
||||||
|
void add_nsevent_listener(NSContainer*,LPCWSTR);
|
||||||
nsresult get_nsinterface(nsISupports*,REFIID,void**);
|
nsresult get_nsinterface(nsISupports*,REFIID,void**);
|
||||||
|
|
||||||
void check_event_attr(HTMLDocument*,nsIDOMElement*);
|
void check_event_attr(HTMLDocument*,nsIDOMElement*);
|
||||||
void release_event_target(event_target_t*);
|
void release_event_target(event_target_t*);
|
||||||
void fire_event(HTMLDocument*,eventid_t,nsIDOMNode*);
|
void fire_event(HTMLDocument*,eventid_t,nsIDOMNode*);
|
||||||
|
eventid_t str_to_eid(LPCWSTR);
|
||||||
|
|
||||||
void set_document_bscallback(HTMLDocument*,nsChannelBSC*);
|
void set_document_bscallback(HTMLDocument*,nsChannelBSC*);
|
||||||
void set_current_mon(HTMLDocument*,IMoniker*);
|
void set_current_mon(HTMLDocument*,IMoniker*);
|
||||||
|
|
|
@ -211,6 +211,42 @@ static nsresult NSAPI handle_node_insert(nsIDOMEventListener *iface, nsIDOMEvent
|
||||||
return NS_OK;
|
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
|
#undef NSEVENTLIST_THIS
|
||||||
|
|
||||||
#define EVENTLISTENER_VTBL(handler) \
|
#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 keypress_vtbl = EVENTLISTENER_VTBL(handle_keypress);
|
||||||
static const nsIDOMEventListenerVtbl load_vtbl = EVENTLISTENER_VTBL(handle_load);
|
static const nsIDOMEventListenerVtbl load_vtbl = EVENTLISTENER_VTBL(handle_load);
|
||||||
static const nsIDOMEventListenerVtbl node_insert_vtbl = EVENTLISTENER_VTBL(handle_node_insert);
|
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,
|
static void init_event(nsIDOMEventTarget *target, const PRUnichar *type,
|
||||||
nsIDOMEventListener *listener, BOOL capture)
|
nsIDOMEventListener *listener, BOOL capture)
|
||||||
|
@ -248,6 +285,29 @@ static void init_listener(nsEventListener *This, NSContainer *container,
|
||||||
This->This = 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)
|
void init_nsevents(NSContainer *This)
|
||||||
{
|
{
|
||||||
nsIDOMWindow *dom_window;
|
nsIDOMWindow *dom_window;
|
||||||
|
@ -266,6 +326,7 @@ void init_nsevents(NSContainer *This)
|
||||||
init_listener(&This->keypress_listener, This, &keypress_vtbl);
|
init_listener(&This->keypress_listener, This, &keypress_vtbl);
|
||||||
init_listener(&This->load_listener, This, &load_vtbl);
|
init_listener(&This->load_listener, This, &load_vtbl);
|
||||||
init_listener(&This->node_insert_listener, This, &node_insert_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);
|
nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
|
||||||
if(NS_FAILED(nsres)) {
|
if(NS_FAILED(nsres)) {
|
||||||
|
|
Loading…
Reference in New Issue