Bug 161623 - Mac embedding APIs are burdensome compared to other platforms because the embeddor must create a top level nsIWidget instead of passing a native one. r=pink/sr=sfraser

This commit is contained in:
ccarlen%netscape.com 2003-06-16 14:59:23 +00:00
parent 5d58c9449f
commit 4de2ea650f
11 changed files with 218 additions and 881 deletions

View File

@ -68,6 +68,10 @@ EXTRA_DSO_LDOPTS= \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
ifeq (mac,$(MOZ_WIDGET_TOOLKIT))
EXTRA_DSO_LDOPTS += $(TK_LIBS)
endif
include $(topsrcdir)/config/rules.mk
INCLUDES += \

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,6 @@
#include "nsIHistoryEntry.h"
#include "nsISHEntry.h"
#include "nsISHistory.h"
#include "nsIWidget.h"
#include "nsIWebBrowserPrint.h"
#include "nsIMacTextInputEventSink.h"
#include "nsCRT.h"
@ -340,57 +339,6 @@ NS_IMETHODIMP CBrowserShell::CommonConstruct()
return NS_OK;
}
/**
* It is a necessary evil to create a top level window widget in order to
* have a parent for our nsIBaseWindow. In order to not put that responsibility
* onto the PowerPlant window which contains us, we do it ourselves here by
* creating the widget if it does not exist and storing it as a window property.
*/
NS_IMETHODIMP CBrowserShell::EnsureTopLevelWidget(nsIWidget **aWidget)
{
NS_ENSURE_ARG_POINTER(aWidget);
*aWidget = nsnull;
OSStatus err;
nsresult rv;
nsIWidget *widget = nsnull;
err = ::GetWindowProperty(GetMacWindow(), 'PPMZ', 'WIDG', sizeof(nsIWidget*), nsnull, (void*)&widget);
if (err == noErr && widget) {
*aWidget = widget;
NS_ADDREF(*aWidget);
return NS_OK;
}
// Create it with huge bounds. The actual bounds that matters is that of the
// nsIBaseWindow. The bounds of the top level widget clips its children so
// we just have to make sure it is big enough to always contain the children.
// Under 10.2, if this rect is too large, subwidget offsets can temporarily push the
// bounds over 32,727 and OffsetRgn() will silently fail. In order to avoid that, we
// err towards a local max of the size of the gray rgn.
nsCOMPtr<nsIWidget> newWidget(do_CreateInstance(kWindowCID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
RgnHandle grayRgn = ::GetGrayRgn();
Rect grayRect;
::GetRegionBounds(grayRgn, &grayRect);
nsRect r(0, 0, grayRect.right - grayRect.left, grayRect.bottom - grayRect.top);
rv = newWidget->Create(GetMacWindow(), r, nsnull, nsnull, nsnull, nsnull, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
widget = newWidget;
err = ::SetWindowProperty(GetMacWindow(), 'PPMZ', 'WIDG', sizeof(nsIWidget*), (void*)&widget);
if (err == noErr) {
*aWidget = newWidget;
NS_ADDREF(*aWidget);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//*****************************************************************************
//*** CBrowserShell: LPane overrides
@ -399,14 +347,6 @@ NS_IMETHODIMP CBrowserShell::EnsureTopLevelWidget(nsIWidget **aWidget)
void CBrowserShell::FinishCreateSelf()
{
FocusDraw();
nsCOMPtr<nsIWidget> aWidget;
ThrowIfError_(EnsureTopLevelWidget(getter_AddRefs(aWidget)));
// the widget is also our avenue for dispatching events into Gecko via
// nsIEventSink. Save this sink for later.
mEventSink = do_QueryInterface(aWidget);
ThrowIfNil_(mEventSink);
Rect portFrame;
CalcPortFrameRect(portFrame);
@ -414,8 +354,10 @@ void CBrowserShell::FinishCreateSelf()
nsresult rv;
mWebBrowserAsBaseWin->InitWindow(aWidget->GetNativeData(NS_NATIVE_WIDGET), nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->InitWindow(GetMacWindow(), nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->Create();
mEventSink = do_GetInterface(mWebBrowser);
ThrowIfNil_(mEventSink);
// Hook up our progress listener
nsWeakPtr weakling(dont_AddRef(NS_GetWeakReference((nsIWebProgressListener *)mProgressListener)));
@ -938,18 +880,6 @@ NS_METHOD CBrowserShell::SetWebBrowser(nsIWebBrowser* aBrowser)
FocusDraw();
/*
CBrowserWindow *ourWindow = dynamic_cast<CBrowserWindow*>(LWindow::FetchWindowObject(GetMacWindow()));
NS_ENSURE_TRUE(ourWindow, NS_ERROR_FAILURE);
nsCOMPtr<nsIWidget> aWidget;
ourWindow->GetWidget(getter_AddRefs(aWidget));
NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE);
*/
nsCOMPtr<nsIWidget> aWidget;
ThrowIfError_(EnsureTopLevelWidget(getter_AddRefs(aWidget)));
mWebBrowser = aBrowser;
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mWebBrowser));
@ -964,8 +894,10 @@ NS_METHOD CBrowserShell::SetWebBrowser(nsIWebBrowser* aBrowser)
CalcPortFrameRect(portFrame);
nsRect r(portFrame.left, portFrame.top, portFrame.right - portFrame.left, portFrame.bottom - portFrame.top);
mWebBrowserAsBaseWin->InitWindow(aWidget->GetNativeData(NS_NATIVE_WIDGET), nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->InitWindow(GetMacWindow(), nsnull, r.x, r.y, r.width, r.height);
mWebBrowserAsBaseWin->Create();
mEventSink = do_GetInterface(mWebBrowser);
ThrowIfNil_(mEventSink);
AdjustFrame();

View File

@ -195,7 +195,6 @@ protected:
NS_METHOD CommonConstruct();
NS_METHOD EnsureTopLevelWidget(nsIWidget **aWidget);
void HandleMouseMoved(const EventRecord& inMacEvent);
void AdjustFrame();

View File

@ -34,7 +34,6 @@
#include "nsIDOMDocument.h"
#include "nsIDOMWindowInternal.h"
#include "nsRect.h"
#include "nsIWidget.h"
#include "nsIWebProgressListener.h"
#include "CBrowserWindow.h"
@ -172,21 +171,6 @@ void CBrowserWindow::FinishCreateSelf()
StartBroadcasting();
}
// ---------------------------------------------------------------------------
// ¥ ShowSelf
// ---------------------------------------------------------------------------
void CBrowserWindow::ShowSelf()
{
Inherited::ShowSelf();
nsIWidget *widget = nsnull;
OSStatus err = ::GetWindowProperty(GetMacWindow(), 'PPMZ', 'WIDG', sizeof(nsIWidget*), nsnull, (void*)&widget);
if (err == noErr && widget)
widget->Show(PR_TRUE);
}
// ---------------------------------------------------------------------------
// ¥ ListenToMessage

View File

@ -60,8 +60,6 @@ public:
virtual void FinishCreateSelf();
virtual void ShowSelf();
virtual void ListenToMessage(MessageT inMessage,
void* ioParam);

View File

@ -71,7 +71,14 @@
#include "nsToolkitCompsCID.h"
#endif
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
#include <MacWindows.h>
#include "nsWidgetSupport.h"
#include "nsIEventSink.h"
#endif
static NS_DEFINE_CID(kWebShellCID, NS_WEB_SHELL_CID);
static NS_DEFINE_IID(kWindowCID, NS_WINDOW_CID);
static NS_DEFINE_CID(kChildCID, NS_CHILD_CID);
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
@ -93,6 +100,9 @@ nsWebBrowser::nsWebBrowser() : mDocShellTreeOwner(nsnull),
mParentWidget(nsnull),
mParent(nsnull),
mListenerArray(nsnull)
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
, mTopLevelWidget(nsnull)
#endif
{
mInitInfo = new nsWebBrowserInitInfo();
mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
@ -135,6 +145,10 @@ NS_IMETHODIMP nsWebBrowser::InternalDestroy()
mListenerArray = nsnull;
}
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
NS_IF_RELEASE(mTopLevelWidget);
#endif
return NS_OK;
}
@ -173,6 +187,11 @@ NS_IMETHODIMP nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink)
if(NS_SUCCEEDED(QueryInterface(aIID, aSink)))
return NS_OK;
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
if (aIID.Equals(NS_GET_IID(nsIEventSink)) && mTopLevelWidget)
return mTopLevelWidget->QueryInterface(NS_GET_IID(nsIEventSink), aSink);
#endif
if (mDocShell) {
if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
nsCOMPtr<nsIContentViewer> viewer;
@ -331,6 +350,40 @@ NS_IMETHODIMP nsWebBrowser::EnableGlobalHistory(PRBool aEnable)
return rv;
}
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
NS_IMETHODIMP nsWebBrowser::EnsureTopLevelWidget(nativeWindow aWindow)
{
WindowPtr macWindow = NS_STATIC_CAST(WindowPtr, aWindow);
nsIWidget *widget = nsnull;
nsCOMPtr<nsIWidget> newWidget;
nsresult rv = NS_ERROR_FAILURE;
::GetWindowProperty(macWindow, kTopLevelWidgetPropertyCreator,
kTopLevelWidgetRefPropertyTag, sizeof(nsIWidget*), nsnull, (void*)&widget);
if (!widget) {
newWidget = do_CreateInstance(kWindowCID, &rv);
if (NS_SUCCEEDED(rv)) {
// Create it with huge bounds. The actual bounds that matters is that of the
// nsIBaseWindow. The bounds of the top level widget clips its children so
// we just have to make sure it is big enough to always contain the children.
nsRect r(0, 0, 32000, 32000);
rv = newWidget->Create(macWindow, r, nsnull, nsnull, nsnull, nsnull, nsnull);
if (NS_SUCCEEDED(rv))
widget = newWidget;
}
}
NS_ASSERTION(widget, "Failed to get or create a toplevel widget!!");
if (widget) {
mTopLevelWidget = widget;
NS_ADDREF(mTopLevelWidget); // Allows multiple nsWebBrowsers to be in 1 window.
rv = NS_OK;
}
return rv;
}
#endif
NS_IMETHODIMP nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow)
{
NS_ENSURE_ARG_POINTER(aTopWindow);
@ -1292,8 +1345,14 @@ NS_IMETHODIMP nsWebBrowser::GetParentNativeWindow(nativeWindow* aParentNativeWin
NS_IMETHODIMP nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWindow)
{
NS_ENSURE_STATE(!mDocShell);
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
nsresult rv = EnsureTopLevelWidget(aParentNativeWindow);
NS_ENSURE_SUCCESS(rv, rv);
mParentNativeWindow = mTopLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
#else
mParentNativeWindow = aParentNativeWindow;
#endif
return NS_OK;
}

View File

@ -158,7 +158,13 @@ protected:
nsIWidget* mParentWidget;
nsIDocShellTreeItem* mParent;
nsVoidArray * mListenerArray;
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
NS_IMETHOD EnsureTopLevelWidget(nativeWindow aWindow);
nsIWidget* mTopLevelWidget;
#endif
};
#endif /* nsWebBrowser_h__ */

View File

@ -53,6 +53,7 @@
#include "nsRegionMac.h"
#include "nsIRollupListener.h"
#include "nsCRT.h"
#include "nsWidgetSupport.h"
#if TARGET_CARBON
#include <CFString.h>
@ -253,7 +254,10 @@ nsMacWindow::~nsMacWindow()
if (mustResetPort)
nsGraphicsUtils::SetPortToKnownGoodPort();
}
else if ( mWindowPtr && !mWindowMadeHere ) {
(void)::RemoveWindowProperty(mWindowPtr, kTopLevelWidgetPropertyCreator,
kTopLevelWidgetRefPropertyTag);
}
}
@ -478,6 +482,7 @@ nsresult nsMacWindow::StandardCreate(nsIWidget *aParent,
{
mWindowPtr = (WindowPtr)aNativeParent;
mWindowMadeHere = PR_FALSE;
mVisible = PR_TRUE;
}
if (mWindowPtr == nsnull)
@ -488,7 +493,9 @@ nsresult nsMacWindow::StandardCreate(nsIWidget *aParent,
// event handlers to get our widget or event sink when all they have
// is a native WindowPtr.
nsIWidget* temp = NS_STATIC_CAST(nsIWidget*, this);
OSStatus swpStatus = ::SetWindowProperty ( mWindowPtr, 'MOSS', 'GEKO', sizeof(nsIWidget*), &temp );
OSStatus swpStatus = ::SetWindowProperty ( mWindowPtr,
kTopLevelWidgetPropertyCreator, kTopLevelWidgetRefPropertyTag,
sizeof(nsIWidget*), &temp );
NS_ASSERTION ( swpStatus == noErr, "couldn't set a property on the window, event handling will fail" );
if ( swpStatus != noErr )
return NS_ERROR_FAILURE;

View File

@ -39,6 +39,7 @@
#include "nsIWidget.h"
#include "nsGUIEvent.h"
#include "nsWidgetAtoms.h"
#include "nsWidgetSupport.h"
#include <Gestalt.h>
#include <Appearance.h>
@ -390,7 +391,9 @@ void
nsToolkit::GetTopWidget ( WindowPtr aWindow, nsIWidget** outWidget )
{
nsIWidget* topLevelWidget = nsnull;
::GetWindowProperty ( aWindow, 'MOSS', 'GEKO', sizeof(nsIWidget*), nsnull, (void*)&topLevelWidget);
::GetWindowProperty ( aWindow,
kTopLevelWidgetPropertyCreator, kTopLevelWidgetRefPropertyTag,
sizeof(nsIWidget*), nsnull, (void*)&topLevelWidget);
if ( topLevelWidget ) {
*outWidget = topLevelWidget;
NS_ADDREF(*outWidget);

View File

@ -56,6 +56,16 @@ class nsICheckButton;
class nsITooltipWidget;
class nsITextWidget;
#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_COCOA)
// A top-level widget stores a reference to itself as a window property
// with the following creator and tag. These constants are used by embedding
// code in addition to widget code.
enum {
kTopLevelWidgetPropertyCreator = 'MOSS',
kTopLevelWidgetRefPropertyTag = 'GEKO'
};
#endif
// These are a series of support methods which help in the creation
// of widgets. They are not needed, but are provided as a convenience
// mechanism when creating widgets