Sync with trunk revision 63128.
[reactos.git] / dll / win32 / mshtml / htmlevent.c
index 4ed833b..b6278cd 100644 (file)
@@ -25,7 +25,6 @@ typedef struct {
 } handler_vector_t;
 
 struct event_target_t {
-    DWORD node_handlers_mask;
     handler_vector_t *event_table[EVENTID_LAST];
 };
 
@@ -142,13 +141,13 @@ typedef struct {
 #define EVENT_DEFAULTLISTENER    0x0001
 #define EVENT_BUBBLE             0x0002
 #define EVENT_FORWARDBODY        0x0004
-#define EVENT_NODEHANDLER        0x0008
+#define EVENT_BIND_TO_BODY       0x0008
 #define EVENT_CANCELABLE         0x0010
 #define EVENT_HASDEFAULTHANDLERS 0x0020
 
 static const event_info_t event_info[] = {
     {abortW,             onabortW,             EVENTT_NONE,   DISPID_EVMETH_ONABORT,
-        EVENT_NODEHANDLER},
+        EVENT_BIND_TO_BODY},
     {beforeunloadW,      onbeforeunloadW,      EVENTT_NONE,   DISPID_EVMETH_ONBEFOREUNLOAD,
         EVENT_DEFAULTLISTENER|EVENT_FORWARDBODY},
     {blurW,              onblurW,              EVENTT_HTML,   DISPID_EVMETH_ONBLUR,
@@ -168,7 +167,7 @@ static const event_info_t event_info[] = {
     {dragstartW,         ondragstartW,         EVENTT_MOUSE,  DISPID_EVMETH_ONDRAGSTART,
         EVENT_CANCELABLE},
     {errorW,             onerrorW,             EVENTT_NONE,   DISPID_EVMETH_ONERROR,
-        EVENT_NODEHANDLER},
+        EVENT_BIND_TO_BODY},
     {focusW,             onfocusW,             EVENTT_HTML,   DISPID_EVMETH_ONFOCUS,
         EVENT_DEFAULTLISTENER},
     {helpW,              onhelpW,              EVENTT_KEY,    DISPID_EVMETH_ONHELP,
@@ -180,7 +179,7 @@ static const event_info_t event_info[] = {
     {keyupW,             onkeyupW,             EVENTT_KEY,    DISPID_EVMETH_ONKEYUP,
         EVENT_DEFAULTLISTENER|EVENT_BUBBLE},
     {loadW,              onloadW,              EVENTT_HTML,   DISPID_EVMETH_ONLOAD,
-        EVENT_NODEHANDLER},
+        EVENT_BIND_TO_BODY},
     {mousedownW,         onmousedownW,         EVENTT_MOUSE,  DISPID_EVMETH_ONMOUSEDOWN,
         EVENT_DEFAULTLISTENER|EVENT_BUBBLE},
     {mousemoveW,         onmousemoveW,         EVENTT_MOUSE,  DISPID_EVMETH_ONMOUSEMOVE,
@@ -205,8 +204,6 @@ static const event_info_t event_info[] = {
         EVENT_DEFAULTLISTENER|EVENT_BUBBLE|EVENT_CANCELABLE}
 };
 
-static const eventid_t node_handled_list[] = { EVENTID_ABORT, EVENTID_ERROR, EVENTID_LOAD };
-
 eventid_t str_to_eid(LPCWSTR str)
 {
     int i;
@@ -232,19 +229,6 @@ static eventid_t attr_to_eid(LPCWSTR str)
     return EVENTID_LAST;
 }
 
-static DWORD get_node_handler_mask(eventid_t eid)
-{
-    DWORD i;
-
-    for(i=0; i<sizeof(node_handled_list)/sizeof(*node_handled_list); i++) {
-        if(node_handled_list[i] == eid)
-            return 1 << i;
-    }
-
-    ERR("Invalid eid %d\n", eid);
-    return ~0;
-}
-
 typedef struct {
     DispatchEx dispex;
     IHTMLEventObj IHTMLEventObj_iface;
@@ -605,20 +589,48 @@ static HRESULT WINAPI HTMLEventObj_get_reason(IHTMLEventObj *iface, LONG *p)
 static HRESULT WINAPI HTMLEventObj_get_x(IHTMLEventObj *iface, LONG *p)
 {
     HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
+    LONG x = 0;
 
-    FIXME("(%p)->(%p)\n", This, p);
+    TRACE("(%p)->(%p)\n", This, p);
 
-    *p = -1;
+    if(This->nsevent) {
+        nsIDOMUIEvent *ui_event;
+        nsresult nsres;
+
+        nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
+        if(NS_SUCCEEDED(nsres)) {
+            /* NOTE: pageX is not exactly right here. */
+            nsres = nsIDOMUIEvent_GetPageX(ui_event, &x);
+            assert(nsres == NS_OK);
+            nsIDOMUIEvent_Release(ui_event);
+        }
+    }
+
+    *p = x;
     return S_OK;
 }
 
 static HRESULT WINAPI HTMLEventObj_get_y(IHTMLEventObj *iface, LONG *p)
 {
     HTMLEventObj *This = impl_from_IHTMLEventObj(iface);
+    LONG y = 0;
 
-    FIXME("(%p)->(%p)\n", This, p);
+    TRACE("(%p)->(%p)\n", This, p);
+
+    if(This->nsevent) {
+        nsIDOMUIEvent *ui_event;
+        nsresult nsres;
+
+        nsres = nsIDOMEvent_QueryInterface(This->nsevent, &IID_nsIDOMUIEvent, (void**)&ui_event);
+        if(NS_SUCCEEDED(nsres)) {
+            /* NOTE: pageY is not exactly right here. */
+            nsres = nsIDOMUIEvent_GetPageY(ui_event, &y);
+            assert(nsres == NS_OK);
+            nsIDOMUIEvent_Release(ui_event);
+        }
+    }
 
-    *p = -1;
+    *p = y;
     return S_OK;
 }
 
@@ -1292,31 +1304,33 @@ static BOOL alloc_handler_vector(event_target_t *event_target, eventid_t eid, in
     return TRUE;
 }
 
-static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, event_target_t *event_target, nsIDOMNode *nsnode, eventid_t eid)
+static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, event_target_t *event_target, eventid_t eid)
 {
-    if(!doc->nsdoc)
-        return S_OK;
+    nsIDOMNode *nsnode = NULL;
 
-    if(event_info[eid].flags & EVENT_NODEHANDLER) {
-        DWORD mask;
+    TRACE("%s\n", debugstr_w(event_info[eid].name));
 
-        mask = get_node_handler_mask(eid);
-        if(event_target->node_handlers_mask & mask)
-            return S_OK;
-
-        add_nsevent_listener(doc, nsnode, event_info[eid].name);
-        event_target->node_handlers_mask |= mask;
+    if(!doc->nsdoc || doc->event_vector[eid] || !(event_info[eid].flags & (EVENT_DEFAULTLISTENER|EVENT_BIND_TO_BODY)))
         return S_OK;
-    }
 
-    if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER))
-        return S_OK;
+    if(event_info[eid].flags & EVENT_BIND_TO_BODY) {
+        nsIDOMHTMLElement *nsbody;
+        nsresult nsres;
 
-    if(!doc->event_vector[eid]) {
-        doc->event_vector[eid] = TRUE;
-        add_nsevent_listener(doc, NULL, event_info[eid].name);
+        nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody);
+        if(NS_SUCCEEDED(nsres) && nsbody) {
+            nsnode = (nsIDOMNode*)nsbody;
+        }else {
+            ERR("GetBody failed: %08x\n", nsres);
+            return E_UNEXPECTED;
+        }
     }
 
+    doc->event_vector[eid] = TRUE;
+    add_nsevent_listener(doc, nsnode, event_info[eid].name);
+
+    if(nsnode)
+        nsIDOMNode_Release(nsnode);
     return S_OK;
 }
 
@@ -1347,7 +1361,7 @@ static HRESULT remove_event_handler(event_target_t **event_target, eventid_t eid
     return S_OK;
 }
 
-static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocumentNode *doc,
+static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDocumentNode *doc,
         eventid_t eid, IDispatch *disp)
 {
     event_target_t *event_target;
@@ -1368,17 +1382,17 @@ static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, nsIDOMN
     event_target->event_table[eid]->handler_prop = disp;
     IDispatch_AddRef(disp);
 
-    return ensure_nsevent_handler(doc, event_target, nsnode, eid);
+    return ensure_nsevent_handler(doc, event_target, eid);
 }
 
-HRESULT set_event_handler(event_target_t **event_target, nsIDOMNode *nsnode, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var)
+HRESULT set_event_handler(event_target_t **event_target, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var)
 {
     switch(V_VT(var)) {
     case VT_NULL:
         return remove_event_handler(event_target, eid);
 
     case VT_DISPATCH:
-        return set_event_handler_disp(event_target, nsnode, doc, eid, V_DISPATCH(var));
+        return set_event_handler_disp(event_target, doc, eid, V_DISPATCH(var));
 
     default:
         FIXME("not handler %s\n", debugstr_variant(var));
@@ -1403,7 +1417,7 @@ HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT
     return S_OK;
 }
 
-HRESULT attach_event(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocument *doc, BSTR name,
+HRESULT attach_event(event_target_t **event_target_ptr, HTMLDocument *doc, BSTR name,
         IDispatch *disp, VARIANT_BOOL *res)
 {
     event_target_t *event_target;
@@ -1434,7 +1448,7 @@ HRESULT attach_event(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTML
     event_target->event_table[eid]->handlers[i] = disp;
 
     *res = VARIANT_TRUE;
-    return ensure_nsevent_handler(doc->doc_node, event_target, nsnode, eid);
+    return ensure_nsevent_handler(doc->doc_node, event_target, eid);
 }
 
 HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name, IDispatch *disp)
@@ -1465,11 +1479,11 @@ HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name,
     return S_OK;
 }
 
-void bind_elem_event(HTMLDocumentNode *doc, HTMLElement *elem, const WCHAR *event, IDispatch *disp)
+void bind_node_event(HTMLDocumentNode *doc, event_target_t **event_target, HTMLDOMNode *node, const WCHAR *event, IDispatch *disp)
 {
     eventid_t eid;
 
-    TRACE("(%p %p %s %p)\n", doc, elem, debugstr_w(event), disp);
+    TRACE("(%p %p %p %s %p)\n", doc, event_target, node, debugstr_w(event), disp);
 
     eid = attr_to_eid(event);
     if(eid == EVENTID_LAST) {
@@ -1477,10 +1491,10 @@ void bind_elem_event(HTMLDocumentNode *doc, HTMLElement *elem, const WCHAR *even
         return;
     }
 
-    set_event_handler_disp(&elem->node.event_target, elem->node.nsnode, doc, eid, disp);
+    set_event_handler_disp(event_target, doc, eid, disp);
 }
 
-void update_cp_events(HTMLInnerWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp, nsIDOMNode *nsnode)
+void update_cp_events(HTMLInnerWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp)
 {
     event_target_t *event_target;
     int i;
@@ -1491,7 +1505,7 @@ void update_cp_events(HTMLInnerWindow *window, event_target_t **event_target_ptr
 
     for(i=0; i < EVENTID_LAST; i++) {
         if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid))
-            ensure_nsevent_handler(window->doc, event_target, nsnode, i);
+            ensure_nsevent_handler(window->doc, event_target, i);
     }
 }
 
@@ -1522,7 +1536,7 @@ void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem)
             if(disp) {
                 hres = get_node(doc, (nsIDOMNode*)nselem, TRUE, &node);
                 if(SUCCEEDED(hres)) {
-                    set_event_handler_disp(get_node_event_target(node), node->nsnode, node->doc, i, disp);
+                    set_event_handler_disp(get_node_event_target(node), node->doc, i, disp);
                     node_release(node);
                 }
                 IDispatch_Release(disp);
@@ -1547,7 +1561,7 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
 
     for(i=0; i < EVENTID_LAST; i++) {
         if(event_info[i].flags & EVENT_HASDEFAULTHANDLERS) {
-            hres = ensure_nsevent_handler(doc, NULL, NULL, i);
+            hres = ensure_nsevent_handler(doc, NULL, i);
             if(FAILED(hres))
                 return hres;
         }