Commit e38c2ceb authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

mshtml: Use window event target instead of body only for selected event properties.

parent 57ca6b90
......@@ -825,13 +825,22 @@ static void HTMLBodyElement_unlink(HTMLDOMNode *iface)
}
}
static EventTarget *HTMLBodyElement_get_event_target(HTMLDOMNode *iface)
static EventTarget *HTMLBodyElement_get_event_prop_target(HTMLDOMNode *iface, int event_id)
{
HTMLBodyElement *This = impl_from_HTMLDOMNode(iface);
switch(event_id) {
case EVENTID_BLUR:
case EVENTID_ERROR:
case EVENTID_FOCUS:
case EVENTID_LOAD:
case EVENTID_SCROLL:
return This->textcont.element.node.doc && This->textcont.element.node.doc->window
? &This->textcont.element.node.doc->window->event_target
: &This->textcont.element.node.event_target;
default:
return &This->textcont.element.node.event_target;
}
}
static BOOL HTMLBodyElement_is_text_edit(HTMLDOMNode *iface)
......@@ -864,7 +873,7 @@ static const NodeImplVtbl HTMLBodyElementImplVtbl = {
HTMLElement_clone,
HTMLElement_handle_event,
HTMLElement_get_attr_col,
HTMLBodyElement_get_event_target,
HTMLBodyElement_get_event_prop_target,
NULL,
NULL,
NULL,
......
......@@ -5036,7 +5036,6 @@ static const dispex_static_data_vtbl_t HTMLDocumentNode_dispex_vtbl = {
HTMLDocumentNode_invoke,
HTMLDocumentNode_get_compat_mode,
NULL,
NULL,
HTMLDocumentNode_bind_event
};
......
......@@ -5332,14 +5332,6 @@ static HRESULT HTMLElement_populate_props(DispatchEx *dispex)
return S_OK;
}
static EventTarget *HTMLElement_get_event_target(DispatchEx *dispex)
{
HTMLElement *This = impl_from_DispatchEx(dispex);
return This->node.vtbl->get_event_target
? This->node.vtbl->get_event_target(&This->node)
: &This->node.event_target;
}
static void HTMLElement_bind_event(DispatchEx *dispex, int eid)
{
HTMLElement *This = impl_from_DispatchEx(dispex);
......@@ -5383,7 +5375,6 @@ static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
HTMLElement_invoke,
NULL,
HTMLElement_populate_props,
HTMLElement_get_event_target,
HTMLElement_bind_event
};
......
......@@ -106,7 +106,6 @@ typedef struct {
#define EVENT_DEFAULTLISTENER 0x0001
#define EVENT_BUBBLE 0x0002
#define EVENT_FORWARDBODY 0x0004
#define EVENT_BIND_TO_BODY 0x0008
#define EVENT_CANCELABLE 0x0010
#define EVENT_HASDEFAULTHANDLERS 0x0020
......@@ -118,7 +117,7 @@ static const event_info_t event_info[] = {
{beforeactivateW, EVENTT_NONE, DISPID_EVMETH_ONBEFOREACTIVATE,
EVENT_FIXME},
{beforeunloadW, EVENTT_NONE, DISPID_EVMETH_ONBEFOREUNLOAD,
EVENT_DEFAULTLISTENER|EVENT_FORWARDBODY},
EVENT_DEFAULTLISTENER},
{blurW, EVENTT_HTML, DISPID_EVMETH_ONBLUR,
EVENT_DEFAULTLISTENER},
{changeW, EVENTT_HTML, DISPID_EVMETH_ONCHANGE,
......@@ -154,7 +153,7 @@ static const event_info_t event_info[] = {
{loadW, EVENTT_HTML, DISPID_EVMETH_ONLOAD,
EVENT_BIND_TO_BODY},
{messageW, EVENTT_NONE, DISPID_EVMETH_ONMESSAGE,
EVENT_FORWARDBODY /* FIXME: remove when we get the target right */ },
EVENT_BUBBLE /* FIXME: remove when we get the target right */ },
{mousedownW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEDOWN,
EVENT_DEFAULTLISTENER|EVENT_BUBBLE|EVENT_CANCELABLE},
{mousemoveW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEMOVE,
......@@ -848,10 +847,6 @@ static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t
handler_vector_t *handler_vector;
struct wine_rb_entry *entry;
vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->get_event_target)
event_target = vtbl->get_event_target(&event_target->dispex);
entry = wine_rb_get(&event_target->handler_map, (const void*)eid);
if(entry)
return WINE_RB_ENTRY_VALUE(entry, handler_vector_t, entry);
......@@ -1067,11 +1062,11 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
HTMLDOMNode *target, IDispatch *script_this)
{
IHTMLEventObj *prev_event;
nsIDOMNode *parent, *nsnode;
nsIDOMNode *parent, *nsnode = NULL;
BOOL prevent_default = FALSE;
HTMLInnerWindow *window;
HTMLDOMNode *node;
UINT16 node_type;
UINT16 node_type = 0;
nsresult nsres;
HRESULT hres;
......@@ -1088,9 +1083,11 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
prev_event = window->event;
window->event = event_obj ? &event_obj->IHTMLEventObj_iface : NULL;
if(target) {
nsIDOMNode_GetNodeType(target->nsnode, &node_type);
nsnode = target->nsnode;
nsIDOMNode_AddRef(nsnode);
}
switch(node_type) {
case ELEMENT_NODE:
......@@ -1116,32 +1113,18 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble))
break;
/* fallthrough */
case DOCUMENT_NODE:
if(event_info[eid].flags & EVENT_FORWARDBODY) {
nsIDOMHTMLElement *nsbody;
nsresult nsres;
nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody);
if(NS_SUCCEEDED(nsres) && nsbody) {
hres = get_node(doc, (nsIDOMNode*)nsbody, FALSE, &node);
if(SUCCEEDED(hres) && node) {
call_event_handlers(doc, event_obj, &node->event_target, node->cp_container, eid,
script_this ? script_this : (IDispatch*)&node->IHTMLDOMNode_iface);
node_release(node);
}
nsIDOMHTMLElement_Release(nsbody);
}else {
ERR("Could not get body: %08x\n", nsres);
}
}
call_event_handlers(doc, event_obj, &doc->node.event_target, &doc->basedoc.cp_container, eid,
script_this ? script_this : (IDispatch*)&doc->basedoc.IHTMLDocument2_iface);
if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble))
break;
/* fallthrough */
default:
FIXME("unimplemented node type %d\n", node_type);
default: /* window object */
call_event_handlers(doc, event_obj, &doc->window->event_target, NULL, eid,
script_this ? script_this : (IDispatch*)&doc->window->base.IHTMLWindow2_iface);
}
if(nsnode)
......@@ -1151,7 +1134,7 @@ static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *e
prevent_default = TRUE;
window->event = prev_event;
if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) {
if(target && !prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) {
nsnode = target->nsnode;
nsIDOMNode_AddRef(nsnode);
......@@ -1601,7 +1584,7 @@ void check_event_attr(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem)
}
}
set_event_handler_disp(&node->event_target, eid, disp);
set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp);
IDispatch_Release(disp);
}
......
......@@ -79,22 +79,27 @@ void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR) DECLSPEC_HIDDEN;
void detach_nsevent(HTMLDocumentNode*,const WCHAR*) DECLSPEC_HIDDEN;
static inline EventTarget *get_node_event_prop_target(HTMLDOMNode *node, eventid_t eid)
{
return node->vtbl->get_event_prop_target ? node->vtbl->get_event_prop_target(node, eid) : &node->event_target;
}
static inline HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
{
return set_event_handler(&node->event_target, eid, var);
return set_event_handler(get_node_event_prop_target(node, eid), eid, var);
}
static inline HRESULT get_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var)
{
return get_event_handler(&node->event_target, eid, var);
return get_event_handler(get_node_event_prop_target(node, eid), eid, var);
}
static inline HRESULT set_doc_event(HTMLDocument *doc, eventid_t eid, VARIANT *var)
{
return set_node_event(&doc->doc_node->node, eid, var);
return set_event_handler(&doc->doc_node->node.event_target, eid, var);
}
static inline HRESULT get_doc_event(HTMLDocument *doc, eventid_t eid, VARIANT *var)
{
return get_node_event(&doc->doc_node->node, eid, var);
return get_event_handler(&doc->doc_node->node.event_target, eid, var);
}
......@@ -2995,12 +2995,6 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
return hres;
}
static EventTarget *HTMLWindow_get_event_target(DispatchEx *dispex)
{
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
return &This->event_target;
}
static void HTMLWindow_bind_event(DispatchEx *dispex, int eid)
{
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
......@@ -3018,7 +3012,6 @@ static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
HTMLWindow_invoke,
NULL,
NULL,
HTMLWindow_get_event_target,
HTMLWindow_bind_event
};
......
......@@ -271,7 +271,6 @@ typedef struct {
compat_mode_t (*get_compat_mode)(DispatchEx*);
HRESULT (*populate_props)(DispatchEx*);
/* We abuse this vtbl for EventTarget functions to avoid separated vtbl. */
EventTarget *(*get_event_target)(DispatchEx*);
void (*bind_event)(DispatchEx*,int);
} dispex_static_data_vtbl_t;
......@@ -714,7 +713,7 @@ typedef struct {
HRESULT (*clone)(HTMLDOMNode*,nsIDOMNode*,HTMLDOMNode**);
HRESULT (*handle_event)(HTMLDOMNode*,DWORD,nsIDOMEvent*,BOOL*);
HRESULT (*get_attr_col)(HTMLDOMNode*,HTMLAttributeCollection**);
EventTarget *(*get_event_target)(HTMLDOMNode*);
EventTarget *(*get_event_prop_target)(HTMLDOMNode*,int);
HRESULT (*put_disabled)(HTMLDOMNode*,VARIANT_BOOL);
HRESULT (*get_disabled)(HTMLDOMNode*,VARIANT_BOOL*);
HRESULT (*get_document)(HTMLDOMNode*,IDispatch**);
......
......@@ -267,23 +267,10 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event
&doc->basedoc.window->base.IHTMLWindow2_iface, 0);
if(doc->nsdoc) {
nsIDOMHTMLElement *nsbody;
flush_pending_tasks(doc->basedoc.task_magic);
nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody);
if(NS_SUCCEEDED(nsres) && nsbody) {
HTMLDOMNode *node;
HRESULT hres;
hres = get_node(doc, (nsIDOMNode*)nsbody, TRUE, &node);
nsIDOMHTMLElement_Release(nsbody);
if(SUCCEEDED(hres)) {
fire_event(doc, EVENTID_LOAD, TRUE, node, event,
(IDispatch*)&doc->window->base.IDispatchEx_iface);
node_release(node);
}
}
fire_event(doc, EVENTID_LOAD, TRUE, &doc->node, event, (IDispatch*)&doc->window->base.IDispatchEx_iface);
fire_event(doc, EVENTID_LOAD, TRUE, NULL, event, (IDispatch*)&doc->window->base.IDispatchEx_iface);
}else {
ERR("NULL nsdoc\n");
nsres = NS_ERROR_FAILURE;
......
......@@ -155,7 +155,7 @@ function test_string_event_handler() {
}
function test_body_events() {
var f = function() {}
var f = function() {}, g = function() {};
document.body.onload = f;
ok(document.body.onload === f, "body.onload != f");
......@@ -164,6 +164,16 @@ function test_body_events() {
document.body.onfocus = f;
ok(document.body.onfocus === f, "body.onfocus != f");
ok(window.onfocus === f, "window.onfocus != f");
window.onfocus = g;
ok(document.body.onfocus === g, "body.onfocus != g");
ok(window.onfocus === g, "window.onfocus != g");
var onclick_called = false;
var onclick_handler = function() { onclick_called = true; };
document.body.attachEvent("onclick", onclick_handler);
window.detachEvent("onclick", onclick_handler);
document.body.click();
ok(onclick_called, "onclick handler not invoked");
}
window.onload = function() {
......
......@@ -774,7 +774,6 @@ static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
NULL,
NULL,
NULL,
NULL,
HTMLXMLHttpRequest_bind_event
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment