TweetFollow Us on Twitter

MACINTOSH C

Demonstration Program

Go to Contents
// 
// FloatingWindows.c
// 
//
// This program utilises custom libraries titled FloatingLib68K (for the 68K project) and
// FloatingLibPPC (for the PowerPC project), for which the source code is provided.  
// At startup, it open two floating windows and a document window.  Subsequently,
// document windows, a modal alert box, a movable modal dialog, and the Standard File 
// open dialog box may be opened and closed, and the floating windows may be hidden and 
// shown, so as to prove correct behaviour of all windows in a floating windows
// environment.
//
// The program utilises the following resources:
//
//   An 'MBAR' resource, and 'MENU' resources for Apple, File, Edit and Floaters menus
//    (preload, non-purgeable).
//
//   'WIND' resources (purgeable) (initially not visible) for the document and floating
//    windows.  
//
//   An 'ALRT' resource (purgeable), and associated 'DITL', 'alrx', and 'dftb' resources 
//    (purgeable), for an alert invoked by the user choosing the About FloatingWindows 
//    item in the Apple  menu.
//
//   A 'DLOG' resource (purgeable), and associated 'DITL', 'dlgx', and 'dftb' resources 
//    (purgeable), for a movable modal dialog box invoked when the user chooses the Find
//    item in the Edit menu.
//
//   'PICT' resources (non-purgeable) containing pictures to  be drawn in the floating 
//    windows.
//
//   A 'STR# ' resource (purgeable) containing error strings for an error alert box.
//
//   An icon family (purgeable), which provides an icon drawn in the document windows.
//
//   A 'SIZE' resource with the acceptSuspendResumeEvents, doesActivateOnFGSwitch, and
//    is32BitCompatible flags set.
//
// 

// ............................................................................. includes

#include <Appearance.h>
#include <Devices.h>
#include <StandardFile.h>
#include <ToolUtils.h>

// .............................................................................. defines  

#define rMenuBar               128
#define mApple                 128
#define  iAbout                1
#define mFile                  129
#define  iNew                  1
#define  iOpen                 2
#define  iClose                4
#define  iQuit                 12
#define mEdit                  130
#define  iFind                 9
#define mFloaters              131
#define  iColours              1
#define  iTools                2
#define rDocumentWindow        128
#define rFloaterColoursWindow  129
#define rFloaterToolsWindow    130
#define rColoursPictActive     128
#define rColoursPictInactive   129
#define rToolsPictActive       130
#define rToolsPictInactive     131
#define rAboutAlert            128
#define rFindDialog            129
#define rIconSuite             128
#define rErrorStrings          128

#define kFloaterKind                  7
#define eWindowNotCreatedError        -2
#define eInvalidWindowOrderingError   -3

// ............................................................................. typedefs

typedef pascal void (*ActivateHandlerProcPtr)
                    (WindowPtr theWindow,Boolean activateWindow);
typedef struct
{
  Handle iconSuiteHdl;
} docStruc;

typedef docStruc **docStrucHandle;

// ..................................................................... global variables

Boolean    gDone;
Boolean    gInBackground;
WindowPtr  gColoursFloaterPtr;
WindowPtr  gToolsFloaterPtr;
Handle     gIconSuiteHdl;

// .................................................................. function prototypes

void        main                              (void);
void        doInitManagers                    (void);
void        doOpenDocumentWindow              (void);
void        doOpenFloatingWindows             (void);
void        doEvents                          (EventRecord *);
void        doMouseDown                       (EventRecord *);
void        doUpdate                          (EventRecord *eventStrucPtr);
pascal void doActivateWindow                  (WindowPtr, Boolean);
pascal void doActivateColoursFloater          (WindowPtr, Boolean);
pascal void doActivateToolsFloater            (WindowPtr, Boolean);
void        doAdjustMenus                     (void);
void        doMenuChoice                      (SInt32);
void        doFloatersMenu                    (SInt16 theItem);
void        doAboutBox                        (void);
void        doStandardFileOpen                (void);
void        doOpenFindDialog                  (void);
void        doCloseDocWindow                  (void);
void        doDrawWindowContent               (WindowPtr,Boolean);
void        doErrorAlert                      (OSErr);

// .......................... function prototypes - functions in floating windows library 

OSErr        FW_GetNewCWindow                  (WindowPtr *,SInt16,WindowPtr,
                                               ActivateHandlerProcPtr,Boolean);
void         FW_DisposeWindow                  (WindowPtr);
void         FW_SelectWindow                   (WindowPtr);
void         FW_HideWindow                     (WindowPtr);
void         FW_ShowWindow                     (WindowPtr);
void         FW_DragWindow                     (WindowPtr, Point, const Rect *);
void         FW_doSuspendEvent                 (void);
void         FW_doResumeEvent                  (void);
void         FW_activateFloatsAndFirstDocWin   (void);
void         FW_deactivateFloatsAndFirstDocWin (void);
WindowPtr    FW_findFrontNonFloatWindow        (void);
void         FW_validateWindowList             (void);
SInt32       FW_GetWRefCon                     (WindowPtr);
void         FW_SetWRefCon                     (WindowPtr, SInt32);

//  main

void  main()
{
  Handle      menubarHdl;
  MenuHandle  menuHdl;
  EventRecord  eventStructure;

  // ................................................................ initialise managers

  doInitManagers();

  // .......................................................... set up menu bar and menus
  
  menubarHdl = GetNewMBar(rMenuBar);
  if(menubarHdl == NULL)
    ExitToShell();
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  menuHdl = GetMenuHandle(mApple);
  if(menuHdl == NULL)
    ExitToShell();
  else
    AppendResMenu(menuHdl,'DRVR');

  // ..................................................................... get icon suite

  GetIconSuite(&gIconSuiteHdl,rIconSuite,kSelectorAllLargeData);

  // ..................................................................... set up windows
  
  doOpenDocumentWindow();
  doOpenFloatingWindows();

  // ................................................................... enter event loop

  gDone = false;
  
  while(!gDone) 
  {
    if(WaitNextEvent(everyEvent,&eventStructure,1500,NULL))
      doEvents(&eventStructure);
  }
}

//  doInitManagers

void  doInitManagers(void)
{
  MaxApplZone();
  MoreMasters();

  InitGraf(&qd.thePort);
  InitFonts();
  InitWindows();
  InitMenus();
  TEInit();
  InitDialogs(NULL);

  InitCursor();
  FlushEvents(everyEvent,0);
  
  RegisterAppearanceClient();
}

//  doOpenDocumentWindow

void  doOpenDocumentWindow(void)
{
  WindowPtr       windowPtr;
  OSErr           osError;
  docStrucHandle  docStrucHdl;
  
  FW_validateWindowList();

  osError = FW_GetNewCWindow(&windowPtr,rDocumentWindow,(WindowPtr) -1,
                             (ActivateHandlerProcPtr) &doActivateWindow,false);
  if(osError == noErr) 
  {
    if(!(docStrucHdl = (docStrucHandle) NewHandle(sizeof(docStruc))))
      ExitToShell();
    FW_SetWRefCon(windowPtr,(SInt32) docStrucHdl);
    (*docStrucHdl)->iconSuiteHdl = gIconSuiteHdl;

    FW_ShowWindow(windowPtr);
  }
  else
    doErrorAlert(osError);
}

//  doOpenFloatingWindows

void  doOpenFloatingWindows(void)
{
  OSErr      osError;
  PicHandle  thePicture;
  
  osError = FW_GetNewCWindow(&gColoursFloaterPtr,rFloaterColoursWindow,(WindowPtr) -1,
                             (ActivateHandlerProcPtr) &doActivateColoursFloater,true);
  if(osError == noErr) 
  {
    thePicture = GetPicture(rColoursPictActive);
    SetWindowPic(gColoursFloaterPtr,thePicture);
    FW_ShowWindow(gColoursFloaterPtr);
  }
  else
    doErrorAlert(osError);

  osError = FW_GetNewCWindow(&gToolsFloaterPtr,rFloaterToolsWindow,(WindowPtr) -1,
                             (ActivateHandlerProcPtr) &doActivateToolsFloater,true);
  if(osError == noErr) 
  {
    thePicture = GetPicture(rToolsPictActive);
    SetWindowPic(gToolsFloaterPtr,thePicture);
    FW_ShowWindow(gToolsFloaterPtr);
  }
  else
    doErrorAlert(osError);
}

//  doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  SInt8  charCode;
  
  switch (eventStrucPtr->what) 
  {
    case mouseDown:      
      doMouseDown(eventStrucPtr);
      break;

    case keyDown:
    case autoKey:
      charCode = eventStrucPtr->message & charCodeMask;
      if((eventStrucPtr->modifiers & cmdKey) != 0)
      {
        doAdjustMenus();
        doMenuChoice(MenuEvent(eventStrucPtr));
      }
      break;

    case updateEvt:
      doUpdate(eventStrucPtr);
      break;

    case osEvt:  
      switch((eventStrucPtr->message >> 24) & 0x000000FF) 
      {
        case suspendResumeMessage:  
          if(eventStrucPtr->message & resumeFlag) 
          {
            gInBackground = false;
            FW_doResumeEvent();
          }
          else 
          {
            gInBackground = true;
            FW_doSuspendEvent();
          }
          break;
      }
      break;
  }
}

