diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 73b03af7841..6cbd8695be2 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -29,10 +29,13 @@
#define NS_OK ((nsresult)0x00000000L)
#define NS_NOINTERFACE ((nsresult)0x80004002L)
#define NS_ERROR_NOT_IMPLEMENTED ((nsresult)0x80004001L)
+#define NS_ERROR_INVALID_ARG ((nsresult)0x80070057L)
#define NS_FAILED(res) ((res) & 0x80000000)
#define NS_SUCCEEDED(res) (!NS_FAILED(res))
+#define NSAPI WINAPI
+
typedef struct NSContainer NSContainer;
typedef struct BindStatusCallback BindStatusCallback;
@@ -72,11 +75,16 @@ typedef struct {
} HTMLDocument;
struct NSContainer {
+ const nsIWebBrowserChromeVtbl *lpWebBrowserChromeVtbl;
+ const nsIContextMenuListenerVtbl *lpContextMenuListenerVtbl;
+
nsIWebBrowser *webbrowser;
nsIWebNavigation *navigation;
nsIBaseWindow *window;
nsIWebBrowserStream *stream;
+ HTMLDocument *doc;
+
HWND hwnd;
};
@@ -99,6 +107,9 @@ struct NSContainer {
#define CONTROL(x) ((IOleControl*) &(x)->lpOleControlVtbl)
#define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl)
+#define NSWBCHROME(x) ((nsIWebBrowserChrome*) &(x)->lpWebBrowserChromeVtbl)
+#define NSCML(x) ((nsIContextMenuListener*) &(x)->lpContextMenuListenerVtbl)
+
#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
HRESULT HTMLDocument_Create(IUnknown*,REFIID,void**);
@@ -113,6 +124,7 @@ void HTMLDocument_NSContainer_Init(HTMLDocument*);
void HTMLDocument_NSContainer_Destroy(HTMLDocument*);
void HTMLDocument_LockContainer(HTMLDocument*,BOOL);
+void HTMLDocument_ShowContextMenu(HTMLDocument*,DWORD,POINT*);
HRESULT ProtocolFactory_Create(REFCLSID,REFIID,void**);
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index ac63af71dce..5610233625f 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -329,6 +329,228 @@ nsIURI *get_nsIURI(LPCWSTR url)
return ret;
}
+#define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface)
+
+static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
+ nsIIDRef riid, nsQIResult result)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+
+ *result = NULL;
+ if(IsEqualGUID(&IID_nsISupports, riid)) {
+ TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
+ *result = NSWBCHROME(This);
+ }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
+ TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
+ *result = NSWBCHROME(This);
+ }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
+ TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
+ *result = NSCML(This);
+ }
+
+ if(*result)
+ return NS_OK;
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
+ return NS_NOINTERFACE;
+}
+
+static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ TRACE("(%p)\n", This);
+ return 2; /* Should we implement ref conunting here? */
+}
+
+static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ TRACE("(%p)\n", This);
+ return 1;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
+ PRUint32 statusType, const PRUnichar *status)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ TRACE("(%p)->(%ld %s)\n", This, statusType, debugstr_w(status));
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
+ nsIWebBrowser **aWebBrowser)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aWebBrowser);
+
+ if(!aWebBrowser)
+ return NS_ERROR_INVALID_ARG;
+
+ *aWebBrowser = This->webbrowser;
+ return S_OK;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
+ nsIWebBrowser *aWebBrowser)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aWebBrowser);
+
+ if(aWebBrowser != This->webbrowser)
+ ERR("Wrong nsWebBrowser!\n");
+
+ return NS_OK;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
+ PRUint32 *aChromeFlags)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)->(%p)\n", This, aChromeFlags);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
+ PRUint32 aChromeFlags)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)->(%08lx)\n", This, aChromeFlags);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ TRACE("(%p)\n", This);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
+ PRInt32 aCX, PRInt32 aCY)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)->(%ld %ld)\n", This, aCX, aCY);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)\n", This);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)->(%p)\n", This, _retval);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
+ nsresult aStatus)
+{
+ NSContainer *This = NSWBCHROME_THIS(iface);
+ WARN("(%p)->(%08lx)\n", This, aStatus);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#undef NSWBCHROME_THIS
+
+static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
+ nsWebBrowserChrome_QueryInterface,
+ nsWebBrowserChrome_AddRef,
+ nsWebBrowserChrome_Release,
+ nsWebBrowserChrome_SetStatus,
+ nsWebBrowserChrome_GetWebBrowser,
+ nsWebBrowserChrome_SetWebBrowser,
+ nsWebBrowserChrome_GetChromeFlags,
+ nsWebBrowserChrome_SetChromeFlags,
+ nsWebBrowserChrome_DestroyBrowserWindow,
+ nsWebBrowserChrome_SizeBrowserTo,
+ nsWebBrowserChrome_ShowAsModal,
+ nsWebBrowserChrome_IsWindowModal,
+ nsWebBrowserChrome_ExitModalEventLoop
+};
+
+#define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface)
+
+static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
+ nsIIDRef riid, nsQIResult result)
+{
+ NSContainer *This = NSCML_THIS(iface);
+ return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
+}
+
+static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
+{
+ NSContainer *This = NSCML_THIS(iface);
+ return nsIContextMenuListener_AddRef(NSWBCHROME(This));
+}
+
+static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
+{
+ NSContainer *This = NSCML_THIS(iface);
+ return nsIWebBrowserChrome_Release(NSWBCHROME(This));
+}
+
+static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
+ PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
+{
+ NSContainer *This = NSCML_THIS(iface);
+ nsIDOMMouseEvent *event;
+ POINT pt;
+ DWORD dwID = CONTEXT_MENU_DEFAULT;
+ nsresult nsres;
+
+ TRACE("(%p)->(%08lx %p %p)\n", This, aContextFlags, aEvent, aNode);
+
+ nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
+ if(NS_FAILED(nsres)) {
+ ERR("Could not get nsIDOMMouseEvent interface: %08lx\n", nsres);
+ return nsres;
+ }
+
+ nsIDOMMouseEvent_GetScreenX(event, &pt.x);
+ nsIDOMMouseEvent_GetScreenY(event, &pt.y);
+ nsIDOMMouseEvent_Release(event);
+
+ switch(aContextFlags) {
+ case CONTEXT_NONE:
+ case CONTEXT_DOCUMENT:
+ case CONTEXT_TEXT:
+ dwID = CONTEXT_MENU_DEFAULT;
+ break;
+ case CONTEXT_IMAGE:
+ case CONTEXT_IMAGE|CONTEXT_LINK:
+ dwID = CONTEXT_MENU_IMAGE;
+ break;
+ case CONTEXT_LINK:
+ dwID = CONTEXT_MENU_ANCHOR;
+ break;
+ case CONTEXT_INPUT:
+ dwID = CONTEXT_MENU_CONTROL;
+ break;
+ default:
+ FIXME("aContextFlags=%08lx\n", aContextFlags);
+ };
+
+ HTMLDocument_ShowContextMenu(This->doc, dwID, &pt);
+
+ return NS_OK;
+}
+
+#undef NSCML_THIS
+
+static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
+ nsContextMenuListener_QueryInterface,
+ nsContextMenuListener_AddRef,
+ nsContextMenuListener_Release,
+ nsContextMenuListener_OnShowContextMenu
+};
+
void HTMLDocument_NSContainer_Init(HTMLDocument *This)
{
nsIWebBrowserSetup *wbsetup;
@@ -341,11 +563,21 @@ void HTMLDocument_NSContainer_Init(HTMLDocument *This)
This->nscontainer = HeapAlloc(GetProcessHeap(), 0, sizeof(NSContainer));
+ This->nscontainer->lpWebBrowserChromeVtbl = &nsWebBrowserChromeVtbl;
+ This->nscontainer->lpContextMenuListenerVtbl = &nsContextMenuListenerVtbl;
+
+ This->nscontainer->doc = This;
+
nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
NULL, &IID_nsIWebBrowser, (void**)&This->nscontainer->webbrowser);
if(NS_FAILED(nsres))
ERR("Creating WebBrowser failed: %08lx\n", nsres);
+ nsres = nsIWebBrowser_SetContainerWindow(This->nscontainer->webbrowser,
+ NSWBCHROME(This->nscontainer));
+ if(NS_FAILED(nsres))
+ ERR("SetContainerWindow failed: %08lx\n", nsres);
+
nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser, &IID_nsIBaseWindow,
(void**)&This->nscontainer->window);
if(NS_FAILED(nsres))
diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl
index 09106a8971c..fc517dcdf35 100644
--- a/dlls/mshtml/nsiface.idl
+++ b/dlls/mshtml/nsiface.idl
@@ -39,12 +39,15 @@ typedef WCHAR PRUnichar;
typedef LPWSTR nswstring;
typedef ULONG PRUint32;
typedef LONG PRInt32;
+typedef WORD PRUint16;
typedef BYTE PRUint8;
typedef BOOL PRBool;
typedef LARGE_INTEGER PRInt64;
+typedef ULARGE_INTEGER PRUint64;
typedef int nsAString;
typedef struct nsACString nsACString;
+typedef PRUint64 DOMTimeStamp;
interface nsIWebBrowserChrome;
@@ -70,6 +73,10 @@ typedef nsISupports nsISimpleEnumerator;
typedef nsISupports nsIWidget;
typedef nsISupports nsIProtocolHandler;
typedef nsISupports nsIChannel;
+typedef nsISupports nsIDOMElement;
+typedef nsISupports nsIDOMNode;
+typedef nsISupports nsIDOMEventTarget;
+typedef nsISupports nsIDOMAbstractView;
[
object,
@@ -303,3 +310,91 @@ interface nsIIOService : nsISupports
nsresult SetOffline(PRBool aOffline);
nsresult AllowPort(PRInt32 aPort, const char *aScheme, PRBool *_retval);
}
+
+[
+ object,
+ uuid(ba434c60-9d52-11d3-afb0-00a024ffc08c)
+]
+interface nsIWebBrowserChrome : nsISupports
+{
+ nsresult SetStatus(PRUint32 statusType, const PRUnichar *status);
+ nsresult GetWebBrowser(nsIWebBrowser **aWebBrowser);
+ nsresult SetWebBrowser(nsIWebBrowser *aWebBrowser);
+ nsresult GetChromeFlags(PRUint32 *aChromeFlags);
+ nsresult SetChromeFlags(PRUint32 aChromeFlags);
+ nsresult DestroyBrowserWindow();
+ nsresult SizeBrowserTo(PRInt32 aCX, PRInt32 aCY);
+ nsresult ShowAsModal();
+ nsresult IsWindowModal(PRBool *_retval);
+ nsresult ExitModalEventLoop(nsresult aStatus);
+}
+
+[
+ object,
+ uuid(a66b7b80-ff46-bd97-0080-5f8ae38add32)
+]
+interface nsIDOMEvent : nsISupports
+{
+ nsresult GetType(nsAString *aType);
+ nsresult GetTarget(nsIDOMEventTarget **aTarget);
+ nsresult GetCurrentTarget(nsIDOMEventTarget **aCurrentTarget);
+ nsresult GetEventPhase(PRUint16 *aEventPhase);
+ nsresult GetBubbles(PRBool *aBubbles);
+ nsresult GetCancelable(PRBool *aCancelable);
+ nsresult GetTimeStamp(DOMTimeStamp *aTimeStamp);
+ nsresult StopPropagation();
+ nsresult PreventDefault();
+ nsresult InitEvent(const nsAString *eventTypeArg, PRBool canBubbleArg, PRBool cancelableArg);
+}
+
+cpp_quote("#define CONTEXT_NONE 0x00");
+cpp_quote("#define CONTEXT_LINK 0x01");
+cpp_quote("#define CONTEXT_IMAGE 0x02");
+cpp_quote("#define CONTEXT_DOCUMENT 0x04");
+cpp_quote("#define CONTEXT_TEXT 0x08");
+cpp_quote("#define CONTEXT_INPUT 0x10");
+cpp_quote("#define CONTEXT_BACKGROUND_IMAGE 0x20");
+
+[
+ object,
+ uuid(3478b6b0-3875-11d4-94ef-0020183bf181)
+]
+interface nsIContextMenuListener : nsISupports
+{
+ nsresult OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode);
+}
+
+[
+ object,
+ uuid(a6cf90c3-15b3-11d2-932e-00805f8add32)
+]
+interface nsIDOMUIEvent : nsIDOMEvent
+{
+ nsresult GetView(nsIDOMAbstractView **aView);
+ nsresult GetDetail(PRInt32 *aDetail);
+ nsresult InitUIEvent(const nsAString *typeArg, PRBool canBubbleArg, PRBool cancelableArg,
+ nsIDOMAbstractView *viewArg, PRInt32 detailArg);
+}
+
+[
+ object,
+ uuid(ff751edc-8b02-aae7-0010-8301838a3123)
+]
+interface nsIDOMMouseEvent : nsIDOMUIEvent
+{
+ nsresult GetScreenX(PRInt32 *aScreenX);
+ nsresult GetScreenY(PRInt32 *aScreenY);
+ nsresult GetClientX(PRInt32 *aClientX);
+ nsresult GetClientY(PRInt32 *aClientY);
+ nsresult GetCtrlKey(PRBool *aCtrlKey);
+ nsresult GetShiftKey(PRBool *aShiftKey);
+ nsresult GetAltKey(PRBool *aAltKey);
+ nsresult GetMetaKey(PRBool *aMetaKey);
+ nsresult GetButton(PRUint16 *aButton);
+ nsresult GetRelatedTarget(nsIDOMEventTarget * *aRelatedTarget);
+ nsresult InitMouseEvent(const nsAString *typeArg, PRBool canBubbleArg, PRBool cancelableArg,
+ nsIDOMAbstractView *viewArg, PRInt32 detailArg, PRInt32 screenXArg, PRInt32 screenYArg,
+ PRInt32 clientXArg, PRInt32 clientYArg, PRBool ctrlKeyArg, PRBool altKeyArg,
+ PRBool shiftKeyArg, PRBool metaKeyArg, PRUint16 buttonArg,
+ nsIDOMEventTarget *relatedTargetArg);
+}
diff --git a/dlls/mshtml/olewnd.c b/dlls/mshtml/olewnd.c
index c1fb1653858..896cdcb11be 100644
--- a/dlls/mshtml/olewnd.c
+++ b/dlls/mshtml/olewnd.c
@@ -255,6 +255,18 @@ static IOleInPlaceObjectWindowlessVtbl OleInPlaceObjectWindowlessVtbl = {
#undef INPLACEWIN_THIS
+void HTMLDocument_ShowContextMenu(HTMLDocument *This, DWORD dwID, POINT *ppt)
+{
+ HRESULT hres;
+
+ hres = IDocHostUIHandler_ShowContextMenu(This->hostui, dwID, ppt,
+ (IUnknown*)CMDTARGET(This), (IDispatch*)HTMLDOC(This));
+ if(hres == S_OK)
+ return;
+
+ FIXME("Show default context menu\n");
+}
+
void HTMLDocument_Window_Init(HTMLDocument *This)
{
This->lpOleInPlaceActiveObjectVtbl = &OleInPlaceActiveObjectVtbl;