Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/displays.c
/************************************************************************************* |
# |
# displays.c |
# |
# This segment handles the Display Manager notification and |
# repositions application windows in response. |
# |
# Author(s): Michael Marinkovich |
# marink@apple.com |
# |
# Modification History: |
# |
# 10/12/95 MWM Initial coding |
# 10/05/96 MWM Removed the fixed window title bar height and |
# replaced it with a func that calculates the |
# proper height. |
# |
# |
# Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved |
# |
# |
# You may incorporate this sample code into your applications without |
# restriction, though the sample code has been provided "AS IS" and the |
# responsibility for its operation is 100% yours. However, what you are |
# not permitted to do is to redistribute the source as "DSC Sample Code" |
# after having made changes. If you're going to re-distribute the source, |
# we require that you make it clear in the source that the code was |
# descended from Apple Sample Code, but that you've made changes. |
# |
*************************************************************************************/ |
#include <Events.h> |
#include <ToolUtils.h> |
#include <Gestalt.h> |
#include <LowMem.h> |
#include <OSUtils.h> |
#include <QuickDraw.h> |
#include "App.h" |
#include "Proto.h" |
//---------------------------------------------------------------------- |
// |
// InstallAEDMNotification - tell DM that we want to be notified by AE. |
// |
// |
//---------------------------------------------------------------------- |
OSErr InstallAEDMNotification(void) |
{ |
OSErr err = noErr; |
err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice, |
NewAEEventHandlerProc(WorldChangedProc), |
0L, false); |
return err; |
} |
//---------------------------------------------------------------------- |
// |
// WorldChangedProc - Display Manager calls this proc when a depth or |
// mode change is made. Your application should |
// handle window repositioning here. |
//---------------------------------------------------------------------- |
pascal OSErr WorldChangedProc(AppleEvent event, AppleEvent reply, long refCon) |
{ |
#pragma unused (refCon) |
OSErr err = noErr; |
err = HandleNotification(&event); |
return noErr; |
} |
//---------------------------------------------------------------------- |
// |
// HandleNotification - handle the AppleEvent returned by the |
// AppleEvent procedure. |
// |
//---------------------------------------------------------------------- |
OSErr HandleNotification(AppleEvent *event) |
{ |
OSErr err = noErr; |
GrafPtr oldPort; |
AEDescList displayList; |
AEDescList aDisplay; |
AERecord oldConfig,newConfig; |
AEKeyword tempWord; |
DisplayIDType displayID; |
unsigned long returnType; |
long count; |
Rect oldRect, newRect; |
GetPort(&oldPort); |
// Get a list of the displays from the Display Notice AppleEvent. |
err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList); |
// How many items in the list |
err = AECountItems(&displayList,&count); |
while (count > 0) // Loop through the list. |
{ |
err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, |
&aDisplay); |
// Get the Old Rect. |
err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord, |
&oldConfig); |
err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard, |
&returnType, &oldRect, 8, nil); |
// Get the DisplayID so we can get the GDevice later. |
err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard, |
&returnType, &displayID, 8, nil); |
// Get the New Rect. |
err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, |
&newConfig); |
err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard, |
&returnType, &newRect, 8, nil); |
// If the New and Old rects are not the same then we can assume |
// the GDevice has changed and we need to rearrange the windows. |
if (err == noErr && !EqualRect(&newRect, &oldRect)) |
HandleDeviceChange(displayID, &newRect); |
count--; |
err = AEDisposeDesc(&aDisplay); |
err = AEDisposeDesc(&oldConfig); |
err = AEDisposeDesc(&newConfig); |
} |
err = AEDisposeDesc(&displayList); |
SetPort(oldPort); |
return err; |
} |
//---------------------------------------------------------------------- |
// |
// HandleDeviceChange - called when the oldconfig is different from |
// newconfig. Will check all windows on effected |
// device and move if needed. |
//---------------------------------------------------------------------- |
OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect) |
{ |
OSErr err; |
GDHandle gd; |
GDHandle onGD; |
WindowRef window; |
// Get the GDevice from the DisplayID. |
err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false); |
if (err == noErr && gd != nil) |
{ |
window = LMGetWindowList(); |
while (nil != window) |
{ |
SetPort(window); |
// which device holds the greatest portion of the window |
onGD = GetGreatestDevice(window); |
// If the window is not 50% or greater on |
// the desired device then pass it up. |
if (onGD == gd) |
{ |
if (OutOfBoundsRect(window->portRect, *newRect)) |
{ |
MoveInbounds(window, gd, *newRect); |
if (OutOfBoundsRect(window->portRect, *newRect)) |
{ |
ResizeInbounds(window, gd, *newRect); |
// If it is one of our document windows then we need |
// to reset the std state and the scroll bars. |
if (GetIsAppWindow(window)) |
AdjustScrollbars(window, true); |
} |
} |
ResetStdState(window); |
} |
window = (WindowRef)(((WindowPeek)window)->nextWindow); |
} |
} |
return err; |
} |
//---------------------------------------------------------------------- |
// |
// OutOfBoundsRect - check to see if the window is out of the device |
// rect. |
// |
//---------------------------------------------------------------------- |
Boolean OutOfBoundsRect(Rect windRect, Rect screenRect) |
{ |
Boolean out = false; |
GlobalToLocal(&TopLeft(screenRect)); |
GlobalToLocal(&BotRight(screenRect)); |
if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom)) |
out = true; |
if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top)) |
out = true; |
return out; |
} |
//---------------------------------------------------------------------- |
// |
// MoveInbounds - Move window on to desired device |
// |
// |
//---------------------------------------------------------------------- |
void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect) |
{ |
Rect bounds; |
short hGlobal; |
short vGlobal; |
bounds = window->portRect; |
LocalToGlobal(&TopLeft(bounds)); |
LocalToGlobal(&BotRight(bounds)); |
hGlobal = bounds.left; |
vGlobal = bounds.top; |
// we want to make the left top a priority so adjust it first |
// as to override the bottom, right movements. This is so we |
// can resize the window later. No need to adjust the top |
// because the top coordinates don't change. |
if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) || |
((bounds.bottom - bounds.top) > (screenRect.bottom - screenRect.top))) |
{ |
// adjust left |
if (bounds.left < screenRect.left) |
hGlobal = screenRect.left + 4; |
vGlobal = screenRect.top; |
if (gd == GetMainDevice()) |
vGlobal += (GetMBarHeight() + GetWTitleHeight(window)); |
} |
else |
{ |
// adjust left |
if (bounds.left < screenRect.left) |
hGlobal = screenRect.left + 4; |
if ((bounds.top - 100 < screenRect.top) && (gd == GetMainDevice())) |
vGlobal = screenRect.top + (GetMBarHeight() + GetWTitleHeight(window)); |
// adjust right |
if (bounds.right > screenRect.right) |
hGlobal = (screenRect.right - (bounds.right - bounds.left)) - 4; |
// adjust bottom |
if (bounds.bottom > screenRect.bottom) |
vGlobal = (screenRect.bottom - (bounds.bottom - bounds.top)) - 4; |
} |
MoveWindow(window, hGlobal, vGlobal,false); |
} |
//---------------------------------------------------------------------- |
// |
// ResizeInbounds - resize the window to fit in the graphics device |
// |
// |
//---------------------------------------------------------------------- |
void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect) |
{ |
Rect windRect; |
short h; |
short v; |
windRect = window->portRect; |
// make the window bounds the size of the gdRect |
// less the fudge factor. |
h = windRect.right - windRect.left; |
v = windRect.bottom - windRect.top; |
if (h > screenRect.right - screenRect.left) |
h = (screenRect.right - screenRect.left) - 8; |
if (v > screenRect.bottom - screenRect.top) |
{ |
v = (screenRect.bottom - screenRect.top) - 8; |
// If we are on the main device then subtract the mBar |
// height. Also subtract the height of the title |
// bar on the window. |
if (gd == GetMainDevice()) |
v -= (LMGetMBarHeight() + GetWTitleHeight(window)); |
} |
SizeWindow(window, h, v, true); |
} |
//---------------------------------------------------------------------- |
// |
// GetGreatestDevice - find thw device that holds the greatest area |
// of the window. |
// |
//---------------------------------------------------------------------- |
GDHandle GetGreatestDevice(WindowRef window) |
{ |
GDHandle gd; |
GDHandle savedGD; |
Rect gdRect; |
Rect foundRect; |
long size; |
long greatest = nil; |
gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays); |
savedGD = gd; |
// Loop through the device list |
while (gd != nil) |
{ |
gdRect = (**gd).gdRect; |
GlobalToLocal(&TopLeft(gdRect)); |
GlobalToLocal(&BotRight(gdRect)); |
if (SectRect(&window->portRect, &gdRect, &foundRect)) |
{ |
size = ((long)(foundRect.right - foundRect.left) * |
(long)(foundRect.bottom - foundRect.top)); |
if (size > greatest) |
{ |
greatest = size; |
savedGD = gd; // save the greatest device |
} |
} |
gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays); |
} |
return savedGD; |
} |
//---------------------------------------------------------------------- |
// |
// ResetStdState - since we are now on a different size screen we need |
// to change the stdState window size so our zooming |
// will work properly. |
//---------------------------------------------------------------------- |
void ResetStdState(WindowRef window) |
{ |
Rect screenRect; |
screenRect = window->portRect; |
LocalToGlobal(&TopLeft(screenRect)); |
LocalToGlobal(&BotRight(screenRect)); |
SetWindowStandardState(window, &screenRect); |
} |
//---------------------------------------------------------------------- |
// |
// GetWTitleHeight - return the height of the titlebar for a given |
// window. If the window is nil a zero height will |
// be returned. |
//---------------------------------------------------------------------- |
short GetWTitleHeight(WindowRef window) |
{ |
short tHeight = 0; |
if (nil != window) |
tHeight = (**((WindowPeek)window)->contRgn).rgnBBox.top - |
(**((WindowPeek)window)->strucRgn).rgnBBox.top; |
return tHeight; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14