//  doMouseDown

void  doMouseDown(EventRecord *eventStrucPtr)
{
  SInt16      partCode;
  WindowPtr   windowPtr;
  WindowPtr   frontWindowPtr;
  Rect        growRect;
  UInt32      newSize;

  partCode = FindWindow(eventStrucPtr->where,&windowPtr);

  switch (partCode) 
  {
    case inMenuBar:
      doAdjustMenus();
      doMenuChoice(MenuSelect(eventStrucPtr->where));
      break;

    case inContent:
      frontWindowPtr = FW_findFrontNonFloatWindow();
      if(windowPtr != frontWindowPtr)
        FW_SelectWindow(windowPtr);
      break;

    case inDrag:
      FW_DragWindow(windowPtr,eventStrucPtr->where,&qd.screenBits.bounds);
      break;

    case inGrow:
      growRect = qd.screenBits.bounds;
      growRect.top   = 80; 
      growRect.left = 160;
      newSize = GrowWindow(windowPtr,eventStrucPtr->where,&growRect);
      if(newSize != 0)
        SizeWindow(windowPtr,LoWord(newSize),HiWord(newSize),true);
      break;

    case inGoAway:
      if(TrackGoAway(windowPtr,eventStrucPtr->where))
      {
        if(((WindowPeek) windowPtr)->windowKind == kFloaterKind)
          FW_HideWindow(windowPtr);
        else
          FW_DisposeWindow(windowPtr);
      }
      break;

    case inZoomIn:
    case inZoomOut:
      if(TrackBox(windowPtr,eventStrucPtr->where,partCode))
      {
        SetPort(windowPtr);
        EraseRect(&windowPtr->portRect);
        ZoomWindow(windowPtr,partCode,false);
      }
      break;
  }
}

//  doUpdate

void  doUpdate(EventRecord *eventStrucPtr)
{
  WindowPtr  windowPtr;

  windowPtr = (WindowPtr) eventStrucPtr->message;
  SetPort(windowPtr);

  BeginUpdate(windowPtr);

  EraseRgn(windowPtr->visRgn);
  doDrawWindowContent(windowPtr,((WindowPeek) windowPtr)->hilited);

  EndUpdate(windowPtr);
}

//  doActivateWindow

pascal void  doActivateWindow(WindowPtr windowPtr,Boolean becomingActive)
{
  GrafPtr  oldPort;

  GetPort(&oldPort);
  SetPort(windowPtr);

  doDrawWindowContent(windowPtr,becomingActive);

  SetPort(oldPort);
}

//  doActivateColoursFloater

pascal void  doActivateColoursFloater(WindowPtr theWindow,Boolean becomingActive)
{
  GrafPtr   oldPort;
  PicHandle thePicture;
  SInt16    pictResourceID;

  GetPort(&oldPort);
  SetPort(theWindow);

  if(becomingActive)
    pictResourceID = rColoursPictActive;
  else
    pictResourceID = rColoursPictInactive;
  thePicture = GetPicture(pictResourceID);

  DrawPicture(thePicture,&((*thePicture)->picFrame));
  SetWindowPic(theWindow,thePicture);

  if(becomingActive == false)
    SetPort(oldPort);
}

//  doActivateToolsFloater

pascal void  doActivateToolsFloater(WindowPtr theWindow,Boolean becomingActive)
{
  GrafPtr   oldPort;
  PicHandle thePicture;
  SInt16    pictResourceID;

  GetPort(&oldPort);
  SetPort(theWindow);

  if(becomingActive)
    pictResourceID = rToolsPictActive;
  else
    pictResourceID = rToolsPictInactive;
  thePicture = GetPicture(pictResourceID);

  DrawPicture(thePicture,&((*thePicture)->picFrame));
  SetWindowPic(theWindow,thePicture);

  if(becomingActive == false)
    SetPort(oldPort);
}

//  doAdjustMenus

void  doAdjustMenus(void)
{
  MenuHandle  fileMenuHdl, floatMenuHdl;
  Boolean     isVisible;

  fileMenuHdl = GetMenuHandle(mFile);
  floatMenuHdl = GetMenuHandle(mFloaters);

  if(FW_findFrontNonFloatWindow() == NULL)
    DisableItem(fileMenuHdl,iClose);
  else
    EnableItem(fileMenuHdl,iClose);

  isVisible = ((WindowPeek) gColoursFloaterPtr)->visible;  
  if(isVisible)
    CheckItem(floatMenuHdl,iColours,true);
  else
    CheckItem(floatMenuHdl,iColours,false);

  isVisible = ((WindowPeek) gToolsFloaterPtr)->visible;  
  if(isVisible)
    CheckItem(floatMenuHdl,iTools,true);
  else
    CheckItem(floatMenuHdl,iTools,false);

  DrawMenuBar();
}

//  doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  SInt16    menuID, menuItem;
  Str255    itemName;
  SInt16    daDriverRefNum;

  menuID = HiWord(menuChoice);
  menuItem = LoWord(menuChoice);

  if(menuID == 0)
    return;

  switch(menuID) 
  {
    case mApple:    
      if(menuItem == iAbout)
        doAboutBox();
      else 
      {
        GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
        daDriverRefNum = OpenDeskAcc(itemName);
      }
      break;

    case mFile:
      switch(menuItem) 
      {
        case iNew:
          doOpenDocumentWindow();
          break;
      
        case iOpen:
          doStandardFileOpen();
          break;
      
        case iClose:
          doCloseDocWindow();
          break;
      
        case iQuit:
          gDone = true;
          break;
      }
      break;

    case mEdit:
      if(menuItem == iFind)
        doOpenFindDialog();
      break;

    case mFloaters:  
      doFloatersMenu(menuItem);
      break;
  }

  HiliteMenu(0);
}

//  doFloatersMenu

void  doFloatersMenu(SInt16 menuItem)
{
  WindowPtr  floaterWindowPtr;
  Boolean    isVisible;

  if(menuItem == iColours)
    floaterWindowPtr = gColoursFloaterPtr;
  else if(menuItem == iTools)
    floaterWindowPtr = gToolsFloaterPtr;

  isVisible = ((WindowPeek) floaterWindowPtr)->visible;  

  if(isVisible)
    FW_HideWindow(floaterWindowPtr);
  else
    FW_ShowWindow(floaterWindowPtr);
}

//  doAboutBox

void  doAboutBox()
{
  SInt16  alertResult;

  FW_deactivateFloatsAndFirstDocWin();

  alertResult = Alert(rAboutAlert,NULL);

  FW_activateFloatsAndFirstDocWin();
}

//  doStandardFileOpen

void  doStandardFileOpen()
{
  SFTypeList        fileTypes;
  StandardFileReply  fileReply;

  fileTypes[0] = '****';

  FW_deactivateFloatsAndFirstDocWin();

  StandardGetFile(NULL,-1,fileTypes,&fileReply);

  FW_activateFloatsAndFirstDocWin();
}

//  doOpenFindDialog

void  doOpenFindDialog(void)
{
  DialogPtr dialogPtr;
  SInt16    itemHit;

  FW_deactivateFloatsAndFirstDocWin();

  dialogPtr = GetNewDialog(rFindDialog,NULL,(WindowPtr) -1);
  SetDialogDefaultItem(dialogPtr,kStdOkItemIndex);

  do
  {
    ModalDialog(NULL,&itemHit);
  } while((itemHit != kStdOkItemIndex) && (itemHit != kStdCancelItemIndex));

  DisposeDialog(dialogPtr);

  FW_activateFloatsAndFirstDocWin();
}

//  doCloseDocWindow

void  doCloseDocWindow()
{
  WindowPtr       windowPtr;
  docStrucHandle  docStrucHdl;

  FW_validateWindowList();

  windowPtr = FW_findFrontNonFloatWindow();

  if(windowPtr != NULL)
  {
    docStrucHdl = (docStrucHandle) (FW_GetWRefCon(windowPtr));;
    DisposeHandle((Handle) docStrucHdl);

    FW_DisposeWindow(windowPtr);
  }
}

//  doDrawWindowContent

void  doDrawWindowContent(WindowPtr windowPtr,Boolean isActive)
{
  docStrucHandle  docStrucHdl;
  Rect            theRect;
  Handle          iconSuiteHdl;
    
  docStrucHdl = (docStrucHandle) (FW_GetWRefCon(windowPtr));
  iconSuiteHdl = (*docStrucHdl)->iconSuiteHdl;

  SetRect(&theRect,5,5,37,37);

  if(isActive)
    PlotIconSuite(&theRect,kAlignNone,kTransformNone,iconSuiteHdl);
  else
    PlotIconSuite(&theRect,kAlignNone,kTransformDisabled,iconSuiteHdl);
}

