From e019f297bb54f0f8cec385a25430da967f5252b6 Mon Sep 17 00:00:00 2001 From: "pinkerton%netscape.com" <pinkerton%netscape.com> Date: Tue, 17 Nov 1998 17:19:01 +0000 Subject: [PATCH] First Checked In. --- widget/src/mac/nsMacMessagePump.cpp | 470 ++++++++++++++++++++++++++++ widget/src/mac/nsMacMessagePump.h | 75 +++++ 2 files changed, 545 insertions(+) create mode 100644 widget/src/mac/nsMacMessagePump.cpp create mode 100644 widget/src/mac/nsMacMessagePump.h diff --git a/widget/src/mac/nsMacMessagePump.cpp b/widget/src/mac/nsMacMessagePump.cpp new file mode 100644 index 0000000000000..ba175a10b6dab --- /dev/null +++ b/widget/src/mac/nsMacMessagePump.cpp @@ -0,0 +1,470 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* + * 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 "nsMacMessagePump.h" +#include "nsMacMessageSink.h" +#include "nsWidgetsCID.h" +#include "nsToolkit.h" +#include "nscore.h" + +#include <MacWindows.h> +#include <LPeriodical.h> +#include <ToolUtils.h> +#include <LowMem.h> + +#define DRAW_ON_RESIZE + +const char SUSPENDRESUMEMESSAGE = 0x01; +const char MOUSEMOVEDMESSAGE = 0xFA; + +//nsWindow* nsMacMessagePump::gCurrentWindow = nsnull; +//nsWindow* nsMacMessagePump::gGrabWindow = nsnull; // need this for grabmouse + +//static NS_DEFINE_IID(kITEXTWIDGETIID, NS_TEXTFIELD_CID); +nsMacMessagePump::nsWindowlessMenuEventHandler nsMacMessagePump::gWindowlessMenuEventHandler = nsnull; + + +bool IsUserWindow ( WindowPtr ) ; + +// a small helper routine, inlined for efficiency +inline +bool IsUserWindow ( WindowPtr wp ) +{ + return wp && (::GetWindowKind(wp) >= kApplicationWindowKind); +} + + +//================================================================= +/* Constructor + * @update dc 08/31/98 + * @param aToolkit -- The toolkit created by the application + * @return NONE + */ +nsMacMessagePump::nsMacMessagePump(nsToolkit *aToolkit, nsMacMessageSink* aSink) + : mToolkit(aToolkit), mMessageSink(aSink) +{ + mRunning = PR_FALSE; +} + +//================================================================= +/* Destructor + * @update dc 08/31/98 + * @param NONE + * @return NONE + */ +nsMacMessagePump::~nsMacMessagePump() +{ + //¥¥¥ release the toolkits and sinks? not if we use COM_auto_ptr. +} + +//================================================================= +/* Runs the message pump for the macintosh. Turns them into Raptor events + * @update dc 08/31/98 + * @param NONE + * @return A boolean which states how the pump terminated + */ +PRBool +nsMacMessagePump::DoMessagePump() +{ + Boolean haveEvent; + EventRecord theEvent; + long sleep = 0; + unsigned short eventMask = (everyEvent - diskMask); + + mRunning = PR_TRUE; + mInBackground = PR_FALSE; + + // calculate the region to watch + RgnHandle mouseRgn = ::NewRgn(); + ::SetRectRgn(mouseRgn, -32000, -32000, -32001, -32001); + + while (mRunning) + { + ::LMSetSysEvtMask(eventMask); // we need keyUp events + haveEvent = ::WaitNextEvent(eventMask, &theEvent, sleep, mouseRgn); + + if (haveEvent) + { + switch(theEvent.what) + { + case keyUp: + case keyDown: + case autoKey: + DoKey(theEvent); + break; + + case mouseDown: + DoMouseDown(theEvent); + break; + + case mouseUp: + DoMouseUp(theEvent); + break; + + case updateEvt: + DoUpdate(theEvent); + break; + + case activateEvt: + DoActivate(theEvent); + break; + + case osEvt: + unsigned char eventType = ((theEvent.message >> 24) & 0x00ff); + switch (eventType) + { + case SUSPENDRESUMEMESSAGE: + if (theEvent.message & 0x00000001) + mInBackground = PR_FALSE; // resume message + else + mInBackground = PR_TRUE; // suspend message + break; + + case MOUSEMOVEDMESSAGE: + DoMouseMove(theEvent); + break; + } + break; + } + } + else + { + DoIdle(theEvent); + if (mRunning) + LPeriodical::DevoteTimeToIdlers(theEvent); + } + + if (mRunning) + LPeriodical::DevoteTimeToRepeaters(theEvent); + } + + return NS_OK; +} + +#pragma mark - +//------------------------------------------------------------------------- +// +// DoUpdate +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoUpdate(EventRecord &anEvent) +{ + WindowPtr whichWindow = (WindowPtr)anEvent.message; + if (IsUserWindow(whichWindow)) + { + GrafPtr savePort; + ::GetPort(&savePort); + ::SetPort(whichWindow); + ::BeginUpdate(whichWindow); +#if 0 //¥¥¥test¥¥¥ + static Boolean aBool = 1; + RGBColor green = {0,65535,0}; + RGBColor red = {65535,0,0}; + ::RGBForeColor((aBool ? &green : &red)); + aBool ^= 1; + ::PenSize(2,2); + ::ClipRect(&whichWindow->portRect); + ::FrameRgn(whichWindow->visRgn); +#endif //¥¥¥¥¥¥¥¥¥ + // The app can do its own updates here + DispatchOSEventToRaptor(anEvent, whichWindow); + ::EndUpdate(whichWindow); + ::SetPort(savePort); + } +} + + +//------------------------------------------------------------------------- +// +// DoMouseDown +// +//------------------------------------------------------------------------- + +void nsMacMessagePump::DoMouseDown(EventRecord &anEvent) +{ + WindowPtr whichWindow; + PRInt16 partCode; + + partCode = ::FindWindow(anEvent.where, &whichWindow); + + switch (partCode) + { + case inSysWindow: + break; + + case inMenuBar: + { + long menuResult = ::MenuSelect(anEvent.where); + if (HiWord(menuResult) != 0) + DoMenu(anEvent, menuResult); + break; + } + + case inContent: + { + ::SetPort(whichWindow); + if (IsWindowHilited(whichWindow)) + DispatchOSEventToRaptor(anEvent, whichWindow); + else + ::SelectWindow(whichWindow); + break; + } + + case inDrag: + { + ::SetPort(whichWindow); + if (!(anEvent.modifiers & cmdKey)) + ::SelectWindow(whichWindow); + Rect screenRect = qd.screenBits.bounds; + ::InsetRect(&screenRect, 4, 4); + screenRect.top += ::LMGetMBarHeight(); + ::DragWindow(whichWindow, anEvent.where, &screenRect); + + ::GetMouse(&anEvent.where); + ::LocalToGlobal(&anEvent.where); + // it's not really necessary to send that event to Raptor but (who knows?) + // some windows may want to know that they have been moved + DispatchOSEventToRaptor(anEvent, whichWindow); + break; + } + + case inGrow: + { + ::SetPort(whichWindow); +#ifdef DRAW_ON_RESIZE + Point oldPt = anEvent.where; + while (::WaitMouseUp()) + { + LPeriodical::DevoteTimeToRepeaters(anEvent); + Point newPt; + ::GetMouse(&newPt); + ::LocalToGlobal(&newPt); + if (::DeltaPoint(oldPt, newPt)) + { + Rect portRect = whichWindow->portRect; + short width = (portRect.right - portRect.left) + (newPt.h - oldPt.h); + short height = (portRect.bottom - portRect.top) + (newPt.v - oldPt.v); + + oldPt = newPt; + ::SizeWindow(whichWindow, width, height, true); + ::DrawGrowIcon(whichWindow); + anEvent.where = newPt; // important! + DispatchOSEventToRaptor(anEvent, whichWindow); + } + } +#else + Rect sizeRect; + sizeRect.bottom = qd.screenBits.bounds.bottom; + sizeRect.right = qd.screenBits.bounds.right; + sizeRect.top = sizeRect.left = 75; + long newSize = ::GrowWindow(whichWindow, anEvent.where, &sizeRect); + if (newSize != 0) + ::SizeWindow(whichWindow, newSize & 0x0FFFF, (newSize >> 16) & 0x0FFFF, true); + ::DrawGrowIcon(whichWindow); + Point newPt; + ::GetMouse(&newPt); + ::LocalToGlobal(&newPt); + anEvent.where = newPt; // important! + DispatchOSEventToRaptor(anEvent, whichWindow); +#endif + break; + } + + case inGoAway: + { + ::SetPort(whichWindow); + if (::TrackGoAway(whichWindow, anEvent.where)) + DispatchOSEventToRaptor(anEvent, whichWindow); + break; + } + + case inZoomIn: + case inZoomOut: + break; + } +} + + +//------------------------------------------------------------------------- +// +// DoMouseUp +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoMouseUp(EventRecord &anEvent) +{ + WindowPtr whichWindow; + PRInt16 partCode; + + partCode = ::FindWindow(anEvent.where, &whichWindow); + if (whichWindow == nil) + { + // We need to report the event even when it happens over no window: + // when the user clicks a widget, keeps the mouse button pressed and + // releases it outside the window, the event needs to be reported to + // the widget so that it can deactivate itself. + whichWindow = ::FrontWindow(); + } + DispatchOSEventToRaptor(anEvent, whichWindow); +} + + +//------------------------------------------------------------------------- +// +// DoMouseMove +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoMouseMove(EventRecord &anEvent) +{ + // same thing as DoMouseUp + WindowPtr whichWindow; + PRInt16 partCode; + + partCode = ::FindWindow(anEvent.where, &whichWindow); + if (whichWindow == nil) + whichWindow = ::FrontWindow(); + DispatchOSEventToRaptor(anEvent, whichWindow); +} + + +//------------------------------------------------------------------------- +// +// DoKey +// +// This is called for keydown, keyup, and key repeating events. So we need +// to be careful not to do things twice. +//------------------------------------------------------------------------- +void nsMacMessagePump::DoKey(EventRecord &anEvent) +{ + char theChar = (char)(anEvent.message & charCodeMask); + if ((anEvent.what == keyDown) && ((anEvent.modifiers & cmdKey) != 0)) + { + // do a menu key command + long menuResult = ::MenuKey(theChar); + if (HiWord(menuResult) != 0) + DoMenu(anEvent, menuResult); + } + else + { + DispatchOSEventToRaptor(anEvent, ::FrontWindow()); + } +} + + +//------------------------------------------------------------------------- +// +// DoMenu +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoMenu(EventRecord &anEvent, long menuResult) +{ + // The app can handle its menu commands here or + // in the nsNativeBrowserWindow and nsNativeViewerApp + if (::FrontWindow() != nil) + { + DispatchMenuCommandToRaptor(anEvent, menuResult); + } + else + { + if (gWindowlessMenuEventHandler != nsnull) + gWindowlessMenuEventHandler(menuResult); + } + HiliteMenu(0); +} + + +//------------------------------------------------------------------------- +// +// DoActivate +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoActivate(EventRecord &anEvent) +{ + WindowPtr whichWindow = (WindowPtr)anEvent.message; + ::SetPort(whichWindow); + if (anEvent.modifiers & activeFlag) + { + ::BringToFront(whichWindow); + ::HiliteWindow(whichWindow,TRUE); + } + else + { + ::HiliteWindow(whichWindow,FALSE); + } + + DispatchOSEventToRaptor(anEvent, whichWindow); +} + + +//------------------------------------------------------------------------- +// +// DoIdle +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DoIdle(EventRecord &anEvent) +{ + // send mouseMove event + static Point lastWhere = {0, 0}; + + if (*(long*)&lastWhere == *(long*)&anEvent.where) + return; + + lastWhere = anEvent.where; + DoMouseMove(anEvent); + + // idle controls //¥TODO? : is this really necessary? + WindowPtr win = ::FrontWindow(); + while (win) + { + ::SetPort(win); + ::SetOrigin(0,0); + ::ClipRect(&win->portRect); + ::IdleControls(win); + win = ::GetNextWindow(win); + } +} + + +#pragma mark - +//------------------------------------------------------------------------- +// +// DispatchOSEventToRaptor +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DispatchOSEventToRaptor( + EventRecord &anEvent, + WindowPtr aWindow) +{ + if (aWindow && IsUserWindow(aWindow)) + mMessageSink->DispatchOSEvent(anEvent, aWindow); +} + + +//------------------------------------------------------------------------- +// +// DispatchMenuCommandToRaptor +// +//------------------------------------------------------------------------- +void nsMacMessagePump::DispatchMenuCommandToRaptor( + EventRecord &anEvent, + long menuResult) +{ + WindowPtr whichWindow = ::FrontWindow(); + if (whichWindow && IsUserWindow(whichWindow)) + mMessageSink->DispatchMenuCommand(anEvent, menuResult); + +} diff --git a/widget/src/mac/nsMacMessagePump.h b/widget/src/mac/nsMacMessagePump.h new file mode 100644 index 0000000000000..0cbc8d5ee3515 --- /dev/null +++ b/widget/src/mac/nsMacMessagePump.h @@ -0,0 +1,75 @@ +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ +/* + * 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 nsMacMessagePump_h__ +#define nsMacMessagePump_h__ + +#include <Events.h> +#include "prtypes.h" + +class nsToolkit; +class nsMacMessageSink; + +//================================================ + +// Macintosh Message Pump Class +class nsMacMessagePump +{ + // CLASS MEMBERS +private: + PRBool mRunning; + Point mMousePoint; // keep track of where the mouse is at all times + PRBool mInBackground; + nsToolkit* mToolkit; + nsMacMessageSink* mMessageSink; //¥¥¥ should be COM_auto_ptr + + // CLASS METHODS + +public: + nsMacMessagePump(nsToolkit *aToolKit, nsMacMessageSink* aSink); + virtual ~nsMacMessagePump(); + + PRBool DoMessagePump(); + void StopRunning() {mRunning = PR_FALSE;} + +private: + void DoMouseDown(EventRecord &anEvent); + void DoMouseUp(EventRecord &anEvent); + void DoMouseMove(EventRecord &anEvent); + void DoUpdate(EventRecord &anEvent); + void DoKey(EventRecord &anEvent); + void DoMenu(EventRecord &anEvent, long menuResult); + void DoActivate(EventRecord &anEvent); + void DoIdle(EventRecord &anEvent); + + void DispatchOSEventToRaptor(EventRecord &anEvent, WindowPtr aWindow); + void DispatchMenuCommandToRaptor(EventRecord &anEvent, long menuResult); + +public: + typedef void (*nsWindowlessMenuEventHandler) (PRInt32 menuResult); + static nsWindowlessMenuEventHandler gWindowlessMenuEventHandler; + static void SetWindowlessMenuEventHandler(nsWindowlessMenuEventHandler func) + {gWindowlessMenuEventHandler = func;} +}; + + + + + +#endif // nsMacMessagePump_h__ + -- GitLab