diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 3aae8133125..25bb78004d8 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -140,8 +140,12 @@ static ULONG WINAPI HTMLDocument_Release(IHTMLDocument2 *iface) IOleInPlaceObjectWindowless_InPlaceDeactivate(INPLACEWIN(This)); if(This->ipsite) IOleDocumentView_SetInPlaceSite(DOCVIEW(This), NULL); + + if(This->tooltips_hwnd) + DestroyWindow(This->tooltips_hwnd); if(This->hwnd) DestroyWindow(This->hwnd); + release_nodes(This); if(This->nscontainer) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 9a9ac1ed22b..478f15206df 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -73,6 +73,7 @@ typedef struct { IOleInPlaceFrame *frame; HWND hwnd; + HWND tooltips_hwnd; BOOL in_place_active; BOOL ui_active; @@ -86,11 +87,14 @@ typedef struct { } HTMLDocument; struct NSContainer { - const nsIWebBrowserChromeVtbl *lpWebBrowserChromeVtbl; - const nsIContextMenuListenerVtbl *lpContextMenuListenerVtbl; - const nsIURIContentListenerVtbl *lpURIContentListenerVtbl; - const nsIEmbeddingSiteWindowVtbl *lpEmbeddingSiteWindowVtbl; - const nsIInterfaceRequestorVtbl *lpInterfaceRequestorVtbl; + const nsIWebBrowserChromeVtbl *lpWebBrowserChromeVtbl; + const nsIContextMenuListenerVtbl *lpContextMenuListenerVtbl; + const nsIURIContentListenerVtbl *lpURIContentListenerVtbl; + const nsIEmbeddingSiteWindowVtbl *lpEmbeddingSiteWindowVtbl; + const nsITooltipListenerVtbl *lpTooltipListenerVtbl; + const nsIInterfaceRequestorVtbl *lpInterfaceRequestorVtbl; + const nsIWeakReferenceVtbl *lpWeakReferenceVtbl; + const nsISupportsWeakReferenceVtbl *lpSupportsWeakReferenceVtbl; nsIWebBrowser *webbrowser; nsIWebNavigation *navigation; @@ -167,6 +171,9 @@ typedef struct { #define NSURICL(x) ((nsIURIContentListener*) &(x)->lpURIContentListenerVtbl) #define NSEMBWNDS(x) ((nsIEmbeddingSiteWindow*) &(x)->lpEmbeddingSiteWindowVtbl) #define NSIFACEREQ(x) ((nsIInterfaceRequestor*) &(x)->lpInterfaceRequestorVtbl) +#define NSTOOLTIP(x) ((nsITooltipListener*) &(x)->lpTooltipListenerVtbl) +#define NSWEAKREF(x) ((nsIWeakReference*) &(x)->lpWeakReferenceVtbl) +#define NSSUPWEAKREF(x) ((nsISupportsWeakReference*) &(x)->lpSupportsWeakReferenceVtbl) #define HTMLELEM(x) ((IHTMLElement*) &(x)->lpHTMLElementVtbl) #define HTMLELEM2(x) ((IHTMLElement2*) &(x)->lpHTMLElement2Vtbl) @@ -190,6 +197,9 @@ void NSContainer_Release(NSContainer*); void HTMLDocument_LockContainer(HTMLDocument*,BOOL); void HTMLDocument_ShowContextMenu(HTMLDocument*,DWORD,POINT*); +void show_tooltip(HTMLDocument*,DWORD,DWORD,LPCWSTR); +void hide_tooltip(HTMLDocument*); + HRESULT ProtocolFactory_Create(REFCLSID,REFIID,void**); void close_gecko(void); @@ -200,6 +210,9 @@ void hlink_frame_navigate(HTMLDocument*,IHlinkFrame*,LPCWSTR,nsIInputStream*,DWO nsIURI *get_nsIURI(LPCWSTR); +void *nsalloc(size_t); +void nsfree(void*); + void nsACString_Init(nsACString*,const char*); PRUint32 nsACString_GetData(const nsACString*,const char**,PRBool*); void nsACString_Finish(nsACString*); diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 9cabc7112bd..a64f6a55510 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -38,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1" #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1" #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1" +#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1" #define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1" #define APPSTARTUP_TOPIC "app-startup" @@ -68,6 +69,7 @@ static HINSTANCE hXPCOM = NULL; static nsIServiceManager *pServMgr = NULL; static nsIComponentManager *pCompMgr = NULL; +static nsIMemory *nsmem = NULL; static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0}; @@ -353,6 +355,11 @@ static BOOL load_gecko(void) set_profile(); + nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_MEMORY_CONTRACTID, + NULL, &IID_nsIMemory, (void**)&nsmem); + if(NS_FAILED(nsres)) + ERR("Could not get nsIMemory: %08lx\n", nsres); + if(registrar) { register_nsservice(registrar, pServMgr); nsIComponentRegistrar_Release(registrar); @@ -361,6 +368,16 @@ static BOOL load_gecko(void) return TRUE; } +void *nsalloc(size_t size) +{ + return nsIMemory_Alloc(nsmem, size); +} + +void nsfree(void *mem) +{ + nsIMemory_Free(nsmem, mem); +} + void nsACString_Init(nsACString *str, const char *data) { NS_CStringContainerInit(str); @@ -431,6 +448,9 @@ void close_gecko() if(pServMgr) nsIServiceManager_Release(pServMgr); + if(nsmem) + nsIMemory_Release(nsmem); + if(hXPCOM) FreeLibrary(hXPCOM); } @@ -462,9 +482,18 @@ static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *ifa }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) { TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result); *result = NSEMBWNDS(This); + }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) { + TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result); + *result = NSTOOLTIP(This); }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) { TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result); *result = NSIFACEREQ(This); + }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) { + TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result); + *result = NSWEAKREF(This); + }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) { + TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result); + *result = NSSUPWEAKREF(This); } if(*result) { @@ -928,6 +957,56 @@ static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = { nsEmbeddingSiteWindow_GetSiteWindow }; +#define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface) + +static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid, + nsQIResult result) +{ + NSContainer *This = NSTOOLTIP_THIS(iface); + return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); +} + +static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface) +{ + NSContainer *This = NSTOOLTIP_THIS(iface); + return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); +} + +static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface) +{ + NSContainer *This = NSTOOLTIP_THIS(iface); + return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); +} + +static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface, + PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText) +{ + NSContainer *This = NSTOOLTIP_THIS(iface); + + show_tooltip(This->doc, aXCoord, aYCoord, aTipText); + + return NS_OK; +} + +static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface) +{ + NSContainer *This = NSTOOLTIP_THIS(iface); + + hide_tooltip(This->doc); + + return NS_OK; +} + +#undef NSTOOLTIM_THIS + +static const nsITooltipListenerVtbl nsTooltipListenerVtbl = { + nsTooltipListener_QueryInterface, + nsTooltipListener_AddRef, + nsTooltipListener_Release, + nsTooltipListener_OnShowTooltip, + nsTooltipListener_OnHideTooltip +}; + #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface) static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface, @@ -971,6 +1050,85 @@ static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = { nsInterfaceRequestor_GetInterface }; +#define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface) + +static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface, + nsIIDRef riid, nsQIResult result) +{ + NSContainer *This = NSWEAKREF_THIS(iface); + return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); +} + +static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface) +{ + NSContainer *This = NSWEAKREF_THIS(iface); + return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); +} + +static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface) +{ + NSContainer *This = NSWEAKREF_THIS(iface); + return nsIWebBrowserChrome_Release(NSWBCHROME(This)); +} + +static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface, + const nsIID *riid, void **result) +{ + NSContainer *This = NSWEAKREF_THIS(iface); + return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); +} + +#undef NSWEAKREF_THIS + +static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = { + nsWeakReference_QueryInterface, + nsWeakReference_AddRef, + nsWeakReference_Release, + nsWeakReference_QueryReferent +}; + +#define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface) + +static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface, + nsIIDRef riid, nsQIResult result) +{ + NSContainer *This = NSSUPWEAKREF_THIS(iface); + return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result); +} + +static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface) +{ + NSContainer *This = NSSUPWEAKREF_THIS(iface); + return nsIWebBrowserChrome_AddRef(NSWBCHROME(This)); +} + +static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface) +{ + NSContainer *This = NSSUPWEAKREF_THIS(iface); + return nsIWebBrowserChrome_Release(NSWBCHROME(This)); +} + +static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface, + nsIWeakReference **_retval) +{ + NSContainer *This = NSSUPWEAKREF_THIS(iface); + + TRACE("(%p)->(%p)\n", This, _retval); + + *_retval = NSWEAKREF(This); + return NS_OK; +} + +#undef NSWEAKREF_THIS + +const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = { + nsSupportsWeakReference_QueryInterface, + nsSupportsWeakReference_AddRef, + nsSupportsWeakReference_Release, + nsSupportsWeakReference_GetWeakReference +}; + + NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) { nsIWebBrowserSetup *wbsetup; @@ -982,11 +1140,15 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NSContainer)); - ret->lpWebBrowserChromeVtbl = &nsWebBrowserChromeVtbl; - ret->lpContextMenuListenerVtbl = &nsContextMenuListenerVtbl; - ret->lpURIContentListenerVtbl = &nsURIContentListenerVtbl; - ret->lpEmbeddingSiteWindowVtbl = &nsEmbeddingSiteWindowVtbl; - ret->lpInterfaceRequestorVtbl = &nsInterfaceRequestorVtbl; + ret->lpWebBrowserChromeVtbl = &nsWebBrowserChromeVtbl; + ret->lpContextMenuListenerVtbl = &nsContextMenuListenerVtbl; + ret->lpURIContentListenerVtbl = &nsURIContentListenerVtbl; + ret->lpEmbeddingSiteWindowVtbl = &nsEmbeddingSiteWindowVtbl; + ret->lpTooltipListenerVtbl = &nsTooltipListenerVtbl; + ret->lpInterfaceRequestorVtbl = &nsInterfaceRequestorVtbl; + ret->lpWeakReferenceVtbl = &nsWeakReferenceVtbl; + ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl; + ret->doc = doc; ret->ref = 1; diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 176ef9b7530..e77090b0e74 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -81,7 +81,6 @@ interface nsISupports } /* Currently we don't need a full declaration of these interfaces */ -typedef nsISupports nsIWeakReference; typedef nsISupports nsISHistory; typedef nsISupports nsISimpleEnumerator; typedef nsISupports nsIWidget; @@ -154,6 +153,37 @@ interface nsIComponentManager : nsISupports nsIIDRef aIID, nsQIResult result); } +[ + object, + uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3) +] +interface nsIMemory : nsISupports +{ + void *Alloc(/*size_t*/ int size); + void *Realloc(void *_ptr, /*size_t*/ int newSize); + void Free(void *_ptr); + nsresult HeapMinimize(PRBool immediate); + nsresult IsLowMemory(PRBool *_retval); +} + +[ + object, + uuid(9188bc85-f92e-11d2-81ef-0060083a0bcf) +] +interface nsIWeakReference : nsISupports +{ + nsresult QueryReferent(const nsIID *riid, void **result); +} + +[ + object, + uuid(9188bc86-f92e-11d2-81ef-0060083a0bcf) +] +interface nsISupportsWeakReference : nsISupports +{ + nsresult GetWeakReference(nsIWeakReference **_retval); +} + [ object, uuid(033a1470-8b2a-11d3-af88-00a024ffc08c) @@ -615,6 +645,16 @@ interface nsIURIContentListener : nsISupports nsresult SetParentContentListener(nsIURIContentListener *aParentContentListener); } +[ + object, + uuid(44b78386-1dd2-11b2-9ad2-e4eee2ca1916) +] +interface nsITooltipListener : nsISupports +{ + nsresult OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText); + nsresult OnHideTooltip(); +} + [ object, uuid(69e5df00-7b8b-11d3-af61-00a024ffc08c) @@ -958,6 +998,15 @@ interface nsIPromptService : nsISupports PRInt32 *aOutSelection, PRBool *_retval); } +[ + object, + uuid(b128a1e6-44f3-4331-8fbe-5af360ff21ee) +] +interface nsITooltipTextProvider : nsISupports +{ + nsresult GetNodeText(nsIDOMNode *aNode, PRUnichar **aText, PRBool *_retval); +} + [ object, uuid(02b0625a-e7f3-11d2-9f5a-006008a6efe9) diff --git a/dlls/mshtml/nsservice.c b/dlls/mshtml/nsservice.c index 62e5a27d54e..44550ad0804 100644 --- a/dlls/mshtml/nsservice.c +++ b/dlls/mshtml/nsservice.c @@ -37,9 +37,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NS_PROMPTSERVICE_CONTRACTID "@mozilla.org/embedcomp/prompt-service;1" #define NS_WINDOWWATCHER_CONTRACTID "@mozilla.org/embedcomp/window-watcher;1" +#define NS_TOOLTIPTEXTPROVIDER_CONTRACTID "@mozilla.org/embedcomp/tooltiptextprovider;1" + +#define NS_TOOLTIPTEXTPROVIDER_CLASSNAME "nsTooltipTextProvider" static const nsIID NS_PROMPTSERVICE_CID = {0xa2112d6a,0x0e28,0x421f,{0xb4,0x6a,0x25,0xc0,0xb3,0x8,0xcb,0xd0}}; +static const nsIID NS_TOOLTIPTEXTPROVIDER_CID = + {0x0b666e3e,0x569a,0x462c,{0xa7,0xf0,0xb1,0x6b,0xb1,0x5d,0x42,0xff}}; static nsresult NSAPI nsWindowCreator_QueryInterface(nsIWindowCreator2 *iface, nsIIDRef riid, nsQIResult result) @@ -260,6 +265,104 @@ static const nsIPromptServiceVtbl PromptServiceVtbl = { static nsIPromptService nsPromptService = { &PromptServiceVtbl }; +static nsresult NSAPI nsTooltipTextProvider_QueryInterface(nsITooltipTextProvider *iface, + nsIIDRef riid, nsQIResult result) +{ + *result = NULL; + + if(IsEqualGUID(&IID_nsISupports, riid)) { + TRACE("(IID_nsISupports %p)\n", result); + *result = iface; + }else if(IsEqualGUID(&IID_nsITooltipTextProvider, riid)) { + TRACE("(IID_nsITooltipTextProvider %p)\n", result); + *result = iface; + } + + if(*result) { + nsITooltipTextProvider_AddRef(iface); + return NS_OK; + } + + WARN("(%s %p)\n", debugstr_guid(riid), result); + return NS_NOINTERFACE; +} + +static nsrefcnt NSAPI nsTooltipTextProvider_AddRef(nsITooltipTextProvider *iface) +{ + return 2; +} + +static nsrefcnt NSAPI nsTooltipTextProvider_Release(nsITooltipTextProvider *iface) +{ + return 1; +} + +static nsresult NSAPI nsTooltipTextProvider_GetNodeText(nsITooltipTextProvider *iface, + nsIDOMNode *aNode, PRUnichar **aText, PRBool *_retval) +{ + nsIDOMHTMLElement *nselem; + nsIDOMNode *node = aNode, *parent; + nsAString title_str; + const PRUnichar *title = NULL; + nsresult nsres; + + TRACE("(%p %p %p)\n", aNode, aText, _retval); + + *aText = NULL; + + nsAString_Init(&title_str, NULL); + + do { + nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMHTMLElement, (void**)&nselem); + if(NS_SUCCEEDED(nsres)) { + title = NULL; + + nsIDOMHTMLElement_GetTitle(nselem, &title_str); + nsIDOMHTMLElement_Release(nselem); + + nsAString_GetData(&title_str, &title, NULL); + if(title && *title) { + if(node != aNode) + nsIDOMNode_Release(node); + break; + } + } + + nsres = nsIDOMNode_GetParentNode(node, &parent); + if(NS_FAILED(nsres)) + parent = NULL; + + if(node != aNode) + nsIDOMNode_Release(node); + node = parent; + } while(node); + + if(title && *title) { + int size = (strlenW(title)+1)*sizeof(PRUnichar); + + *aText = nsalloc(size); + memcpy(*aText, title, size); + TRACE("aText = %s\n", debugstr_w(*aText)); + + *_retval = TRUE; + }else { + *_retval = FALSE; + } + + nsAString_Finish(&title_str); + + return NS_OK; +} + +static const nsITooltipTextProviderVtbl nsTooltipTextProviderVtbl = { + nsTooltipTextProvider_QueryInterface, + nsTooltipTextProvider_AddRef, + nsTooltipTextProvider_Release, + nsTooltipTextProvider_GetNodeText +}; + +static nsITooltipTextProvider nsTooltipTextProvider = { &nsTooltipTextProviderVtbl }; + typedef struct { const nsIFactoryVtbl *lpFactoryVtbl; nsISupports *service; @@ -333,6 +436,11 @@ static nsServiceFactory nsPromptServiceFactory = { (nsISupports*)&nsPromptService }; +static nsServiceFactory nsTooltipTextFactory = { + &nsServiceFactoryVtbl, + (nsISupports*)&nsTooltipTextProvider +}; + void register_nsservice(nsIComponentRegistrar *registrar, nsIServiceManager *service_manager) { nsIWindowWatcher *window_watcher; @@ -354,4 +462,10 @@ void register_nsservice(nsIComponentRegistrar *registrar, nsIServiceManager *ser }else { ERR("Could not get WindowWatcher object: %08lx\n", nsres); } + + nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_TOOLTIPTEXTPROVIDER_CID, + NS_TOOLTIPTEXTPROVIDER_CLASSNAME, NS_TOOLTIPTEXTPROVIDER_CONTRACTID, + NSFACTORY(&nsTooltipTextFactory)); + if(NS_FAILED(nsres)) + ERR("RegisterFactory failed: %08lx\n", nsres); } diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index dda2f4bc7ad..31e0b077701 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Jacek Caban + * Copyright 2005-2006 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,6 +27,7 @@ #include "winbase.h" #include "winuser.h" #include "wingdi.h" +#include "commctrl.h" #include "ole2.h" #include "resource.h" @@ -39,8 +40,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); static const WCHAR wszInternetExplorer_Server[] = {'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','_','S','e','r','v','e','r',0}; +static const WCHAR wszTooltipData[] = {'t','o','o','l','t','i','p','_','d','a','t','a',0}; + static ATOM serverwnd_class = 0; +typedef struct { + HTMLDocument *doc; + WNDPROC proc; +} tooltip_data; + static void paint_disabled(HWND hwnd) { HDC hdc; PAINTSTRUCT ps; @@ -149,6 +157,7 @@ static HRESULT activate_window(HTMLDocument *This) WARN("GetWindowContext failed: %08lx\n", hres); return hres; } + if(pIPWnd) IOleInPlaceUIWindow_Release(pIPWnd); TRACE("got window context: %p %p {%ld %ld %ld %ld} {%ld %ld %ld %ld} {%d %x %p %p %d}\n", @@ -221,6 +230,77 @@ static HRESULT activate_window(HTMLDocument *This) return S_OK; } +static LRESULT tooltips_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + tooltip_data *data = GetPropW(hwnd, wszTooltipData); + + TRACE("%d %p\n", msg, data); + + if(msg == TTM_WINDOWFROMPOINT) { + RECT rect; + POINT *pt = (POINT*)lParam; + + TRACE("TTM_WINDOWFROMPOINT (%ld,%ld)\n", pt->x, pt->y); + + GetWindowRect(data->doc->hwnd, &rect); + + if(rect.left <= pt->x && pt->x <= rect.right + && rect.top <= pt->y && pt->y <= rect.bottom) + return (LPARAM)data->doc->hwnd; + } + + return CallWindowProcW(data->proc, hwnd, msg, wParam, lParam); +} + +static void create_tooltips_window(HTMLDocument *This) +{ + tooltip_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)); + + This->tooltips_hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, TTS_NOPREFIX | WS_POPUP, + CW_USEDEFAULT, CW_USEDEFAULT, 10, 10, This->hwnd, NULL, hInst, NULL); + + data->doc = This; + data->proc = (WNDPROC)GetWindowLongPtrW(This->tooltips_hwnd, GWLP_WNDPROC); + + SetPropW(This->tooltips_hwnd, wszTooltipData, data); + + SetWindowLongPtrW(This->tooltips_hwnd, GWLP_WNDPROC, (LONG_PTR)tooltips_proc); + + SetWindowPos(This->tooltips_hwnd, HWND_TOPMOST,0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + +} + +void show_tooltip(HTMLDocument *This, DWORD x, DWORD y, LPCWSTR text) +{ + TTTOOLINFOW toolinfo = { + sizeof(TTTOOLINFOW), 0, This->hwnd, 0xdeadbeef, + {x>2 ? x-2 : 0, y>0 ? y-2 : 0, x+2, y+2}, /* FIXME */ + NULL, (LPWSTR)text, 0}; + MSG msg = {This->hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(x,y), 0, {x,y}}; + + TRACE("(%p)->(%ld %ld %s)\n", This, x, y, debugstr_w(text)); + + if(!This->tooltips_hwnd) + create_tooltips_window(This); + + SendMessageW(This->tooltips_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfo); + SendMessageW(This->tooltips_hwnd, TTM_ACTIVATE, TRUE, 0); + SendMessageW(This->tooltips_hwnd, TTM_RELAYEVENT, 0, (LPARAM)&msg); +} + +void hide_tooltip(HTMLDocument *This) +{ + TTTOOLINFOW toolinfo = { + sizeof(TTTOOLINFOW), 0, This->hwnd, 0xdeadbeef, + {0,0,0,0}, NULL, NULL, 0}; + + TRACE("(%p)\n", This); + + SendMessageW(This->tooltips_hwnd, TTM_DELTOOLW, 0, (LPARAM)&toolinfo); + SendMessageW(This->tooltips_hwnd, TTM_ACTIVATE, FALSE, 0); +} + /********************************************************** * IOleDocumentView implementation */ @@ -579,6 +659,7 @@ void HTMLDocument_View_Init(HTMLDocument *This) This->ipsite = NULL; This->frame = NULL; This->hwnd = NULL; + This->tooltips_hwnd = NULL; This->in_place_active = FALSE; This->ui_active = FALSE;