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