mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
1058 lines
33 KiB
C
1058 lines
33 KiB
C
/*
|
|
File: WindowList.c
|
|
Contains: Patches to key routines in the window and layer manager to implement a
|
|
layerless windowing environment for applications.
|
|
|
|
Written by: David Collins
|
|
|
|
Copyright: © 1992-1993 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM4> 6/17/93 KW (LW2 fau) Changed the DragFlag from a Boolean Ptr to a short
|
|
ptr, since it is a word in lowmem.
|
|
<14> 10/30/92 DTY Use Get/Set macros to access ExpandMem.
|
|
<13> 6/29/92 DC Fixed the patch on HiliteWindow to make windoids in MacDraw Pro
|
|
work. (and hopefully, by extension, other home-brew windoids)
|
|
<12> 6/25/92 DC Fixed a bug wind GetParent such that it returns a NULL if it
|
|
can't find a layer for the window. (previously, it was
|
|
returning garbage) Fixed my patch on SetTrapAddress to preserve
|
|
D1 and A1.
|
|
<11> 6/8/92 DC Added startup icon. Fixed FindLayer for Plus's and SE's. Fixed
|
|
BusErr with EvenBetterBusErr
|
|
<10> 6/3/92 DC Fixed some bugs with FindWindow. No more crashes with Help on.
|
|
<9> 5/31/92 DC Did the extra work referred to in the last comment. Most of the
|
|
rough edges taken off of layer ShowHiding.
|
|
<8> 5/15/92 DC Changes to ShowHide to make applicatin hiding work - still needs
|
|
work.
|
|
<7> 5/14/92 DC Fix SendBehind to adjust the ordering of windows at the right
|
|
time.
|
|
<6> 4/20/92 DC Fixed BringToFrontGuts to work across layers.
|
|
<5> 4/20/92 DTY Rename emPackGlobals[0] to emWindowListGlobals. Also, reduce
|
|
__InitWindowLists to a call to _NewPtr ,Sys,Clear. This saves
|
|
all the code that clears out the new data structure.
|
|
<4> 4/14/92 DC Fixed GetNextWindow to be pascal (just fits a little better in
|
|
assembly that way) Added BringToFrontGuts (unrefined).
|
|
<3> 4/10/92 DC What I said in comment <2> (I only checked in last time to save
|
|
my state before restructuring the INIT) Works O.K. but needs
|
|
more patching to get around cases where the ROM window manager
|
|
explicitly get the NextWindow field of a WindowRecord.
|
|
<2> 4/1/92 DC Patched everything over LayerMgr. Not a good idea. I get
|
|
spanked by LayerMgr's backpatches. I'm going to incorporate a
|
|
copy of LayerMgr.c and WindowMgrPatches.a into my INIT so that I
|
|
can make changes to that code as necessary. All changes to
|
|
working code will be conditionalized.
|
|
<1> 3/20/92 DC first checked in
|
|
|
|
*/
|
|
|
|
/*
|
|
There are a number of assumptions made in this implementation of a layerless application
|
|
world. They are all currently valid. If we are to keep this implementation in future system
|
|
releases, they must remain valid. This basicly promotes them from assumptions to enforcable
|
|
restrictions on future uses of layers. If these assumptions are no longer valid for some
|
|
system release in which this code is used, the implementation will have to be changed to
|
|
adjust. These assumptions are as follows:
|
|
|
|
1.) No application except process manager will ever be allowed to create a layer that is not
|
|
a never-active (floating) layer. This code assumes that if you start at the root and travel
|
|
down only non-floating layers, you will either hit a window in an application layer or a
|
|
never-active (floating) layer within an application layer. This is certainly O.K. for now
|
|
since no third-party application can create any layers. If we want to allow application
|
|
writers to explicitly or implicitly create floating layers, that will also be O.K. and the
|
|
world will work. Creating a non-floating layer under an application doesen't make sense
|
|
anymore anyway, since a non-floating layers don't actually layer things.
|
|
|
|
2.) Process manager is never going to do anything drasticly different in terms of its layer handling.
|
|
Specificly, it should never use non-floating layers for anything other than the root,
|
|
one multifinder layer and all the application layers.
|
|
|
|
3.) Never-active (floating) layers have only windows for children - no layers. This restriction
|
|
could be relaxed to be that never-active layers only have windows or other never-active
|
|
layers for children with a minor tweak to the existing code. I'm not sure that we would
|
|
ever need a hierarchy of floating windows, but it is an arbitrary restriction and it could
|
|
be removed.
|
|
|
|
To build the INIT using BBS use the following command line (impressive, isn't it):
|
|
|
|
Build -d hasLayerlessAppsINIT=TRUE -d hasLayerlessApps=TRUE system -co '-opt full' -INIT Shuffler -p ¶
|
|
-noLink ¶
|
|
-wointerface ¶
|
|
WindowMgrPatches.a.o ¶
|
|
LayerMgr.c.o ¶
|
|
InvalMenuBarPatch.a.o ¶
|
|
WindowList.a.o ¶
|
|
WindowList.c.o
|
|
Rez -i "{RIncludes}" "{Sources}ToolBox:WindowMgr:WindowList.r" -append -o "{Sources}BuildResults:System:Shuffler"
|
|
SetFile -a iB -t INIT -c shfl "{Sources}BuildResults:System:Shuffler"
|
|
|
|
*/
|
|
|
|
#ifndef __MEMORY__
|
|
#include "Memory.h"
|
|
#endif
|
|
|
|
#ifndef __LAYERS__
|
|
#include "Layers.h"
|
|
#endif
|
|
|
|
#ifndef __SYSEQU__
|
|
#include "SysEqu.h"
|
|
#endif
|
|
|
|
#ifndef __EXPANDMEMPRIV__
|
|
#include "ExpandMemPriv.h"
|
|
#endif
|
|
|
|
#ifndef __OSUTILS__
|
|
#include "OSUtils.h"
|
|
#endif
|
|
|
|
#ifndef __MFPRIVATE__
|
|
#include "MFPrivate.h"
|
|
#endif
|
|
|
|
#ifndef hasLayerlessAppsINIT
|
|
#define hasLayerlessAppsINIT 0
|
|
#endif
|
|
|
|
#define kIsLayer ((short) 0xDEAD)
|
|
#define FastIsLayer(window) (((GrafPtr) window)->txSize == kIsLayer)
|
|
|
|
#define theDeskHook (*(long *)DeskHook)
|
|
#define CurLayer (*(LayerPeek*)0xA90)
|
|
#define SaveVisRgn (*(RgnHandle*)0x9F2)
|
|
#define WMgrUpdate (*(WindowPeek*)0xAFC)
|
|
#define theWMgrPort (*(GrafPtr*)WMgrPort)
|
|
#define theWMgrCPort (*(GrafPtr*)0xD2C)
|
|
#define theGrayRgnHandle (*(RgnHandle*)GrayRgn)
|
|
#define paintWhiteState (*(short*)PaintWhite)
|
|
#define saveUpdateState (*(short*)0x9DA)
|
|
#define DeskPort (*(GrafPtr*)0x9E2)
|
|
#define ROM85 (*(unsigned short*)0x28E)
|
|
#define DragFlag (*(short *)0xA44) // <LW2>
|
|
#define HaveCQD() (ROM85 <= 0x3FFF)
|
|
|
|
pascal void PaintDesk(void);
|
|
|
|
#define cacheSize 101
|
|
|
|
typedef struct holder
|
|
{
|
|
WindowPeek whichWindow; // the window we are managing
|
|
LayerPeek parent; // its layer
|
|
struct holder **inFrontOf; // window in behind this window
|
|
struct holder **behind; // window in front of this window
|
|
struct holder **next; // the next WindowHolder in the hash bucket
|
|
Boolean visible // stored show/hide state for layer show/hides
|
|
} WindowHolder, *WindowHolderPtr, **WindowHolderHandle;
|
|
|
|
typedef struct
|
|
{
|
|
WindowHolderHandle lastWindow; // windowHolder of the window whose click was detected most recently
|
|
Ptr oldOSDispatch; // address of unpatched OSDispatch
|
|
ProcessSerialNumber bringToFrontProcess; // process being made frontmost
|
|
WindowHolderHandle windowHolderList;
|
|
WindowHolderHandle windowHolderListEnd;
|
|
WindowHolderHandle hashTable[cacheSize];
|
|
} WindowListData, *WindowListDataPtr;
|
|
|
|
pascal void __InitWindowLists(void)
|
|
{
|
|
SetExpandMemWindowListGlobals((long)(NewPtrSysClear(sizeof(WindowListData))));
|
|
}
|
|
|
|
pascal WindowHolderHandle *GetHashLoc(unsigned long windowPeekValue)
|
|
{
|
|
register unsigned short entryNo = (windowPeekValue >> 1) & 0xffff;
|
|
entryNo %= cacheSize;
|
|
return &(((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->hashTable[entryNo]);
|
|
}
|
|
|
|
pascal WindowHolderHandle GetWindowHolder(register WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle hashBucket;
|
|
|
|
if (theWindow <= 0)
|
|
{
|
|
register WindowListDataPtr theData = (WindowListDataPtr)(GetExpandMemWindowListGlobals());
|
|
|
|
if (!theWindow)
|
|
hashBucket = theData->windowHolderListEnd;
|
|
else if ((long)theWindow == -1)
|
|
hashBucket = theData->windowHolderList;
|
|
|
|
if (hashBucket)
|
|
theWindow = (*hashBucket)->whichWindow;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
hashBucket = *GetHashLoc((unsigned long)theWindow);
|
|
|
|
while (hashBucket)
|
|
{
|
|
WindowHolderPtr hashBucketPtr = *hashBucket;
|
|
|
|
if (hashBucketPtr->whichWindow == theWindow)
|
|
break;
|
|
|
|
hashBucket = hashBucketPtr->next;
|
|
}
|
|
|
|
return hashBucket;
|
|
}
|
|
|
|
WindowHolderHandle FirstNonFloatingWindowHolder(void)
|
|
{
|
|
register WindowHolderHandle theWindowHolderHandle = ((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderList;
|
|
register WindowHolderPtr theWindowHolderPtr;
|
|
|
|
while (theWindowHolderHandle &&
|
|
(theWindowHolderPtr = *theWindowHolderHandle, theWindowHolderPtr->parent->neverActive))
|
|
theWindowHolderHandle = theWindowHolderPtr->inFrontOf;
|
|
|
|
return theWindowHolderHandle;
|
|
}
|
|
|
|
// This routine takes a floating layer with no children and returns the WindowHolder
|
|
// in front of which a new member of this layer should be placed. The basic rule is
|
|
// to place ourselves behind the first floating window in front of us. If there are not
|
|
// any, we will place ourselves in front of the front most window. The net result is that
|
|
// we will "bump into" the first floating layer in front of us.
|
|
|
|
pascal OSErr FindPlaceAction(WindowPeek theWindow, LayerPeek theParent, WindowPeek *lastNeverActiveWindow)
|
|
{
|
|
if (theParent->neverActive)
|
|
*lastNeverActiveWindow = theWindow;
|
|
|
|
return noErr;
|
|
}
|
|
|
|
pascal WindowHolderHandle FindPlaceForFloater(LayerPeek floatParent)
|
|
{
|
|
register WindowHolderHandle theWindowHolder = ((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderList;
|
|
|
|
if (theWindowHolder)
|
|
{
|
|
WindowPeek lastNeverActiveWindow = NULL;
|
|
|
|
EachWindow((*theWindowHolder)->whichWindow,
|
|
(WindowPeek)floatParent,
|
|
floatParent->parent,
|
|
(WindowAction *)FindPlaceAction,
|
|
(void *)(&lastNeverActiveWindow));
|
|
|
|
if (lastNeverActiveWindow)
|
|
return GetWindowHolder(lastNeverActiveWindow);
|
|
else
|
|
return theWindowHolder;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// FirstNonFloatingLayer is a utility used by FrontMostApplicationLayer below. It returns the first
|
|
// non never-active layer in a the parameter layer.
|
|
|
|
pascal LayerPeek FirstNonFloatingLayer(register LayerPeek theLayer)
|
|
{
|
|
register WindowPeek child = theLayer->subWindows;
|
|
|
|
while (child && (!FastIsLayer(child) || ((LayerPeek)child)->neverActive))
|
|
child = child->nextWindow;
|
|
|
|
return (LayerPeek)child;
|
|
}
|
|
|
|
// FrontMostApplicationLayer: the name says it all. Returns the front-most application layer. This routine
|
|
// is a little more outlandish than it has to be, since we can pretty much assume that the multifinder layer
|
|
// is the front-most non floating child of the root and that the front-most application layer will be the first
|
|
// child of that layer. This routine will find the front-most application layer under slightly broader
|
|
// conditions (say for example, process manager is changed to add another layer of hierarchy between it and the root)
|
|
// without adding too much more overhead.
|
|
//
|
|
// NOTE: this is where we make the assumption that no application layer will ever have anything other than
|
|
// floating layera or windows for children. If it had any other kind, we might descend into them, and return
|
|
// something other than an application layer.
|
|
|
|
LayerPeek FrontMostApplicationLayer(void)
|
|
{
|
|
register long parent = (long)GetRootLayer(),
|
|
layer;
|
|
|
|
while (layer = (long)FirstNonFloatingLayer((LayerPeek)parent))
|
|
parent = layer;
|
|
|
|
return (LayerPeek)parent;
|
|
}
|
|
|
|
pascal WindowPtr __FrontWindowIn(LayerPtr layer);
|
|
|
|
// This routine takes a window that is being either moved to the front or otherwise
|
|
// inserted front most into its layer. It returns the WindowHolder of the window
|
|
// in front of which this window should be placed in the global window list. If this
|
|
// routine returns NULL, it means place the window at the back of the list.
|
|
|
|
pascal WindowHolderHandle GetNullInsertionPoint(WindowHolderHandle theWindowHolder)
|
|
{
|
|
register LayerPeek theParent = (*theWindowHolder)->parent;
|
|
register WindowPeek frontWindow;
|
|
|
|
// Choose ActiveWindow as the insertion point if this window is a child of
|
|
// either the root layer or the front-most application layer.
|
|
|
|
if ((theParent->parent == NULL) || (theParent == FrontMostApplicationLayer()))
|
|
return FirstNonFloatingWindowHolder();
|
|
|
|
// At this point the window we're looking at is either the child of a never-active
|
|
// layer or the child of a background application layer. In either case, the right
|
|
// thing to do is to place the window in front of the front-most window in this layer
|
|
//
|
|
// NOTE: This is the place where an assumption is made that a floating window will
|
|
// only have windows for children. If, for example, the Parent were a floating
|
|
// layer with two neverActive layers for children, __FrontWindowIn would return NULL.
|
|
|
|
if (frontWindow = (WindowPeek)__FrontWindowIn((LayerPtr)theParent))
|
|
return GetWindowHolder(frontWindow);
|
|
|
|
// At this point we're dealing with an empty layer, floating or regular. Most likely
|
|
// this is because its a new layer and the window we're inserting is its first child.
|
|
// The question is: where to put the child we're inserting in the global ordering?
|
|
// If this is an application layer (non-floater) the answer is easy. We return NULL
|
|
// which will inform the caller to GetNullInstertionPoint that we should put this
|
|
// window back-most. I mean, why not? In a layer-less world this makes as much
|
|
// sense as anyplace for a window that's being created by a background application.
|
|
// The floating layer is more difficult so we have a routine that executes the logic
|
|
// for that case.
|
|
|
|
if (theParent->neverActive)
|
|
return FindPlaceForFloater(theParent);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
pascal void InsertInFrontOf(register WindowHolderHandle theWindowHolder, WindowHolderHandle inFrontOfHolder)
|
|
{
|
|
register WindowHolderHandle *insertionPoint = (inFrontOfHolder != NULL) ?
|
|
&((*inFrontOfHolder)->behind) :
|
|
&(((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderListEnd);
|
|
|
|
register long restOfList = (long)(*insertionPoint);
|
|
|
|
if (restOfList == theWindowHolder)
|
|
return;
|
|
|
|
*insertionPoint = theWindowHolder;
|
|
|
|
(*theWindowHolder)->inFrontOf = inFrontOfHolder;
|
|
(*theWindowHolder)->behind = (WindowHolderHandle)restOfList;
|
|
|
|
if (restOfList)
|
|
(*((WindowHolderHandle)restOfList))->inFrontOf = theWindowHolder;
|
|
else
|
|
((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderList = theWindowHolder;
|
|
}
|
|
|
|
pascal void InsertBehind(WindowHolderHandle theWindowHolder, register WindowHolderHandle behindHolder)
|
|
{
|
|
InsertInFrontOf(theWindowHolder, (behindHolder != NULL) ? (*behindHolder)->inFrontOf : GetNullInsertionPoint(theWindowHolder));
|
|
}
|
|
|
|
pascal void DeleteHolder(WindowHolderHandle theWindowHolder)
|
|
{
|
|
register WindowHolderHandle firstPartOfList;
|
|
register WindowHolderHandle lastPartOfList;
|
|
|
|
if (!theWindowHolder)
|
|
return;
|
|
|
|
firstPartOfList = (*theWindowHolder)->behind;
|
|
lastPartOfList = (*theWindowHolder)->inFrontOf;
|
|
|
|
if (firstPartOfList)
|
|
(*firstPartOfList)->inFrontOf = lastPartOfList;
|
|
else
|
|
((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderList = lastPartOfList;
|
|
|
|
if (lastPartOfList)
|
|
(*lastPartOfList)->behind = firstPartOfList;
|
|
else
|
|
((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderListEnd = firstPartOfList;
|
|
}
|
|
|
|
pascal OSErr WindowHolderDeleter(register WindowPeek theWindow, LayerPeek, void *)
|
|
{
|
|
if (!FastIsLayer(theWindow))
|
|
DeleteHolder(GetWindowHolder(theWindow));
|
|
|
|
return noErr;
|
|
}
|
|
|
|
pascal void DeleteWindowHolders(register WindowPeek theWindow)
|
|
{
|
|
if (FastIsLayer((WindowPtr)theWindow))
|
|
{
|
|
EachWindow(firstWindow, afterLastWindow, (LayerPeek)theWindow, (WindowAction *)WindowHolderDeleter, NULL);
|
|
((LayerPeek)theWindow)->subWindows = NULL; // this is so that KillPicture isn't called on the child list
|
|
}
|
|
else
|
|
DeleteHolder(GetWindowHolder(theWindow));
|
|
}
|
|
|
|
pascal void HashWindow(WindowPeek theWindow, WindowPeek behind, Boolean visible)
|
|
{
|
|
register WindowHolderHandle theNewHolderHandle = (WindowHolderHandle)NewHandleSys(sizeof(WindowHolder)),
|
|
*hashLoc = GetHashLoc((long)theWindow);
|
|
register WindowHolderPtr theNewHolderPtr = *theNewHolderHandle;
|
|
|
|
if (theNewHolderHandle)
|
|
{
|
|
theNewHolderPtr->whichWindow = theWindow;
|
|
theNewHolderPtr->next = (*hashLoc);
|
|
(*hashLoc) = theNewHolderHandle;
|
|
theNewHolderPtr->parent = CurLayer;
|
|
theNewHolderPtr->visible = visible;
|
|
|
|
InsertBehind(theNewHolderHandle, GetWindowHolder(behind));
|
|
}
|
|
}
|
|
|
|
pascal void DeHashWindow(WindowPeek theWindow)
|
|
{
|
|
if (!FastIsLayer((WindowPtr)theWindow))
|
|
{
|
|
register WindowHolderHandle *theWindowHolderPtr = GetHashLoc((long)theWindow);
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
while (theWindowHolder = *theWindowHolderPtr)
|
|
{
|
|
if ((*theWindowHolder)->whichWindow == theWindow)
|
|
{
|
|
(*theWindowHolderPtr) = (*theWindowHolder)->next;
|
|
|
|
DeleteHolder(theWindowHolder);
|
|
DisposHandle((Handle)theWindowHolder);
|
|
|
|
return;
|
|
}
|
|
|
|
theWindowHolderPtr = &((*theWindowHolder)->next);
|
|
}
|
|
}
|
|
}
|
|
|
|
pascal void Rearrange(register WindowHolderHandle theWindowHolder, WindowHolderHandle behind)
|
|
{
|
|
// The following condition checks if theWindow is for real, that we're not trying to
|
|
// insert ourselves behind ourselves, and that if behind is not null, that the
|
|
// arrangement we want is not already in effect. If all this is O.K. we delete
|
|
// theWindowHolder from its place in the global window list and insert it behind
|
|
// its intended destination.
|
|
|
|
if (theWindowHolder && (theWindowHolder != behind) &&
|
|
(!behind || ((*behind)->inFrontOf != theWindowHolder)))
|
|
{
|
|
DeleteHolder(theWindowHolder);
|
|
InsertBehind(theWindowHolder, behind);
|
|
}
|
|
}
|
|
|
|
pascal LayerPeek __patchGetParent(WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
if (!theWindow)
|
|
return CurLayer;
|
|
else if (FastIsLayer((WindowPtr)theWindow))
|
|
return ((LayerPeek)theWindow)->parent;
|
|
else if (theWindowHolder = GetWindowHolder(theWindow))
|
|
return (*theWindowHolder)->parent;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
#pragma parameter VisRgnChanged(__A0)
|
|
pascal void VisRgnChanged(WindowPtr)
|
|
= { 0x7000, 0xA0A5 };
|
|
|
|
pascal void UpdatedVisRgn(WindowPeek window);
|
|
|
|
pascal short HitTestWindow(Point,WindowPeek);
|
|
|
|
pascal WindowHolderHandle FindWindowHolder(register Point thePoint, short *theLocation)
|
|
{
|
|
register WindowHolderHandle theWindowHolder = ((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->windowHolderList;
|
|
|
|
while (theWindowHolder)
|
|
{
|
|
register WindowPeek theWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if (theWindow->visible && PtInRgn(thePoint, theWindow->strucRgn) && (*theLocation = HitTestWindow(thePoint, theWindow)))
|
|
{
|
|
((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->lastWindow = theWindowHolder;
|
|
return theWindowHolder;
|
|
}
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
pascal LayerPeek AncestorThatIsChildOfCurLayer(register LayerPeek theLayer)
|
|
{
|
|
while (theLayer && (theLayer->parent != CurLayer))
|
|
theLayer = theLayer->parent;
|
|
|
|
return theLayer;
|
|
}
|
|
|
|
pascal long PointInMenuBar(Point);
|
|
|
|
pascal short __patchFindLayer(Point thePoint, register WindowPeek *whichWindow)
|
|
{
|
|
short temp;
|
|
register short returnValue;
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
*whichWindow = NULL;
|
|
|
|
if (PointInMenuBar(thePoint) >= 0)
|
|
returnValue = inMenuBar;
|
|
else if (theWindowHolder = FindWindowHolder(thePoint, &temp))
|
|
{
|
|
register LayerPeek theParent = (*theWindowHolder)->parent;
|
|
|
|
if (theParent == CurLayer)
|
|
{
|
|
*whichWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if ((*whichWindow)->windowKind < 0)
|
|
returnValue = inSysWindow;
|
|
else
|
|
returnValue = temp + 2;
|
|
}
|
|
else if (theParent = AncestorThatIsChildOfCurLayer(theParent))
|
|
{
|
|
*whichWindow = (WindowPeek)theParent;
|
|
returnValue = inContent;
|
|
}
|
|
else
|
|
returnValue = inDesk;
|
|
}
|
|
else
|
|
{
|
|
if (theDeskHook)
|
|
returnValue = inSysWindow;
|
|
else
|
|
returnValue = inDesk;
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
pascal short __FindWindow(Point point, WindowPtr *window)
|
|
{
|
|
short returnValue;
|
|
|
|
if (((returnValue = FindLayer(point, window)) == inContent) && FastIsLayer(*window))
|
|
return inDesk;
|
|
else
|
|
return returnValue;
|
|
}
|
|
|
|
pascal void VisRgnToLocalCoordinates(WindowPeek theWindow)
|
|
{
|
|
BitMap *theMap;
|
|
|
|
if ((theMap = &(theWindow->port.portBits))->rowBytes < 0)
|
|
theMap = *((BitMap **) theMap->baseAddr);
|
|
|
|
OffsetRgn(((WindowPtr)theWindow)->visRgn, theMap->bounds.left, theMap->bounds.top);
|
|
}
|
|
|
|
pascal OSErr VisCalcer(WindowPeek theWindow, LayerPeek, long)
|
|
{
|
|
if (!FastIsLayer(theWindow))
|
|
CalcVis(theWindow);
|
|
|
|
return noErr;
|
|
}
|
|
|
|
pascal void __patchCalcVis(register WindowPeek theWindow)
|
|
{
|
|
if (!theWindow)
|
|
return;
|
|
|
|
if (!FastIsLayer((WindowPtr)theWindow))
|
|
{
|
|
if (theWindow->visible)
|
|
{
|
|
register long theVisRgn = (long)theWindow->port.visRgn;
|
|
register RgnHandle *wMgrPortClipRgnPtr = &(theWMgrPort->clipRgn);
|
|
register long saveClip = (long)(*wMgrPortClipRgnPtr);
|
|
CopyRgn(theWindow->contRgn, (RgnHandle)theVisRgn);
|
|
*wMgrPortClipRgnPtr = (RgnHandle)theVisRgn;
|
|
ClipAbove(theWindow);
|
|
*wMgrPortClipRgnPtr = (RgnHandle)saveClip;
|
|
|
|
VisRgnToLocalCoordinates(theWindow);
|
|
}
|
|
else
|
|
SetEmptyRgn(((WindowPtr)theWindow)->visRgn);
|
|
|
|
UpdatedVisRgn(theWindow);
|
|
}
|
|
else
|
|
EachWindow(firstWindow, afterLastWindow, (LayerPeek)theWindow, (WindowAction *)VisCalcer, NULL);
|
|
|
|
}
|
|
|
|
// This routine can be made to be order N in the number of visible windows. It is currently and
|
|
// always has been order N^2.
|
|
|
|
pascal void __patchCalcVisBehind(register WindowPeek theWindow, RgnHandle clobberedRegion)
|
|
{
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
if (!theWindow)
|
|
return;
|
|
|
|
if (!FastIsLayer((WindowPtr)theWindow))
|
|
{
|
|
CalcVis(theWindow);
|
|
|
|
if (!(theWindowHolder = GetWindowHolder(theWindow)) || !(theWindowHolder = (*theWindowHolder)->inFrontOf))
|
|
return;
|
|
|
|
do {
|
|
theWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if (theWindow->visible && RectInRgn(&((*(theWindow->contRgn))->rgnBBox), clobberedRegion))
|
|
CalcVis(theWindow);
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
} while (theWindowHolder);
|
|
}
|
|
}
|
|
|
|
pascal void __patchClipAbove(register WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle theWindowHolder;
|
|
register long wMgrClipRgn = (long)(theWMgrPort->clipRgn);
|
|
|
|
SectRgn((RgnHandle)wMgrClipRgn, theGrayRgnHandle, (RgnHandle)wMgrClipRgn);
|
|
|
|
// doing a clipabove on a layer is a meaningless operation in the layerless world
|
|
|
|
if (theWindow && FastIsLayer((WindowPtr)theWindow))
|
|
return;
|
|
|
|
// we will loop through all the of the windows in front of theWindow, merrily subtracting out structure
|
|
// regions to arrive at a visRgn that allows us to draw in ourselves, but not our brethren to the front.
|
|
// If theWindow is NULL, as it is in the case of CalcDeskPortVisRgn, GetWindowHolder will return the
|
|
// rear of the global window list, which is where we want to seed the loop in this case.
|
|
|
|
if ((theWindowHolder = GetWindowHolder(theWindow)) && (!theWindow || (theWindowHolder = (*theWindowHolder)->behind)))
|
|
{
|
|
do {
|
|
theWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if (theWindow->visible)
|
|
DiffRgn((RgnHandle)wMgrClipRgn, theWindow->strucRgn, (RgnHandle)wMgrClipRgn);
|
|
|
|
theWindowHolder = (*theWindowHolder)->behind;
|
|
} while (theWindowHolder);
|
|
}
|
|
}
|
|
|
|
void CalcDeskPortVisRgn(void)
|
|
{
|
|
register GrafPtr wMgrPort = theWMgrPort;
|
|
register long deskPortVisRgn = (long)(DeskPort->visRgn);
|
|
register RgnHandle wMgrPortClipRgn = wMgrPort->clipRgn;
|
|
|
|
CopyRgn(theGrayRgnHandle, (RgnHandle)deskPortVisRgn);
|
|
wMgrPort->clipRgn = (RgnHandle)deskPortVisRgn;
|
|
ClipAbove(nil);
|
|
wMgrPort->clipRgn = wMgrPortClipRgn;
|
|
}
|
|
|
|
void PaintTheDesk(RgnHandle clobberedRgn)
|
|
{
|
|
register GrafPtr wMgrPort = theWMgrPort;
|
|
register GrafPtr deskPort = DeskPort;
|
|
register RgnHandle wMgrPortClipRgn = wMgrPort->clipRgn;
|
|
|
|
CalcDeskPortVisRgn();
|
|
SectRgn(clobberedRgn, deskPort->visRgn, wMgrPortClipRgn);
|
|
{
|
|
register RgnHandle deskUpdate = ((WindowPeek) deskPort)->updateRgn;
|
|
UnionRgn(deskUpdate, wMgrPortClipRgn, deskUpdate);
|
|
}
|
|
|
|
if (HaveCQD())
|
|
wMgrPort = (GrafPtr) theWMgrCPort;
|
|
|
|
SetPort(wMgrPort);
|
|
PaintDesk();
|
|
}
|
|
|
|
pascal void __patchPaintBehind(register WindowPeek theWindow, register long clobberedRgn)
|
|
{
|
|
PaintTheDesk((RgnHandle)clobberedRgn);
|
|
|
|
if (!theWindow)
|
|
return;
|
|
|
|
if (!FastIsLayer(theWindow))
|
|
{
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
theWindowHolder = GetWindowHolder(theWindow);
|
|
|
|
while (theWindowHolder)
|
|
{
|
|
if ((theWindow = (*theWindowHolder)->whichWindow)->visible)
|
|
PaintOne(theWindow, (RgnHandle)clobberedRgn);
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This patch catches the HiliteWindow that is called on the frontmost window of an application that is being brought forward
|
|
// by process manager. It probably catches some other cases as well, but that should be O.K. since BringToFront won't do
|
|
// anything if the window is frontmost which should be the true except in the case of changing front processes. If the window
|
|
// is being hilited.
|
|
|
|
pascal void __patchHiliteWindow(WindowPeek theWindow, Boolean hiliteValue)
|
|
{
|
|
pascal void oldHiliteWindow(WindowPeek theWindow, Boolean hiliteValue);
|
|
|
|
if (!FastIsLayer((WindowPtr)theWindow))
|
|
{
|
|
register long windowParent = (long)GetParent((WindowPtr)theWindow);
|
|
register WindowHolderHandle *lastWindow = &(((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->lastWindow);
|
|
|
|
if (hiliteValue && (theWindow == (WindowPeek)__FrontWindowIn((LayerPtr)windowParent)) && (windowParent == (long)FrontMostApplicationLayer()))
|
|
{
|
|
if ((GetWVariant((WindowPtr)theWindow) == movableDBoxProc) || (*lastWindow && ((**lastWindow)->whichWindow == theWindow)))
|
|
BringToFront((WindowPtr)theWindow);
|
|
|
|
*lastWindow = NULL;
|
|
}
|
|
|
|
oldHiliteWindow(theWindow, hiliteValue);
|
|
}
|
|
}
|
|
|
|
pascal WindowHolderHandle GetNextWindowHolder(register WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
if (!(theWindowHolder = GetWindowHolder(theWindow)))
|
|
return NULL;
|
|
|
|
return (*((WindowHolderHandle)theWindowHolder))->inFrontOf;
|
|
}
|
|
|
|
pascal WindowPeek GetNextWindow(register WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle theWindowHolder = GetNextWindowHolder(theWindow);
|
|
|
|
if (theWindowHolder)
|
|
return (*theWindowHolder)->whichWindow;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
pascal WindowPeek GetNextVisibleWindow(register WindowPeek theWindow)
|
|
{
|
|
register WindowHolderHandle theWindowHolder = GetNextWindowHolder(theWindow);
|
|
|
|
theWindow = NULL;
|
|
|
|
while (theWindowHolder)
|
|
{
|
|
theWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if (theWindow->visible)
|
|
break;
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
}
|
|
|
|
return theWindow;
|
|
}
|
|
|
|
pascal WindowPeek FirstWindowIn(LayerPeek);
|
|
|
|
pascal void BringChildrenToFront(LayerPeek theLayer)
|
|
{
|
|
if (FastIsLayer((WindowPtr)theLayer))
|
|
{
|
|
ProcessSerialNumber *bringToFrontProcess = &(((WindowListDataPtr)(GetExpandMemWindowListGlobals()))->bringToFrontProcess);
|
|
|
|
if (bringToFrontProcess->highLongOfPSN || bringToFrontProcess->lowLongOfPSN)
|
|
{
|
|
ProcessSerialNumber thePSN;
|
|
|
|
if ((GetProcessFromLayer(&thePSN, (LayerPtr)theLayer) == noErr) && (thePSN == *bringToFrontProcess))
|
|
{
|
|
WindowPeek theWindow;
|
|
|
|
bringToFrontProcess->highLongOfPSN = 0;
|
|
bringToFrontProcess->lowLongOfPSN = 0;
|
|
|
|
if (theWindow = FirstWindowIn(theLayer))
|
|
{
|
|
WindowHolderHandle lastWindowHolder = NULL;
|
|
register long clobberedRegion = (long)NewRgn();
|
|
|
|
do {
|
|
WindowHolderHandle windowHolder;
|
|
|
|
if (windowHolder = GetWindowHolder(theWindow))
|
|
{
|
|
WindowHolderHandle inFrontHolder = (*windowHolder)->behind;
|
|
|
|
while (inFrontHolder)
|
|
{
|
|
if ((*inFrontHolder)->parent != theLayer)
|
|
UnionRgn((RgnHandle)clobberedRegion, ((*inFrontHolder)->whichWindow)->strucRgn, (RgnHandle)clobberedRegion);
|
|
|
|
inFrontHolder = (*inFrontHolder)->behind;
|
|
}
|
|
|
|
if (!lastWindowHolder || ((*lastWindowHolder)->inFrontOf != windowHolder))
|
|
{
|
|
DeleteHolder(windowHolder);
|
|
InsertBehind(windowHolder, lastWindowHolder);
|
|
}
|
|
|
|
lastWindowHolder = windowHolder;
|
|
}
|
|
|
|
PaintOne(theWindow, (RgnHandle)clobberedRegion);
|
|
CalcVis(theWindow);
|
|
|
|
theWindow = theWindow->nextWindow;
|
|
} while (theWindow);
|
|
|
|
if (lastWindowHolder && (lastWindowHolder = (*lastWindowHolder)->inFrontOf))
|
|
CalcVisBehind((*lastWindowHolder)->whichWindow, (RgnHandle)clobberedRegion);
|
|
|
|
DisposeRgn((RgnHandle)clobberedRegion);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pascal void CoolOffsetRgn(RgnHandle rgn, Point offsetPoint)
|
|
= 0xA8E0;
|
|
|
|
pascal void BringToFrontGuts(register WindowPeek theWindow)
|
|
{
|
|
pascal void BringToFrontOfCurLayer(WindowPeek);
|
|
register WindowHolderHandle theWindowHolder,
|
|
insertionPoint;
|
|
|
|
// Layers don't need any fussing around visRgns, etc. They just need to be brought to the front.
|
|
|
|
if (FastIsLayer(theWindow))
|
|
{
|
|
BringToFrontOfCurLayer(theWindow);
|
|
|
|
return;
|
|
}
|
|
|
|
theWindowHolder = GetWindowHolder(theWindow);
|
|
|
|
if (theWindowHolder && ((insertionPoint = GetNullInsertionPoint(theWindowHolder)) != theWindowHolder))
|
|
{
|
|
WindowHolderHandle windowTowardScreen = (*theWindowHolder)->behind;
|
|
register long clobberRegion = (long)NewRgn();
|
|
register long changedWindowsStructRgn = (long)(theWindow->strucRgn);
|
|
GrafPtr savedPort;
|
|
|
|
GetPort(&savedPort);
|
|
|
|
while (windowTowardScreen)
|
|
{
|
|
WindowPtr whichWindow = (*windowTowardScreen)->whichWindow;
|
|
|
|
if (((WindowPeek)whichWindow)->visible)
|
|
{
|
|
register long visRgn = (long)(((GrafPtr)whichWindow)->visRgn);
|
|
Point offsetPoint = {0,0},
|
|
backPoint;
|
|
|
|
SetPort(whichWindow);
|
|
LocalToGlobal(&offsetPoint);
|
|
backPoint.h = -offsetPoint.h;
|
|
backPoint.v = -offsetPoint.v;
|
|
|
|
CoolOffsetRgn((RgnHandle)visRgn, offsetPoint);
|
|
DiffRgn((RgnHandle)visRgn, (RgnHandle)changedWindowsStructRgn, (RgnHandle)visRgn);
|
|
CoolOffsetRgn((RgnHandle)visRgn, backPoint);
|
|
|
|
UnionRgn(((WindowPeek)whichWindow)->strucRgn, (RgnHandle)clobberRegion, (RgnHandle)clobberRegion);
|
|
}
|
|
|
|
windowTowardScreen = (*windowTowardScreen)->behind;
|
|
}
|
|
|
|
BringToFrontOfCurLayer(theWindow);
|
|
|
|
DeleteHolder(theWindowHolder);
|
|
InsertInFrontOf(theWindowHolder, insertionPoint);
|
|
|
|
SetPort(theWMgrPort);
|
|
|
|
if (!DragFlag)
|
|
{
|
|
SectRgn((RgnHandle)changedWindowsStructRgn, (RgnHandle)clobberRegion, (RgnHandle)clobberRegion);
|
|
PaintOne(theWindow, (RgnHandle)clobberRegion);
|
|
}
|
|
|
|
__patchCalcVisBehind(theWindow, (RgnHandle)changedWindowsStructRgn);
|
|
|
|
SetPort(savedPort);
|
|
|
|
DisposeRgn((RgnHandle)clobberRegion);
|
|
}
|
|
}
|
|
|
|
pascal void romCallWindowCalc(WindowPeek);
|
|
|
|
pascal OSErr StateSaver(register WindowPeek theWindow, LayerPeek theLayer, long showFlag)
|
|
{
|
|
if (!FastIsLayer(theWindow))
|
|
{
|
|
register long clobberedRgn = (long)(((GrafPtr)theLayer)->visRgn);
|
|
register WindowHolderHandle theWindowHolder;
|
|
|
|
if (theWindowHolder = GetWindowHolder(theWindow))
|
|
{
|
|
if (!showFlag)
|
|
{
|
|
if (theWindow->visible)
|
|
(*theWindowHolder)->visible = true;
|
|
|
|
theWindow->visible = false;
|
|
}
|
|
else
|
|
theWindow->visible = (*theWindowHolder)->visible;
|
|
}
|
|
|
|
if (!showFlag)
|
|
{
|
|
UnionRgn((RgnHandle)clobberedRgn, theWindow->strucRgn, (RgnHandle)clobberedRgn);
|
|
romCallWindowCalc(theWindow);
|
|
}
|
|
else
|
|
{
|
|
romCallWindowCalc(theWindow);
|
|
UnionRgn((RgnHandle)clobberedRgn, theWindow->strucRgn, (RgnHandle)clobberedRgn);
|
|
PaintOne(theWindow, theGrayRgnHandle);
|
|
}
|
|
|
|
CalcVis(theWindow);
|
|
}
|
|
|
|
return noErr;
|
|
}
|
|
|
|
pascal OSErr WindowFinder(register WindowPeek theWindow, LayerPeek, WindowPeek *foundWindow)
|
|
{
|
|
if (!FastIsLayer(theWindow))
|
|
{
|
|
*foundWindow = theWindow;
|
|
return haltIterator;
|
|
}
|
|
|
|
return noErr;
|
|
}
|
|
|
|
pascal WindowPeek FirstWindowIn(register LayerPeek theLayer)
|
|
{
|
|
WindowPeek theWindow;
|
|
|
|
if (EachWindow(firstWindow, afterLastWindow, theLayer, (WindowAction *)WindowFinder, (void *)(&theWindow)) != noErr)
|
|
return theWindow;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
pascal WindowHolderHandle FirstWindowHolderIn(register LayerPeek theLayer)
|
|
{
|
|
register long theWindow = (long)FirstWindowIn(theLayer);
|
|
|
|
if (theWindow)
|
|
return GetWindowHolder((WindowPeek)theWindow);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
pascal void ShowHideLayer(register LayerPeek theLayer, register Boolean showFlag)
|
|
{
|
|
if ((theLayer->visible ^ showFlag) & 1)
|
|
{
|
|
theLayer->visible = showFlag;
|
|
|
|
if (theLayer->subWindows)
|
|
{
|
|
register WindowHolderHandle theWindowHolder = FirstWindowHolderIn(theLayer);
|
|
|
|
if (theWindowHolder)
|
|
{
|
|
register long clobberedRgn = (long)(((GrafPtr)theLayer)->visRgn);
|
|
GrafPtr savePort;
|
|
|
|
SetEmptyRgn((RgnHandle)clobberedRgn);
|
|
|
|
GetPort(&savePort);
|
|
SetPort(theWMgrPort);
|
|
|
|
// if we're hiding this layer, we should unhilite the front most window. Process Mgr tries to do
|
|
// this but it dosen't work anymore because I make all the windows in the layer invisible. Process Mgr
|
|
// calls FrontWindowIn to find the frontmost window in the hidden layer so it can call unhilite it.
|
|
// Unfortunately, I make all the windows in the layer invisible (as you're about to see in the following
|
|
// code). FrontWindowIn returns NULL for a layer full of invisible windows so Process Manager just
|
|
// craps out (lucky it dosen't crash).
|
|
|
|
if (!showFlag)
|
|
HiliteWindow((WindowPtr)__FrontWindowIn((LayerPtr)theLayer), false);
|
|
|
|
(void)EachWindow(firstWindow, afterLastWindow, theLayer, (WindowAction *)StateSaver, (void *)showFlag);
|
|
|
|
PaintTheDesk((RgnHandle)clobberedRgn);
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
|
|
while (theWindowHolder)
|
|
{
|
|
register WindowPeek theWindow = (*theWindowHolder)->whichWindow;
|
|
|
|
if (theWindow->visible && ((*theWindowHolder)->parent != theLayer))
|
|
{
|
|
if (!showFlag)
|
|
PaintOne(theWindow, (RgnHandle)clobberedRgn);
|
|
|
|
if (RectInRgn(&((*(theWindow->contRgn))->rgnBBox), (RgnHandle)clobberedRgn))
|
|
CalcVis(theWindow);
|
|
}
|
|
|
|
theWindowHolder = (*theWindowHolder)->inFrontOf;
|
|
}
|
|
|
|
SetPort(savePort);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|