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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue