1354 lines
35 KiB
C++
1354 lines
35 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public License
|
||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
* http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
* for the specific language governing rights and limitations under the
|
||
* NPL.
|
||
*
|
||
* The Initial Developer of this code under the NPL is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
|
||
|
||
// ***IMPORTANT***
|
||
// On all platforms, we are assuming in places that the implementation of |nsIWidget|
|
||
// is really |nsWindow| and then calling methods specific to nsWindow to finish the job.
|
||
// This is by design and the assumption is safe because an nsIWidget can only be created through
|
||
// our Widget factory where all our widgets, including the XP widgets, inherit from nsWindow.
|
||
// Still, in the places (or most of them) where this assumption is done, a |static_cast| has been used.
|
||
// A similar warning is in nsWidgetFactory.cpp.
|
||
|
||
|
||
#include "nsWindow.h"
|
||
#include "nsIFontMetrics.h"
|
||
#include "nsIDeviceContext.h"
|
||
#include "nsCOMPtr.h"
|
||
#include "nsToolkit.h"
|
||
#include "nsIEnumerator.h"
|
||
#include <Appearance.h>
|
||
|
||
#include "nsplugindefs.h"
|
||
#include "nsMacEventHandler.h"
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// nsWindow constructor
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this)
|
||
{
|
||
strcpy(gInstanceClassName, "nsWindow");
|
||
|
||
mParent = nsnull;
|
||
mBounds.SetRect(0,0,0,0);
|
||
|
||
mResizingChildren = PR_FALSE;
|
||
mVisible = PR_FALSE;
|
||
mEnabled = PR_TRUE;
|
||
SetPreferredSize(0,0);
|
||
|
||
mFontMetrics = nsnull;
|
||
mMenuBar = nsnull;
|
||
mTempRenderingContext = nsnull;
|
||
|
||
mWindowRegion = nsnull;
|
||
mVisRegion = nsnull;
|
||
mWindowPtr = nsnull;
|
||
mDrawing = PR_FALSE;
|
||
mDestroyCalled = PR_FALSE;
|
||
mDestructorCalled = PR_FALSE;
|
||
|
||
SetBackgroundColor(NS_RGB(255, 255, 255));
|
||
SetForegroundColor(NS_RGB(0, 0, 0));
|
||
|
||
mPluginPort = nsnull;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// nsWindow destructor
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
nsWindow::~nsWindow()
|
||
{
|
||
mDestructorCalled = PR_TRUE;
|
||
|
||
//Destroy();
|
||
|
||
if (mWindowRegion)
|
||
{
|
||
::DisposeRgn(mWindowRegion);
|
||
mWindowRegion = nsnull;
|
||
}
|
||
|
||
if (mVisRegion)
|
||
{
|
||
::DisposeRgn(mVisRegion);
|
||
mVisRegion = nsnull;
|
||
}
|
||
|
||
NS_IF_RELEASE(mTempRenderingContext);
|
||
|
||
NS_IF_RELEASE(mMenuBar);
|
||
NS_IF_RELEASE(mMenuListener);
|
||
|
||
if (mPluginPort) {
|
||
delete mPluginPort;
|
||
}
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Utility method for implementing both Create(nsIWidget ...) and
|
||
// Create(nsNativeWidget...)
|
||
//-------------------------------------------------------------------------
|
||
|
||
nsresult nsWindow::StandardCreate(nsIWidget *aParent,
|
||
const nsRect &aRect,
|
||
EVENT_CALLBACK aHandleEventFunction,
|
||
nsIDeviceContext *aContext,
|
||
nsIAppShell *aAppShell,
|
||
nsIToolkit *aToolkit,
|
||
nsWidgetInitData *aInitData,
|
||
nsNativeWidget aNativeParent) // should always be nil here
|
||
{
|
||
mParent = aParent;
|
||
mBounds = aRect;
|
||
CalcWindowRegions();
|
||
|
||
BaseCreate(aParent, aRect, aHandleEventFunction,
|
||
aContext, aAppShell, aToolkit, aInitData);
|
||
|
||
if (mParent)
|
||
{
|
||
SetBackgroundColor(mParent->GetBackgroundColor());
|
||
SetForegroundColor(mParent->GetForegroundColor());
|
||
}
|
||
|
||
if (mWindowPtr == nsnull) {
|
||
if (aParent)
|
||
mWindowPtr = (WindowPtr)aParent->GetNativeData(NS_NATIVE_DISPLAY);
|
||
else if (aAppShell)
|
||
mWindowPtr = (WindowPtr)aAppShell->GetNativeData(NS_NATIVE_SHELL);
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// create a nswindow
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Create(nsIWidget *aParent,
|
||
const nsRect &aRect,
|
||
EVENT_CALLBACK aHandleEventFunction,
|
||
nsIDeviceContext *aContext,
|
||
nsIAppShell *aAppShell,
|
||
nsIToolkit *aToolkit,
|
||
nsWidgetInitData *aInitData)
|
||
{
|
||
return(StandardCreate(aParent, aRect, aHandleEventFunction,
|
||
aContext, aAppShell, aToolkit, aInitData,
|
||
nsnull));
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Creates a main nsWindow using a native widget
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Create(nsNativeWidget aNativeParent, // this is a nsWindow*
|
||
const nsRect &aRect,
|
||
EVENT_CALLBACK aHandleEventFunction,
|
||
nsIDeviceContext *aContext,
|
||
nsIAppShell *aAppShell,
|
||
nsIToolkit *aToolkit,
|
||
nsWidgetInitData *aInitData)
|
||
{
|
||
// On Mac, a native widget is a nsWindow* because
|
||
// nsWindow::GetNativeData(NS_NATIVE_WIDGET) returns 'this'
|
||
nsIWidget* aParent = (nsIWidget*)aNativeParent;
|
||
|
||
return(Create(aParent, aRect, aHandleEventFunction,
|
||
aContext, aAppShell, aToolkit, aInitData));
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Close this nsWindow
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Destroy()
|
||
{
|
||
if (mDestroyCalled)
|
||
return NS_OK;
|
||
mDestroyCalled = PR_TRUE;
|
||
|
||
nsBaseWidget::OnDestroy();
|
||
nsBaseWidget::Destroy();
|
||
|
||
NS_IF_RELEASE(mMenuBar);
|
||
SetMenuBar(nsnull);
|
||
|
||
ReportDestroyEvent(); // beard: this seems to cause the window to be deleted. moved all release code to destructor.
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
#pragma mark -
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Get this nsWindow parent
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
nsIWidget* nsWindow::GetParent(void)
|
||
{
|
||
NS_IF_ADDREF(mParent);
|
||
return mParent;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Return some native data according to aDataType
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
void* nsWindow::GetNativeData(PRUint32 aDataType)
|
||
{
|
||
nsPoint point;
|
||
void* retVal = nsnull;
|
||
|
||
switch (aDataType)
|
||
{
|
||
case NS_NATIVE_WIDGET:
|
||
case NS_NATIVE_WINDOW:
|
||
retVal = (void*)this;
|
||
break;
|
||
|
||
case NS_NATIVE_GRAPHIC:
|
||
case NS_NATIVE_DISPLAY:
|
||
retVal = (void*)mWindowPtr;
|
||
break;
|
||
|
||
case NS_NATIVE_REGION:
|
||
// retVal = (void*)mWindowRegion;
|
||
retVal = (void*)mVisRegion;
|
||
break;
|
||
|
||
case NS_NATIVE_COLORMAP:
|
||
//<2F>TODO
|
||
break;
|
||
|
||
case NS_NATIVE_OFFSETX:
|
||
point.MoveTo(mBounds.x, mBounds.y);
|
||
LocalToWindowCoordinate(point);
|
||
retVal = (void*)point.x;
|
||
break;
|
||
|
||
case NS_NATIVE_OFFSETY:
|
||
point.MoveTo(mBounds.x, mBounds.y);
|
||
LocalToWindowCoordinate(point);
|
||
retVal = (void*)point.y;
|
||
break;
|
||
|
||
case NS_NATIVE_PLUGIN_PORT:
|
||
// this needs to be a combination of the port and the offsets.
|
||
if (mPluginPort == nsnull)
|
||
mPluginPort = new nsPluginPort;
|
||
|
||
point.MoveTo(mBounds.x, mBounds.y);
|
||
LocalToWindowCoordinate(point);
|
||
|
||
// for compatibility with 4.X, this origin is what you'd pass
|
||
// to SetOrigin.
|
||
mPluginPort->port = CGrafPtr(mWindowPtr);
|
||
mPluginPort->portx = -point.x;
|
||
mPluginPort->porty = -point.y;
|
||
|
||
retVal = (void*)mPluginPort;
|
||
}
|
||
|
||
return retVal;
|
||
}
|
||
|
||
#pragma mark -
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_METHOD nsWindow::IsVisible(PRBool & bState)
|
||
{
|
||
bState = mVisible;
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Hide or show this component
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Show(PRBool bState)
|
||
{
|
||
mVisible = bState;
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Enable/disable this component
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Enable(PRBool bState)
|
||
{
|
||
mEnabled = bState;
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Set the focus on this component
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::SetFocus(void)
|
||
{
|
||
if (mToolkit)
|
||
((nsToolkit*)mToolkit)->SetFocus(this);
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Get this component font
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
nsIFontMetrics* nsWindow::GetFont(void)
|
||
{
|
||
return mFontMetrics;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Set this component font
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::SetFont(const nsFont &aFont)
|
||
{
|
||
NS_IF_RELEASE(mFontMetrics);
|
||
if (mContext)
|
||
mContext->GetMetricsFor(aFont, mFontMetrics);
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Set the colormap of the window
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::SetColorMap(nsColorMap *aColorMap)
|
||
{
|
||
//<2F>TODO
|
||
// We may need to move this to nsMacWindow:
|
||
// I'm not sure all the individual widgets
|
||
// can have each their own colorMap on Mac.
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Set the widget's MenuBar.
|
||
// Must be called after Create.
|
||
// Releases a previously set nsIMenuBar
|
||
// AddRefs the passed in nsIMenuBar
|
||
// @param aMenuBar a pointer to an nsIMenuBar interface on an object
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::SetMenuBar(nsIMenuBar * aMenuBar)
|
||
{
|
||
if (mMenuBar)
|
||
mMenuBar->SetParent(nsnull);
|
||
NS_IF_RELEASE(mMenuBar);
|
||
NS_IF_ADDREF(aMenuBar);
|
||
mMenuBar = aMenuBar;
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Get the widget's MenuBar.
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
nsIMenuBar* nsWindow::GetMenuBar()
|
||
{
|
||
return mMenuBar;
|
||
}
|
||
|
||
|
||
//
|
||
// SetCursor
|
||
//
|
||
// Override to set the cursor on the mac
|
||
//
|
||
NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
|
||
{
|
||
nsBaseWidget::SetCursor(aCursor);
|
||
|
||
// mac specific cursor manipulation
|
||
//<2F>TODO: We need a way to get non-os cursors here.
|
||
if (nsToolkit::HasAppearanceManager())
|
||
{
|
||
short cursor = -1;
|
||
switch (aCursor)
|
||
{
|
||
case eCursor_standard: cursor = kThemeArrowCursor; break;
|
||
case eCursor_wait: cursor = kThemeWatchCursor; break;
|
||
case eCursor_select: cursor = kThemeIBeamCursor; break;
|
||
case eCursor_hyperlink: cursor = kThemePointingHandCursor; break;
|
||
case eCursor_sizeWE: cursor = kThemeResizeLeftRightCursor; break;
|
||
case eCursor_sizeNS: cursor = kThemeResizeLeftRightCursor; break; //<2F>TODO: bad id
|
||
}
|
||
if (cursor >= 0)
|
||
::SetThemeCursor(cursor);
|
||
}
|
||
else
|
||
{
|
||
short cursor = -1;
|
||
switch (aCursor)
|
||
{
|
||
case eCursor_standard: ::InitCursor(); break;
|
||
case eCursor_wait: cursor = watchCursor; break;
|
||
case eCursor_select: cursor = iBeamCursor; break;
|
||
case eCursor_hyperlink: cursor = plusCursor; break;
|
||
}
|
||
if (cursor > 0)
|
||
::SetCursor(*(::GetCursor(cursor)));
|
||
}
|
||
|
||
return NS_OK;
|
||
|
||
} // nsWindow :: SetCursor
|
||
|
||
|
||
#pragma mark -
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Get this component dimension
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::GetBounds(nsRect &aRect)
|
||
{
|
||
aRect = mBounds;
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Move this component
|
||
// aX and aY are in the parent widget coordinate system
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Move(PRUint32 aX, PRUint32 aY)
|
||
{
|
||
if ((mBounds.x != aX) || (mBounds.y != aY))
|
||
{
|
||
// Invalidate the current location (unless it's the top-level window)
|
||
if (mParent != nsnull)
|
||
Invalidate(PR_FALSE);
|
||
|
||
// Set the bounds
|
||
mBounds.x = aX;
|
||
mBounds.y = aY;
|
||
|
||
// Recalculate the regions
|
||
CalcWindowRegions();
|
||
|
||
// Report the event
|
||
ReportMoveEvent();
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Resize this component
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Resize(PRUint32 aWidth, PRUint32 aHeight, PRBool aRepaint)
|
||
{
|
||
if ((mBounds.width != aWidth) || (mBounds.height != aHeight))
|
||
{
|
||
// Set the bounds
|
||
mBounds.width = aWidth;
|
||
mBounds.height = aHeight;
|
||
|
||
// Recalculate the regions
|
||
CalcWindowRegions();
|
||
|
||
// Invalidate the new location
|
||
if (aRepaint)
|
||
Invalidate(PR_FALSE);
|
||
|
||
// Report the event
|
||
ReportSizeEvent();
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Resize this component
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Resize(PRUint32 aX, PRUint32 aY, PRUint32 aWidth, PRUint32 aHeight, PRBool aRepaint)
|
||
{
|
||
nsWindow::Move(aX, aY);
|
||
nsWindow::Resize(aWidth, aHeight, aRepaint);
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
NS_METHOD nsWindow::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
|
||
{
|
||
aWidth = mPreferredWidth;
|
||
aHeight = mPreferredHeight;
|
||
return NS_ERROR_FAILURE;
|
||
}
|
||
|
||
NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
|
||
{
|
||
mPreferredWidth = aWidth;
|
||
mPreferredHeight = aHeight;
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::BeginResizingChildren(void)
|
||
{
|
||
mResizingChildren = PR_TRUE;
|
||
mSaveVisible = mVisible;
|
||
mVisible = PR_FALSE;
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::EndResizingChildren(void)
|
||
{
|
||
mResizingChildren = PR_FALSE;
|
||
mVisible = mSaveVisible;
|
||
|
||
CalcWindowRegions();
|
||
return NS_OK;
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Invalidate this component visible area
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Invalidate(const nsRect &aRect, PRBool aIsSynchronous)
|
||
{
|
||
if (!mWindowPtr)
|
||
return NS_OK;
|
||
|
||
#if 0 // We don't want to draw synchronously on Mac: it makes the xpfe apps much slower
|
||
static PRBool reentrant = PR_FALSE;
|
||
if (aIsSynchronous && !reentrant)
|
||
{
|
||
reentrant = PR_TRUE; // no reentrance please
|
||
Update();
|
||
reentrant = PR_FALSE;
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
nsRect wRect = aRect;
|
||
Rect macRect;
|
||
LocalToWindowCoordinate(wRect);
|
||
nsRectToMacRect(wRect, macRect);
|
||
|
||
GrafPtr savePort;
|
||
::GetPort(&savePort);
|
||
::SetPort(mWindowPtr);
|
||
Rect savePortRect = mWindowPtr->portRect;
|
||
::SetOrigin(0, 0);
|
||
::InvalRect(&macRect);
|
||
//<2F>REVISIT ::SetOrigin(savePortRect.left, savePortRect.top);
|
||
::SetPort(savePort);
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Invalidate this component visible area
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Invalidate(PRBool aIsSynchronous)
|
||
{
|
||
nsWindow::Invalidate(mBounds, aIsSynchronous);
|
||
return NS_OK;
|
||
}
|
||
|
||
inline PRUint16 COLOR8TOCOLOR16(PRUint8 color8)
|
||
{
|
||
// return (color8 == 0xFF ? 0xFFFF : (color8 << 8));
|
||
return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
// StartDraw
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
void nsWindow::StartDraw(nsIRenderingContext* aRenderingContext)
|
||
{
|
||
if (mDrawing)
|
||
return;
|
||
mDrawing = PR_TRUE;
|
||
|
||
CalcWindowRegions(); //<2F>REVISIT
|
||
|
||
if (aRenderingContext == nsnull)
|
||
{
|
||
// make sure we have a rendering context
|
||
mTempRenderingContext = GetRenderingContext();
|
||
mTempRenderingContextMadeHere = PR_TRUE;
|
||
}
|
||
else
|
||
{
|
||
// if we already have a rendering context, save its state
|
||
NS_IF_ADDREF(aRenderingContext);
|
||
mTempRenderingContext = aRenderingContext;
|
||
mTempRenderingContextMadeHere = PR_FALSE;
|
||
mTempRenderingContext->PushState();
|
||
|
||
// set the environment to the current widget
|
||
mTempRenderingContext->Init(mContext, this);
|
||
}
|
||
|
||
// set the widget font. nsMacControl implements SetFont, which is where
|
||
// the font should get set.
|
||
if (mFontMetrics)
|
||
{
|
||
mTempRenderingContext->SetFont(mFontMetrics);
|
||
}
|
||
|
||
// set the widget background and foreground colors
|
||
nscolor color = GetBackgroundColor();
|
||
RGBColor macColor;
|
||
macColor.red = COLOR8TOCOLOR16(NS_GET_R(color));
|
||
macColor.green = COLOR8TOCOLOR16(NS_GET_G(color));
|
||
macColor.blue = COLOR8TOCOLOR16(NS_GET_B(color));
|
||
::RGBBackColor(&macColor);
|
||
|
||
color = GetForegroundColor();
|
||
macColor.red = COLOR8TOCOLOR16(NS_GET_R(color));
|
||
macColor.green = COLOR8TOCOLOR16(NS_GET_G(color));
|
||
macColor.blue = COLOR8TOCOLOR16(NS_GET_B(color));
|
||
::RGBForeColor(&macColor);
|
||
|
||
mTempRenderingContext->SetColor(color); // just in case, set the rendering context color too
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
// EndDraw
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
void nsWindow::EndDraw()
|
||
{
|
||
if (! mDrawing)
|
||
return;
|
||
mDrawing = PR_FALSE;
|
||
|
||
if (mTempRenderingContextMadeHere)
|
||
{
|
||
PRBool clipEmpty;
|
||
mTempRenderingContext->PopState(clipEmpty);
|
||
}
|
||
NS_RELEASE(mTempRenderingContext);
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::OnPaint(nsPaintEvent &event)
|
||
{
|
||
// override this
|
||
return PR_TRUE;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
// Update
|
||
//
|
||
// Redraw this widget.
|
||
//
|
||
// We draw the widget between BeginUpdate and EndUpdate because some
|
||
// operations go much faster when the visRgn contains what needs to be
|
||
// painted. Then we restore the original updateRgn and validate this
|
||
// widget's rectangle.
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Update()
|
||
{
|
||
if (! mVisible)
|
||
return NS_OK;
|
||
|
||
static PRBool reentrant = PR_FALSE;
|
||
|
||
if (reentrant)
|
||
HandleUpdateEvent();
|
||
else
|
||
{
|
||
reentrant = PR_TRUE;
|
||
|
||
// make a copy of the window update rgn
|
||
RgnHandle saveUpdateRgn = ::NewRgn();
|
||
if (!saveUpdateRgn)
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
::CopyRgn(((WindowRecord*)mWindowPtr)->updateRgn, saveUpdateRgn);
|
||
|
||
// draw the widget
|
||
GrafPtr savePort;
|
||
::GetPort(&savePort);
|
||
::SetPort(mWindowPtr);
|
||
|
||
::BeginUpdate(mWindowPtr);
|
||
HandleUpdateEvent();
|
||
::EndUpdate(mWindowPtr);
|
||
|
||
// restore the window update rgn
|
||
::CopyRgn(saveUpdateRgn, ((WindowRecord*)mWindowPtr)->updateRgn);
|
||
|
||
// validate the rect of the widget we have just drawn
|
||
nsRect bounds = mBounds;
|
||
LocalToWindowCoordinate(bounds);
|
||
Rect macRect;
|
||
nsRectToMacRect(bounds, macRect);
|
||
::ValidRect(&macRect);
|
||
::DisposeRgn(saveUpdateRgn);
|
||
|
||
::SetPort(savePort);
|
||
reentrant = PR_FALSE;
|
||
}
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
// HandleUpdateEvent
|
||
//
|
||
// Called by the event handler to redraw the top-level widget.
|
||
// Must be called between BeginUpdate/EndUpdate: the window visRgn
|
||
// is expected to be set to whatever needs to be drawn.
|
||
//-------------------------------------------------------------------------
|
||
nsresult nsWindow::HandleUpdateEvent()
|
||
{
|
||
if (! mVisible)
|
||
return NS_OK;
|
||
|
||
// get the damaged region from the OS
|
||
RgnHandle damagedRgn = mWindowPtr->visRgn;
|
||
|
||
// calculate the update region relatively to the window port rect
|
||
// (at this point, the grafPort origin should always be 0,0
|
||
// so mWindowRegion has to be converted to window coordinates)
|
||
RgnHandle updateRgn = ::NewRgn();
|
||
if (!updateRgn)
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
::CopyRgn(mWindowRegion, updateRgn);
|
||
|
||
nsRect bounds = mBounds;
|
||
LocalToWindowCoordinate(bounds);
|
||
::OffsetRgn(updateRgn, bounds.x, bounds.y);
|
||
|
||
// check if the update region is visible
|
||
::SectRgn(damagedRgn, updateRgn, updateRgn);
|
||
if (!::EmptyRgn(updateRgn))
|
||
{
|
||
nsIRenderingContext* renderingContext = GetRenderingContext();
|
||
if (renderingContext)
|
||
{
|
||
// determine the rect to draw
|
||
nsRect rect;
|
||
Rect macRect = (*updateRgn)->rgnBBox;
|
||
::OffsetRect(&macRect, -bounds.x, -bounds.y);
|
||
rect.SetRect(macRect.left, macRect.top, macRect.right - macRect.left, macRect.bottom - macRect.top);
|
||
|
||
// update the widget
|
||
UpdateWidget(rect, renderingContext);
|
||
|
||
NS_RELEASE(renderingContext);
|
||
}
|
||
}
|
||
::DisposeRgn(updateRgn);
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
|
||
{
|
||
if (! mVisible)
|
||
return;
|
||
|
||
// initialize the paint event
|
||
nsPaintEvent paintEvent;
|
||
paintEvent.eventStructType = NS_PAINT_EVENT; // nsEvent
|
||
paintEvent.message = NS_PAINT;
|
||
paintEvent.widget = this; // nsGUIEvent
|
||
paintEvent.nativeMsg = NULL;
|
||
paintEvent.renderingContext = aContext; // nsPaintEvent
|
||
paintEvent.rect = &aRect;
|
||
|
||
// draw the widget
|
||
StartDraw(aContext);
|
||
if (OnPaint(paintEvent))
|
||
DispatchWindowEvent(paintEvent);
|
||
EndDraw();
|
||
|
||
// recursively draw the children
|
||
nsCOMPtr<nsIEnumerator> children(dont_AddRef(GetChildren()));
|
||
if (children)
|
||
{
|
||
children->First();
|
||
do
|
||
{
|
||
nsISupports* child;
|
||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||
{
|
||
nsWindow* childWindow = static_cast<nsWindow*>(child);
|
||
NS_RELEASE(child);
|
||
|
||
nsRect childBounds;
|
||
childWindow->GetBounds(childBounds);
|
||
|
||
// redraw only the intersection of the child rect and the update rect
|
||
nsRect intersection;
|
||
if (intersection.IntersectRect(aRect, childBounds))
|
||
{
|
||
intersection.MoveBy(-childBounds.x, -childBounds.y);
|
||
childWindow->UpdateWidget(intersection, aContext);
|
||
}
|
||
}
|
||
} while (NS_SUCCEEDED(children->Next()));
|
||
}
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Scroll the bits of a window
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
||
{
|
||
if (! mVisible)
|
||
return NS_OK;
|
||
|
||
#if 0 //<2F>REVISIT
|
||
// scroll the rect
|
||
nsRect scrollRect;
|
||
if (aClipRect)
|
||
scrollRect = *aClipRect;
|
||
else
|
||
{
|
||
scrollRect = mBounds;
|
||
scrollRect.x = scrollRect.y = 0;
|
||
}
|
||
|
||
Rect macRect;
|
||
nsRectToMacRect(scrollRect, macRect);
|
||
|
||
RgnHandle updateRgn = ::NewRgn();
|
||
if (updateRgn == nil)
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
|
||
StartDraw();
|
||
::ScrollRect(&macRect, aDx, aDy, updateRgn);
|
||
::InvalRgn(updateRgn);
|
||
::DisposeRgn(updateRgn);
|
||
EndDraw();
|
||
#else
|
||
Invalidate(PR_FALSE);
|
||
#endif
|
||
|
||
// scroll the children
|
||
nsCOMPtr<nsIEnumerator> children(dont_AddRef(GetChildren()));
|
||
if (children)
|
||
{
|
||
children->First();
|
||
do
|
||
{
|
||
nsISupports* child;
|
||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||
{
|
||
nsWindow* childWindow = static_cast<nsWindow*>(child);
|
||
NS_RELEASE(child);
|
||
|
||
nsRect bounds;
|
||
childWindow->GetBounds(bounds);
|
||
bounds.x += aDx;
|
||
bounds.y += aDy;
|
||
childWindow->SetBounds(bounds);
|
||
childWindow->Scroll(aDx, aDy, &bounds);
|
||
}
|
||
} while (NS_SUCCEEDED(children->Next()));
|
||
}
|
||
|
||
// recalculate the window regions
|
||
CalcWindowRegions();
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
|
||
PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
|
||
{
|
||
switch (aStatus)
|
||
{
|
||
case nsEventStatus_eIgnore: return(PR_FALSE);
|
||
case nsEventStatus_eConsumeNoDefault: return(PR_TRUE); // don't do default processing
|
||
case nsEventStatus_eConsumeDoDefault: return(PR_FALSE);
|
||
default:
|
||
NS_ASSERTION(0, "Illegal nsEventStatus enumeration value");
|
||
break;
|
||
}
|
||
return(PR_FALSE);
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Invokes callback and ProcessEvent method on Event Listener object
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
||
{
|
||
aStatus = nsEventStatus_eIgnore;
|
||
if (! mDestructorCalled)
|
||
{
|
||
nsIWidget* aWidget = event->widget;
|
||
NS_IF_ADDREF(aWidget);
|
||
|
||
if (nsnull != mMenuListener){
|
||
if(NS_MENU_EVENT == event->eventStructType)
|
||
aStatus = mMenuListener->MenuSelected( static_cast<nsMenuEvent&>(*event) );
|
||
}
|
||
if (mEventCallback)
|
||
aStatus = (*mEventCallback)(event);
|
||
|
||
// Dispatch to event listener if event was not consumed
|
||
if ((aStatus != nsEventStatus_eConsumeNoDefault) && (mEventListener != nsnull))
|
||
aStatus = mEventListener->ProcessEvent(*event);
|
||
|
||
NS_IF_RELEASE(aWidget);
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::DispatchWindowEvent(nsGUIEvent &event)
|
||
{
|
||
nsEventStatus status;
|
||
DispatchEvent(&event, status);
|
||
return ConvertStatus(status);
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
// Deal with all sort of mouse event
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::DispatchMouseEvent(nsMouseEvent &aEvent)
|
||
{
|
||
|
||
PRBool result = PR_FALSE;
|
||
if (nsnull == mEventCallback && nsnull == mMouseListener) {
|
||
return result;
|
||
}
|
||
|
||
// call the event callback
|
||
if (nsnull != mEventCallback)
|
||
{
|
||
result = (DispatchWindowEvent(aEvent));
|
||
return result;
|
||
}
|
||
|
||
if (nsnull != mMouseListener) {
|
||
switch (aEvent.message) {
|
||
case NS_MOUSE_MOVE: {
|
||
result = ConvertStatus(mMouseListener->MouseMoved(aEvent));
|
||
nsRect rect;
|
||
GetBounds(rect);
|
||
if (rect.Contains(aEvent.point.x, aEvent.point.y))
|
||
{
|
||
//if (mWindowPtr == NULL || mWindowPtr != this)
|
||
//{
|
||
printf("Mouse enter");
|
||
//mCurrentWindow = this;
|
||
//}
|
||
}
|
||
else
|
||
{
|
||
printf("Mouse exit");
|
||
}
|
||
|
||
} break;
|
||
|
||
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
||
case NS_MOUSE_MIDDLE_BUTTON_DOWN:
|
||
case NS_MOUSE_RIGHT_BUTTON_DOWN:
|
||
result = ConvertStatus(mMouseListener->MousePressed(aEvent));
|
||
break;
|
||
|
||
case NS_MOUSE_LEFT_BUTTON_UP:
|
||
case NS_MOUSE_MIDDLE_BUTTON_UP:
|
||
case NS_MOUSE_RIGHT_BUTTON_UP:
|
||
result = ConvertStatus(mMouseListener->MouseReleased(aEvent));
|
||
result = ConvertStatus(mMouseListener->MouseClicked(aEvent));
|
||
break;
|
||
} // switch
|
||
}
|
||
return result;
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::ReportDestroyEvent()
|
||
{
|
||
// nsEvent
|
||
nsGUIEvent moveEvent;
|
||
moveEvent.eventStructType = NS_GUI_EVENT;
|
||
moveEvent.message = NS_DESTROY;
|
||
moveEvent.point.x = 0;
|
||
moveEvent.point.y = 0;
|
||
moveEvent.time = PR_IntervalNow();
|
||
|
||
// nsGUIEvent
|
||
moveEvent.widget = this;
|
||
moveEvent.nativeMsg = nsnull;
|
||
|
||
// dispatch event
|
||
return (DispatchWindowEvent(moveEvent));
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::ReportMoveEvent()
|
||
{
|
||
// nsEvent
|
||
nsGUIEvent moveEvent;
|
||
moveEvent.eventStructType = NS_GUI_EVENT;
|
||
moveEvent.message = NS_MOVE;
|
||
moveEvent.point.x = mBounds.x;
|
||
moveEvent.point.y = mBounds.y;
|
||
moveEvent.time = PR_IntervalNow();
|
||
|
||
// nsGUIEvent
|
||
moveEvent.widget = this;
|
||
moveEvent.nativeMsg = nsnull;
|
||
|
||
// dispatch event
|
||
return (DispatchWindowEvent(moveEvent));
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::ReportSizeEvent()
|
||
{
|
||
// nsEvent
|
||
nsSizeEvent sizeEvent;
|
||
sizeEvent.eventStructType = NS_SIZE_EVENT;
|
||
sizeEvent.message = NS_SIZE;
|
||
sizeEvent.point.x = 0;
|
||
sizeEvent.point.y = 0;
|
||
sizeEvent.time = PR_IntervalNow();
|
||
|
||
// nsGUIEvent
|
||
sizeEvent.widget = this;
|
||
sizeEvent.nativeMsg = nsnull;
|
||
|
||
// nsSizeEvent
|
||
sizeEvent.windowSize = &mBounds;
|
||
sizeEvent.mWinWidth = mBounds.width;
|
||
sizeEvent.mWinHeight = mBounds.height;
|
||
|
||
// dispatch event
|
||
return(DispatchWindowEvent(sizeEvent));
|
||
}
|
||
|
||
|
||
|
||
#pragma mark -
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
void nsWindow::CalcWindowRegions()
|
||
{
|
||
//------
|
||
// calculate the window region
|
||
if (mWindowRegion == nsnull)
|
||
{
|
||
mWindowRegion = ::NewRgn();
|
||
if (mWindowRegion == nsnull)
|
||
return;
|
||
}
|
||
::SetRectRgn(mWindowRegion, 0, 0, mBounds.width, mBounds.height);
|
||
|
||
|
||
//------
|
||
// calculate the visible region
|
||
if (mVisRegion == nsnull)
|
||
{
|
||
mVisRegion = ::NewRgn();
|
||
if (mVisRegion == nsnull)
|
||
return;
|
||
}
|
||
::CopyRgn(mWindowRegion, mVisRegion);
|
||
|
||
// intersect with all the parents
|
||
nsWindow* parent = (nsWindow*)mParent;
|
||
nsPoint origin(-mBounds.x, -mBounds.y);
|
||
while (parent)
|
||
{
|
||
if (parent->mWindowRegion)
|
||
{
|
||
::OffsetRgn(parent->mWindowRegion, origin.x, origin.y);
|
||
::SectRgn(mVisRegion, parent->mWindowRegion, mVisRegion);
|
||
::OffsetRgn(parent->mWindowRegion, -origin.x, -origin.y);
|
||
}
|
||
origin.x -= parent->mBounds.x;
|
||
origin.y -= parent->mBounds.y;
|
||
parent = (nsWindow*)parent->mParent;
|
||
}
|
||
|
||
// clip the children out of the visRgn
|
||
RgnHandle childRgn = ::NewRgn();
|
||
if (!childRgn) return;
|
||
|
||
nsCOMPtr<nsIEnumerator> children(dont_AddRef(GetChildren()));
|
||
if (children)
|
||
{
|
||
children->First();
|
||
do
|
||
{
|
||
nsISupports* child;
|
||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||
{
|
||
nsWindow* childWindow = static_cast<nsWindow*>(child);
|
||
NS_RELEASE(child);
|
||
|
||
nsRect childRect;
|
||
childWindow->GetBounds(childRect);
|
||
|
||
Rect macRect;
|
||
::SetRect(&macRect, childRect.x, childRect.y, childRect.XMost(), childRect.YMost());
|
||
::RectRgn(childRgn, &macRect);
|
||
::DiffRgn(mVisRegion, childRgn, mVisRegion);
|
||
}
|
||
} while (NS_SUCCEEDED(children->Next()));
|
||
}
|
||
::DisposeRgn(childRgn);
|
||
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
/*
|
||
* @update dc 08/28/98
|
||
* @param aTheRegion -- The region to intersect with for this widget
|
||
* @return PR_TRUE if the these regions intersect
|
||
*/
|
||
|
||
PRBool nsWindow::RgnIntersects(RgnHandle aTheRegion, RgnHandle aIntersectRgn)
|
||
{
|
||
::SectRgn(aTheRegion, this->mWindowRegion, aIntersectRgn);
|
||
return (::EmptyRgn(aIntersectRgn) != false);
|
||
}
|
||
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
/* Calculate the x and y offsets for this particular widget
|
||
* @update ps 09/22/98
|
||
* @param aX -- x offset amount
|
||
* @param aY -- y offset amount
|
||
* @return NOTHING
|
||
*/
|
||
NS_IMETHODIMP nsWindow::CalcOffset(PRInt32 &aX,PRInt32 &aY)
|
||
{
|
||
aX = aY = 0;
|
||
nsIWidget* grandParent;
|
||
nsIWidget* theParent = this->GetParent();
|
||
while (theParent)
|
||
{
|
||
nsRect theRect;
|
||
theParent->GetBounds(theRect);
|
||
aX += theRect.x;
|
||
aY += theRect.y;
|
||
|
||
grandParent = theParent->GetParent();
|
||
NS_IF_RELEASE(theParent);
|
||
theParent = grandParent;
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
// PointInWidget
|
||
// Find if a point in local coordinates is inside this object
|
||
//-------------------------------------------------------------------------
|
||
PRBool nsWindow::PointInWidget(Point aThePoint)
|
||
{
|
||
// get the origin in local coordinates
|
||
nsPoint widgetOrigin(0, 0);
|
||
LocalToWindowCoordinate(widgetOrigin);
|
||
|
||
// get rectangle relatively to the parent
|
||
nsRect widgetRect;
|
||
GetBounds(widgetRect);
|
||
|
||
// convert the topLeft corner to local coordinates
|
||
widgetRect.MoveBy(widgetOrigin.x, widgetOrigin.y);
|
||
|
||
// finally tell whether it's a hit
|
||
return(widgetRect.Contains(aThePoint.h, aThePoint.v));
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------
|
||
// FindWidgetHit
|
||
// Recursively look for the widget hit
|
||
// @param aParent -- parent widget.
|
||
// @param aThePoint -- a point in local coordinates to test for the hit.
|
||
//-------------------------------------------------------------------------
|
||
nsWindow* nsWindow::FindWidgetHit(Point aThePoint)
|
||
{
|
||
if (!mVisible || !PointInWidget(aThePoint))
|
||
return nsnull;
|
||
|
||
nsWindow* widgetHit = this;
|
||
|
||
nsIBidirectionalEnumerator* children = static_cast<nsIBidirectionalEnumerator*>(GetChildren());
|
||
if (children)
|
||
{
|
||
// traverse through all the nsWindows to find out who got hit, lowest level of course
|
||
children->Last();
|
||
do
|
||
{
|
||
nsISupports* child;
|
||
if (NS_SUCCEEDED(children->CurrentItem(&child)))
|
||
{
|
||
nsWindow* childWindow = static_cast<nsWindow*>(child);
|
||
NS_RELEASE(child);
|
||
|
||
nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint);
|
||
if (deeperHit)
|
||
{
|
||
widgetHit = deeperHit;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
while (NS_SUCCEEDED(children->Prev()));
|
||
NS_RELEASE(children);
|
||
}
|
||
|
||
return widgetHit;
|
||
}
|
||
|
||
#pragma mark -
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
|
||
{
|
||
NS_NOTYETIMPLEMENTED("nsWindow::WidgetToScreen");
|
||
return NS_OK;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------
|
||
//
|
||
//
|
||
//
|
||
//-------------------------------------------------------------------------
|
||
NS_IMETHODIMP nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
|
||
{
|
||
NS_NOTYETIMPLEMENTED("nsWindow::ScreenToWidget");
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
/*
|
||
* Set a Mac Rect to the value of an nsRect
|
||
* The source rect is assumed to be in pixels not TWIPS
|
||
* @update gpk 08/27/98
|
||
* @param aRect -- The nsRect that is the source
|
||
* @param aMacRect -- The Mac Rect destination
|
||
*/
|
||
void nsWindow::nsRectToMacRect(const nsRect& aRect, Rect& aMacRect) const
|
||
{
|
||
aMacRect.left = aRect.x;
|
||
aMacRect.top = aRect.y;
|
||
aMacRect.right = aRect.x + aRect.width;
|
||
aMacRect.bottom = aRect.y + aRect.height;
|
||
}
|
||
|
||
|
||
//=================================================================
|
||
/* Convert the coordinates to some device coordinates so GFX can draw.
|
||
* @update dc 09/16/98
|
||
* @param nscoord -- X coordinate to convert
|
||
* @param nscoord -- Y coordinate to convert
|
||
* @return NONE
|
||
*/
|
||
void nsWindow::ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY)
|
||
{
|
||
PRInt32 offX, offY;
|
||
this->CalcOffset(offX,offY);
|
||
|
||
aX += offX;
|
||
aY += offY;
|
||
}
|