diff --git a/widget/src/mac/nsMacControl.cpp b/widget/src/mac/nsMacControl.cpp new file mode 100644 index 000000000000..2a7ab6441b4e --- /dev/null +++ b/widget/src/mac/nsMacControl.cpp @@ -0,0 +1,176 @@ +/* -*- 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 "nsMacControl.h" +#include "nsColor.h" + + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +nsMacControl::nsMacControl() : nsWindow() +{ + mButtonSet = PR_FALSE; + mWidgetArmed = PR_FALSE; + mMouseInButton = PR_FALSE; + mControl = nsnull; + mControlType = pushButProc; +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsMacControl::Create(nsIWidget *aParent, + const nsRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsIDeviceContext *aContext, + nsIAppShell *aAppShell, + nsIToolkit *aToolkit, + nsWidgetInitData *aInitData) +{ + nsWindow::Create(aParent, aRect, aHandleEventFunction, + aContext, aAppShell, aToolkit, aInitData); + + + // create native control + nsRect ctlRect = aRect; + ctlRect.x = ctlRect.y = 0; + Rect macRect; + nsRectToMacRect(ctlRect, macRect); + mControl = ::NewControl(mWindowPtr, &macRect, "\p", true, 0, 0, 1, mControlType, nil); + + return NS_OK; +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +nsMacControl::~nsMacControl() +{ + if (mControl) + { + ::DisposeControl(mControl); + mControl = nsnull; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +PRBool nsMacControl::OnPaint(nsPaintEvent &aEvent) +{ + if (mControl) + { + // set the control text attributes + // (the rendering context has already set these attributes for + // the window: we just have to transfer them over to the control) + ControlFontStyleRec fontStyleRec; + fontStyleRec.flags = (kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask); + fontStyleRec.font = mWindowPtr->txFont; + fontStyleRec.size = mWindowPtr->txSize; + fontStyleRec.style = mWindowPtr->txFace; + ::SetControlFontStyle(mControl, &fontStyleRec); + +/* + // set the background color + //¥TODO: this should be done by the rendering context + #define COLOR8TOCOLOR16(color8) (color8 == 0xFF ? 0xFFFF : (color8 << 8)) + nscolor backColor = GetBackgroundColor(); + RGBColor macColor; + macColor.red = COLOR8TOCOLOR16(NS_GET_R(backColor)); + macColor.green = COLOR8TOCOLOR16(NS_GET_G(backColor)); + macColor.blue = COLOR8TOCOLOR16( NS_GET_B(backColor)); + ::RGBBackColor(&macColor); +*/ + // draw the control + Str255 aStr; + StringToStr255(mLabel, aStr); + ::SetControlTitle(mControl, aStr); + + ::SetControlValue(mControl, (mButtonSet ? 1 : 0)); + + if (mEnabled) + ::HiliteControl(mControl, (mWidgetArmed && mMouseInButton ? 1 : 0)); + else + ::HiliteControl(mControl, kControlInactivePart); + + ::ValidRect(&(*mControl)->contrlRect); + } + return PR_FALSE; +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +PRBool nsMacControl::OnResize(nsSizeEvent &aEvent) +{ + return PR_FALSE; +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +PRBool nsMacControl::DispatchMouseEvent(nsMouseEvent &aEvent) +{ + PRBool eatEvent = PR_FALSE; + switch (aEvent.message) + { + case NS_MOUSE_LEFT_BUTTON_DOWN: + if (mEnabled) + { + mMouseInButton = PR_TRUE; + mWidgetArmed = PR_TRUE; + Invalidate(PR_TRUE); + } + break; + + case NS_MOUSE_LEFT_BUTTON_UP: + // if the widget was not armed, eat the event + if (!mWidgetArmed) + eatEvent = PR_TRUE; + // if the mouseUp happened on another widget, eat the event too + // (the widget which got the mouseDown is always notified of the mouseUp) + if (aEvent.widget != this) + eatEvent = PR_TRUE; + mWidgetArmed = PR_FALSE; + if (mMouseInButton) + Invalidate(PR_TRUE); + break; + + case NS_MOUSE_EXIT: + mMouseInButton = PR_FALSE; + if (mWidgetArmed) + Invalidate(PR_TRUE); + break; + + case NS_MOUSE_ENTER: + mMouseInButton = PR_TRUE; + if (mWidgetArmed) + Invalidate(PR_TRUE); + break; + } + if (eatEvent) + return PR_TRUE; + return (nsWindow::DispatchMouseEvent(aEvent)); +} diff --git a/widget/src/mac/nsMacControl.h b/widget/src/mac/nsMacControl.h new file mode 100644 index 000000000000..fbe186013450 --- /dev/null +++ b/widget/src/mac/nsMacControl.h @@ -0,0 +1,58 @@ +/* -*- 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. + */ + +#ifndef nsMacControl_h__ +#define nsMacControl_h__ + +#include "nsWindow.h" +#include + + +class nsMacControl : public nsWindow +{ + +public: + nsMacControl(); + virtual ~nsMacControl(); + + NS_IMETHOD Create(nsIWidget *aParent, + const nsRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsIDeviceContext *aContext = nsnull, + nsIAppShell *aAppShell = nsnull, + nsIToolkit *aToolkit = nsnull, + nsWidgetInitData *aInitData = nsnull); + + virtual void SetControlType(short type) {mControlType = type;} + + // event handling + virtual PRBool OnPaint(nsPaintEvent & aEvent); + virtual PRBool OnResize(nsSizeEvent &aEvent); + virtual PRBool DispatchMouseEvent(nsMouseEvent &aEvent); + + +protected: + nsString mLabel; + PRBool mWidgetArmed; + PRBool mMouseInButton; + PRBool mButtonSet; + ControlHandle mControl; + short mControlType; +}; + +#endif // nsMacControl_h__ diff --git a/widget/src/mac/nsMacEventHandler.cpp b/widget/src/mac/nsMacEventHandler.cpp new file mode 100644 index 000000000000..b10669dc3df3 --- /dev/null +++ b/widget/src/mac/nsMacEventHandler.cpp @@ -0,0 +1,404 @@ +/* -*- 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 "nsMacEventHandler.h" +#include "prinrval.h" + + +//------------------------------------------------------------------------- +// +// nsMacEventHandler constructor/destructor +// +//------------------------------------------------------------------------- +nsMacEventHandler::nsMacEventHandler(nsWindow* aTopLevelWidget) +{ + mTopLevelWidget = aTopLevelWidget; + mLastWidgetHit = nsnull; + mLastWidgetPointed = nsnull; +} + + +nsMacEventHandler::~nsMacEventHandler() +{ +} + + +#pragma mark - +//------------------------------------------------------------------------- +// +// HandleOSEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleOSEvent( + EventRecord& aOSEvent) +{ + PRBool retVal = PR_FALSE; + + switch (aOSEvent.what) + { + case keyUp: + case keyDown: + case autoKey: + retVal = HandleKeyEvent(aOSEvent); + break; + + case activateEvt: + retVal = HandleActivateEvent(aOSEvent); + break; + + case updateEvt: + retVal = HandleUpdateEvent(aOSEvent); + break; + + case mouseDown: + retVal = HandleMouseDownEvent(aOSEvent); + break; + + case mouseUp: + retVal = HandleMouseUpEvent(aOSEvent); + break; + + case osEvt: + case nullEvent: + retVal = HandleMouseMoveEvent(aOSEvent); + break; + } + + return retVal; +} + +//------------------------------------------------------------------------- +// +// Handle Menu commands +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleMenuCommand( + EventRecord& aOSEvent, + long aMenuResult) +{ + // get focused widget + nsWindow* focusedWidget = mTopLevelWidget; + + //¥TODO: should get the focus from the toolkit and + // propagate the event all the way up to the window + // if it's not handled by the different parents + + + // nsEvent + nsMenuEvent menuEvent; + menuEvent.eventStructType = NS_MENU_EVENT; + menuEvent.message = NS_MENU_SELECTED; + menuEvent.point.x = aOSEvent.where.h; + menuEvent.point.y = aOSEvent.where.v; + menuEvent.time = PR_IntervalNow(); + + // nsGUIEvent + menuEvent.widget = focusedWidget; + menuEvent.nativeMsg = (void*)&aOSEvent; + + // nsMenuEvent + menuEvent.mMenuItem = nsnull; //¥TODO: initialize mMenuItem + menuEvent.mCommand = aMenuResult; + + return (focusedWidget->DispatchWindowEvent(menuEvent)); +} + + +#pragma mark - +//------------------------------------------------------------------------- +// +// HandleKeyEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent) +{ + // get the focused widget + nsWindow* focusedWidget = nsnull; + nsToolkit* toolkit = (nsToolkit*)mTopLevelWidget->GetToolkit(); + if (toolkit) + { + focusedWidget = toolkit->GetFocus(); + NS_RELEASE(toolkit); + } + + if (focusedWidget == nsnull) + focusedWidget = mTopLevelWidget; + + // nsEvent + nsKeyEvent keyEvent; + keyEvent.eventStructType = NS_KEY_EVENT; + switch (aOSEvent.what) + { + case keyUp: keyEvent.message = NS_KEY_UP; break; + case keyDown: keyEvent.message = NS_KEY_DOWN; break; + case autoKey: keyEvent.message = NS_KEY_DOWN; break; + } + keyEvent.point.x = 0; + keyEvent.point.y = 0; + keyEvent.time = PR_IntervalNow(); + + // nsGUIEvent + keyEvent.widget = focusedWidget; + keyEvent.nativeMsg = (void*)&aOSEvent; + + // nsInputEvent + keyEvent.isShift = ((aOSEvent.modifiers & shiftKey) != 0); + keyEvent.isControl = ((aOSEvent.modifiers & controlKey) != 0); + keyEvent.isAlt = ((aOSEvent.modifiers & optionKey) != 0); + + // nsKeyEvent + keyEvent.keyCode = (aOSEvent.message & charCodeMask); //¥TODO: do special keys conversions for NS_VK_F1 etc... + + return(focusedWidget->DispatchWindowEvent(keyEvent)); +} + + +//------------------------------------------------------------------------- +// +// HandleActivateEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleActivateEvent(EventRecord& aOSEvent) +{ + Boolean isActive = ((aOSEvent.modifiers & activeFlag) != 0); + if (isActive) + { + // get focused widget + nsWindow* focusedWidget = mTopLevelWidget; + nsIMenuBar* menuBar = focusedWidget->GetMenuBar(); + //¥TODO: should get the focus from the toolkit and + // look all the way up to the window + // until one of the parents has a menubar + + //¥TODO: set the menu bar here + } + return PR_TRUE; +} + + +//------------------------------------------------------------------------- +// +// HandleUpdateEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleUpdateEvent(EventRecord& aOSEvent) +{ + mTopLevelWidget->Update(); + + return PR_TRUE; +} + + +//------------------------------------------------------------------------- +// +// HandleMouseDownEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleMouseDownEvent( + EventRecord& aOSEvent) +{ + PRBool retVal = PR_FALSE; + + WindowPtr whichWindow; + short partCode = ::FindWindow(aOSEvent.where, &whichWindow); + + switch (partCode) + { + case inDrag: + { + Point macPoint; + macPoint = topLeft(whichWindow->portRect); + ::LocalToGlobal(&macPoint); + mTopLevelWidget->Move(macPoint.h, macPoint.v); + break; + } + + case inGrow: + { + Rect macRect = whichWindow->portRect; + ::LocalToGlobal(&topLeft(macRect)); + ::LocalToGlobal(&botRight(macRect)); + mTopLevelWidget->Resize(macRect.right - macRect.left, macRect.bottom - macRect.top, PR_FALSE); + break; + } + + case inGoAway: + { + mTopLevelWidget->Destroy(); + break; + } + + case inContent: + { + nsMouseEvent mouseEvent; + ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN); + nsWindow* widgetHit = (nsWindow*)mouseEvent.widget; + if (widgetHit) + { + // set the focus on the widget hit + nsToolkit* toolkit = (nsToolkit*)widgetHit->GetToolkit(); + if (toolkit) + { + toolkit->SetFocus(widgetHit); + NS_RELEASE(toolkit); + } + + // dispatch the event + retVal = widgetHit->DispatchMouseEvent(mouseEvent); + } + mLastWidgetHit = widgetHit; + break; + } + } + return retVal; +} + + +//------------------------------------------------------------------------- +// +// HandleMouseUpEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleMouseUpEvent( + EventRecord& aOSEvent) +{ + PRBool retVal = PR_FALSE; + + nsMouseEvent mouseEvent; + ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_UP); + + nsWindow* widgetReleased = (nsWindow*)mouseEvent.widget; + if ((widgetReleased != nsnull) && (widgetReleased != mLastWidgetHit)) + retVal |= widgetReleased->DispatchMouseEvent(mouseEvent); + + if (mLastWidgetHit != nsnull) + { + retVal |= mLastWidgetHit->DispatchMouseEvent(mouseEvent); + mLastWidgetHit = nsnull; + } + + return retVal; +} + + +//------------------------------------------------------------------------- +// +// HandleMouseMoveEvent +// +//------------------------------------------------------------------------- +PRBool nsMacEventHandler::HandleMouseMoveEvent( + EventRecord& aOSEvent) +{ + PRBool retVal = PR_FALSE; + + nsMouseEvent mouseEvent; + ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_MOVE); + + nsWindow* widgetPointed = (nsWindow*)mouseEvent.widget; + if (widgetPointed != mLastWidgetPointed) + { + if (mLastWidgetPointed != nsnull) + { + mouseEvent.widget = mLastWidgetPointed; + mouseEvent.message = NS_MOUSE_EXIT; + retVal |= mLastWidgetPointed->DispatchMouseEvent(mouseEvent); + mLastWidgetPointed = nsnull; + mouseEvent.widget = widgetPointed; + } + if (widgetPointed != nsnull) + { + mouseEvent.message = NS_MOUSE_ENTER; + retVal |= widgetPointed->DispatchMouseEvent(mouseEvent); + mLastWidgetPointed = widgetPointed; + } + } + else + { + if (widgetPointed != nsnull) + retVal |= widgetPointed->DispatchMouseEvent(mouseEvent); + } + + return retVal; +} + + +#pragma mark - +//------------------------------------------------------------------------- +// +// ConvertOSEventToMouseEvent +// +//------------------------------------------------------------------------- +void nsMacEventHandler::ConvertOSEventToMouseEvent( + EventRecord& aOSEvent, + nsMouseEvent& aMouseEvent, + PRUint32 aMessage) +{ + static long lastWhen = 0; + static Point lastWhere = {0, 0}; + static short lastClickCount = 0; + + // get the click count + if (((aOSEvent.when - lastWhen) < ::LMGetDoubleTime()) + && (abs(aOSEvent.where.h - lastWhere.h) < 5) + && (abs(aOSEvent.where.v - lastWhere.v) < 5)) + { + if (aOSEvent.what == mouseDown) + lastClickCount ++; + } + else + { + if (! ::StillDown()) + lastClickCount = 0; + } + lastWhen = aOSEvent.when; + lastWhere = aOSEvent.where; + + // get the widget hit and its hit point + Point hitPoint = aOSEvent.where; + ::SetOrigin(0, 0); + ::GlobalToLocal(&hitPoint); + nsPoint widgetHitPoint(hitPoint.h, hitPoint.v); + + nsWindow* widgetHit = mTopLevelWidget->FindWidgetHit(hitPoint); + if (widgetHit) + { + nsRect bounds; + widgetHit->GetBounds(bounds); + nsPoint widgetOrigin(bounds.x, bounds.y); + widgetHit->LocalToWindowCoordinate(widgetOrigin); + widgetHitPoint.MoveBy(-widgetOrigin.x, -widgetOrigin.y); + } + + // nsEvent + aMouseEvent.eventStructType = NS_MOUSE_EVENT; + aMouseEvent.message = aMessage; + aMouseEvent.point = widgetHitPoint; + aMouseEvent.time = PR_IntervalNow(); + + // nsGUIEvent + aMouseEvent.widget = widgetHit; + aMouseEvent.nativeMsg = (void*)&aOSEvent; + + // nsInputEvent + aMouseEvent.isShift = ((aOSEvent.modifiers & shiftKey) != 0); + aMouseEvent.isControl = ((aOSEvent.modifiers & controlKey) != 0); + aMouseEvent.isAlt = ((aOSEvent.modifiers & optionKey) != 0); + + // nsMouseEvent + aMouseEvent.clickCount = lastClickCount; +} diff --git a/widget/src/mac/nsMacEventHandler.h b/widget/src/mac/nsMacEventHandler.h new file mode 100644 index 000000000000..95d8ba9dcb83 --- /dev/null +++ b/widget/src/mac/nsMacEventHandler.h @@ -0,0 +1,74 @@ +/* -*- 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. + */ +#ifndef MacMacEventHandler_h__ +#define MacMacEventHandler_h__ + +#include +#include +#include "nsWindow.h" + + +class nsMacEventHandler +{ +public: + nsMacEventHandler(nsWindow* aTopLevelWidget); + virtual ~nsMacEventHandler(); + + virtual PRBool HandleOSEvent( + EventRecord& aOSEvent); + + virtual PRBool HandleMenuCommand( + EventRecord& aOSEvent, + long aMenuResult); + +protected: + + virtual PRBool HandleKeyEvent(EventRecord& aOSEvent); + virtual PRBool HandleActivateEvent(EventRecord& aOSEvent); + virtual PRBool HandleUpdateEvent(EventRecord& aOSEvent); + virtual PRBool HandleMouseDownEvent(EventRecord& aOSEvent); + virtual PRBool HandleMouseUpEvent(EventRecord& aOSEvent); + virtual PRBool HandleMouseMoveEvent(EventRecord& aOSEvent); + +//-- virtual void ConvertOSEventToPaintEvent( +//-- EventRecord& aOSEvent, +//-- nsPaintEvent& aPaintEvent); + + virtual void ConvertOSEventToMouseEvent( + EventRecord& aOSEvent, + nsMouseEvent& aMouseEvent, + PRUint32 aMessage); + +//-- virtual void ConvertOSEventToKeyEvent(EventRecord& aOSEvent, nsKeyEvent& aKeyEvent); + + //¥TODO: virtual ConvertOSEventToScrollbarEvent(EventRecord& aOSEvent, nsScrollbarEvent& sizeEvent); + //¥TODO: virtual ConvertOSEventToTooltipEvent(EventRecord& aOSEvent, nsTooltipEvent& sizeEvent); + +//-- virtual PRBool PropagateEventRecursively(nsEvent& aRaptorEvent, nsIWidget& aWidget); +//-- virtual PRBool DispatchEvent(nsEvent& aRaptorEvent, nsIWidget& aWidget); + + + +protected: + nsWindow* mTopLevelWidget; + nsWindow* mLastWidgetHit; + nsWindow* mLastWidgetPointed; + RgnHandle mUpdateRgn; +}; + +#endif // MacMacEventHandler_h__ diff --git a/widget/src/mac/nsMacWindow.cpp b/widget/src/mac/nsMacWindow.cpp new file mode 100644 index 000000000000..5b279ac8a9b7 --- /dev/null +++ b/widget/src/mac/nsMacWindow.cpp @@ -0,0 +1,245 @@ +/* -*- 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 "nsWindow.h" +#include "nsMacWindow.h" +#include "nsMacEventHandler.h" + + +const short kWindowTitleBarHeight = 20; + +NS_IMPL_ADDREF(nsMacWindow); +NS_IMPL_RELEASE(nsMacWindow); + +//------------------------------------------------------------------------- +// +// nsMacWindow constructor +// +//------------------------------------------------------------------------- +nsMacWindow::nsMacWindow() : nsWindow() +{ + NS_INIT_REFCNT(); + strcpy(gInstanceClassName, "nsMacWindow"); + mMacEventHandler = new nsMacEventHandler(this); +} + + +//------------------------------------------------------------------------- +// +// nsMacWindow destructor +// +//------------------------------------------------------------------------- +nsMacWindow::~nsMacWindow() +{ + if (mMacEventHandler) + { + delete mMacEventHandler; + mMacEventHandler = nsnull; + } + + 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; + + if (theRefData) + 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); + + // init base class + nsWindow::StandardCreate(aParent, aRect, 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); + ::ShowHide(mWindowPtr, bState); + return NS_OK; +} + +//------------------------------------------------------------------------- +// +// Move this window +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsMacWindow::Move(PRUint32 aX, PRUint32 aY) +{ + long minY = ::LMGetMBarHeight() + kWindowTitleBarHeight; + if (aY < minY) + aY = minY; + //¥TODO: should check that the new window location + // belongs to one of the screens + + nsWindow::Move(aX, aY); + + ::MoveWindow(mWindowPtr, aX, aY, false); + return NS_OK; +} + +//------------------------------------------------------------------------- +// +// Resize this window +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsMacWindow::Resize(PRUint32 aWidth, PRUint32 aHeight, PRBool aRepaint) +{ + ::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) + retVal = mMacEventHandler->HandleOSEvent(aOSEvent); + else + retVal = PR_FALSE; + return retVal; +} + +//------------------------------------------------------------------------- +// +// Handle Menu commands +// +//------------------------------------------------------------------------- +PRBool nsMacWindow::HandleMenuCommand( + EventRecord& aOSEvent, + long aMenuResult) +{ + PRBool retVal; + if (mMacEventHandler) + retVal = mMacEventHandler->HandleMenuCommand(aOSEvent, aMenuResult); + else + retVal = PR_FALSE; + return retVal; +} + + +//------------------------------------------------------------------------- +// +// Find if a point in local coordinates is inside this object +// +//------------------------------------------------------------------------- +PRBool nsMacWindow::PointInWidget(Point aThePoint) +{ + // get widget rect: it's in global coordinates because it's the top level window + nsRect widgetRect; + GetBounds(widgetRect); + + // set the origin to 0 because the point is in local coordinates + widgetRect.x = widgetRect.y = 0; + + // finally tell whether it's a hit + return(widgetRect.Contains(aThePoint.h, aThePoint.v)); +} diff --git a/widget/src/mac/nsMacWindow.h b/widget/src/mac/nsMacWindow.h new file mode 100644 index 000000000000..0f4d9bed3210 --- /dev/null +++ b/widget/src/mac/nsMacWindow.h @@ -0,0 +1,120 @@ +/* -*- 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. + */ +#ifndef MacWindow_h__ +#define MacWindow_h__ + +#include "nsWindow.h" +#include "nsMacEventHandler.h" + +class nsMacEventHandler; + +//------------------------------------------------------------------------- +// +// nsMacWindow +// +//------------------------------------------------------------------------- +// MacOS native window + +class nsMacWindow : public nsWindow +{ + +public: + nsMacWindow(); + virtual ~nsMacWindow(); + + // nsISupports + NS_IMETHOD_(nsrefcnt) AddRef(); + NS_IMETHOD_(nsrefcnt) Release(); + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + +/* + // nsIWidget interface + NS_IMETHOD Create(nsIWidget *aParent, + const nsRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsIDeviceContext *aContext, + nsIAppShell *aAppShell = nsnull, + nsIToolkit *aToolkit = nsnull, + nsWidgetInitData *aInitData = nsnull); +*/ + NS_IMETHOD Create(nsNativeWidget aParent, + const nsRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsIDeviceContext *aContext, + nsIAppShell *aAppShell = nsnull, + nsIToolkit *aToolkit = nsnull, + nsWidgetInitData *aInitData = nsnull); + + // Utility method for implementing both Create(nsIWidget ...) and + // Create(nsNativeWidget...) + + virtual nsresult StandardCreate(nsIWidget *aParent, + const nsRect &aRect, + EVENT_CALLBACK aHandleEventFunction, + nsIDeviceContext *aContext, + nsIAppShell *aAppShell, + nsIToolkit *aToolkit, + nsWidgetInitData *aInitData, + nsNativeWidget aNativeParent = nsnull); + + NS_IMETHOD Show(PRBool aState); + NS_IMETHOD Move(PRUint32 aX, PRUint32 aY); + NS_IMETHOD Resize(PRUint32 aWidth,PRUint32 aHeight, PRBool aRepaint); + + virtual PRBool HandleOSEvent( + EventRecord& aOSEvent); + + virtual PRBool HandleMenuCommand( + EventRecord& aOSEvent, + long aMenuResult); + + + PRBool PointInWidget(Point aThePoint); + +protected: + PRBool mWindowMadeHere; // true if we created the window + nsMacEventHandler* mMacEventHandler; +}; + + + +//------------------------------------------------------------------------- +// +// nsRefData +// +//------------------------------------------------------------------------- +// Class to pass data around in the mac windows refCon + +class nsRefData +{ + +protected: + nsMacWindow* mNSMacWindow; // The nsMacWindow, ie. the top level widget + long mUserData; // Embedding applications data, guaranteed not to be used by widget code + +public: + nsMacWindow* GetNSMacWindow() {return(mNSMacWindow);} + long GetUserData() {return(mUserData);} + + void SetNSMacWindow(nsMacWindow* aNSMacWindow) {mNSMacWindow = aNSMacWindow;} + void SetUserData(long aUserData) {mUserData = aUserData;} + +}; + + +#endif // MacWindow_h__