//  doErrorAlert

void  doErrorAlert(OSErr errorCode)
{
  AlertStdAlertParamRec paramRec;
  Str255                errorString;
  SInt16                itemHit;

  paramRec.movable        = true;
  paramRec.helpButton     = false;
  paramRec.filterProc     = NULL;
  paramRec.defaultText    = (StringPtr) kAlertDefaultOKText;
  paramRec.cancelText     = NULL;
  paramRec.otherText      = NULL;
  paramRec.defaultButton  = kAlertStdAlertOKButton;
  paramRec.cancelButton   = 0;
  paramRec.position       = kWindowDefaultPosition;

  if(errorCode == eWindowNotCreatedError)
    GetIndString(errorString,rErrorStrings,1);
  else if(errorCode == eInvalidWindowOrderingError)
    GetIndString(errorString,rErrorStrings,2);

  StandardAlert(kAlertStopAlert,errorString,NULL,¶mRec,&itemHit);
  ExitToShell();
}

// 
// FloatingLib.c
// 

// ............................................................................. includes

#include <LowMem.h>

// .............................................................................. defines  

#define kFloaterKind                  7
#define eWindowNotCreatedError        -2
#define eInvalidWindowOrderingError   -3

#define CallActivateHandler(userRoutine,theWindow,activateWindow) \
                           (*userRoutine) (theWindow,activateWindow)

// ............................................................................. typedefs  

typedef pascal void (*ActivateHandlerProcPtr)
                    (WindowPtr theWindow,Boolean activateWindow);

typedef struct 
{
  ActivateHandlerProcPtr  activateHandler;
  Boolean                 wasVisible;
  SInt32                  replacementRefCon;
} refConExtend;

typedef refConExtend **refConExtendHandle;

// .................................................................. function prototypes

OSErr                FW_GetNewCWindow                  (WindowPtr *,SInt16,WindowPtr,
                                                       ActivateHandlerProcPtr,Boolean);
void                 FW_DisposeWindow                  (WindowPtr);
void                 FW_SelectWindow                   (WindowPtr);
void                 FW_HideWindow                     (WindowPtr);
void                 FW_ShowWindow                     (WindowPtr);
void                 FW_DragWindow                     (WindowPtr,Point,const Rect *);
void                 FW_doSuspendEvent                 (void);
void                 FW_doResumeEvent                  (void);
void                 FW_deactivateFloatsAndFirstDocWin (void);
void                 FW_activateFloatsAndFirstDocWin   (void);
WindowPtr            FW_findFrontNonFloatWindow        (void);
void                 FW_validateWindowList             (void);
SInt32               FW_GetWRefCon                     (WindowPtr);
void                 FW_SetWRefCon                     (WindowPtr,SInt32);
void                 activateWindow                    (WindowPtr);
void                 deactivateWindow                  (WindowPtr);
void                 highlightAndActivateWindow        (WindowPtr,Boolean);
WindowPtr            findLastFloatingWindow            (void);
OSErr                checkWindowOrdering               (Boolean,WindowPtr *);
WindowPtr            getNextVisibleWindow              (WindowPtr);
Boolean              getWasVisible                     (WindowPtr);
void                 setWasVisible                     (WindowPtr,Boolean);
Boolean              isWindowModal                     (WindowPtr);
void                 bringFloatersToFront              (WindowPtr);
Boolean              isFrontProcess                    (void);
Boolean              getIsWindowVisible                (WindowPtr);
WindowPtr            getNextWindow                     (WindowPtr);
SInt16               getWindowKind                     (WindowPtr);
RgnHandle            getStructureRegion                (WindowPtr);
RgnHandle            getContentRegion                  (WindowPtr);
ActivateHandlerProcPtr  getActivateHandler             (WindowPtr);
void                setActivateHandler                 (WindowPtr,ActivateHandlerProcPtr);

//  FW_GetNewCWindow

OSErr  FW_GetNewCWindow(WindowPtr *windowPtr,SInt16 windResourceID,WindowPtr behind,
                        ActivateHandlerProcPtr activateHandler,Boolean isFloater)
{
  OSErr               result;
  refConExtendHandle  refConExtendHdl;
  WindowPtr           newWindowPtr;
  SInt32              replacementRefCon;
  Boolean             isVisible;

  *windowPtr = NULL;

   result = checkWindowOrdering(isFloater,&behind);
   if(result != noErr)
     return result;  

  refConExtendHdl = (refConExtendHandle) NewHandle(sizeof(refConExtend));
  
  if((result = MemError()) == noErr)
  {
    newWindowPtr = GetNewCWindow(windResourceID,NULL,behind);

    if(newWindowPtr != NULL)
    {
      *windowPtr = newWindowPtr;

      replacementRefCon = GetWRefCon(newWindowPtr);
      SetWRefCon(newWindowPtr,(SInt32) refConExtendHdl);
      FW_SetWRefCon(newWindowPtr,replacementRefCon);

      setActivateHandler(newWindowPtr,activateHandler);

      if(isFloater)
      {
        ((WindowPeek) newWindowPtr)->windowKind = kFloaterKind;

        isVisible = ((WindowPeek) newWindowPtr)->visible;

        if(isVisible)
        {
          if(!isFrontProcess())
          {
            ShowHide(newWindowPtr,false);
            setWasVisible(newWindowPtr,true);
          }  
        }
      }
    }
    else
    {
      DisposeHandle((Handle) refConExtendHdl);
      result = eWindowNotCreatedError;
    }
  }
  return result;
}

//  FW_DisposeWindow

void  FW_DisposeWindow(WindowPtr windowPtr)
{
  refConExtendHandle  refConExtendHdl;

  if(getIsWindowVisible(windowPtr))
    FW_HideWindow(windowPtr);

  refConExtendHdl = (refConExtendHandle) GetWRefCon(windowPtr);
  if(refConExtendHdl != NULL)
    DisposeHandle((Handle) refConExtendHdl);

  DisposeWindow(windowPtr);
}

//  FW_SelectWindow

void  FW_SelectWindow(WindowPtr windowPtr)
{
  Boolean    frontProcess, isFloatingWindow;
  WindowPtr  currentFrontWindowPtr, lastFloatingWindowPtr;

  frontProcess = isFrontProcess();

  if(getWindowKind(windowPtr) == kFloaterKind) 
  {
    isFloatingWindow = true;
    currentFrontWindowPtr = FrontWindow();
  }
  else 
  {
    isFloatingWindow = false;
    currentFrontWindowPtr = FW_findFrontNonFloatWindow();
    lastFloatingWindowPtr = findLastFloatingWindow();
  }

  if(currentFrontWindowPtr != windowPtr) 
  {
    if(isFloatingWindow)
    {
      BringToFront(windowPtr);
    }
    else
    {
      if(frontProcess)
        deactivateWindow(currentFrontWindowPtr);

      if(lastFloatingWindowPtr == NULL)
      {
        BringToFront(windowPtr);
      }
      else
      {
        SendBehind(windowPtr,lastFloatingWindowPtr);
      }

      if(frontProcess)
        activateWindow(windowPtr);
    }
  }
}

//  FW_HideWindow

void  FW_HideWindow(WindowPtr windowPtr)
{
  WindowPtr  frontFloatWindowPtr, frontNonFloatWindowPtr, windowBehind;

  if(getIsWindowVisible(windowPtr) == false)
    return;
  
  frontFloatWindowPtr = FrontWindow();
  if(getWindowKind(frontFloatWindowPtr) != kFloaterKind)
    frontFloatWindowPtr = NULL;

  frontNonFloatWindowPtr = FW_findFrontNonFloatWindow();
  
  ShowHide(windowPtr,false);
  
  if(windowPtr == frontFloatWindowPtr)
  {
    windowBehind = getNextVisibleWindow(windowPtr);

    if((windowBehind != NULL) && (getWindowKind(windowBehind) == kFloaterKind))
      BringToFront(windowBehind);
  }
  else if(windowPtr == frontNonFloatWindowPtr)
  {
    windowBehind = getNextVisibleWindow(windowPtr);
    
    if(windowBehind != NULL)
    {
      SendBehind(windowPtr,windowBehind);

      if(isFrontProcess())
        activateWindow(windowBehind);
    }
  }
}

//  FW_ShowWindow

void  FW_ShowWindow(WindowPtr windowPtr)
{
  Boolean                 frontProcess, needsActivate, highlightState;
  Boolean                 modalUp, showingModal;
  SInt16                  windowKind;
  WindowPtr               windowBehind;
  WindowPtr               frontNonFloatWindowPtr;
  ActivateHandlerProcPtr  activateHandler;

  if(getIsWindowVisible(windowPtr) != false)
    return;

  frontProcess = isFrontProcess();

  windowKind = getWindowKind(windowPtr);

  modalUp = isWindowModal(FrontWindow());

  showingModal = isWindowModal(windowPtr);
  if(showingModal)
    BringToFront(windowPtr);

  FW_validateWindowList();

  if(!frontProcess && windowKind == kFloaterKind)
  {
    setWasVisible(windowPtr,true);
    return;
  }

  if(frontProcess)
  {
    if(showingModal)
    {
      highlightState = true;
      needsActivate = true;
    }
    else if(modalUp)
    {
      highlightState = false;
      needsActivate = false;
    }
    else
    {
      if(windowKind == kFloaterKind)
      {
        highlightState = true;
        needsActivate = true;
      }
      else
      {
        frontNonFloatWindowPtr = FW_findFrontNonFloatWindow();
        if(frontNonFloatWindowPtr == NULL)
        {
          highlightState = true;
          needsActivate = true;
        }
        else
        {
          highlightState = false;
          needsActivate = false;

          windowBehind = getNextWindow(windowPtr);
          while(windowBehind != NULL)
          {
            if(windowBehind == frontNonFloatWindowPtr)
            {
              deactivateWindow(frontNonFloatWindowPtr);
              highlightState = true;
              needsActivate = true;
              break;
            }
            windowBehind = getNextVisibleWindow(windowBehind);
          }
        }
      }
    }
  }
  else
  {
    highlightState = false;
    needsActivate = false;
  }

  HiliteWindow(windowPtr,highlightState);
  ShowHide(windowPtr,true);

  if(needsActivate) 
  {
    activateHandler = getActivateHandler(windowPtr);
    if(activateHandler != NULL)
      CallActivateHandler(activateHandler,windowPtr,true);
  }
}

//  FW_DragWindow

void  FW_DragWindow(WindowPtr windowPtr,Point startPoint,const Rect *draggingBounds)
{
  SInt16    topLimit, newHorizontalWindowPosition, newVerticalWindowPosition;
  Rect      dragRect;
  SInt16    horizontalOffset, verticalOffset;
  GrafPtr   savePort, windowManagerPort;
  KeyMap    keyMap;
  Boolean   commandKeyDown = false;
  RgnHandle dragRegionHdl, windowContentRegionHdl;
  SInt32    dragResult;

  if(StillDown()) 
  {
    topLimit = LMGetMBarHeight() + 4;
    dragRect = *draggingBounds;
    if(dragRect.top < topLimit)
      dragRect.top = topLimit;
  
    GetPort(&savePort);
    GetWMgrPort(&windowManagerPort);
    SetPort(windowManagerPort);

    SetClip(GetGrayRgn());

    GetKeys(keyMap);
    if(keyMap[1] & 0x8000)
      commandKeyDown = true;
  
    if((commandKeyDown == true) || (getWindowKind(windowPtr) != kFloaterKind)) 
    {
      if(commandKeyDown == false)
        ClipAbove(FW_findFrontNonFloatWindow());
      else
        ClipAbove(windowPtr);
    }

    dragRegionHdl = NewRgn();
    CopyRgn(getStructureRegion(windowPtr),dragRegionHdl);
  
    dragResult = DragGrayRgn(dragRegionHdl,startPoint,&dragRect,&dragRect,noConstraint,
                             NULL);
    SetPort(savePort);

    if(dragResult != 0) 
    {
      horizontalOffset = dragResult & 0xFFFF;
      verticalOffset = dragResult >> 16;

      if(verticalOffset != -32768) 
      {
        windowContentRegionHdl = NewRgn();
        CopyRgn(getContentRegion(windowPtr),windowContentRegionHdl);
  
        newHorizontalWindowPosition = (**windowContentRegionHdl).rgnBBox.left + 
                                      horizontalOffset;
        newVerticalWindowPosition = (**windowContentRegionHdl).rgnBBox.top + 
                                    verticalOffset;
        MoveWindow(windowPtr,newHorizontalWindowPosition,newVerticalWindowPosition,
                   false);
                   
        DisposeRgn(windowContentRegionHdl);
      }
    }

    if(commandKeyDown == false)
      FW_SelectWindow(windowPtr);

    DisposeRgn(dragRegionHdl);
  }
}

//  FW_doSuspendEvent

void  FW_doSuspendEvent(void)
{
  WindowPtr  currentWindowPtr;
  Boolean    windowIsVisible;

  currentWindowPtr = LMGetWindowList();

  if(isWindowModal(FrontWindow()))
    return;

  while((currentWindowPtr != NULL) && 
        (getWindowKind(currentWindowPtr) == kFloaterKind))
  {
    windowIsVisible = getIsWindowVisible(currentWindowPtr);
    setWasVisible(currentWindowPtr,windowIsVisible);

    if(windowIsVisible)
      ShowHide(currentWindowPtr,false);
      
    currentWindowPtr = getNextWindow(currentWindowPtr);
  }

  currentWindowPtr = FW_findFrontNonFloatWindow();
  if(currentWindowPtr != NULL)
    deactivateWindow(currentWindowPtr);
}

//  FW_doResumeEvent

void  FW_doResumeEvent(void)
{
  WindowPtr  currentWindowPtr;
  Boolean    windowWasVisible;

  currentWindowPtr = LMGetWindowList();

  if(isWindowModal(FrontWindow()))
    return;
    
  while((currentWindowPtr != NULL) &&
        (getWindowKind(currentWindowPtr) == kFloaterKind))
  {
    windowWasVisible = getWasVisible(currentWindowPtr);
    if(windowWasVisible) 
    {
      ShowHide(currentWindowPtr,true);
      activateWindow(currentWindowPtr);
    }

    currentWindowPtr = getNextWindow(currentWindowPtr);
  }

  currentWindowPtr = FW_findFrontNonFloatWindow();
  if(currentWindowPtr != NULL)
    activateWindow(currentWindowPtr);
}

//  FW_activateFloatsAndFirstDocWin

void  FW_activateFloatsAndFirstDocWin(void)
{
  WindowPtr  firstWindowPtr, secondDocumentWindowPtr, currentWindowPtr;
  Boolean    frontProcess;

  if(isWindowModal(FrontWindow()))
    return;

  frontProcess = isFrontProcess();

  if(frontProcess == false)
    FW_doSuspendEvent();
  else 
  {
    firstWindowPtr = FrontWindow();
    secondDocumentWindowPtr = FW_findFrontNonFloatWindow();

    if(secondDocumentWindowPtr != NULL)
      secondDocumentWindowPtr = getNextWindow(secondDocumentWindowPtr);

    currentWindowPtr = firstWindowPtr;

    while(currentWindowPtr != secondDocumentWindowPtr) 
    {
      if(getIsWindowVisible(currentWindowPtr))
        activateWindow(currentWindowPtr);
      currentWindowPtr = getNextWindow(currentWindowPtr);
    }
  }
}

//  FW_deactivateFloatsAndFirstDocWin

void  FW_deactivateFloatsAndFirstDocWin(void)
{
  WindowPtr  firstWindowPtr, secondDocumentWindowPtr, currentWindowPtr;

  FW_validateWindowList();

  firstWindowPtr = FrontWindow();
  secondDocumentWindowPtr = FW_findFrontNonFloatWindow();

  if(secondDocumentWindowPtr != NULL)
    secondDocumentWindowPtr = getNextWindow(secondDocumentWindowPtr);

  currentWindowPtr = firstWindowPtr;

  while(currentWindowPtr != secondDocumentWindowPtr) 
  {
    if(getIsWindowVisible(currentWindowPtr))
      deactivateWindow(currentWindowPtr);
    currentWindowPtr = getNextWindow(currentWindowPtr);
  }
}

//  FW_findFrontNonFloatWindow

WindowPtr  FW_findFrontNonFloatWindow(void)
{
  WindowPtr  windowPtr;

  windowPtr = FrontWindow();

  while((windowPtr != NULL) && (getWindowKind(windowPtr) == kFloaterKind)) 
  {
    do 
    {
      windowPtr = getNextWindow(windowPtr);
    } while((windowPtr != NULL) && (getIsWindowVisible(windowPtr) == false));
  }

  return windowPtr;
}

//  FW_validateWindowList

void  FW_validateWindowList(void)
{
  WindowPtr  windowPtr;
  WindowPtr  lastFloatingWindowPtr;

  windowPtr = LMGetWindowList();
  lastFloatingWindowPtr = findLastFloatingWindow();

  if(lastFloatingWindowPtr == NULL)
    return;

  if(getWindowKind(windowPtr) == kFloaterKind)
    return;

  if(isWindowModal(windowPtr))
    return;

  bringFloatersToFront(windowPtr);
}

//  FW_GetWRefCon

SInt32  FW_GetWRefCon(WindowPtr windowPtr)
{
  refConExtendHandle  refConExtendHdl;

  refConExtendHdl =(refConExtendHandle) GetWRefCon(windowPtr);
  if(refConExtendHdl != NULL)
    return((*refConExtendHdl)->replacementRefCon);
  else
    return 0;
}

//  FW_SetWRefCon

void  FW_SetWRefCon(WindowPtr windowPtr,SInt32 refCon)
{
  refConExtendHandle  refConExtendHdl;

  refConExtendHdl =(refConExtendHandle) GetWRefCon(windowPtr);
  if(refConExtendHdl != NULL)
  {
    (*refConExtendHdl)->replacementRefCon = refCon;
  }
}

//  activateWindow

void  activateWindow(WindowPtr windowPtr)
{
  highlightAndActivateWindow(windowPtr,true);
}

//  deactivateWindow

void  deactivateWindow(WindowPtr windowPtr)
{
  highlightAndActivateWindow(windowPtr,false);
}

//  highlightAndActivateWindow

void  highlightAndActivateWindow(WindowPtr windowPtr,Boolean activate)
{
  ActivateHandlerProcPtr  activateHandler;
  
  if(windowPtr == NULL)
    return;

  activateHandler = getActivateHandler(windowPtr);

  HiliteWindow(windowPtr,activate);

  if(activateHandler != NULL)
    CallActivateHandler(activateHandler,windowPtr,activate);
}

//  findLastFloatingWindow

WindowPtr  findLastFloatingWindow(void)
{
  WindowPtr  windowPtr;

  WindowPtr  lastFloatingWindowPtr;

  windowPtr = LMGetWindowList();
  lastFloatingWindowPtr = NULL;
  
  while(windowPtr != NULL) 
  {
    if(getWindowKind(windowPtr) == kFloaterKind)
      lastFloatingWindowPtr = windowPtr;

    windowPtr = getNextWindow(windowPtr);
  }

  return lastFloatingWindowPtr;
}

//  checkWindowOrdering

OSErr  checkWindowOrdering(Boolean isFloater,WindowPtr *behind)
{
  OSErr      result = noErr;
  WindowPtr  lastFloaterPtr;
  
  if(isFloater)
  {
    if(((*behind == NULL) && (FW_findFrontNonFloatWindow() != NULL)) ||
       ((*behind != (WindowPtr) -1) && (getWindowKind(*behind) != kFloaterKind))  )
    {
      result = eInvalidWindowOrderingError;
    }
  }
   else
  {
    lastFloaterPtr = findLastFloatingWindow();
 
    if(lastFloaterPtr != NULL)
    {
      if(*behind == (WindowPtr) -1)
      {
        *behind = lastFloaterPtr;
      }
      else if(*behind != NULL && *behind != lastFloaterPtr &&
              (getWindowKind(*behind) == kFloaterKind))
      {
        result = eInvalidWindowOrderingError;
      }
    }
  }
  
   return result;
}

//  getNextVisibleWindow

WindowPtr  getNextVisibleWindow(WindowPtr windowPtr)
{
  WindowPtr  nextWindowPtr;
  
  nextWindowPtr = getNextWindow(windowPtr);

  while(nextWindowPtr != NULL)
  {
    if(getIsWindowVisible(nextWindowPtr))
      break;
    nextWindowPtr = getNextWindow(nextWindowPtr);
  }

  return nextWindowPtr;
}

//  getWasVisible

Boolean  getWasVisible(WindowPtr windowPtr)
{
  refConExtendHandle  refConExtendHdl;
  
  refConExtendHdl =(refConExtendHandle) GetWRefCon(windowPtr);

  if(refConExtendHdl != NULL)
    return((*refConExtendHdl)->wasVisible);
  else
    return false;
}

//  setWasVisible

void  setWasVisible(WindowPtr windowPtr,Boolean wasVisible)
{
  refConExtendHandle  refConExtendHdl;

  refConExtendHdl = (refConExtendHandle) GetWRefCon(windowPtr);

  if(refConExtendHdl != NULL)
    (*refConExtendHdl)->wasVisible = wasVisible;
}

//  isWindowModal

Boolean  isWindowModal(WindowPtr windowPtr)
{
  SInt16  windowVariant;
  SInt16  windowKind;

  windowVariant = GetWVariant(windowPtr);
  windowKind = getWindowKind(windowPtr);

  if(windowKind == kDialogWindowKind && (windowVariant == 2 || windowVariant == 3))
    return true;
  else
    return false;
}

//  bringFloatersToFront

void  bringFloatersToFront(WindowPtr windowPtr)
{
  WindowPtr  thisFloaterPtr;

  while(windowPtr != NULL && getWindowKind(windowPtr) != kFloaterKind)
    windowPtr = getNextWindow(windowPtr);

  if(windowPtr == NULL)
    return;

  thisFloaterPtr = windowPtr;

  bringFloatersToFront(getNextWindow(windowPtr));

  BringToFront(thisFloaterPtr);
}

//  isFrontProcess

Boolean  isFrontProcess(void)
{
  ProcessSerialNumber  frontPSN, currentPSN;
  OSErr                getFrontProcessResult, getCurrentProcessResult;
  Boolean              isSameProcess = false;

  getFrontProcessResult = GetFrontProcess(&frontPSN);
  getCurrentProcessResult = GetCurrentProcess(¤tPSN);
  
  if((getFrontProcessResult == noErr) && (getCurrentProcessResult == noErr))
    SameProcess(&frontPSN,¤tPSN,&isSameProcess);

  return(isSameProcess);
}

//  getIsWindowVisible

Boolean  getIsWindowVisible(WindowPtr windowPtr)
{
  return(((WindowPeek) windowPtr)->visible);
}

//  getNextWindow

WindowPtr  getNextWindow(WindowPtr windowPtr)
{
  return((WindowPtr) ((WindowPeek) windowPtr)->nextWindow);
}

//  getWindowKind

SInt16  getWindowKind(WindowPtr windowPtr)
{
  return(((WindowPeek) windowPtr)->windowKind);
}

//  getStructureRegion

RgnHandle  getStructureRegion(WindowPtr windowPtr)
{
  return(((WindowPeek) windowPtr)->strucRgn);
}

//  getContentRegion

RgnHandle  getContentRegion(WindowPtr windowPtr)
{
  return(((WindowPeek) windowPtr)->contRgn);
}

//  getActivateHandler

ActivateHandlerProcPtr  getActivateHandler(WindowPtr windowPtr)
{
  refConExtendHandle  refConExtendHdl;

  refConExtendHdl = (refConExtendHandle) GetWRefCon(windowPtr);
  if(refConExtendHdl != NULL)
    return((*refConExtendHdl)->activateHandler);
  else
    return NULL;
}

//  setActivateHandler

void  setActivateHandler(WindowPtr windowPtr,ActivateHandlerProcPtr activateHandler)
{
  refConExtendHandle  refConExtendHdl;

  refConExtendHdl = (refConExtendHandle) GetWRefCon(windowPtr);

  if(refConExtendHdl != NULL)
    (*refConExtendHdl)->activateHandler = activateHandler;
}

// 

Demonstration Program Comments

With regard to the source code file FloatingLib.c, which contains all the special
functions required to implement floating windows, two options are available.
Firstly,FloatingLib.c may be added to the FloatingWindows. project, along with
the source codefile FloatingWindows.c, in the normal way.  Secondly, FloatingLib.c
may be compiled as alibrary (68K or PowerPC, as required) and added to the 
FloatingWindows. project as such. The latter option has been adopted in the
accompanying demonstration program package.

When this program is run, the user should open and close document windows, hide and show
the floating windows (using the Floater menu items and the windows' close boxes), open
and close the About FloatingWindows... modal alert box, open and close the Find movable
modal dialog box (using the Find item in the Edit menu), open and close the Standard File
open dialog, and send/bring the application to the background/foreground.  In particular,
the user should observe the following:

*   Document window behaviour, in terms of activation and deactivation, is identical to
    that observed in a normal window environment, including when:

*   The program is sent to the background and brought to the foreground.

*   A document window is closed or a new document window is opened.

*   The About FloatingWindows... modal alert box, the Find... movable modal dialog box,
    or the Standard File open dialog is invoked.

*   An inactive document window is dragged with the Command key held down.

*   Floating window behaviour is as follows:

*   The floating window frames are drawn in the inactive state, and their content is
    dimmed, when the alert and dialog boxes are invoked.

*   The floating windows are hidden when the application is sent to the background and 
    shown again when the application is brought to the foreground.

*   When document windows are clicked, the icon at the top left of the window is drawn
    in such a way (normal or dimmed) as to prove that the application "knows" which
    document windows to activate and deactivate.

FloatingWindows.c

#define

rDocumentWindow and the following two constants represent the resource IDs of the 'WIND'
resources for document windows, the "Colours" floating window, and the "Tools" floating
window.  The next four constants represent the resource IDs of four 'PICT' resources used
by the floating windows.

kFloaterKind will be assigned to the windowKind field of the floating window window
structures.  The next two constants represent error codes that may be returned by a call
to the window creation function in FloatingLib.c.

#typedef

A document structure of type docStruc will be created for each document window.  For the
purposes of this demonstration, this is simply to prove the correct operation of the two
substitute functions FW_SetWRefCon and FW_GetWRefCon.  (These functions will
assign/retrieve the handle to the window's document structure to/from a reference
constant field in a special structure created by the window creation function in
FloatingLib.c.)

Global Variables

gColoursFloaterPtr and gToolsFloaterPtr will be assigned pointers to the colour 
graphics port structures for the floating windows.  gIconSuiteHdl will be assigned a 
handle to an icon suite.

main

Following the call to RegisterAppearanceClient, routine descriptors are created for the
three window activation functions.

The call to GetIconSuite creates an icon family.  The appropriate icon from this family
will be drawn in the top left corner of document windows.  The handle will be assigned to
the single field in the document window's document structure.

The next two lines call application-defined functions which open one document window and
both floating windows.

doOpenDocumentWindow

doOpenDocumentWindow opens a document window.

Firstly, FW_ validateWindowList is called as a safety measure to ensure that all floating
windows are in front of all document windows (if any).

FW_GetNewCWindow is called to create the window.  The universal procedure pointer to the
document window activation function is passed in the fourth parameter.  false is passed
in the fifth parameter to indicate to FW_GetNewCWindow that this is not a floating
window.

If FW_GetNewCWindow does not return an error, a block for a document structure is created
and the handle is assigned by FW_SetWRefCon to the reference constant field of a
structure created by FW_GetNewCWindow.  (FW_GetNewCWindow assigns the handle to this
latter structure to the window's refCon field.)  The handle to the icon family is
assigned to the single field of the document structure.

FW_ShowWindow is called to show the window.

If FW_GetNewCWindow does return an error, an application-defined function is called to
handle the error.

doOpenFloatingWindows

doOpenFloatingWindows opens both floating windows.

For each of the two floating windows, FW_GetNewCWindow is called to create the window. 
 A pointer to the appropriate window activation function is passed in the fourth 
parameter.  true is passed in the fifth parameter to indicate to FW_GetNewCWindow that 
this is a floating window.

If FW_GetNewCWindow does not return an error, GetPicture loads the specified 'PICT'
resource, SetWindowPic stores the handle to the picture structure in the windowPic field
of the window structure (meaning that the Window Manager will draw the picture in the
window instead of generating update events for it), and FW_ShowWindow is called to
display the floating window.

If FW_GetNewCWindow does return an error, an application-defined function is called to
handle the error.

doEvents

Note that activate events are ignored in the main event loop area because, in a floating
windows environment, the normal windows activation/deactivation mechanism must be
over-ruled.

At the suspendResumeMessage case in the osEvt case, FW_doResumeEvent is called for a
resume event and FW_doResumeEvent is called for a suspend event.

doMouseDown

At the inContent case, if the window in which the mouse-down occurred is not the front
non-floating window, FW_SelectWindow is called.

At the inDrag case, FW_DragWindow is called.

At the inGoAway case, if the window is one of the floating windows, FW_HideWindow is
called to hide the window.  If the window is a document window, FW_DisposeWindow is
called to dispose of the window.

doUpdate

An update event results in a call to doDrawWindowContent, which draws an icon in the
window in the appropriate state (normal or dimmed).  (Recall that, because of the
setWindowPic calls in the function doOpenFloatingWindows, the floating windows will not
receive update events.  Accordingly, the only windows redrawn by the application in this
demonstration are the document windows.)

doActivateWindow

doActivateWindow is called from functions within FloatingLib.c.  It is not called from
within FloatingWindows.c.

doActivateWindow is the window activation function for document windows.
doDrawWindowContent is called to draw an icon in the window in the state (normal or
dimmed) specified by the becomingActive parameter.

doActivateColoursFloater and doActivateToolsFloater

doActivateColoursFloater and doActivateToolsFloater are called from functions within
FloatingLib.c.  They are not called from within FloatingWindows.c.

These two functions are the window activation functions for the floating windows. 
Depending on whether the window is being activated or deactivated, the appropriate
picture (normal or dimmed) is drawn in the window and SetWindowPict is called to store
the handle to the picture structure in the windowPic field of the window structure
(meaning that the Window Manager will draw the picture in the window instead of
generating update events for it).

doAdjustMenus

FW_findFrontNonFloatWindow() is called to determine whether any document windows are
currently open.  If not, the Close item in the File menu is disabled.

If the floating windows are currently hidden, the relevant item in the Floaters menu is
unchecked, otherwise it is checked.

doFloatersMenu

doFloatersMenu further processes Floater menu choices.

If the floating window relating to the chosen menu item is currently showing,
FW_HideWindow is called to hide the window, otherwise FW_ShowWindow is called to show the
window.

doAboutBox, doStandardFileOpen, and doOpenFindDialog

doAboutBox is called when the user chooses the About FloatingWindows... item in the Apple
menu.  FW_deactivateFloatsAndFirstDocWin is called to deactivate all the document and
floating windows before Alert is called to display the About alert box.  When the alert
box is dismissed, FW_activateFloatsAndFirstDocWin is called to return the windows to the
activation status they were in prior to the call to FW_deactivateFloatsAndFirstDocWin.

The same activation/deactivation procedure is followed in the functions
doStandardFileOpen and doOpenFindDialog.

doCloseDocWindow

doCloseDocWindow is called in response to a choice of the Close item in the File menu and
to a click in a document window's close box.

FW_validateWindowList is called as a safety measure to ensure that all floating windows
are in front of all document windows.

The call to FW_findFrontNonFloatWindow returns a pointer to the front document window
(and also confirms that at least one document window is open.  FW_GetWRefCon is called to
get the handle to the window's document structure, which allows that block to be disposed
of. FW_DisposeWindow is then called to dispose of the block containing the special data
structure created by FW_GetNewCWindow, to remove the window from the screen and window
list, and to discard all the window's data storage.

doDrawWindowContent

doDrawDocWindowContent is called when an update event is received and when the document
window activate function is called from within FloatingLib.c.  It simply draws an icon in
the top left of the window in the state (normal or dimmed) specified by the isActive
formal parameter.

FloatingLib.c

FloatingLib.c contains the special functions required to support a floating windows
environment, including functions which are called in lieu of the usual calls to
GetNewCWindow, DisposeWindow, SelectWindow, HideWindow, ShowWindow, DragWindow,
SetWRefCon, and GetWRefCon.

#define

kFloaterKind will be assigned to the windowKind field of the window structures for 
floating windows.  The next two constants represent error codes returned by 
FW_GetNewCWindow.  CallActivateHandler simply makes the call to the appropriate window 
activation handler at the bottom of the functions FW_ShowWindow and 
highlightAndActivateWindow a little less cryptic.

#typedef

A structure of type refConExtend will be created for all windows, and a handle to 
that structure will be assigned to the window structure's refCon field.  A pointer to 
the relevant window activation function will be assigned to the first field.  The 
second field will be used to keep track of the window's visibility status.  The third 
field may be used by the application for those purposes for which it would normally use 
the window structure's refCon field.

FW_GetNewCWindow

To create a window, FW_GetNewCWindow is called in lieu of the usual call to
GetNewCWindow.  The isFloater parameter specifies whether the window is to be a document
window or a floating window.

At the first line, failure is assumed.  

checkWindowOrdering is called to ensure that the behind formal parameter is not
attempting to open the window at an inappropriate "behind" or "in front of" location in
the window list.  As part of this process, and in the case of document windows,
checkWindowOrdering changes a behind assignment of (WindowPtr) -1 to the pointer to the
last floating window, causing the window to be opened behind that floating window rather
than in front of all windows.  Apart from that particular case, inappropriate behind
specifications will cause an error to be returned.

The call to NewHandle creates a block for a refConExtend structure.  If this call is not
successful, the function exits and an error code is returned to the calling function.

The call to GetNewCWindow creates the window, following which a pointer to the window is 
returned to the calling function.  The next three lines assign the handle to the 
refConExtend structure to the window structure's refCon field and assign the previous 
value in the refCon field to the refConExtend structure's replacementRefCon field.  The 
next line assigns the pointer to the window's activation function to the refConExtend 
structure's activateHandler field.

If the visible field of the window's window structure indicates that the window is
currently visible, and if the application is currently not the front process, ShowHide is
called to hide the window and setWasVisible is called to record the visibility status of
the window by assigning true to the refConExtend structure's wasVisible field.  (This
block caters for the possibility of windows being created while the application is in the
background, for example, by Apple events.  It prevents the window from being highlighted
on creation.)

If the call to GetNewCWindow was not successful, the subsequent if block is bypassed,
DisposeHandle is called to dispose of the refConExtend structure, and an error code is
returned to the calling function.

FW_DisposeWindow

FW_DisposeWindow is called in lieu of the usual call to DisposeWindow.

If the specified window (which will invariably be a document window) is visible, a call
is made to FW_HideWindow so that the next document window in the list (if any) is
activated.  The window's refConExtend structure is then disposed of, following which
DisposeWindow is called to remove the window from the screen, remove it from the window
list, and discard all its data storage.

FW_SelectWindow

FW_SelectWindow is called in lieu of the usual call to SelectWindow.  It selects the
window and brings it to the front of its section of the window list.  Selecting a
floating window makes it the absolute frontmost window on the screen, whereas selecting a
document window makes it the frontmost window behind the floating windows (or, if no
floating windows are open, the absolute frontmost window).

The first line determines whether the application is the front process.

If the window clicked is of the floating kind, that fact is recorded and the pointer to
the current front floating window is retrieved.  Otherwise, if the window clicked is a
document window, that fact is recorded, and pointers to the first document window and
last floating window in the window list are retrieved.

If the window clicked is not the current front window in either the floating or document
window sections of the window list and if the window clicked is a floating window, that
window is brought to the very front of the list by the call to BringToFront.  Otherwise,
if the window clicked is a document window: if the application is the front process, the
current front document window is deactivated; if their are no floating windows,
BringToFront is called to bring the window to the front; if there are floating windows,
SendBehind is called to locate the window immediately behind the last floating window; if
the application is the front process, the window is activated.

FW_HideWindow

FW_HideWindow is called in lieu of the usual call to HideWindow.  If the window is the
frontmost window, it is moved behind the window immediately behind it.

At the first two lines, if the window is not visible, the function returns without doing
anything.

The next line gets the pointer to the frontmost window.  If this window is not a floating
window, a variable is set to record that fact.

The next line gets the pointer to the first document window.

The call to ShowHide hides the specified window without affecting the front-to-back
ordering of the windows.

If the newly hidden window is the front floating window, and if the next window in the
list (if any) is a floating window, BringToFront is called to bring that next window to
the front.  Otherwise, if the newly hidden window is the first document window, and if
there is another visible document window, SendBehind is called to move the newly hidden
window behind that visible document window.  Also, if the application is the front
process, that visible document window is activated.

FW_ShowWindow

FW_ShowWindow is called in lieu of the usual call to ShowWindow.  If the specified
(hidden) window is the frontmost document window, the window behind it is deactivated and
the specified window is activated.  If the window is modal, the function makes sure it is
in front.

At the first two lines, if the specified window is currently visible, the function
returns without doing anything.  The next line determines whether the application is the
front process.

The next line records whether the specified window is a floating window.  The line after
that records whether the front window is a modal window.

At the next block, if the specified window is a modal window, BringToFront is called to
bring it to the front (without activating it).

Before proceeding further, FW_validateWindowList is called as a safety measure to ensure
that all windows in the window list are in the right place.

If the application is not the front process, and the specified window is a floating
window, it is marked as visible so that it will be shown on resume.  (The function
setWasVisible assigns true to the wasVisible field of the window's refConExtend
structure.)

The large if block executes only if the application is the front process.  If the
specified window is modal, two local variables are set to true (ensuring that modal
windows will always be activated and highlighted).  If the front window is modal, these
variables are set to false (ensuring that, whatever the specified window type, it will
not be activated and highlighted when a modal window is up).  If neither the specified
nor front window is modal:

*   If the specified window is a floating window, the two local variables are set to
    true.  (New floating windows are always highlighted and activated.)

*   If the specified window is a document window, and it is the only document window,
    the two local variables are set to true so that it will be highlighted and
    activated.  If it is not the only document window: the two local variables are 
    initially set to false (assume the specified window is behind the front one); the
    window list is walked to determine whether the specified window is coming up in
    front of the frontmost document window, in which case the front document window
    is deactivated and the variables are set so that the specified window will be
    highlighted and activated.

If the application is not the front process (the last else block), the two local
variables are set to false so that no highlighting/activation will occur.

HiliteState is called to either unhighlight or highlight the specified window depending 
on the result of the previous machinations.  If the previous machinations determined 
that the window should be activated, pointer to the window's activation function is 
retrieved from the window's refConExtend structure and passed in a call to 
CallActivateHandlerProc, which causes the activation function to execute.

FW_DragWindow

FW_DragWindow is called in lieu of the usual call to DragWindow.  It drags the specified
window around, ensuring that document windows remain behind floating windows.  Like
DragWindow, FW_DragWindow does not bring the window forward if the Command key is held
down during the drag.

WaitMouseUp tests whether the mouse button has remained down since the last mouse-down
event.  If it has, the following occurs.

The first block adjusts the top of the dragging rectangle so that it is below the menu
bar.  The next block saves the current colour graphics port and sets the window manager
port as the current colour graphics port.  The call to SetClip sets the clipping region
to the region below the menu bar.

The next three lines check whether the Command key is down and, if so, set a variable to
record that fact.  

If the Command key is not down and the window is not a floating window, the ClipAbove
call at sets the clipping region to the gray region minus the structure regions of all
windows in front of the front non-floating window. (In this instance, the front document
window is being dragged, so the windows in front are the floating windows.)  If the
window is not a floating window and the Command key is down, the ClipAbove call sets the
clipping region to the gray region minus the structure regions of all windows in front of
the window being dragged. (In this instance, there could be one or more document windows,
as well as floating windows, above the document window being dragged.)

The next two lines create a region to drag, specifically, the structure region of the
specified window.  This is passed as a parameter to the call to DragGrayRgn, which moves
a dotted outline of the region, following the mouse as it moves and retaining control
until the mouse button is released.

When the mouse button is released, SetPort sets the colour graphics port to the saved
earlier.

DragGrayRgn returns an SInt32.  If the mouse was outside the slop rectangle when the
button was released, -32768 is returned in both words, otherwise the high word contains
the vertical distance moved and the low word contains the horizontal distance moved.  If
the value returned is not zero, the value in both words is retrieved.  If the mouse was
not outside the slop rectangle, the new horizontal and vertical global coordinates are
calculated and passed as a parameter in the MoveWindow call, which moves the window to
the new location without bringing it to the front.

If the Command key was not down during the drag (the third last line), the call to
FW_SelectWindow brings the window to the absolute front of the window list (floating
window) or to the front of the document windows section of the list (document window).

FW_doSuspendEvent

FW_doSuspendEvent hides any visible floating windows and deactivates the frontmost
document window.  It should be called when the application receives a suspend event.

The first line gets the pointer to the front window's window structure from the
low-memory global WindowList.

If the first visible window is modal, the floating and front document windows will
already be deactivated, so the function simply returns.

The while loop executes for all floating windows.  The current visibility status of the
window is saved to the wasVisible field of its window's refConExtend structure.  If the
window is visible, it is hidden without affecting the front-to-back ordering of the open
windows.

At the last block, if there are any document windows, the frontmost document window is
deactivated.

FW_doResumeEvent

FW_doResumeEvent shows all floating windows which were hidden by FW_doSuspendEvent.  As
each window is shown, the activation function for that window is called.  This function
should be called when the application receives a resume event.

The first line gets the pointer to the front window's window structure from the
low-memory global WindowList.  

If the first visible window is modal, the floating and front document windows will
already be activated, so the function simply returns.

The while loop executes for all floating windows.  The saved visibility status of the
window is retrieved from the wasVisible field of its window's refConExtend structure.  If
the window was visible when FW_doSuspendEvent was called, it is shown without affecting
the front-to-back ordering of the open windows.

At the last block, if there are any document windows, the frontmost document window is
activated.

FW_activateFloatsAndFirstDocWin

FW_activateFloatsAndFirstDocWin activates those windows which were visible and activated
before deactivateFloatersAndFirstDocWin was called.  It should be called immediately
after an modal alert or dialog box is dismissed.

The first two lines cause the function to assume that, if a modal dialog is up, the
caller did not really mean to call this function.

The next line determines if the application is the front process.

If the application is in the background, the floating windows should be hidden rather
than shown, so FW_doSuspendEvent is called.

If the application is in the foreground, activateWindow is called on all visible windows
in the list up to but not including the second document window in the list.

FW_deactivateFloatsAndFirstDocWin

FW_deactivateFloatsAndFirstDocWin deactivates all visible floating windows and the active
document window.  It should be called immediately before an modal alert or dialog box is
dismissed.

The first line is a safety check to ensure that the window ordering has not been changed.

deactivateWindow is called on all visible windows in the list up to but not including the
second document window in the list.

FW_findFrontNonFloatWindow

FW_findFrontNonFloatWindow returns a pointer to the first visible window in the window
list that is not a floating window.

FW_validateWindowList

FW_validateWindowList is called from FW_ShowWindow and FW_deactivateFloatsAndFirstDocWin. 
It should also be called from the application immediately before document windows are
opened and closed.  It is intended to cater for the remote possibility that document
windows might somehow have been pulled in front of floating windows, in which case it
will pull the floating windows to the front.

If there are no floating windows, the function simply returns.  If the first window in
the window list is a floating window, the function assumes that all is well.  (Note that
the function does not check whether a document window is "between" the floating windows.) 
If the first window is modal, the function returns.

If a return has not occurred prior to the last line, that line calls a function which
brings the floating windows to the front.

FW_GetWRefCon and FW_SetWRefCon

FW_GetWRefCon and FW_SetWRefCon retrieve/assign values from/to the replacementRefCon
field of the window's refConExtend structure.


activateWindow, deactivateWindow, and highlightAndActivateWindow

activateWindow and/or deactivateWindow are called from FW_SelectWindow, FW_HideWindow, FW_ShowWindow, FW_doSuspendEvent, FW_doResumeEvent, FW_deactivateFloatsAndFirstDocWin, and FW_activateFloatsAndFirstDocWin. They simply set a Boolean variable to indicate whether the specified window is to be highlighted and activated or unhighlighted and deactivated, and then pass further processing to highlightAndActivateWindow. highlightAndActivateWindow highlights or unhighlights the specified window, retrieves the pointer to the window's activation function from the window's refConExtend structure, and calls that function.

findLastFloatingWindow

findLastFloatingWindow returns a pointer to last floating window in the window list.

checkWindowOrdering

checkWindowOrdering is called from FW_GetNewCWindow to ensure that the behind formal
parameter is not attempting to open the window at an inappropriate "behind" or "in front
of" location in the window list.  As part of this process, and in the case of document
windows, checkWindowOrdering changes a behind assignment of (WindowPtr) -1 to the pointer
to the last floating window, causing the window to be opened behind that floating window
rather than in front of all windows.  Apart from that particular case, inappropriate
behind specifications will cause an error to be returned. 

If the window to be created is a floating window, an error will be returned if:

*   The behind formal parameter calls for the window to be created behind all other
    windows when non-floating windows exist.

*   The behind formal parameter specifies the window behind which the new window is to
    be created and that window is not a floating window.

If the window to be created is a document window, and if a floating window exists:

*   If the behind formal parameter specifies that the window should be created in front
    of all other windows, the behind parameter is changed so that the window will be
    created behind the last floating window.

*   If the behind formal parameter specifies that the window behind which the window is
    to be opened is a floating window, but it is not the last floating window, an error
    is returned.

getNextVisibleWindow, getWasVisible, and setWasVisible

getNextVisibleWindow returns the pointer to the next visible window in the window list.

getWasVisible returns the value in the wasVisible field of the specified window's
refConExtend structure.

setWasVisible sets the value in the wasVisible field of the specified window's
refConExtend structure.

isWindowModal

isWindowModal determines whether a window is modal.

If the value in the window structure's windowKind field is kDialogWindowKind and the
window's variant code is 2 or 3 (the variant codes for kWindowModalDialogProc and
kWindowMovableModalDialogProc dialog boxes), true is returned.
This function assumes that an application's modeless dialog boxes will not use
kWindowGrowDocumentProc or kWindowVertZoomDocumentProc windows (which also have variant
codes of 2 and 3).  It also assumes that only kWindowModalDialogProc and
kWindowMovableModalDialogProc windows will be used for modal and movable modal dialog
boxes.  If this is not the case, this function will have to be modified.

bringFloatersToFront

bringFloatersToFront is called from FW_validateWindowList in the unlikely event that the
floating windows are not in front of the document windows.  This is a recursive function
(that is, it calls itself) that brings all floating windows to the front of the window
list.

When the while loop finds a floating window, the function remembers it (thisFloaterPtr =
windowPtr) and then calls itself to look further.  When the end of the window list is
reached (thisWindow == NULL), the function "unwinds", calling BringToFront on each found
floating window.

isFrontProcess

isFrontProcess compares the serial numbers of the current process and the front process
and returns true if they are the same, that is, the application is the front process.

getIsWindowVisible, getNextWindow, getWindowKind, getStructureRegion,
and getContentRegion

getIsWindowVisible returns the value in the visible field of the specified window's
window structure.

getNextWindow returns the value in the nextWindow field of the specified window's window
structure.

getWindowKind returns the value in the windowKind field of the specified window's window
structure.

getStructureRegion returns the RgnHandle in the strucRgn field of the specified window's
window structure.

getContentRegion returns the RgnHandle in the contRgn field of the specified window's
window structure.


getActivateHandler and setActivateHandler

getActivateHandler returns the pointer in the activateHandler field of the specified window's refConExtend structure. setActivateHandler assigns a pointer to the activateHandler field of the specified window's refConExtend structure.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links... | Read more »
Price of Glory unleashes its 1.4 Alpha u...
As much as we all probably dislike Maths as a subject, we do have to hand it to geometry for giving us the good old Hexgrid, home of some of the best strategy games. One such example, Price of Glory, has dropped its 1.4 Alpha update, stocked full... | Read more »
The SLC 2025 kicks off this month to cro...
Ever since the Solo Leveling: Arise Championship 2025 was announced, I have been looking forward to it. The promotional clip they released a month or two back showed crowds going absolutely nuts for the previous competitions, so imagine the... | Read more »
Dive into some early Magicpunk fun as Cr...
Excellent news for fans of steampunk and magic; the Precursor Test for Magicpunk MMORPG Crystal of Atlan opens today. This rather fancy way of saying beta test will remain open until March 5th and is available for PC - boo - and Android devices -... | Read more »
Prepare to get your mind melted as Evang...
If you are a fan of sci-fi shooters and incredibly weird, mind-bending anime series, then you are in for a treat, as Goddess of Victory: Nikke is gearing up for its second collaboration with Evangelion. We were also treated to an upcoming... | Read more »
Square Enix gives with one hand and slap...
We have something of a mixed bag coming over from Square Enix HQ today. Two of their mobile games are revelling in life with new events keeping them alive, whilst another has been thrown onto the ever-growing discard pile Square is building. I... | Read more »
Let the world burn as you have some fest...
It is time to leave the world burning once again as you take a much-needed break from that whole “hero” lark and enjoy some celebrations in Genshin Impact. Version 5.4, Moonlight Amidst Dreams, will see you in Inazuma to attend the Mikawa Flower... | Read more »
Full Moon Over the Abyssal Sea lands on...
Aether Gazer has announced its latest major update, and it is one of the loveliest event names I have ever heard. Full Moon Over the Abyssal Sea is an amazing name, and it comes loaded with two side stories, a new S-grade Modifier, and some fancy... | Read more »
Open your own eatery for all the forest...
Very important question; when you read the title Zoo Restaurant, do you also immediately think of running a restaurant in which you cook Zoo animals as the course? I will just assume yes. Anyway, come June 23rd we will all be able to start up our... | Read more »
Crystal of Atlan opens registration for...
Nuverse was prominently featured in the last month for all the wrong reasons with the USA TikTok debacle, but now it is putting all that behind it and preparing for the Crystal of Atlan beta test. Taking place between February 18th and March 5th,... | Read more »

Price Scanner via MacPrices.net

AT&T is offering a 65% discount on the ne...
AT&T is offering the new iPhone 16e for up to 65% off their monthly finance fee with 36-months of service. No trade-in is required. Discount is applied via monthly bill credits over the 36 month... Read more
Use this code to get a free iPhone 13 at Visi...
For a limited time, use code SWEETDEAL to get a free 128GB iPhone 13 Visible, Verizon’s low-cost wireless cell service, Visible. Deal is valid when you purchase the Visible+ annual plan. Free... Read more
M4 Mac minis on sale for $50-$80 off MSRP at...
B&H Photo has M4 Mac minis in stock and on sale right now for $50 to $80 off Apple’s MSRP, each including free 1-2 day shipping to most US addresses: – M4 Mac mini (16GB/256GB): $549, $50 off... Read more
Buy an iPhone 16 at Boost Mobile and get one...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering one year of free Unlimited service with the purchase of any iPhone 16. Purchase the iPhone at standard MSRP, and then choose... Read more
Get an iPhone 15 for only $299 at Boost Mobil...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering the 128GB iPhone 15 for $299.99 including service with their Unlimited Premium plan (50GB of premium data, $60/month), or $20... Read more
Unreal Mobile is offering $100 off any new iP...
Unreal Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering a $100 discount on any new iPhone with service. This includes new iPhone 16 models as well as iPhone 15, 14, 13, and SE... Read more
Apple drops prices on clearance iPhone 14 mod...
With today’s introduction of the new iPhone 16e, Apple has discontinued the iPhone 14, 14 Pro, and SE. In response, Apple has dropped prices on unlocked, Certified Refurbished, iPhone 14 models to a... Read more
B&H has 16-inch M4 Max MacBook Pros on sa...
B&H Photo is offering a $360-$410 discount on new 16-inch MacBook Pros with M4 Max CPUs right now. B&H offers free 1-2 day shipping to most US addresses: – 16″ M4 Max MacBook Pro (36GB/1TB/... Read more
Amazon is offering a $100 discount on the M4...
Amazon has the M4 Pro Mac mini discounted $100 off MSRP right now. Shipping is free. Their price is the lowest currently available for this popular mini: – Mac mini M4 Pro (24GB/512GB): $1299, $100... Read more
B&H continues to offer $150-$220 discount...
B&H Photo has 14-inch M4 MacBook Pros on sale for $150-$220 off MSRP. B&H offers free 1-2 day shipping to most US addresses: – 14″ M4 MacBook Pro (16GB/512GB): $1449, $150 off MSRP – 14″ M4... Read more

Jobs Board

All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.