From: Alex Henrie Subject: [PATCH] mshtml: Use the same click event handler for anchor and area elements. Message-Id: <1438932108-2149-1-git-send-email-alexhenrie24@gmail.com> Date: Fri, 7 Aug 2015 01:21:48 -0600 Fixes https://bugs.winehq.org/show_bug.cgi?id=29468 Supersedes "mshtml: Add support for clicking image maps." --- dlls/mshtml/htmlanchor.c | 145 ++++++++++++++++++++++--------------------- dlls/mshtml/htmlarea.c | 33 +++++++++- dlls/mshtml/mshtml_private.h | 1 + 3 files changed, 108 insertions(+), 71 deletions(-) diff --git a/dlls/mshtml/htmlanchor.c b/dlls/mshtml/htmlanchor.c index a52c049..684f3ae 100644 --- a/dlls/mshtml/htmlanchor.c +++ b/dlls/mshtml/htmlanchor.c @@ -43,29 +43,18 @@ typedef struct { nsIDOMHTMLAnchorElement *nsanchor; } HTMLAnchorElement; -static HRESULT navigate_anchor_window(HTMLAnchorElement *This, const WCHAR *target) +static HRESULT navigate_href_new_window(HTMLElement *element, nsAString *href_str, const WCHAR *target) { - nsAString href_str; + const PRUnichar *href; IUri *uri; - nsresult nsres; HRESULT hres; - nsAString_Init(&href_str, NULL); - nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str); - if(NS_SUCCEEDED(nsres)) { - const PRUnichar *href; - - nsAString_GetData(&href_str, &href); - hres = create_relative_uri(This->element.node.doc->basedoc.window, href, &uri); - }else { - ERR("Could not get anchor href: %08x\n", nsres); - hres = E_FAIL; - } - nsAString_Finish(&href_str); + nsAString_GetData(href_str, &href); + hres = create_relative_uri(element->node.doc->basedoc.window, href, &uri); if(FAILED(hres)) return hres; - hres = navigate_new_window(This->element.node.doc->basedoc.window, uri, target, NULL, NULL); + hres = navigate_new_window(element->node.doc->basedoc.window, uri, target, NULL, NULL); IUri_Release(uri); return hres; } @@ -119,49 +108,69 @@ HTMLOuterWindow *get_target_window(HTMLOuterWindow *window, nsAString *target_st return ret_window; } -static HRESULT navigate_anchor(HTMLAnchorElement *This) +static HRESULT navigate_href(HTMLElement *element, nsAString *href_str, nsAString *target_str) { - nsAString href_str, target_str; HTMLOuterWindow *window; BOOL use_new_window; - nsresult nsres; - HRESULT hres = E_FAIL; + const PRUnichar *href; + HRESULT hres; + window = get_target_window(element->node.doc->basedoc.window, target_str, &use_new_window); + if(!window) { + if(use_new_window) { + const PRUnichar *target; + nsAString_GetData(target_str, &target); + return navigate_href_new_window(element, href_str, target); + }else { + return S_OK; + } + } - nsAString_Init(&target_str, NULL); - nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str); - if(NS_FAILED(nsres)) - return E_FAIL; + nsAString_GetData(href_str, &href); + if(*href) { + hres = navigate_url(window, href, window->uri_nofrag, BINDING_NAVIGATED); + }else { + TRACE("empty href\n"); + hres = S_OK; + } + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + return hres; +} - window = get_target_window(This->element.node.doc->basedoc.window, &target_str, &use_new_window); - if(!window && use_new_window) { - const PRUnichar *target; +HRESULT handle_link_click_event(HTMLElement *element, nsAString *href_str, nsAString *target_str, + nsIDOMEvent *event, BOOL *prevent_default) +{ + nsIDOMMouseEvent *mouse_event; + INT16 button; + nsresult nsres; + HRESULT hres; - nsAString_GetData(&target_str, &target); - hres = navigate_anchor_window(This, target); - nsAString_Finish(&target_str); - return hres; - } + TRACE("CLICK\n"); - nsAString_Finish(&target_str); - if(!window) - return S_OK; + nsres = nsIDOMEvent_QueryInterface(event, &IID_nsIDOMMouseEvent, (void**)&mouse_event); + assert(nsres == NS_OK); - nsAString_Init(&href_str, NULL); - nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str); - if(NS_SUCCEEDED(nsres)) { - const PRUnichar *href; + nsres = nsIDOMMouseEvent_GetButton(mouse_event, &button); + assert(nsres == NS_OK); - nsAString_GetData(&href_str, &href); - if(*href) { - hres = navigate_url(window, href, window->uri_nofrag, BINDING_NAVIGATED); - }else { - TRACE("empty href\n"); - hres = S_OK; - } + nsIDOMMouseEvent_Release(mouse_event); + + switch(button) { + case 0: + *prevent_default = TRUE; + hres = navigate_href(element, href_str, target_str); + break; + case 1: + *prevent_default = TRUE; + hres = navigate_href_new_window(element, href_str, NULL); + break; + default: + *prevent_default = FALSE; + hres = S_OK; } - nsAString_Finish(&href_str); - IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + + nsAString_Finish(href_str); + nsAString_Finish(target_str); return hres; } @@ -721,33 +730,29 @@ static HRESULT HTMLAnchorElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv) static HRESULT HTMLAnchorElement_handle_event(HTMLDOMNode *iface, eventid_t eid, nsIDOMEvent *event, BOOL *prevent_default) { HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface); + nsAString href_str, target_str; + nsresult nsres; if(eid == EVENTID_CLICK) { - nsIDOMMouseEvent *mouse_event; - INT16 button; - nsresult nsres; - - TRACE("CLICK\n"); - - nsres = nsIDOMEvent_QueryInterface(event, &IID_nsIDOMMouseEvent, (void**)&mouse_event); - assert(nsres == NS_OK); + nsAString_Init(&href_str, NULL); + nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str); + if (NS_FAILED(nsres)) { + ERR("Could not get anchor href: %08x\n", nsres); + goto fallback; + } - nsres = nsIDOMMouseEvent_GetButton(mouse_event, &button); - assert(nsres == NS_OK); + nsAString_Init(&target_str, NULL); + nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str); + if (NS_FAILED(nsres)) { + ERR("Could not get anchor target: %08x\n", nsres); + goto fallback; + } - nsIDOMMouseEvent_Release(mouse_event); + return handle_link_click_event(&This->element, &href_str, &target_str, event, prevent_default); - switch(button) { - case 0: - *prevent_default = TRUE; - return navigate_anchor(This); - case 1: - *prevent_default = TRUE; - return navigate_anchor_window(This, NULL); - default: - *prevent_default = FALSE; - return S_OK; - } +fallback: + nsAString_Finish(&href_str); + nsAString_Finish(&target_str); } return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default); diff --git a/dlls/mshtml/htmlarea.c b/dlls/mshtml/htmlarea.c index 33a0468..1a81483 100644 --- a/dlls/mshtml/htmlarea.c +++ b/dlls/mshtml/htmlarea.c @@ -403,12 +403,43 @@ static HRESULT HTMLAreaElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv) return S_OK; } +static HRESULT HTMLAreaElement_handle_event(HTMLDOMNode *iface, eventid_t eid, nsIDOMEvent *event, BOOL *prevent_default) +{ + HTMLAreaElement *This = impl_from_HTMLDOMNode(iface); + nsAString href_str, target_str; + nsresult nsres; + + if(eid == EVENTID_CLICK) { + nsAString_Init(&href_str, NULL); + nsres = nsIDOMHTMLAreaElement_GetHref(This->nsarea, &href_str); + if (NS_FAILED(nsres)) { + ERR("Could not get area href: %08x\n", nsres); + goto fallback; + } + + nsAString_Init(&target_str, NULL); + nsres = nsIDOMHTMLAreaElement_GetTarget(This->nsarea, &target_str); + if (NS_FAILED(nsres)) { + ERR("Could not get area target: %08x\n", nsres); + goto fallback; + } + + return handle_link_click_event(&This->element, &href_str, &target_str, event, prevent_default); + +fallback: + nsAString_Finish(&href_str); + nsAString_Finish(&target_str); + } + + return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default); +} + static const NodeImplVtbl HTMLAreaElementImplVtbl = { HTMLAreaElement_QI, HTMLElement_destructor, HTMLElement_cpc, HTMLElement_clone, - HTMLElement_handle_event, + HTMLAreaElement_handle_event, HTMLElement_get_attr_col }; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 43fa2a7..58ef423 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -996,6 +996,7 @@ HRESULT search_window_props(HTMLInnerWindow*,BSTR,DWORD,DISPID*) DECLSPEC_HIDDEN HRESULT get_frame_by_name(HTMLOuterWindow*,const WCHAR*,BOOL,HTMLOuterWindow**) DECLSPEC_HIDDEN; HRESULT get_doc_elem_by_id(HTMLDocumentNode*,const WCHAR*,HTMLElement**) DECLSPEC_HIDDEN; HTMLOuterWindow *get_target_window(HTMLOuterWindow*,nsAString*,BOOL*) DECLSPEC_HIDDEN; +HRESULT handle_link_click_event(HTMLElement*,nsAString*,nsAString*,nsIDOMEvent*,BOOL*) DECLSPEC_HIDDEN; HRESULT wrap_iface(IUnknown*,IUnknown*,IUnknown**) DECLSPEC_HIDDEN; -- 2.5.0