home *** CD-ROM | disk | FTP | other *** search
- /*
- SmartDragWindow.c
-
- Written by Hiep Dam
- From The Witches' Brew
- Date: November 16, 1995
- Internet: starlabs@aol.com
-
- ---------------------------------------------------------------------
-
- This is in the public domain. Insert it into all of your applications!
- (There's no reason not to!) <grin>
-
- This routine does the right thing for normal & tricky situations:
- * ...handling multiple monitor situations
- (thanks to GetDominantDevice())
- * ...not drawing over other windows if they are on top
- of the window that is dragged (a subtle fact missed until
- I noticed how the Finder implemented command-dragging).
- * ...hiding the drag outline if the mouse moves outside of
- the limit rect - just like DragWindow.
-
-
- Note: Because this routine fiddles with the Window Manager port,
- compatibility with future versions of the system software may be
- compromised. But this looks to be waaaaay in the future...
-
- The code is "somewhat" Copland-aware (uses the STRICT_WINDOWS accessors).
-
- Feel free to make changes/improvements to the code and distribute
- it as you wish. Just drop me a copy, OK?
-
- ---------------------------------------------------------------------
-
- Portions written by Norman Basham, and a few ideas here and there
- taken from C.K. Haun.
-
- Version History:
- 1.0 11/16/95 Wrote it. Initially much easier than I thought.
- Then slightly harder when trying to handle the
- tricky situations above. But still not difficult
- at all...
- 1.1 11/18/95 Added support for snap procs, and thus support
- for grid snapping and window snapping as well.
- 1.0.1 11/18/95 Noticed slight discrepancy when dragging near
- menubar. Added code to exclude menubar region
- as if it was an overlapping window.
- */
-
-
- #include "SmartDragWindow.h"
- #ifndef __LOWMEM__
- #include <LowMem.h>
- #endif
-
- // ---------------------------------------------------------------------------
-
- static Boolean DoWindowDrag(
- WindowPtr dragWindow,
- Point startPoint,
- const Rect *limitRect,
- short snapToDistance,
- Rect *dragResultRect,
- SnapCallback snapProc);
-
- static void AdjustWindowForStructure(WindowRef theWindow, Rect *adjustRect);
-
- static void SnapBottomToBottom(Rect *snapRect, const Rect *magnetRect, short snapToDistance);
- static void SnapTopToTop(Rect *snapRect, const Rect *magnetRect, short snapToDistance);
- static void SnapRightToRight(Rect *snapRect, const Rect *magnetRect, short snapToDistance);
- static void SnapLeftToLeft(Rect *snapRect, const Rect *magnetRect, short snapToDistance);
-
- static Boolean WithinRange(short theValue, short rangeValue, short range);
- static void MoveRectTo(Rect *theRect, short h, short v);
-
- static GDHandle GetDominantDevice (Rect *r);
- static Boolean IsActiveScreenDevice();
- static long GetRectArea(Rect r);
-
- // ---------------------------------------------------------------------------
-
- #pragma mark === Hiep Dam ===
-
-
- enum {
- kSnapToMargin = 10
- };
-
- #define kExtremeNeg -32768
- #define kExtremePos (32767 - 1) // required to address an old region bug,
- //see develop 20 Q&As
-
- #define HOTKEY_DISABLE IsControlKeyDown()
-
- // ---------------------------------------------------------------------------
-
- void SmartDragWindow(
- WindowRef windowToDrag,
- Point startPoint,
- const Rect *limitRect,
- short snapToDistance) {
-
- SuperSmartDragWindow(windowToDrag, startPoint, limitRect, snapToDistance, MonitorSnapProc);
- } // END SmartDragWindow
-
- // ---------------------------------------------------------------------------
-
- void SuperSmartDragWindow(
- WindowRef windowToDrag,
- Point startPoint,
- const Rect *limitRect,
- short snapToDistance,
- SnapCallback snapProc) {
-
- GrafPtr wMgrPort;
- RgnHandle wMgrSaveRgn;
- RgnHandle clipRgn;
- RgnHandle strucRgn;
- PenState wMgrPenState;
- Rect dragResult;
- Rect menuBarRect;
- Boolean selectWindow;
- Boolean dragOK;
- WindowPtr aWindow;
- GrafPtr savePort;
- Rect wideOpen;
-
- if (HOTKEY_DISABLE)
- snapProc = NULL;
-
- // Is this a normal drag or a "cmd-key" drag?
- selectWindow = true;
- if (windowToDrag != FrontWindow() && IsCmdKeyDown())
- selectWindow = false;
-
- GetPort(&savePort);
- GetWMgrPort(&wMgrPort);
-
- // Set to window manager port & get its settings (pen, clipping region)
- SetPort(wMgrPort);
- GetPenState(&wMgrPenState);
- wMgrSaveRgn = NewRgn();
- GetClip(wMgrSaveRgn);
-
- // Enlarge clipping area so we can drag all over the place...
- SetRect(&wideOpen, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
- ClipRect(&wideOpen);
- clipRgn = NewRgn();
- GetClip(clipRgn);
-
- strucRgn = NewRgn();
- // Account for any windows which may be on top of ours. If there
- // are any, subtract their structure regions from the clipping
- // region so we don't draw into them (just like what DragWindow() does).
- if (windowToDrag != FrontWindow()) {
- // Get first window
- aWindow = FrontWindow();
-
- while (aWindow != windowToDrag && aWindow != NULL) {
- if (IsWindowVisible(aWindow)) {
- GetWindowStructureRgn(aWindow, strucRgn);
- DiffRgn(clipRgn, strucRgn, clipRgn);
- }
- aWindow = GetNextWindow(aWindow);
- }
- }
-
- // Remember to exclude menu bar as well. In this case we treat
- // it like one of the windows above - we subtract it's area
- // from the total draggable clipping region.
- // This part unfortunately relies on a low-memory global...
- menuBarRect = (**GetMainDevice()).gdRect;
- menuBarRect.bottom = menuBarRect.top + LMGetMBarHeight();
- RectRgn(strucRgn, &menuBarRect);
- DiffRgn(clipRgn, strucRgn, clipRgn);
- DisposeRgn(strucRgn);
-
- // Set our "adjusted" clipping region
- SetClip(clipRgn);
-
- // Illegal snap-to distance?
- if (snapToDistance < 0)
- snapToDistance = kSnapToMargin;
-
- // Do the actual dirty work
- dragOK = DoWindowDrag(
- windowToDrag,
- startPoint,
- limitRect,
- snapToDistance,
- &dragResult,
- snapProc);
-
- // Restore window manager port
- SetClip(wMgrSaveRgn);
- SetPenState(&wMgrPenState);
- DisposeRgn(wMgrSaveRgn);
- DisposeRgn(clipRgn);
-
- if (dragOK) {
- // Adjust dragResult for structure region of window (i.e. drag bar)
- AdjustWindowForStructure(windowToDrag, &dragResult);
- MoveWindow(windowToDrag, dragResult.left, dragResult.top, selectWindow);
- }
-
- SetPort(savePort);
- } // END SmartDragWindow
-
- // ---------------------------------------------------------------------------
-
- /*
- DoWindowDrag().
- The real meat 'n potatoes of the outfit.
-
- Returns true if mouseloc was inside limitRect when mouse was released,
- else false.
- If true, argument <dragResultRect> will contain the new dragged rect
- (note: the rect is the size of the window's structure region and
- needs to be adjusted before calling MoveWindow())
- */
-
- Boolean DoWindowDrag(
- WindowPtr dragWindow,
- Point startPoint,
- const Rect *limitRect,
- short snapToDistance,
- Rect *dragResultRect,
- SnapCallback snapProc) {
-
- Rect dragRect;
- Rect oldRect;
- Rect confineRect;
- Rect grayRgnRect;
- RgnHandle strucRgn;
- Point mouseLoc;
- short offsetH,
- offsetV;
- short windowWidth,
- windowHeight;
- Boolean insideConfineRect;
- char i;
- Pattern grayPat;
- Pattern blackPat;
-
- /*
- Why can't we auto-initialize the patterns grayPat & blackPat,
- as in "grayPat = { 0xAA, 0x55, 0xAA, 0x55, etc... }"?
-
- Well, looking at the definition of a Pattern, it's a string
- of 8 chars! So the above is a string initialization, which in
- turn makes the initialization string 0xAA, 0x55 a global
- string. This is NOT what is intended! Doing this will cause
- the compiler to allocate at least 16 bytes of global data.
- */
- for (i = 0; i < 8; i++) {
- grayPat.pat[i] = 0xAA;
- blackPat.pat[i] = 0xAA;
- }
- for (i = 1; i < 8; i += 2)
- grayPat.pat[i] = 0x55;
-
- // Determine limit rect (& be smart about it!)
- grayRgnRect = (**GetGrayRgn()).rgnBBox;
- if (limitRect == NULL || EmptyRect(limitRect)) {
- // Don't use screenBits.bounds, please!
- confineRect = grayRgnRect;
- InsetRect(&confineRect, 4, 4);
- }
- else {
- // If users passed the grayRgn or screenBits.bounds, adjust
- // the limit rect for them, just like DragWindow() does.
- // We shouldn't use globals, so assuming that screenBits.bounds
- // is the same as (**GetMainDevice).gdRect...
- if (EqualRect(limitRect, &grayRgnRect) ||
- EqualRect(limitRect, &(**GetMainDevice()).gdRect)) {
- confineRect = grayRgnRect;
- InsetRect(&confineRect, 4, 4);
- }
- else {
- // Passed a non-standard limit rect. Use it instead.
- confineRect = *limitRect;
- }
- }
- insideConfineRect = true;
-
- // Get window height, width
- strucRgn = NewRgn();
- GetWindowStructureRgn(dragWindow, strucRgn);
- windowWidth = dragRect.right - dragRect.left;
- windowHeight = dragRect.bottom - dragRect.top;
- dragRect = (**strucRgn).rgnBBox;
-
- // Since the mouse probably isn't at the topleft of the window,
- // we have to make adjustments
- offsetH = startPoint.h - dragRect.left;
- offsetV = startPoint.v - dragRect.top;
-
- // Now we can rubberband
- PenMode(srcXor);
- PenPat(&grayPat);
- // Draw it for the first time
- oldRect = dragRect;
- FrameRect(&dragRect);
-
- while (StillDown()) {
- GetMouse(&mouseLoc);
-
- if (PtInRect(mouseLoc, &confineRect)) {
- MoveRectTo(&dragRect, mouseLoc.h - offsetH, mouseLoc.v - offsetV);
-
- if (snapProc)
- snapProc(dragWindow, snapToDistance, &dragRect);
-
- // Draw only if mouse moved and it moved inside of limit rect
- if (!insideConfineRect) {
- // Mouse was outside of limit rect and now it
- // has moved back inside.
- FrameRect(&dragRect);
- oldRect = dragRect;
- }
- else if (!EqualRect(&oldRect, &dragRect)) {
- FrameRect(&dragRect);
- FrameRect(&oldRect);
- oldRect = dragRect;
- }
-
- insideConfineRect = true;
- }
- else {
- if (insideConfineRect) {
- // Mouse was inside limit rect and now has moved
- // outside of it.
-
- // Erase drag outline
- FrameRect(&oldRect);
- insideConfineRect = false;
- }
- }
- }
-
- // Erase the last drag outline (if it hasn't been
- // already erased by the mouse being outside of confineRect)
- if (insideConfineRect)
- FrameRect(&dragRect);
-
- DisposeRgn(strucRgn);
-
- // Restore drawing modes
- PenMode(srcCopy);
- PenPat(&blackPat);
-
- if (insideConfineRect)
- *dragResultRect = dragRect;
-
- return(insideConfineRect);
- } // END DoWindowDrag
-
- // ---------------------------------------------------------------------------
-
- /*
- Adjust the drag rect by accounting for the window's drag bar.
- DoWindowDrag() returns the dragged rect - but this rect is the
- total structure rect of the window. MoveWindow(), on the other
- hand, expects the rect to be in terms of the content region.
- So we have to adjust it...
- */
-
- void AdjustWindowForStructure(WindowRef theWindow, Rect *adjustRect) {
- RgnHandle strucRgn, contRgn;
-
- strucRgn = NewRgn();
- contRgn = NewRgn();
-
- GetWindowStructureRgn(theWindow, strucRgn);
- GetWindowContentRgn(theWindow, contRgn);
-
- // We only have to worry about the left and top sides
- // of the rect, since MoveWindow takes only h and v arguments.
- adjustRect->top += (**contRgn).rgnBBox.top - (**strucRgn).rgnBBox.top;
- adjustRect->left += (**contRgn).rgnBBox.left - (**strucRgn).rgnBBox.left;
-
- // Here is a tricky situation. If the window is "rolled up", a la
- // Aaron, we get errorneous contRgn areas. The top
- // of the contRgn is one less than it is if it wasn't rolled up.
- // So we have to adjust for this.
- // WindowShade does use the correct values.
- /*
- if ((**contRgn).rgnBBox.top == (**contRgn).rgnBBox.bottom) {
- adjustRect->top++;
- }
- */
-
- DisposeRgn(strucRgn);
- DisposeRgn(contRgn);
- } // END AdjustWindowForStructure
-
- // ---------------------------------------------------------------------------
-
- /*
- MonitorSnapProc.
- Snaps the rect to the edges of the monitor. Multiple-monitor savvy.
- */
-
- void MonitorSnapProc(WindowPtr windowToDrag, short snapToDistance, Rect *snapRect) {
- GDHandle theMonitor;
- Rect monitorRect;
-
- // This is where we adjust the drag rect to "snap to" the
- // edges of the monitors.
- theMonitor = GetDominantDevice(snapRect);
- monitorRect = (**theMonitor).gdRect;
- if (theMonitor == GetMainDevice()) {
- // If this is the main monitor, adjust "snap to" rect
- // to account for menu bar.
- monitorRect.top += LMGetMBarHeight();
- }
-
- // Is the rect close enought to left or right edges
- // of the magnetRect?
- SnapRightToRight(snapRect, &monitorRect, snapToDistance);
- SnapLeftToLeft(snapRect, &monitorRect, snapToDistance);
-
- // How about the top or bottom edges?
- SnapBottomToBottom(snapRect, &monitorRect, snapToDistance);
- SnapTopToTop(snapRect, &monitorRect, snapToDistance);
- } // END MonitorSnapProc
-
- // ---------------------------------------------------------------------------
-
- /*
- WindowSnapProc.
- Snap to edges of other windows.
- */
-
- enum {
- kMaxWindowsSnap = 10
- };
-
- void WindowSnapProc(WindowPtr windowToDrag, short snapToDistance, Rect *snapRect) {
- Rect strucRgnRect;
- short snapRectWidth, snapRectHeight;
- short i, numWindows;
- WindowRef theWindow;
- WindowRef windowList[kMaxWindowsSnap];
- RgnHandle strucRgn;
-
- theWindow = FrontWindow();
- if (theWindow == NULL) return;
-
- snapRectWidth = snapRect->right - snapRect->left;
- snapRectHeight = snapRect->bottom - snapRect->top;
-
- // Make a list of windows which meet our criteria
- // of "snappable" windows
- i = numWindows = 0;
- while ((theWindow != NULL) && (i < kMaxWindowsSnap)) {
- if (IsWindowVisible(theWindow) && (theWindow != windowToDrag)) {
- windowList[i++] = theWindow;
- numWindows++;
- }
- theWindow = GetNextWindow(theWindow);
- }
-
- strucRgn = NewRgn();
-
- // We're going to give the topmost window the highest priority
- // when determining which window to snap to. To do this, we
- // step through the window list backwards (since the topmost
- // window is the first entry in the window list).
- for (i = numWindows-1; i >= 0; i--) {
- GetWindowStructureRgn(windowList[i], strucRgn);
- strucRgnRect = (**strucRgn).rgnBBox;
-
- /*
- Below is a tortuous road of if-then-checks. sigh.
-
- The problem here is that we have to do eight checks:
- the left of the snap window to the left of the magnet window,
- the left of the snap window to the right of the magnet window,
- the top of the snap window to the top of the magnet window,
- the top of the snap window to the bottom of the magnet window,
- and so on for all 4 sides x 2...
- */
-
- // Check left to left snapping
- if (WithinRange(snapRect->left, strucRgnRect.left, snapToDistance)) {
- if ((snapRect->top > strucRgnRect.bottom) ||
- (snapRect->bottom < strucRgnRect.top)) {
- // Do nothing
- }
- else {
- snapRect->left = strucRgnRect.left;
- snapRect->right = snapRect->left + snapRectWidth;
- }
- // Top gets preference, so we check that last
- SnapBottomToBottom(snapRect, &strucRgnRect, snapToDistance);
- SnapTopToTop(snapRect, &strucRgnRect, snapToDistance);
- }
- // Check right to right snapping
- else if (WithinRange(snapRect->right, strucRgnRect.right, snapToDistance)) {
- if ((snapRect->top > strucRgnRect.bottom) ||
- (snapRect->bottom < strucRgnRect.top)) {
- // Do nothing
- }
- else {
- snapRect->right = strucRgnRect.right;
- snapRect->left = snapRect->right - snapRectWidth;
- }
- // Top gets preference, so we check that last
- SnapBottomToBottom(snapRect, &strucRgnRect, snapToDistance);
- SnapTopToTop(snapRect, &strucRgnRect, snapToDistance);
- }
-
-
- // Check top to top snapping
- if (WithinRange(snapRect->top, strucRgnRect.top, snapToDistance)) {
- if ((snapRect->left > strucRgnRect.right) ||
- (snapRect->right < strucRgnRect.left)) {
- // Do nothing
- }
- else {
- snapRect->top = strucRgnRect.top;
- snapRect->bottom = snapRect->top + snapRectHeight;
- }
- // Left get preference, so check that last
- SnapRightToRight(snapRect, &strucRgnRect, snapToDistance);
- SnapLeftToLeft(snapRect, &strucRgnRect, snapToDistance);
- }
- // Check bottom to bottom snapping
- else if (WithinRange(snapRect->bottom, strucRgnRect.bottom, snapToDistance)) {
- if ((snapRect->left > strucRgnRect.right) ||
- (snapRect->right < strucRgnRect.left)) {
- // Do nothing
- }
- else {
- snapRect->bottom = strucRgnRect.bottom;
- snapRect->top = snapRect->bottom - snapRectHeight;
- }
- // Left get preference, so check that last
- SnapRightToRight(snapRect, &strucRgnRect, snapToDistance);
- SnapLeftToLeft(snapRect, &strucRgnRect, snapToDistance);
- }
-
-
- // Check left to right snapping
- if (WithinRange(snapRect->left, strucRgnRect.right, snapToDistance)) {
- if ((snapRect->top > strucRgnRect.bottom) ||
- (snapRect->bottom < strucRgnRect.top)) {
- // Do nothing
- }
- else {
- snapRect->left = strucRgnRect.right;
- snapRect->right = snapRect->left + snapRectWidth;
-
- }
- // Top gets preference, so we check that last
- SnapBottomToBottom(snapRect, &strucRgnRect, snapToDistance);
- SnapTopToTop(snapRect, &strucRgnRect, snapToDistance);
- }
- // Check right to left snapping
- else if (WithinRange(snapRect->right, strucRgnRect.left, snapToDistance)) {
- if ((snapRect->top > strucRgnRect.bottom) ||
- (snapRect->bottom < strucRgnRect.top)) {
- // Do nothing
- }
- else {
- snapRect->right = strucRgnRect.left;
- snapRect->left = snapRect->right - snapRectWidth;
- }
- // Top gets preference, so we check that last
- SnapBottomToBottom(snapRect, &strucRgnRect, snapToDistance);
- SnapTopToTop(snapRect, &strucRgnRect, snapToDistance);
- }
-
-
- // Check top to bottom snapping
- if (WithinRange(snapRect->top, strucRgnRect.bottom, snapToDistance)) {
- if ((snapRect->left > strucRgnRect.right) ||
- (snapRect->right < strucRgnRect.left)) {
- // Do nothing
- }
- else {
- snapRect->top = strucRgnRect.bottom;
- snapRect->bottom = snapRect->top + snapRectHeight;
- }
- // Left get preference, so check that last
- SnapRightToRight(snapRect, &strucRgnRect, snapToDistance);
- SnapLeftToLeft(snapRect, &strucRgnRect, snapToDistance);
- }
- // Check bottom to top snapping
- else if (WithinRange(snapRect->bottom, strucRgnRect.top, snapToDistance)) {
- if ((snapRect->left > strucRgnRect.right) ||
- (snapRect->right < strucRgnRect.left)) {
- // Do nothing
- }
- else {
- snapRect->bottom = strucRgnRect.top;
- snapRect->top = snapRect->bottom - snapRectHeight;
- }
- // Left get preference, so check that last
- SnapRightToRight(snapRect, &strucRgnRect, snapToDistance);
- SnapLeftToLeft(snapRect, &strucRgnRect, snapToDistance);
- }
- }
-
- DisposeRgn(strucRgn);
- } // END WindowSnapProc
-
- // ---------------------------------------------------------------------------
-
- /*
- GridSnapProc.
- Snap rect to the grid.
- */
-
- void GridSnapProc(WindowPtr windowToDrag, short gridSize, Rect *snapRect) {
- short leftMod, topMod;
- short snapRectWidth, snapRectHeight;
-
- snapRectWidth = snapRect->right - snapRect->left;
- snapRectHeight = snapRect->bottom - snapRect->top;
-
- leftMod = snapRect->left / gridSize;
- snapRect->left = leftMod * gridSize;
- topMod = snapRect->top / gridSize;
- snapRect->top = topMod * gridSize;
- snapRect->right = snapRect->left + snapRectWidth;
- snapRect->bottom = snapRect->top + snapRectHeight;
- } // END GridSnapProc
-
- // ---------------------------------------------------------------------------
-
- void SnapBottomToBottom(Rect *snapRect, const Rect *magnetRect, short snapToDistance) {
- short snapRectHeight;
-
- if (WithinRange(snapRect->bottom, magnetRect->bottom, snapToDistance)) {
- snapRectHeight = snapRect->bottom - snapRect->top;
- snapRect->bottom = magnetRect->bottom;
- snapRect->top = snapRect->bottom - snapRectHeight;
- }
- } // END SnapBottomToBottom
-
- void SnapTopToTop(Rect *snapRect, const Rect *magnetRect, short snapToDistance) {
- short snapRectHeight;
-
- if (WithinRange(snapRect->top, magnetRect->top, snapToDistance)) {
- snapRectHeight = snapRect->bottom - snapRect->top;
- snapRect->top = magnetRect->top;
- snapRect->bottom = snapRect->top + snapRectHeight;
- }
- } // END SnapTopToTop
-
- void SnapRightToRight(Rect *snapRect, const Rect *magnetRect, short snapToDistance) {
- short snapRectWidth;
-
- if (WithinRange(snapRect->right, magnetRect->right, snapToDistance)) {
- snapRectWidth = snapRect->right - snapRect->left;
- snapRect->right = magnetRect->right;
- snapRect->left = snapRect->right - snapRectWidth;
- }
- } // END SnapRightToRight
-
- void SnapLeftToLeft(Rect *snapRect, const Rect *magnetRect, short snapToDistance) {
- short snapRectWidth;
-
- if (WithinRange(snapRect->left, magnetRect->left, snapToDistance)) {
- snapRectWidth = snapRect->right - snapRect->left;
- snapRect->left = magnetRect->left;
- snapRect->right = snapRect->left + snapRectWidth;
- }
- } // END SnapLeftToLeft
-
- // ---------------------------------------------------------------------------
-
- Boolean WithinRange(short theValue, short rangeValue, short range) {
- if (theValue < rangeValue + range &&
- theValue > rangeValue - range)
- return(true);
- else
- return(false);
- } // END WithinRange
-
- // ---------------------------------------------------------------------------
-
- void MoveRectTo(Rect *theRect, short h, short v) {
- short width = theRect->right - theRect->left;
- short height = theRect->bottom - theRect->top;
- theRect->left = h;
- theRect->top = v;
- theRect->right = theRect->left + width;
- theRect->bottom = theRect->top + height;
- } // END MoveRectTo
-
- // ---------------------------------------------------------------------------
-
- /*
- Quick 'n dirty. Mea culpa...
- */
- Boolean IsKeyDown(unsigned short theKey);
- Boolean IsKeyDown(unsigned short theKey) {
- unsigned char km[16];
-
- GetKeys(*((KeyMap*) &km));
- return ((km[theKey>>3] >> (theKey & 7)) & 1);
- }
-
- Boolean IsCmdKeyDown() {
- return IsKeyDown(0x37);
- }
-
- Boolean IsControlKeyDown() {
- return IsKeyDown(0x3B);
- }
-
- // ---------------------------------------------------------------------------
-
- /*
- The following routines were written by Norman Basham.
- They were taken from "Monitors.cpp"
-
- Thanks a mil, Norman!
- */
- #pragma mark === Norman Basham ===
-
- // ------------------------------------------------------------------------
- // Given rect r, which device does it overlap most. An example of its use
- // would be passing in (**wp->visRgn).rgnBBox to find out which device a
- // window is overlapping the most, as in the case of zooming a window.
- // ------------------------------------------------------------------------
- GDHandle GetDominantDevice (Rect *r)
- {
- GDHandle aGDevice;
- GDHandle bigGDevice;
- Rect screenRect;
- Rect sectRect;
- long area;
- long biggestArea = 0L;
-
- aGDevice = GetDeviceList (); // start at begining of device list
- while (aGDevice != nil) // loop if device exists
- {
- if (IsActiveScreenDevice (aGDevice)) // if device is a monitor and active
- {
- screenRect = (**aGDevice).gdRect; // get the devices global rect
- SectRect (&screenRect, r, §Rect); // get overlapping rect of device and r
-
- area = GetRectArea (sectRect); // changed 3/21/94
- if (area > biggestArea) // if overlapping rect has the biggest area
- {
- bigGDevice = aGDevice; // set big device to current device
- biggestArea = area; // set big area to current area
- }
-
- aGDevice = GetNextDevice (aGDevice); // check next device in list
- }
- }
-
- return bigGDevice; // return device containing biggest portion of r
- }
-
- // ------------------------------------------------------------------------
- // Given a device, return wether it is a monitor and wether it's active
- // ------------------------------------------------------------------------
- Boolean IsActiveScreenDevice(GDHandle theDevice)
- {
- return (
- (TestDeviceAttribute (theDevice, screenDevice)) &&
- (TestDeviceAttribute (theDevice, screenActive))
- );
- }
-
- long GetRectArea(Rect r)
- {
- Rect temp = r;
-
- OffsetRect (&temp, -temp.left, -temp.top); // rids us of neg values
- return (long) temp.right * temp.bottom; // return width x heigth
- }
-