2011-11-22 21:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
===========================================================================
|
|
|
|
|
|
|
|
|
|
Doom 3 GPL Source Code
|
|
|
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
|
|
2011-12-06 16:14:59 +00:00
|
|
|
|
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
2011-11-22 21:28:15 +00:00
|
|
|
|
|
|
|
|
|
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
Doom 3 Source Code is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
|
|
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
|
|
|
|
|
|
===========================================================================
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "../../idlib/precompiled.h"
|
|
|
|
|
#include <Carbon/Carbon.h>
|
|
|
|
|
#include "PickMonitor.h"
|
|
|
|
|
|
|
|
|
|
//====================================================================================
|
|
|
|
|
// CONSTANTS
|
|
|
|
|
//====================================================================================
|
|
|
|
|
|
|
|
|
|
#define kMaxMonitors 16
|
|
|
|
|
|
|
|
|
|
//====================================================================================
|
|
|
|
|
// TYPES
|
|
|
|
|
//====================================================================================
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
GDHandle device;
|
|
|
|
|
Rect origRect;
|
|
|
|
|
Rect scaledRect;
|
|
|
|
|
int isMain;
|
|
|
|
|
}
|
|
|
|
|
Monitor;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//====================================================================================
|
|
|
|
|
// GLOBALS
|
|
|
|
|
//====================================================================================
|
|
|
|
|
static GDHandle sSelectedDevice;
|
|
|
|
|
static int sNumMonitors;
|
|
|
|
|
static Monitor sMonitors[kMaxMonitors];
|
|
|
|
|
|
|
|
|
|
static RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
|
|
|
|
|
static RGBColor rgbWhite = { 0xffff, 0xffff, 0xffff };
|
|
|
|
|
static RGBColor rgbGray = { 0x5252, 0x8A8A, 0xCCCC }; // this is the blue used in the Displays control panel
|
|
|
|
|
|
|
|
|
|
//====================================================================================
|
|
|
|
|
// MACROS
|
|
|
|
|
//====================================================================================
|
|
|
|
|
|
|
|
|
|
#undef PtInRect
|
|
|
|
|
#undef OffsetRect
|
|
|
|
|
#undef InsetRect
|
|
|
|
|
#undef EraseRect
|
|
|
|
|
#undef MoveTo
|
|
|
|
|
#undef LineTo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//====================================================================================
|
|
|
|
|
// IMPLEMENTATION
|
|
|
|
|
//====================================================================================
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// SetupUserPaneProcs
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Call this to initialize the specified user pane control before displaying
|
|
|
|
|
// the dialog window. Pass NULL for any user pane procs you don't need to install.
|
|
|
|
|
|
|
|
|
|
OSErr SetupUserPaneProcs( ControlRef inUserPane,
|
|
|
|
|
ControlUserPaneDrawProcPtr inDrawProc,
|
|
|
|
|
ControlUserPaneHitTestProcPtr inHitTestProc,
|
|
|
|
|
ControlUserPaneTrackingProcPtr inTrackingProc)
|
|
|
|
|
{
|
|
|
|
|
OSErr err = noErr;
|
|
|
|
|
ControlUserPaneDrawUPP drawUPP;
|
|
|
|
|
ControlUserPaneHitTestUPP hitTestUPP;
|
|
|
|
|
ControlUserPaneTrackingUPP trackingUPP;
|
|
|
|
|
|
|
|
|
|
if (0 == inUserPane) return paramErr;
|
|
|
|
|
|
|
|
|
|
if (inDrawProc && noErr == err)
|
|
|
|
|
{
|
|
|
|
|
drawUPP = NewControlUserPaneDrawUPP(inDrawProc);
|
|
|
|
|
|
|
|
|
|
if (0 == drawUPP)
|
|
|
|
|
err = memFullErr;
|
|
|
|
|
else
|
|
|
|
|
err = SetControlData( inUserPane,
|
|
|
|
|
kControlEntireControl,
|
|
|
|
|
kControlUserPaneDrawProcTag,
|
|
|
|
|
sizeof(ControlUserPaneDrawUPP),
|
|
|
|
|
(Ptr)&drawUPP);
|
|
|
|
|
}
|
|
|
|
|
if (inHitTestProc && noErr == err)
|
|
|
|
|
{
|
|
|
|
|
hitTestUPP = NewControlUserPaneHitTestUPP(inHitTestProc);
|
|
|
|
|
|
|
|
|
|
if (0 == hitTestUPP)
|
|
|
|
|
err = memFullErr;
|
|
|
|
|
else
|
|
|
|
|
err = SetControlData( inUserPane,
|
|
|
|
|
kControlEntireControl,
|
|
|
|
|
kControlUserPaneHitTestProcTag,
|
|
|
|
|
sizeof(ControlUserPaneHitTestUPP),
|
|
|
|
|
(Ptr)&hitTestUPP);
|
|
|
|
|
}
|
|
|
|
|
if (inTrackingProc && noErr == err)
|
|
|
|
|
{
|
|
|
|
|
trackingUPP = NewControlUserPaneTrackingUPP(inTrackingProc);
|
|
|
|
|
|
|
|
|
|
if (0 == trackingUPP)
|
|
|
|
|
err = memFullErr;
|
|
|
|
|
else
|
|
|
|
|
err = SetControlData( inUserPane,
|
|
|
|
|
kControlEntireControl,
|
|
|
|
|
kControlUserPaneTrackingProcTag,
|
|
|
|
|
sizeof(ControlUserPaneTrackingUPP),
|
|
|
|
|
(Ptr)&trackingUPP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// DisposeUserPaneProcs
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Call this to clean up when you're done with the specified user pane control.
|
|
|
|
|
|
|
|
|
|
OSErr DisposeUserPaneProcs(ControlRef inUserPane)
|
|
|
|
|
{
|
|
|
|
|
ControlUserPaneDrawUPP drawUPP;
|
|
|
|
|
ControlUserPaneHitTestUPP hitTestUPP;
|
|
|
|
|
ControlUserPaneTrackingUPP trackingUPP;
|
|
|
|
|
Size actualSize;
|
|
|
|
|
OSErr err;
|
|
|
|
|
|
|
|
|
|
err = GetControlData(inUserPane, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(ControlUserPaneDrawUPP), (Ptr)&drawUPP, &actualSize);
|
|
|
|
|
if (err == noErr) DisposeControlUserPaneDrawUPP(drawUPP);
|
|
|
|
|
|
|
|
|
|
err = GetControlData(inUserPane, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(ControlUserPaneHitTestUPP), (Ptr)&hitTestUPP, &actualSize);
|
|
|
|
|
if (err == noErr) DisposeControlUserPaneHitTestUPP(hitTestUPP);
|
|
|
|
|
|
|
|
|
|
err = GetControlData(inUserPane, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(ControlUserPaneTrackingUPP), (Ptr)&trackingUPP, &actualSize);
|
|
|
|
|
if (err == noErr) DisposeControlUserPaneTrackingUPP(trackingUPP);
|
|
|
|
|
|
|
|
|
|
return noErr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// drawProc
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Custom drawProc for our UserPane control.
|
|
|
|
|
|
|
|
|
|
static pascal void drawProc(ControlRef inControl, SInt16 inPart)
|
|
|
|
|
{
|
|
|
|
|
#pragma unused(inControl, inPart)
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
RGBColor saveForeColor;
|
|
|
|
|
RGBColor saveBackColor;
|
|
|
|
|
PenState savePenState;
|
|
|
|
|
|
|
|
|
|
GetForeColor(&saveForeColor);
|
|
|
|
|
GetBackColor(&saveBackColor);
|
|
|
|
|
GetPenState(&savePenState);
|
|
|
|
|
|
|
|
|
|
RGBForeColor(&rgbBlack);
|
|
|
|
|
RGBBackColor(&rgbWhite);
|
|
|
|
|
PenNormal();
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < sNumMonitors; i++)
|
|
|
|
|
{
|
|
|
|
|
RGBForeColor(&rgbGray);
|
|
|
|
|
PaintRect(&sMonitors[i].scaledRect);
|
|
|
|
|
if (sMonitors[i].isMain)
|
|
|
|
|
{
|
|
|
|
|
Rect r = sMonitors[i].scaledRect;
|
|
|
|
|
InsetRect(&r, 1, 1);
|
|
|
|
|
r.bottom = r.top + 6;
|
|
|
|
|
RGBForeColor(&rgbWhite);
|
|
|
|
|
PaintRect(&r);
|
|
|
|
|
RGBForeColor(&rgbBlack);
|
|
|
|
|
PenSize(1,1);
|
|
|
|
|
MoveTo(r.left, r.bottom);
|
|
|
|
|
LineTo(r.right, r.bottom);
|
|
|
|
|
}
|
|
|
|
|
if (sMonitors[i].device == sSelectedDevice)
|
|
|
|
|
{
|
|
|
|
|
PenSize(3,3);
|
|
|
|
|
RGBForeColor(&rgbBlack);
|
|
|
|
|
FrameRect(&sMonitors[i].scaledRect);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
PenSize(1,1);
|
|
|
|
|
RGBForeColor(&rgbBlack);
|
|
|
|
|
FrameRect(&sMonitors[i].scaledRect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// restore the original pen state and colors
|
|
|
|
|
RGBForeColor(&saveForeColor);
|
|
|
|
|
RGBBackColor(&saveBackColor);
|
|
|
|
|
SetPenState(&savePenState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// hitTestProc
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Custom hitTestProc for our UserPane control.
|
|
|
|
|
// This allows FindControlUnderMouse() to locate our control, which allows
|
|
|
|
|
// ModalDialog() to call TrackControl() or HandleControlClick() for our control.
|
|
|
|
|
|
|
|
|
|
static pascal ControlPartCode hitTestProc(ControlRef inControl, Point inWhere)
|
|
|
|
|
{
|
|
|
|
|
// return a valid part code so HandleControlClick() will be called
|
|
|
|
|
return kControlButtonPart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// trackingProc
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Custom trackingProc for our UserPane control.
|
|
|
|
|
// This won't be called for our control unless the kControlHandlesTracking feature
|
|
|
|
|
// bit is specified when the userPane is created.
|
|
|
|
|
|
|
|
|
|
static pascal ControlPartCode trackingProc (
|
|
|
|
|
ControlRef inControl,
|
|
|
|
|
Point inStartPt,
|
|
|
|
|
ControlActionUPP inActionProc)
|
|
|
|
|
{
|
|
|
|
|
#pragma unused (inControl, inStartPt, inActionProc)
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < sNumMonitors; i++)
|
|
|
|
|
{
|
|
|
|
|
if (PtInRect(inStartPt, &sMonitors[i].scaledRect))
|
|
|
|
|
{
|
|
|
|
|
if (sMonitors[i].device != sSelectedDevice)
|
|
|
|
|
{
|
|
|
|
|
sSelectedDevice = sMonitors[i].device;
|
|
|
|
|
DrawOneControl(inControl);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kControlNoPart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// SetupPickMonitorPane
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Call this to initialize the user pane control that is the Pick Monitor
|
|
|
|
|
// control. Pass the ControlRef of the user pane control and a display ID
|
|
|
|
|
// for the monitor you want selected by default (pass 0 for the main monitor).
|
|
|
|
|
// Call this function before displaying the dialog window.
|
|
|
|
|
|
|
|
|
|
OSErr SetupPickMonitorPane(ControlRef inPane, DisplayIDType inDefaultMonitor)
|
|
|
|
|
{
|
|
|
|
|
GDHandle dev = GetDeviceList();
|
|
|
|
|
OSErr err = noErr;
|
|
|
|
|
|
|
|
|
|
// make the default monitor the selected device
|
|
|
|
|
if (inDefaultMonitor)
|
|
|
|
|
DMGetGDeviceByDisplayID(inDefaultMonitor, &sSelectedDevice, true);
|
|
|
|
|
else
|
|
|
|
|
sSelectedDevice = GetMainDevice();
|
|
|
|
|
|
|
|
|
|
// build the list of monitors
|
|
|
|
|
sNumMonitors = 0;
|
|
|
|
|
while (dev && sNumMonitors < kMaxMonitors)
|
|
|
|
|
{
|
|
|
|
|
if (TestDeviceAttribute(dev, screenDevice) && TestDeviceAttribute(dev, screenActive))
|
|
|
|
|
{
|
|
|
|
|
sMonitors[sNumMonitors].device = dev;
|
|
|
|
|
sMonitors[sNumMonitors].origRect = (**dev).gdRect;
|
|
|
|
|
sMonitors[sNumMonitors].isMain = (dev == GetMainDevice());
|
|
|
|
|
sNumMonitors++;
|
|
|
|
|
}
|
|
|
|
|
dev = GetNextDevice(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate scaled rects
|
|
|
|
|
if (sNumMonitors)
|
|
|
|
|
{
|
|
|
|
|
Rect origPaneRect, paneRect;
|
|
|
|
|
Rect origGrayRect, grayRect, scaledGrayRect;
|
|
|
|
|
float srcAspect, dstAspect, scale;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
GetControlBounds(inPane, &origPaneRect);
|
|
|
|
|
paneRect = origPaneRect;
|
|
|
|
|
OffsetRect(&paneRect, -paneRect.left, -paneRect.top);
|
|
|
|
|
|
|
|
|
|
GetRegionBounds(GetGrayRgn(), &origGrayRect);
|
|
|
|
|
grayRect = origGrayRect;
|
|
|
|
|
OffsetRect(&grayRect, -grayRect.left, -grayRect.top);
|
|
|
|
|
|
|
|
|
|
srcAspect = (float)grayRect.right / (float)grayRect.bottom;
|
|
|
|
|
dstAspect = (float)paneRect.right / (float)paneRect.bottom;
|
|
|
|
|
|
|
|
|
|
scaledGrayRect = paneRect;
|
|
|
|
|
|
|
|
|
|
if (srcAspect < dstAspect)
|
|
|
|
|
{
|
|
|
|
|
scaledGrayRect.right = (float)paneRect.bottom * srcAspect;
|
|
|
|
|
scale = (float)scaledGrayRect.right / grayRect.right;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
scaledGrayRect.bottom = (float)paneRect.right / srcAspect;
|
|
|
|
|
scale = (float)scaledGrayRect.bottom / grayRect.bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < sNumMonitors; i++)
|
|
|
|
|
{
|
|
|
|
|
Rect r = sMonitors[i].origRect;
|
|
|
|
|
Rect r2 = r;
|
|
|
|
|
|
|
|
|
|
// normalize rect and scale
|
|
|
|
|
OffsetRect(&r, -r.left, -r.top);
|
|
|
|
|
r.bottom = (float)r.bottom * scale;
|
|
|
|
|
r.right = (float)r.right * scale;
|
|
|
|
|
|
|
|
|
|
// offset rect wrt gray region
|
|
|
|
|
OffsetRect(&r, (float)(r2.left - origGrayRect.left) * scale,
|
|
|
|
|
(float)(r2.top - origGrayRect.top) * scale);
|
|
|
|
|
|
|
|
|
|
sMonitors[i].scaledRect = r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// center scaledGrayRect in the pane
|
|
|
|
|
OffsetRect(&scaledGrayRect, (paneRect.right - scaledGrayRect.right) / 2,
|
|
|
|
|
(paneRect.bottom - scaledGrayRect.bottom) / 2);
|
|
|
|
|
|
|
|
|
|
// offset monitors to match
|
|
|
|
|
for (i = 0; i < sNumMonitors; i++)
|
|
|
|
|
OffsetRect(&sMonitors[i].scaledRect, scaledGrayRect.left, scaledGrayRect.top);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return paramErr;
|
|
|
|
|
|
|
|
|
|
// setup the procs for the pick monitor user pane
|
|
|
|
|
err = SetupUserPaneProcs(inPane, drawProc, hitTestProc, trackingProc);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// TearDownPickMonitorPane
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Disposes of everything associated with the Pick Monitor pane. You should
|
|
|
|
|
// call this when disposing the dialog.
|
|
|
|
|
|
|
|
|
|
OSErr TearDownPickMonitorPane(ControlRef inPane)
|
|
|
|
|
{
|
|
|
|
|
OSErr err;
|
|
|
|
|
err = DisposeUserPaneProcs(inPane);
|
|
|
|
|
sNumMonitors = 0;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------
|
|
|
|
|
// <20> PickMonitorHandler
|
|
|
|
|
//------------------------------------------------------------------------------------
|
|
|
|
|
// Our command handler for the PickMonitor dialog.
|
|
|
|
|
|
|
|
|
|
static pascal OSStatus PickMonitorHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* inUserData )
|
|
|
|
|
{
|
|
|
|
|
#pragma unused( inHandler )
|
|
|
|
|
|
|
|
|
|
HICommand cmd;
|
|
|
|
|
OSStatus result = eventNotHandledErr;
|
|
|
|
|
WindowRef theWindow = (WindowRef)inUserData;
|
|
|
|
|
|
|
|
|
|
// The direct object for a 'process commmand' event is the HICommand.
|
|
|
|
|
// Extract it here and switch off the command ID.
|
|
|
|
|
|
|
|
|
|
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof( cmd ), NULL, &cmd );
|
|
|
|
|
|
|
|
|
|
switch ( cmd.commandID )
|
|
|
|
|
{
|
|
|
|
|
case kHICommandOK:
|
|
|
|
|
QuitAppModalLoopForWindow( theWindow );
|
|
|
|
|
result = noErr;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case kHICommandCancel:
|
|
|
|
|
// Setting sSelectedDevice to zero will signal that the user cancelled.
|
|
|
|
|
sSelectedDevice = 0;
|
|
|
|
|
QuitAppModalLoopForWindow( theWindow );
|
|
|
|
|
result = noErr;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// CanUserPickMonitor
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Returns true if more than one monitor is available to choose from.
|
|
|
|
|
|
|
|
|
|
Boolean CanUserPickMonitor (void)
|
|
|
|
|
{
|
|
|
|
|
GDHandle dev = GetDeviceList();
|
|
|
|
|
OSErr err = noErr;
|
|
|
|
|
int numMonitors;
|
|
|
|
|
|
|
|
|
|
// build the list of monitors
|
|
|
|
|
numMonitors = 0;
|
|
|
|
|
while (dev && numMonitors < kMaxMonitors)
|
|
|
|
|
{
|
|
|
|
|
if (TestDeviceAttribute(dev, screenDevice) && TestDeviceAttribute(dev, screenActive))
|
|
|
|
|
{
|
|
|
|
|
numMonitors++;
|
|
|
|
|
}
|
|
|
|
|
dev = GetNextDevice(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (numMonitors > 1) return true;
|
|
|
|
|
else return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// PickMonitor
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Prompts for a monitor. Returns userCanceledErr if the user cancelled.
|
|
|
|
|
|
|
|
|
|
OSStatus PickMonitor (DisplayIDType *inOutDisplayID, WindowRef parentWindow)
|
|
|
|
|
{
|
|
|
|
|
WindowRef theWindow;
|
|
|
|
|
OSStatus status = noErr;
|
|
|
|
|
static const ControlID kUserPane = { 'MONI', 1 };
|
|
|
|
|
|
|
|
|
|
// Fetch the dialog
|
|
|
|
|
|
|
|
|
|
IBNibRef aslNib;
|
|
|
|
|
CFBundleRef theBundle = CFBundleGetMainBundle();
|
|
|
|
|
status = CreateNibReferenceWithCFBundle(theBundle, CFSTR("ASLCore"), &aslNib);
|
|
|
|
|
status = ::CreateWindowFromNib(aslNib, CFSTR( "Pick Monitor" ), &theWindow );
|
|
|
|
|
if (status != noErr)
|
|
|
|
|
{
|
|
|
|
|
assert(false);
|
|
|
|
|
return userCanceledErr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// Put game name in window title. By default the title includes the token <<<kGameName>>>.
|
|
|
|
|
|
|
|
|
|
Str255 windowTitle;
|
|
|
|
|
GetWTitle(theWindow, windowTitle);
|
|
|
|
|
FormatPStringWithGameName(windowTitle);
|
|
|
|
|
SetWTitle(theWindow, windowTitle);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Set up the controls
|
|
|
|
|
|
|
|
|
|
ControlRef monitorPane;
|
|
|
|
|
GetControlByID( theWindow, &kUserPane, &monitorPane );
|
|
|
|
|
assert(monitorPane);
|
|
|
|
|
|
|
|
|
|
SetupPickMonitorPane(monitorPane, *inOutDisplayID);
|
|
|
|
|
|
|
|
|
|
// Create our UPP and install the handler.
|
|
|
|
|
|
|
|
|
|
EventTypeSpec cmdEvent = { kEventClassCommand, kEventCommandProcess };
|
|
|
|
|
EventHandlerUPP handler = NewEventHandlerUPP( PickMonitorHandler );
|
|
|
|
|
InstallWindowEventHandler( theWindow, handler, 1, &cmdEvent, theWindow, NULL );
|
|
|
|
|
|
|
|
|
|
// Show the window
|
|
|
|
|
|
|
|
|
|
if (parentWindow)
|
|
|
|
|
ShowSheetWindow( theWindow, parentWindow );
|
|
|
|
|
else
|
|
|
|
|
ShowWindow( theWindow );
|
|
|
|
|
|
|
|
|
|
// Now we run modally. We will remain here until the PrefHandler
|
|
|
|
|
// calls QuitAppModalLoopForWindow if the user clicks OK or
|
|
|
|
|
// Cancel.
|
|
|
|
|
|
|
|
|
|
RunAppModalLoopForWindow( theWindow );
|
|
|
|
|
|
|
|
|
|
// OK, we're done. Dispose of our window and our UPP.
|
|
|
|
|
// We do the UPP last because DisposeWindow can send out
|
|
|
|
|
// CarbonEvents, and we haven't explicitly removed our
|
|
|
|
|
// handler. If we disposed the UPP, the Toolbox might try
|
|
|
|
|
// to call it. That would be bad.
|
|
|
|
|
|
|
|
|
|
TearDownPickMonitorPane(monitorPane);
|
|
|
|
|
if (parentWindow)
|
|
|
|
|
HideSheetWindow( theWindow );
|
|
|
|
|
DisposeWindow( theWindow );
|
|
|
|
|
DisposeEventHandlerUPP( handler );
|
|
|
|
|
|
|
|
|
|
// Return settings to caller
|
|
|
|
|
|
|
|
|
|
if (sSelectedDevice != 0)
|
|
|
|
|
{
|
|
|
|
|
// Read back the controls
|
|
|
|
|
DMGetDisplayIDByGDevice (sSelectedDevice, &*inOutDisplayID, true);
|
|
|
|
|
return noErr;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return userCanceledErr;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|