mshtml: Use window event target instead of body only for selected event properties.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
57ca6b90bb
commit
e38c2ceb51
@ -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);
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
nsIDOMNode_GetNodeType(target->nsnode, &node_type);
|
||||
nsnode = target->nsnode;
|
||||
nsIDOMNode_AddRef(nsnode);
|
||||
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);
|
||||
break;
|
||||
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
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user