mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-22 08:30:05 +00:00
4325cdcc78
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.
512 lines
13 KiB
C
512 lines
13 KiB
C
/*
|
|
File: LayerMgrPatches.c
|
|
|
|
Contains: Glue between Process Mgr and the Layer Manager.
|
|
|
|
Written by: Ed Tecot
|
|
|
|
Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<6> 4/9/92 KST JH,There is only one float layer now instead of one float layer
|
|
for each application.
|
|
<5> 10/9/91 YK Added NewFloatLayer and DisposeFloatLayer.
|
|
<4> 5/23/91 dba do a style of coercion that MPW 3.2 C likes
|
|
<3> 1/21/91 DFH (KSM) Process Menu is now called Application Menu.
|
|
<0> 4/18/89 EMT New Today.
|
|
|
|
*/
|
|
|
|
|
|
#pragma segment kernel_segment
|
|
|
|
#include <types.h>
|
|
#include <toolutils.h>
|
|
#include <osutils.h>
|
|
#include <memory.h>
|
|
#include <quickdraw.h>
|
|
#include <events.h>
|
|
#include <resources.h>
|
|
#include <retrace.h>
|
|
#include <windows.h>
|
|
#include <palette.h>
|
|
#include <errors.h>
|
|
|
|
#include "Glue.h"
|
|
#include "Lomem.h"
|
|
#include "Data.h"
|
|
#include "ScrapCoercion.h"
|
|
#include "OSDispatchPrivate.h"
|
|
|
|
Point GetApplicationMenuLeftCoord(void);
|
|
pascal void ZoomRect(Rect *, Rect *, Boolean);
|
|
|
|
/* GetLayer. This routine returns the layer pointer for the current
|
|
* process.
|
|
*/
|
|
pascal LayerPtr
|
|
c_getlayer(void)
|
|
{
|
|
unsigned long olda5;
|
|
LayerPtr retval;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
retval = pCurrentProcess->p_layer;
|
|
A5SimpleRestore(olda5);
|
|
return(retval);
|
|
}
|
|
|
|
/* LayerInsert. Can't support anymore. SysError instead. (June 89) */
|
|
pascal void
|
|
c_layerinsert(LayerPtr, LayerPtr)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LayerDelete. Can't support anymore. SysError instead. (June 89) */
|
|
pascal LayerPtr
|
|
c_layerdelete(LayerPtr)
|
|
{
|
|
SysError(dsCoreErr);
|
|
return nil;
|
|
}
|
|
|
|
/* LNewWindow. Can't support anymore. SysError instead. (June 89) */
|
|
pascal void
|
|
c_lnewwindow(WindowPeek)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LCloseWindow. Can't support anymore. SysError instead. (June 89) */
|
|
pascal void
|
|
c_lclosewindow(WindowPeek)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LCalcVis. Don't support anymore. SysError instead. (April 90) */
|
|
pascal void
|
|
c_LCalcVis(LayerPtr, WindowPeek)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LCVBehind. Don't support anymore. SysError instead. (April 90) */
|
|
pascal void
|
|
c_LCVBehind(LayerPtr, WindowPeek, RgnHandle)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LPaintOne. Don't support anymore. SysError instead. (April 90) */
|
|
pascal void
|
|
c_LPaintOne(LayerPtr, WindowPeek, RgnHandle)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LPaintBehind. Don't support anymore. SysError instead. (April 90) */
|
|
pascal void
|
|
c_LPaintBehind(LayerPtr, WindowPeek, RgnHandle)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LShowHide. Don't need anymore. SysError instead. (March 90) */
|
|
pascal void
|
|
c_LShowHide(LayerPtr, Boolean)
|
|
{
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* LClipAbove. ClipAbove knowing about layers closer to the front. */
|
|
pascal void
|
|
c_LClipAbove(LayerPtr layer, WindowPeek window)
|
|
{
|
|
layer = SwapCurLayer(layer);
|
|
ClipAbove(window);
|
|
SetCurLayer(layer);
|
|
}
|
|
|
|
/* MakeTopLayer. This routine will make the given layer the frontmost
|
|
* layer, doing the necessary redrawing and visRgn recomputation. We avoid
|
|
* calling SelectWindow, since it will generate an extra deactivate/activate.
|
|
*/
|
|
pascal void
|
|
c_maketoplayer(LayerPtr layer)
|
|
{
|
|
WindowPtr topWindow;
|
|
unsigned long olda5;
|
|
THz tempZone;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
|
|
/* Recalculate vis regions, etc. Switch to the system heap since this is a
|
|
* cross-application operation, and we don't want to penalize the current
|
|
* application's zone for the memory needed to do the region operations.
|
|
* Layer operations are to us what window operations are to apps.
|
|
*/
|
|
SafeSetZone(tempZone, SYSZONE);
|
|
BringToFront(layer);
|
|
SafeRestoreZone(tempZone);
|
|
|
|
/* Highlight the front window (before making layer visible, to avoid flash). */
|
|
if ((topWindow = FrontWindowIn(layer)) != nil)
|
|
{
|
|
HiliteWindow(topWindow, true);
|
|
if (Colorized)
|
|
ActivatePalette(topWindow);
|
|
}
|
|
|
|
/* Bring layer back out of hiding */
|
|
if (((LayerPeek) layer)->visible == false)
|
|
HideLayer(layer, true);
|
|
|
|
A5Restore(olda5);
|
|
}
|
|
|
|
/* Closelayer. This routine is called by exiting processes to remove the
|
|
* layer from the screen. Although it is named layerCLOSE, it actually
|
|
* destroys the layer. If the layer is owned by the owner of the desktop,
|
|
* we also close the desktop layer.
|
|
* NOTE: This will not be good if the desktop owner has multiple layers,
|
|
* and just wants to close one of them!
|
|
*/
|
|
pascal void
|
|
c_layerclose(LayerPtr layer)
|
|
{
|
|
/* We own the desklayer too. */
|
|
if ((LayerOwner(layer) == desklayerowner))
|
|
desklayerowner = nil;
|
|
DisposeWindow(layer);
|
|
}
|
|
|
|
/* LayerInit. This routine will initialize the current process' layer. If the
|
|
* process is a normal one, the layer goes to the front of the list. If the process
|
|
* is a background layer, he goes to the back of the list.
|
|
* NOTE: We assume that launch called SetCurLayer(MFLayer). This keeps the layer/window
|
|
* lists synchronized before this call, and ensures proper placement of the layer we
|
|
* create here.
|
|
*/
|
|
pascal void
|
|
c_layerinit(void)
|
|
{
|
|
register PEntryPtr pCurrProc;
|
|
LayerPtr behind;
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
pCurrProc = pCurrentProcess;
|
|
if (pCurrProc->p_layer != nil)
|
|
dbmsg("Current application called InitWindows twice");
|
|
|
|
/* Figure out where the layer should go (foreground vs background). */
|
|
behind = (pCurrProc == pFrontProcess) ? (LayerPtr) -1 : nil;
|
|
|
|
(void) NewLayer(&pCurrProc->p_layer, true, false, behind, (long) pCurrProc);
|
|
SetCurLayer(pCurrProc->p_layer);
|
|
|
|
A5Restore(olda5);
|
|
}
|
|
|
|
/* c_LGetNextLayer. Given a layer, returns the next layer in the list. Given nil,
|
|
* returns first.
|
|
*/
|
|
pascal LayerPtr
|
|
c_LGetNextLayer(LayerPtr pCurLayer, Boolean wantVisiblesOnly)
|
|
{
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
|
|
/* Nil means start at the first layer */
|
|
pCurLayer = (pCurLayer == nil) ? GetFrontAppLayer() : ((LayerPeek) pCurLayer)->nextWindow;
|
|
|
|
/* If the caller will take any layer, return the pCurLayer.
|
|
* Otherwise, find the first visible one.
|
|
*/
|
|
while (pCurLayer != nil)
|
|
{
|
|
if (wantVisiblesOnly == false || ((LayerPeek) pCurLayer)->visible)
|
|
break;
|
|
pCurLayer = ((LayerPeek) pCurLayer)->nextWindow;
|
|
}
|
|
|
|
A5Restore(olda5);
|
|
return(pCurLayer);
|
|
}
|
|
|
|
/* LayerFind. Given a global mouse coordinate, this routine will snoop through all of
|
|
* the layers' windowlists looking for the frontmost layer which contains this mouse
|
|
* point. The layer pointer is returned if the mouse is in a layer, otherwise zero is
|
|
* returned. Note that it no longer checks the deskrgn.
|
|
*/
|
|
pascal LayerPtr
|
|
c_layerfind(Point where)
|
|
{
|
|
LayerPtr pLayer, saveLayer;
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
|
|
saveLayer = SwapCurLayer(MFLayer);
|
|
if (FindLayer(where, &pLayer) != inContent)
|
|
pLayer = nil;
|
|
SetCurLayer(saveLayer);
|
|
A5Restore(olda5);
|
|
return(pLayer);
|
|
}
|
|
|
|
/* LGetAuxWin. This routine returns the AuxWin Handle for the given window in the
|
|
* given layer. If the window is nil, the handle to the default record is returned.
|
|
* The boolean return is TRUE if a unique aux handle was found, FALSE if the default
|
|
* is returned.
|
|
*/
|
|
pascal short
|
|
c_lgetauxwin(LayerPtr layer, WindowPeek window, AuxWinHandle awh)
|
|
{
|
|
short result;
|
|
|
|
layer = SwapCurLayer(layer);
|
|
result = GetAuxWin(window, awh);
|
|
SetCurLayer(layer);
|
|
return result;
|
|
}
|
|
|
|
/* ColorInvalRect. This routine intersects every displayed window with the given
|
|
* device rectangle; for those that intersect, an update is generated.
|
|
* NOTE: This routine may change thePort.
|
|
*/
|
|
pascal void
|
|
c_lcolorinvalrect(Rect *pDevRect, short, short sysupdates)
|
|
{
|
|
#pragma unused (sysupdates)
|
|
RgnHandle clobberedRgn;
|
|
|
|
clobberedRgn = NewRgn();
|
|
RectRgn(clobberedRgn, pDevRect);
|
|
PaintOnePal(nil, clobberedRgn);
|
|
DisposeRgn(clobberedRgn);
|
|
}
|
|
|
|
#define ARE_EQUAL_BOOLEANS(b1, b2) ((((b1) ^ (b2)) & 1) == 0)
|
|
#define ARE_NOT_EQUAL_BOOLEANS(b1, b2) ((((b1) ^ (b2)) & 1) != 0)
|
|
|
|
/* HideLayer. Do the user interface-y aspects of layer hiding.
|
|
* NOTE: Requires A5 == PROCESSMGRGLOBALS
|
|
*/
|
|
Rect hideDstRect; /* Set up at init time */
|
|
|
|
pascal void
|
|
HideLayer(LayerPtr layer, Boolean showFlag)
|
|
{
|
|
register WindowPeek pFrontWindow;
|
|
PEntryPtr pProc;
|
|
|
|
/* Do nothing if layer is already in requested state (to prevent zooming) */
|
|
if (ARE_EQUAL_BOOLEANS(((LayerPeek) layer)->visible, showFlag))
|
|
return;
|
|
|
|
/* Locate topmost visible window. */
|
|
pFrontWindow = FrontWindowIn(layer);
|
|
do
|
|
{
|
|
/* Escape from loop if there are no visibles */
|
|
if (pFrontWindow == nil)
|
|
break;
|
|
|
|
/* Ignore window if it has nothing on the screen (empty strucRgn), or it is
|
|
* a fake DA window (p_wptr is a pointer to it).
|
|
*/
|
|
if (pFrontWindow->visible)
|
|
{
|
|
pProc = LayerOwner(layer);
|
|
if ( (EmptyRgn(pFrontWindow->strucRgn) == false)
|
|
&& (pFrontWindow != pProc->p_wptr) )
|
|
break;
|
|
}
|
|
|
|
/* Link to next window back in layer */
|
|
pFrontWindow = pFrontWindow->nextWindow;
|
|
}
|
|
while (true);
|
|
|
|
/* If hiding, hide windows before zoom */
|
|
if (!showFlag)
|
|
ShowHide(layer, false);
|
|
|
|
/* Zoom the top window, if any. */
|
|
if (pFrontWindow != nil)
|
|
{
|
|
Rect hideDstRect, globalOfPortRect;
|
|
Rect *pPortBitsBounds;
|
|
register short globalToLocalY;
|
|
register short globalToLocalX;
|
|
|
|
/* Create the rect for the top window */
|
|
pPortBitsBounds = (pFrontWindow->port.portBits.rowBytes < 0)
|
|
? &(*((CGrafPtr)pFrontWindow)->portPixMap)->bounds
|
|
: &pFrontWindow->port.portBits.bounds;
|
|
globalToLocalY = pPortBitsBounds->top;
|
|
globalToLocalX = pPortBitsBounds->left;
|
|
|
|
/* Create the rect for the Application menu. */
|
|
*((Point *)&hideDstRect.top) = *((Point *)&hideDstRect.bottom) = GetApplicationMenuLeftCoord();
|
|
|
|
/* Convert the "global" port rect to global coords */
|
|
globalOfPortRect = pFrontWindow->port.portRect;
|
|
globalOfPortRect.top -= globalToLocalY;
|
|
globalOfPortRect.left -= globalToLocalX;
|
|
globalOfPortRect.bottom -= globalToLocalY;
|
|
globalOfPortRect.right -= globalToLocalX;
|
|
|
|
/* Zoom it, globally */
|
|
ZoomRect(&hideDstRect, &globalOfPortRect, showFlag);
|
|
}
|
|
|
|
/* If showing, show windows now that zoom is done. */
|
|
if (showFlag)
|
|
ShowHide(layer, true);
|
|
}
|
|
|
|
/* ShowHideOthers. Set the invisibility of all layers but the current app and the
|
|
* desk layer.
|
|
*/
|
|
void
|
|
ShowHideOthers(Boolean showFlag)
|
|
{
|
|
LayerPtr pLayer;
|
|
|
|
pLayer = GetFrontAppLayer();
|
|
while ((pLayer = ((LayerPeek) pLayer)->nextWindow) != nil)
|
|
ShowHide(pLayer, showFlag);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
*
|
|
* Below are the kernel support routines for the layer manager.
|
|
*
|
|
* --------------------------------------------------------------------- */
|
|
|
|
/* FindAppLayer. For the given window, this routine finds the ancestral
|
|
* layer which is a child of MFLayer. If it can't be found, returns nil.
|
|
*/
|
|
LayerPtr
|
|
FindAppBaseLayer(WindowPtr window, LayerPtr layerPtr)
|
|
{
|
|
register LayerPtr ancestor;
|
|
|
|
/* Paddle upriver. Must call GetParent the first time, since WindowRecords have
|
|
* no "parent" field (parent must be derived). Once we know we have a layer, we
|
|
* can use the "parent" field directly.
|
|
*/
|
|
ancestor = GetParent(window);
|
|
while ((ancestor != nil) && (ancestor != layerPtr))
|
|
{
|
|
window = ancestor;
|
|
ancestor = ((LayerPeek) ancestor)->parent;
|
|
}
|
|
|
|
/* No-find means the given layer not below MFLayer. By (the current)
|
|
* definition, applications do not control such layers.
|
|
*/
|
|
if (ancestor == nil)
|
|
window = nil;
|
|
|
|
return (LayerPtr) window;
|
|
}
|
|
|
|
/* CancelUpdateAction. An action procedure which sets the update region to empty. */
|
|
pascal OSErr
|
|
CancelUpdateAction(WindowPeek window, LayerPeek, void *)
|
|
{
|
|
SetEmptyRgn(window->updateRgn);
|
|
return noErr;
|
|
}
|
|
|
|
/* CancelPendingUpdates. For the given layer, set the update regions of every
|
|
* window to the empty region.
|
|
*/
|
|
void
|
|
CancelPendingUpdates(LayerPtr layerPtr)
|
|
{
|
|
(void) EachWindow(layerPtr, ((LayerPeek)layerPtr)->nextWindow, nil, CancelUpdateAction, nil);
|
|
}
|
|
|
|
|
|
|
|
/* Floating Window stuff */
|
|
|
|
#pragma parameter __D0 GetHelpLayer(__D0);
|
|
pascal LayerPtr GetHelpLayer()
|
|
= {
|
|
0x2078,0x02B6, // MOVE.L ExpandMem,A0
|
|
0x2068,0x0078, // MOVE.L ExpandMemRec.emHelpGlobals(A0),A0
|
|
0x2028,0x00E6 // MOVE.L hmgLayer(A0),D0
|
|
};
|
|
|
|
pascal OSErr
|
|
C_NewFloatLayer( LayerPtr *newFloatLayer)
|
|
{
|
|
LayerPtr hmLayer;
|
|
LayerPtr currLayer;
|
|
OSErr err = noErr;
|
|
unsigned long olda5;
|
|
THz tempZone;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
if ( (*newFloatLayer = pCurrentProcess->p_floatLayer)!=nil )
|
|
{
|
|
A5Restore(olda5);
|
|
return noErr;
|
|
}
|
|
|
|
currLayer = SwapCurLayer( GetRootLayer());
|
|
SafeSetZone(tempZone, SYSZONE);
|
|
if ( IMLayer==nil )
|
|
{
|
|
if ( ( hmLayer = GetHelpLayer() )==nil )
|
|
{
|
|
hmLayer = (LayerPtr)-1;
|
|
}
|
|
err = NewLayer( &IMLayer, true, true, hmLayer, (long)nil);
|
|
}
|
|
/****
|
|
if ( err==noErr )
|
|
{
|
|
SetCurLayer( IMLayer);
|
|
err = NewLayer( newFloatLayer, true, true, (WindowPtr)-1, (long)pCurrentProcess);
|
|
}
|
|
****/
|
|
SafeRestoreZone(tempZone);
|
|
//pCurrentProcess->p_floatLayer = *newFloatLayer;
|
|
*newFloatLayer = IMLayer;
|
|
SetCurLayer( currLayer);
|
|
|
|
A5Restore(olda5);
|
|
return err;
|
|
}
|
|
|
|
pascal OSErr
|
|
C_DisposeFloatLayer( LayerPtr *floatLayer)
|
|
{
|
|
OSErr err = noErr;
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5Setup();
|
|
|
|
if ( pCurrentProcess->p_floatLayer == (*floatLayer) )
|
|
{
|
|
DisposeWindow(*floatLayer);
|
|
*floatLayer = nil;
|
|
}
|
|
else
|
|
err = paramErr;
|
|
|
|
A5Restore(olda5);
|
|
return err;
|
|
}
|
|
|