/* -*- 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. */ #include #include "nsWindow.h" #include "nsMacWindow.h" #include "nsMacEventHandler.h" // from MacHeaders.c #ifndef topLeft #define topLeft(r) (((Point *) &(r))[0]) #endif #ifndef botRight #define botRight(r) (((Point *) &(r))[1]) #endif const short kWindowTitleBarHeight = 20; NS_IMPL_ADDREF(nsMacWindow); NS_IMPL_RELEASE(nsMacWindow); //------------------------------------------------------------------------- // // nsMacWindow constructor // //------------------------------------------------------------------------- nsMacWindow::nsMacWindow() : nsWindow() , mWindowMadeHere(PR_FALSE), mMacEventHandler(new nsMacEventHandler(this)) { NS_INIT_REFCNT(); strcpy(gInstanceClassName, "nsMacWindow"); } //------------------------------------------------------------------------- // // nsMacWindow destructor // //------------------------------------------------------------------------- nsMacWindow::~nsMacWindow() { if (mWindowPtr) { nsRefData* theRefData = (nsRefData*)::GetWRefCon(mWindowPtr); if (mWindowMadeHere) ::CloseWindow(mWindowPtr); else ::SetWRefCon(mWindowPtr, theRefData->GetUserData()); // restore the refCon if we did not create the window mWindowPtr = nsnull; delete theRefData; } } //------------------------------------------------------------------------- // // //------------------------------------------------------------------------- nsresult nsMacWindow::QueryInterface(const nsIID& aIID, void** aInstancePtr) { static NS_DEFINE_IID(kIWindowIID, NS_IWINDOW_IID); //¥¥¥ if (aIID.Equals(kIWindowIID)) { *aInstancePtr = (void*) ((nsIWidget*)(nsISupports*)this); AddRef(); return NS_OK; } return nsWindow::QueryInterface(aIID,aInstancePtr); } //------------------------------------------------------------------------- // // Utility method for implementing both Create(nsIWidget ...) and // Create(nsNativeWidget...) //------------------------------------------------------------------------- nsresult nsMacWindow::StandardCreate(nsIWidget *aParent, const nsRect &aRect, EVENT_CALLBACK aHandleEventFunction, nsIDeviceContext *aContext, nsIAppShell *aAppShell, nsIToolkit *aToolkit, nsWidgetInitData *aInitData, nsNativeWidget aNativeParent) { // build the main native window if (aNativeParent == nsnull) { Rect wRect; nsRectToMacRect(aRect, wRect); wRect.top += ::LMGetMBarHeight() + kWindowTitleBarHeight; mWindowPtr = ::NewCWindow(nil, &wRect, "\p-", false, 0, (GrafPort*)-1, true, (long)nsnull); mWindowMadeHere = PR_TRUE; } else { mWindowPtr = (WindowPtr)aNativeParent; mWindowMadeHere = PR_FALSE; } // set the refData nsRefData* theRefData = new nsRefData(); if (theRefData == nsnull) return NS_ERROR_OUT_OF_MEMORY; theRefData->SetNSMacWindow(this); theRefData->SetUserData(::GetWRefCon(mWindowPtr)); // save the actual refCon in case we did not create the window ::SetWRefCon(mWindowPtr, (long)theRefData); // reset the coordinates to (0,0) because it's the top level widget nsRect bounds(0, 0, aRect.width, aRect.height); // init base class nsWindow::StandardCreate(aParent, bounds, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData); return NS_OK; } //------------------------------------------------------------------------- // // Create a nsMacWindow using a native window provided by the application // //------------------------------------------------------------------------- NS_IMETHODIMP nsMacWindow::Create(nsNativeWidget aNativeParent, // this is a windowPtr const nsRect &aRect, EVENT_CALLBACK aHandleEventFunction, nsIDeviceContext *aContext, nsIAppShell *aAppShell, nsIToolkit *aToolkit, nsWidgetInitData *aInitData) { return(StandardCreate(nsnull, aRect, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData, aNativeParent)); } //------------------------------------------------------------------------- // // Hide or show this window // //------------------------------------------------------------------------- NS_IMETHODIMP nsMacWindow::Show(PRBool bState) { nsWindow::Show(bState); // we need to make sure we call ::Show/HideWindow() to generate the // necessary activate/deactivate events. Calling ::ShowHide() is // not adequate (pinkerton). if ( bState ) ::ShowWindow(mWindowPtr); else ::HideWindow(mWindowPtr); return NS_OK; } //------------------------------------------------------------------------- // // Move this window // //------------------------------------------------------------------------- NS_IMETHODIMP nsMacWindow::Move(PRUint32 aX, PRUint32 aY) { //¥TODO: We should check that the new window belongs to one of the screens // but "qd.screenBits.bounds" is not the right way to do it. Rect screenRect = qd.screenBits.bounds; ::InsetRect(&screenRect, 4, 4); screenRect.top += ::LMGetMBarHeight() + kWindowTitleBarHeight; short windowWidth = mWindowPtr->portRect.right - mWindowPtr->portRect.left; if (((PRInt32)aX) < screenRect.left - windowWidth) aX = screenRect.left - windowWidth; else if (((PRInt32)aX) > screenRect.right) aX = screenRect.right; if (((PRInt32)aY) < screenRect.top) aY = screenRect.top; else if (((PRInt32)aY) > screenRect.bottom) aY = screenRect.bottom; // propagate the event in global coordinates nsWindow::Move(aX, aY); // reset the coordinates to (0,0) because it's the top level widget mBounds.x = 0; mBounds.y = 0; // move the window if it has not been moved yet // (ie. if this function isn't called in response to a DragWindow event) Point macPoint; macPoint = topLeft(mWindowPtr->portRect); ::LocalToGlobal(&macPoint); if ((macPoint.h != aX) || (macPoint.v != aY)) { ::MoveWindow(mWindowPtr, aX, aY, false); } return NS_OK; } //------------------------------------------------------------------------- // // Resize this window // //------------------------------------------------------------------------- NS_IMETHODIMP nsMacWindow::Resize(PRUint32 aWidth, PRUint32 aHeight, PRBool aRepaint) { // move the window if it has not been moved yet // (ie. if this function isn't called in response to a GrowWindow event) Rect macRect = mWindowPtr->portRect; if (((macRect.right - macRect.left) != aWidth) || ((macRect.bottom - macRect.top) != aHeight)) { ::SizeWindow(mWindowPtr, aWidth, aHeight, aRepaint); } nsWindow::Resize(aWidth, aHeight, aRepaint); return NS_OK; } //------------------------------------------------------------------------- // // Handle OS events // //------------------------------------------------------------------------- PRBool nsMacWindow::HandleOSEvent( EventRecord& aOSEvent) { PRBool retVal; if (mMacEventHandler.get()) retVal = mMacEventHandler->HandleOSEvent(aOSEvent); else retVal = PR_FALSE; return retVal; } //------------------------------------------------------------------------- // // Handle Menu commands // //------------------------------------------------------------------------- PRBool nsMacWindow::HandleMenuCommand( EventRecord& aOSEvent, long aMenuResult) { PRBool retVal; if (mMacEventHandler.get()) retVal = mMacEventHandler->HandleMenuCommand(aOSEvent, aMenuResult); else retVal = PR_FALSE; return retVal; }