mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-03-21 18:21:08 +00:00
Get rid of Sys_DoPreferences()
The OSX backend was the only one utilizing this to set CVars for the video mode. Not required anymore since its now based on SDL.
This commit is contained in:
parent
3c90c12605
commit
1fed72fbb4
10 changed files with 0 additions and 1497 deletions
|
@ -623,8 +623,6 @@ if (APPLE)
|
|||
set(src_sys_core
|
||||
sys/glimp.cpp
|
||||
sys/glimp_ati_fragment_shader.cpp
|
||||
sys/osx/PickMonitor.cpp
|
||||
sys/osx/PreferencesDialog.cpp
|
||||
sys/osx/DOOMController.mm
|
||||
sys/osx/macosx_misc.mm
|
||||
)
|
||||
|
|
|
@ -2977,9 +2977,6 @@ void idCommonLocal::InitGame( void ) {
|
|||
// if any archived cvars are modified after this, we will trigger a writing of the config file
|
||||
cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
|
||||
|
||||
// cvars are initialized, but not the rendering system. Allow preference startup dialog
|
||||
Sys_DoPreferences();
|
||||
|
||||
// init the user command input code
|
||||
usercmdGen->Init();
|
||||
|
||||
|
|
|
@ -283,13 +283,6 @@ void idSysLocal::OpenURL( const char *url, bool quit ) {
|
|||
sys->StartProcess( cmdline, quit );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_DoPreferences
|
||||
==================
|
||||
*/
|
||||
void Sys_DoPreferences( void ) { }
|
||||
|
||||
/*
|
||||
===============
|
||||
mem consistency stuff
|
||||
|
|
|
@ -1,526 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
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 "sys/platform.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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// drawProc
|
||||
//-----------------------------------------------------------------------------
|
||||
// Custom drawProc for our UserPane control.
|
||||
|
||||
static pascal void drawProc(ControlRef, SInt16)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// ¥ PickMonitorHandler
|
||||
//------------------------------------------------------------------------------------
|
||||
// Our command handler for the PickMonitor dialog.
|
||||
|
||||
static pascal OSStatus PickMonitorHandler( EventHandlerCallRef, EventRef inEvent, void* inUserData )
|
||||
{
|
||||
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;
|
||||
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef PICKMONITOR_H
|
||||
#define PICKMONITOR_H
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
OSStatus PickMonitor (DisplayIDType *inOutDisplayID, WindowRef parentWindow);
|
||||
Boolean CanUserPickMonitor (void);
|
||||
|
||||
#endif // PICKMONITOR_H
|
|
@ -1,835 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
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 <list>
|
||||
#include <set>
|
||||
|
||||
#include "sys/platform.h"
|
||||
#include "framework/CVarSystem.h"
|
||||
#include "sys/osx/PickMonitor.h"
|
||||
|
||||
#include "PreferencesDialog.h"
|
||||
|
||||
static idCVar r_stretched( "r_stretched", "0", CVAR_ARCHIVE | CVAR_BOOL, "Used stretched resolution" );
|
||||
|
||||
#define kPref_PrefsDialogAlways CFSTR("PrefsDialogAlways")
|
||||
#define kPref_PrefsDialogOpenAL CFSTR("UseOpenAL")
|
||||
|
||||
#ifndef kAppCreator
|
||||
#define kAppCreator 'DOM3' // Creator type
|
||||
#endif
|
||||
|
||||
const UInt32 kRes_Stretched = (1 << 0); // set if the resolution is a stretched mode (kCGDisplayModeIsStretched)
|
||||
const UInt32 kRes_Safe = (1 << 1); // ¥¥¥Ê(currently unused) set if the resolution is safe (kCGDisplayModeIsSafeForHardware)
|
||||
|
||||
// Data to be presented and edited in the prefs dialog
|
||||
struct PrefInfo
|
||||
{
|
||||
// prefs values
|
||||
GameDisplayMode prefGameDisplayMode;
|
||||
CGDirectDisplayID prefDisplayID;
|
||||
int prefWidth;
|
||||
int prefHeight;
|
||||
int prefDepth;
|
||||
Fixed prefFrequency;
|
||||
UInt32 prefResFlags;
|
||||
Boolean prefAlways;
|
||||
Boolean prefOpenAL;
|
||||
|
||||
bool okPressed; // Set to true if the user pressed the OK button
|
||||
|
||||
// The following are private data passed from GameDisplayPreferencesDialog() to it's command handler.
|
||||
WindowRef window;
|
||||
ControlRef fullscreenBtn;
|
||||
ControlRef inAWindowBtn;
|
||||
ControlRef resolutionPopup;
|
||||
ControlRef refreshRatePopup;
|
||||
ControlRef chooseMonitorsBtn;
|
||||
ControlRef alwaysBtn;
|
||||
ControlRef openALBtn;
|
||||
|
||||
ValidModeCallbackProc callback; // To validate display modes
|
||||
|
||||
bool multiMonitor; // Does user have multiple monitors
|
||||
std::list<Fixed> refreshRates; // List of refresh rates available for the selected monitor
|
||||
SInt32 freqMenuIndex;
|
||||
};
|
||||
|
||||
bool R_GetModeInfo( int *width, int *height, int mode );
|
||||
|
||||
static int GetScreenIndexForDisplayID( CGDirectDisplayID inDisplayID ) {
|
||||
unsigned int i;
|
||||
OSErr err;
|
||||
int r_screen = -1;
|
||||
CGDisplayCount count;
|
||||
|
||||
err = CGGetActiveDisplayList(0, NULL, &count);
|
||||
if (noErr == err) {
|
||||
CGDirectDisplayID displays[count];
|
||||
err = CGGetActiveDisplayList(count, displays, &count);
|
||||
if (noErr == err) {
|
||||
for ( i = 0; i < count; i++)
|
||||
if (displays[i] == inDisplayID)
|
||||
r_screen = i;
|
||||
}
|
||||
}
|
||||
return r_screen;
|
||||
}
|
||||
|
||||
static CGDirectDisplayID GetDisplayIDForScreenIndex( int inScreenIndex ) {
|
||||
OSErr err;
|
||||
int r_screen = -1;
|
||||
CGDisplayCount count;
|
||||
|
||||
err = CGGetActiveDisplayList(0, NULL, &count);
|
||||
if (noErr == err) {
|
||||
CGDirectDisplayID displays[count];
|
||||
err = CGGetActiveDisplayList(count, displays, &count);
|
||||
if (noErr == err) {
|
||||
if ( inScreenIndex >= 0 && inScreenIndex <= count )
|
||||
return displays[inScreenIndex];
|
||||
}
|
||||
}
|
||||
return (CGDirectDisplayID)r_screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Sys_DoPreferences( void ) {
|
||||
|
||||
// An NSKeyDown event is not fired if the user holds down Cmd during startup.
|
||||
// Cmd is treated purely as a modifier. To capture the user
|
||||
// holding down Cmd, you would need to override NSApplication's
|
||||
// keydown handler. That's overkill for a single check at
|
||||
// startup, use the Carbon GetKeys approach.
|
||||
unsigned char km[16];
|
||||
const int kMacKeyCodeCommand = 0x37;
|
||||
KeyMap *keymap = (KeyMap*)&km;
|
||||
GetKeys(*keymap);
|
||||
|
||||
Boolean prefAways, keyFound, useOpenAL;
|
||||
prefAways = CFPreferencesGetAppBooleanValue ( kPref_PrefsDialogAlways, kCFPreferencesCurrentApplication, &keyFound );
|
||||
bool fAlways = prefAways && keyFound;
|
||||
|
||||
if ( fAlways || ( km[kMacKeyCodeCommand>>3] >> ( kMacKeyCodeCommand & 7 ) ) & 1 ) {
|
||||
GameDisplayInfo info;
|
||||
info.mode = cvarSystem->GetCVarBool( "r_fullscreen" ) ? kFullScreen : kWindow;
|
||||
info.displayID = GetDisplayIDForScreenIndex( cvarSystem->GetCVarInteger( "r_screen" ) );
|
||||
|
||||
int w = 800, h = 600;
|
||||
R_GetModeInfo( &w, &h, cvarSystem->GetCVarInteger( "r_mode" ) );
|
||||
info.width = w;
|
||||
info.height = h;
|
||||
info.depth = 32;
|
||||
info.frequency = cvarSystem->GetCVarInteger( "r_maxDisplayRefresh" );
|
||||
info.windowLoc.x = 0;
|
||||
info.windowLoc.y = 0;
|
||||
info.flags = 0;
|
||||
info.resFlags = 0;
|
||||
if ( r_stretched.GetBool() )
|
||||
info.resFlags |= kRes_Stretched;
|
||||
|
||||
WindowRef prefWindow;
|
||||
if ( CreateGameDisplayPreferencesDialog( &info, &prefWindow ) == noErr ) {
|
||||
if ( RunGameDisplayPreferencesDialog( &info, prefWindow ) == noErr ) {
|
||||
cvarSystem->SetCVarBool( "r_fullscreen", info.mode == kFullScreen );
|
||||
|
||||
int i = 0;
|
||||
int r_mode = -1;
|
||||
while ( r_mode == -1 && R_GetModeInfo( &w, &h, i ) ) {
|
||||
if ( w == info.width && h == info.height )
|
||||
r_mode = i;
|
||||
i++;
|
||||
}
|
||||
cvarSystem->SetCVarInteger( "r_mode", r_mode );
|
||||
if ( r_mode == -1 ) {
|
||||
cvarSystem->SetCVarInteger( "r_customWidth", info.width );
|
||||
cvarSystem->SetCVarInteger( "r_customHeight", info.height );
|
||||
}
|
||||
|
||||
float r = (float) info.width / (float) info.height;
|
||||
if ( r > 1.7f )
|
||||
cvarSystem->SetCVarInteger( "r_aspectRatio", 1 ); // 16:9
|
||||
else if ( r > 1.55f )
|
||||
cvarSystem->SetCVarInteger( "r_aspectRatio", 2 ); // 16:10
|
||||
else
|
||||
cvarSystem->SetCVarInteger( "r_aspectRatio", 0 ); // 4:3
|
||||
|
||||
r_stretched.SetBool( info.resFlags & kRes_Stretched );
|
||||
cvarSystem->SetCVarInteger( "r_screen", GetScreenIndexForDisplayID( info.displayID ) );
|
||||
cvarSystem->SetCVarInteger( "r_minDisplayRefresh", (int)FixedToFloat( info.frequency ) );
|
||||
cvarSystem->SetCVarInteger( "r_maxDisplayRefresh", (int)FixedToFloat( info.frequency ) );
|
||||
}
|
||||
else {
|
||||
Sys_Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
useOpenAL = CFPreferencesGetAppBooleanValue (kPref_PrefsDialogOpenAL, kCFPreferencesCurrentApplication, &keyFound);
|
||||
if ( keyFound && useOpenAL ) {
|
||||
cvarSystem->SetCVarInteger( "com_asyncSound", 1 );
|
||||
cvarSystem->SetCVarInteger( "s_useOpenAL", 1 );
|
||||
}
|
||||
else {
|
||||
cvarSystem->SetCVarInteger( "com_asyncSound", 2 );
|
||||
cvarSystem->SetCVarInteger( "s_useOpenAL", 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define EnablePopupMenuItem(inControl,inMenuItem) EnableMenuItem(GetControlPopupMenuRef(inControl),inMenuItem)
|
||||
#define DisablePopupMenuItem(inControl,inMenuItem) DisableMenuItem(GetControlPopupMenuRef(inControl),inMenuItem)
|
||||
#define IsPopupMenuItemEnabled(inControl,inMenuItem) IsMenuItemEnabled(GetControlPopupMenuRef(inControl),inMenuItem)
|
||||
|
||||
// Command IDs used in the NIB file
|
||||
enum
|
||||
{
|
||||
kCmdFullscreen = 'Full',
|
||||
kCmdInAWindow = 'Wind',
|
||||
kCmdResolution = 'Reso',
|
||||
kCmdRefreshRate = 'Refr',
|
||||
kCmdChooseMonitors = 'Moni',
|
||||
};
|
||||
|
||||
// Control IDs used in the NIB file
|
||||
static const ControlID kFullscreenBtn = { 'PREF', 1 };
|
||||
static const ControlID kInAWindowBtn = { 'PREF', 2 };
|
||||
static const ControlID kResolutionPopup = { 'PREF', 3 };
|
||||
static const ControlID kRefreshRatePopup = { 'PREF', 4 };
|
||||
static const ControlID kChooseMonitorsBtn = { 'PREF', 5 };
|
||||
static const ControlID kAlwaysBtn = { 'PREF', 6 };
|
||||
static const ControlID kOpenALBtn = { 'PREF', 7 };
|
||||
|
||||
struct Res
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
UInt32 resFlags;
|
||||
};
|
||||
|
||||
static bool operator< (const Res& a, const Res& b)
|
||||
{
|
||||
if (a.width == b.width)
|
||||
{
|
||||
if (a.height == b.height)
|
||||
{
|
||||
if (a.resFlags == b.resFlags)
|
||||
{
|
||||
return (a.depth < b.depth);
|
||||
}
|
||||
return (a.resFlags < b.resFlags);
|
||||
}
|
||||
return (a.height < b.height);
|
||||
}
|
||||
return (a.width < b.width);
|
||||
}
|
||||
|
||||
inline Res MakeRes(int width, int height, int depth)
|
||||
{
|
||||
Res temp = { width, height, depth, 0 };
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline Res MakeRes(int width, int height, int depth, UInt32 resFlags)
|
||||
{
|
||||
Res temp = { width, height, depth, resFlags };
|
||||
return temp;
|
||||
}
|
||||
|
||||
static bool ValidDisplayID (CGDirectDisplayID inDisplayID)
|
||||
{
|
||||
unsigned int i;
|
||||
CGDisplayErr err;
|
||||
CGDisplayCount count;
|
||||
|
||||
err = CGGetActiveDisplayList(0, NULL, &count);
|
||||
if (noErr == err)
|
||||
{
|
||||
CGDirectDisplayID displays[count];
|
||||
err = CGGetActiveDisplayList(count, displays, &count);
|
||||
if (noErr == err)
|
||||
{
|
||||
for ( i = 0; i < count; i++)
|
||||
if (displays[i] == inDisplayID)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int BuildResolutionList(CGDirectDisplayID inDisplayID, Res *ioList, ValidModeCallbackProc inCallback)
|
||||
{
|
||||
std::set<Res> modes;
|
||||
int i, total = 0;
|
||||
|
||||
if (inDisplayID == (CGDirectDisplayID)-1) // special case, not associated with any display
|
||||
{
|
||||
Res stdModes[] = { { 640, 480 }, { 800, 600 }, { 1024, 768 }, { 1152, 768 },
|
||||
{ 1280, 854 }, { 1280, 960 }, { 1280, 1024 }, { 1440, 900 } };
|
||||
total = sizeof(stdModes) / sizeof(Res);
|
||||
for (i = 0; i < total; i++)
|
||||
{
|
||||
if (inCallback == NULL || inCallback(inDisplayID, stdModes[i].width, stdModes[i].height, 32, 0))
|
||||
modes.insert( MakeRes(stdModes[i].width, stdModes[i].height, 32) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CGDirectDisplayID displayID = inDisplayID ? inDisplayID : kCGDirectMainDisplay;
|
||||
CFArrayRef modeArrayRef = CGDisplayAvailableModes(displayID);
|
||||
CFIndex numModes = CFArrayGetCount(modeArrayRef);
|
||||
|
||||
for (i = 0; i < numModes; i++)
|
||||
{
|
||||
CFDictionaryRef modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modeArrayRef, i);
|
||||
|
||||
long value = 0;
|
||||
CFNumberRef valueRef;
|
||||
Boolean success;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayBitsPerPixel);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int depth = value;
|
||||
if (depth != 32) continue;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayWidth);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int width = value;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayHeight);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int height = value;
|
||||
|
||||
UInt32 resFlags = 0;
|
||||
CFBooleanRef boolRef;
|
||||
if (CFDictionaryGetValueIfPresent (modeRef, kCGDisplayModeIsStretched, (const void **)&boolRef))
|
||||
if (CFBooleanGetValue (boolRef))
|
||||
resFlags |= kRes_Stretched;
|
||||
|
||||
|
||||
if (inCallback)
|
||||
success = inCallback(displayID, width, height, depth, 0);
|
||||
else
|
||||
success = true;
|
||||
|
||||
if (success)
|
||||
modes.insert(MakeRes(width, height, depth, resFlags));
|
||||
}
|
||||
}
|
||||
|
||||
total = modes.size();
|
||||
|
||||
if (ioList)
|
||||
{
|
||||
std::set<Res>::iterator it = modes.begin();
|
||||
for (i = 0; it != modes.end(); i++)
|
||||
ioList[i] = *it++;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void BuildRefreshRates(CGDirectDisplayID inDisplayID, int inWidth, int inHeight, std::list<Fixed>* inList, ValidModeCallbackProc inCallback)
|
||||
{
|
||||
CGDirectDisplayID displayID = inDisplayID ? inDisplayID : kCGDirectMainDisplay;
|
||||
|
||||
CFArrayRef modeArrayRef = CGDisplayAvailableModes(displayID);
|
||||
CFIndex numModes = CFArrayGetCount(modeArrayRef);
|
||||
|
||||
inList->clear();
|
||||
|
||||
for (int i = 0; i < numModes; i++)
|
||||
{
|
||||
CFDictionaryRef modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modeArrayRef, i);
|
||||
|
||||
long value = 0;
|
||||
CFNumberRef valueRef;
|
||||
Boolean success;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayBitsPerPixel);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int depth = value;
|
||||
if (depth != 32) continue;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayWidth);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int width = value;
|
||||
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayHeight);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
|
||||
int height = value;
|
||||
|
||||
if (width == inWidth && height == inHeight)
|
||||
{
|
||||
double freqDouble;
|
||||
valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayRefreshRate);
|
||||
success = CFNumberGetValue(valueRef, kCFNumberDoubleType, &freqDouble);
|
||||
Fixed freq = FloatToFixed(freqDouble);
|
||||
if (inCallback)
|
||||
success = inCallback(displayID, width, height, depth, freq);
|
||||
else
|
||||
success = true;
|
||||
if (success)
|
||||
inList->push_back(freq);
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow 0, which we reserve to mean "automatic"
|
||||
inList->remove(0);
|
||||
|
||||
inList->sort();
|
||||
|
||||
// Remove duplicates - yes they can occur.
|
||||
inList->unique();
|
||||
}
|
||||
|
||||
static void BuildRefreshPopupButton(ControlRef inControl, std::list<Fixed>* inList)
|
||||
{
|
||||
MenuRef menu = GetControlPopupMenuRef(inControl);
|
||||
assert(menu);
|
||||
if (!menu) return;
|
||||
|
||||
// The menu has two permanent items - "Auto" & a divider line. Delete everything else.
|
||||
DeleteMenuItems(menu, 3, CountMenuItems(menu)-2);
|
||||
|
||||
for (std::list<Fixed>::const_iterator iter = inList->begin(); iter != inList->end(); ++iter)
|
||||
{
|
||||
float value = FixedToFloat(*iter);
|
||||
CFStringRef menuString = CFStringCreateWithFormat (kCFAllocatorDefault, 0, CFSTR("%g Hz"), value);
|
||||
InsertMenuItemTextWithCFString(menu, menuString, CountMenuItems(menu), 0, 0);
|
||||
}
|
||||
|
||||
SetControlMaximum(inControl, CountMenuItems(menu));
|
||||
}
|
||||
|
||||
static SInt32 FindRefreshPopupMenuItem(std::list<Fixed>* inList, Fixed inFrequency)
|
||||
{
|
||||
SInt32 index = 3; // skip over the "Auto" and divider ine
|
||||
for (std::list<Fixed>::const_iterator iter = inList->begin(); iter != inList->end(); ++iter)
|
||||
{
|
||||
if (*iter == inFrequency)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return 1; // Return the "Automatic" item if we didn't find a match
|
||||
}
|
||||
|
||||
static void BuildResolutionPopupButton(ControlRef inControl, CGDirectDisplayID inDisplayID, ValidModeCallbackProc inCallback)
|
||||
{
|
||||
// Get the list of valid resolutions
|
||||
int count = BuildResolutionList(inDisplayID, NULL, inCallback);
|
||||
Res resList[count];
|
||||
BuildResolutionList(inDisplayID, resList, inCallback);
|
||||
|
||||
// Clear the menu
|
||||
MenuRef menu = GetControlPopupMenuRef(inControl);
|
||||
assert(menu);
|
||||
if (!menu) return;
|
||||
DeleteMenuItems(menu, 1, CountMenuItems(menu));
|
||||
|
||||
OSStatus err;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
CFStringRef menuString = CFStringCreateWithFormat (kCFAllocatorDefault, 0, CFSTR("%d x %d %@"),
|
||||
resList[count].width, resList[count].height, (resList[count].resFlags & kRes_Stretched) ? CFSTR("(Stretched)") : CFSTR(""));
|
||||
InsertMenuItemTextWithCFString (menu, menuString, 0, 0, 0);
|
||||
err = SetMenuItemProperty (menu, 1, kAppCreator, 'Res ', sizeof(resList[count]), &resList[count]);
|
||||
}
|
||||
|
||||
SetControlMaximum(inControl, CountMenuItems(menu));
|
||||
}
|
||||
|
||||
static void GetResolutionFromPopupMenuItem(ControlRef inControl, MenuItemIndex inItem, int *outX, int *outY, int *outDepth, UInt32 *outResFlags)
|
||||
{
|
||||
MenuRef menu = GetControlPopupMenuRef(inControl);
|
||||
Res res;
|
||||
OSStatus err;
|
||||
|
||||
err = GetMenuItemProperty (menu, inItem, kAppCreator, 'Res ', sizeof(res), NULL, &res);
|
||||
if (!err)
|
||||
{
|
||||
*outX = res.width;
|
||||
*outY = res.height;
|
||||
*outResFlags = res.resFlags;
|
||||
*outDepth = 32;
|
||||
}
|
||||
}
|
||||
|
||||
static void AdjustResolutionPopupMenu(ControlRef inControl, CGDirectDisplayID inDisplayID, bool isFullscreen, int& screenwidth, int& screenheight, int& screendepth, UInt32& screenResFlags)
|
||||
{
|
||||
int screenX = INT_MAX, screenY = INT_MAX;
|
||||
|
||||
// In windowed mode, you have to disable resolutions that are larger than the current screen size
|
||||
if (!isFullscreen)
|
||||
{
|
||||
screenX = (int)CGDisplayPixelsWide(inDisplayID);
|
||||
screenY = (int)CGDisplayPixelsHigh(inDisplayID);
|
||||
}
|
||||
|
||||
MenuRef menu = GetControlPopupMenuRef(inControl);
|
||||
int resX, resY, depth;
|
||||
UInt32 resFlags;
|
||||
int count = CountMenuItems(menu);
|
||||
int item;
|
||||
|
||||
for( item = 1; item <= count; item++)
|
||||
{
|
||||
GetResolutionFromPopupMenuItem(inControl, item, &resX, &resY, &depth, &resFlags);
|
||||
|
||||
if (screenX < resX || screenY < resY)
|
||||
DisablePopupMenuItem(inControl, item);
|
||||
else
|
||||
EnablePopupMenuItem(inControl, item);
|
||||
|
||||
if (resX == screenwidth && resY == screenheight && depth == screendepth && resFlags == screenResFlags)
|
||||
SetControlValue(inControl, item);
|
||||
}
|
||||
|
||||
// If we just disabled the current item, then choose something else.
|
||||
if (!IsPopupMenuItemEnabled(inControl, GetControlValue (inControl)))
|
||||
{
|
||||
for(item = 1; item <= count; item++)
|
||||
{
|
||||
if (IsPopupMenuItemEnabled(inControl, item))
|
||||
{
|
||||
SetControlValue(inControl, item);
|
||||
GetResolutionFromPopupMenuItem(inControl, item, &screenwidth, &screenheight, &screendepth, &screenResFlags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AdjustDisplayControls(PrefInfo *prefInfo)
|
||||
{
|
||||
// Build new resolution popup and select appropriate resolution
|
||||
if ((prefInfo->prefGameDisplayMode != kFullScreen))
|
||||
{
|
||||
BuildResolutionPopupButton(prefInfo->resolutionPopup, (CGDirectDisplayID)-1, prefInfo->callback);
|
||||
if (prefInfo->multiMonitor)
|
||||
EnableControl(prefInfo->chooseMonitorsBtn);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildResolutionPopupButton(prefInfo->resolutionPopup, prefInfo->prefDisplayID, prefInfo->callback);
|
||||
if (prefInfo->multiMonitor)
|
||||
EnableControl(prefInfo->chooseMonitorsBtn);
|
||||
}
|
||||
AdjustResolutionPopupMenu(prefInfo->resolutionPopup, prefInfo->prefDisplayID,
|
||||
prefInfo->prefGameDisplayMode == kFullScreen,
|
||||
prefInfo->prefWidth, prefInfo->prefHeight, prefInfo->prefDepth, prefInfo->prefResFlags);
|
||||
|
||||
// Build new refresh popup and select appropriate rate
|
||||
BuildRefreshRates(prefInfo->prefDisplayID, prefInfo->prefWidth, prefInfo->prefHeight,
|
||||
&prefInfo->refreshRates, prefInfo->callback);
|
||||
BuildRefreshPopupButton(prefInfo->refreshRatePopup, &prefInfo->refreshRates);
|
||||
|
||||
if (prefInfo->refreshRates.size() == 0)
|
||||
{ // No refresh rates, so pick Auto
|
||||
prefInfo->freqMenuIndex = 1;
|
||||
prefInfo->prefFrequency = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefInfo->freqMenuIndex = FindRefreshPopupMenuItem(&prefInfo->refreshRates, prefInfo->prefFrequency);
|
||||
if (prefInfo->freqMenuIndex == 1)
|
||||
prefInfo->prefFrequency = 0; // just in case FindRefreshPopupMenuItem didn't find prefInfo->prefFrequency
|
||||
}
|
||||
SetControlValue (prefInfo->refreshRatePopup, prefInfo->freqMenuIndex);
|
||||
|
||||
// Disable refresh rate if NOT fullscreen
|
||||
if ((prefInfo->prefGameDisplayMode != kFullScreen) || (prefInfo->refreshRates.size() == 0))
|
||||
DisableControl (prefInfo->refreshRatePopup);
|
||||
else
|
||||
EnableControl (prefInfo->refreshRatePopup);
|
||||
}
|
||||
|
||||
static pascal OSStatus PrefHandler( EventHandlerCallRef, EventRef inEvent, void* inUserData )
|
||||
{
|
||||
HICommand cmd;
|
||||
OSStatus result = eventNotHandledErr;
|
||||
PrefInfo* prefInfo = (PrefInfo*)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:
|
||||
|
||||
prefInfo->okPressed = true;
|
||||
|
||||
prefInfo->prefAlways = GetControlValue (prefInfo->alwaysBtn);
|
||||
prefInfo->prefOpenAL = GetControlValue (prefInfo->openALBtn);
|
||||
|
||||
CFPreferencesSetAppValue (kPref_PrefsDialogAlways,
|
||||
prefInfo->prefAlways ? kCFBooleanTrue : kCFBooleanFalse,
|
||||
kCFPreferencesCurrentApplication);
|
||||
|
||||
CFPreferencesSetAppValue (kPref_PrefsDialogOpenAL,
|
||||
prefInfo->prefOpenAL ? kCFBooleanTrue : kCFBooleanFalse,
|
||||
kCFPreferencesCurrentApplication);
|
||||
|
||||
CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
|
||||
|
||||
QuitAppModalLoopForWindow( prefInfo->window );
|
||||
result = noErr;
|
||||
break;
|
||||
|
||||
case kHICommandCancel:
|
||||
|
||||
prefInfo->okPressed = false;
|
||||
|
||||
QuitAppModalLoopForWindow( prefInfo->window );
|
||||
result = noErr;
|
||||
break;
|
||||
|
||||
case kCmdFullscreen:
|
||||
case kCmdInAWindow:
|
||||
if (cmd.commandID == kCmdFullscreen)
|
||||
prefInfo->prefGameDisplayMode = kFullScreen;
|
||||
else
|
||||
prefInfo->prefGameDisplayMode = kWindow;
|
||||
SetControlValue (prefInfo->fullscreenBtn, prefInfo->prefGameDisplayMode == kFullScreen);
|
||||
SetControlValue (prefInfo->inAWindowBtn, 1 - (prefInfo->prefGameDisplayMode == kFullScreen));
|
||||
if (prefInfo->prefGameDisplayMode == kFullScreen)
|
||||
EnableControl (prefInfo->refreshRatePopup);
|
||||
else
|
||||
DisableControl (prefInfo->refreshRatePopup);
|
||||
if (prefInfo->multiMonitor)
|
||||
EnableControl (prefInfo->chooseMonitorsBtn);
|
||||
else
|
||||
DisableControl (prefInfo->chooseMonitorsBtn);
|
||||
|
||||
// Adjust resolutions, refresh rates
|
||||
AdjustDisplayControls(prefInfo);
|
||||
result = noErr;
|
||||
break;
|
||||
|
||||
|
||||
case kCmdChooseMonitors:
|
||||
{
|
||||
PickMonitor((DisplayIDType*)&prefInfo->prefDisplayID, prefInfo->window);
|
||||
// Adjust resolutions, refresh rates for potentially new display ID
|
||||
AdjustDisplayControls(prefInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCmdResolution:
|
||||
{
|
||||
// Pick a new resolution
|
||||
int item = GetControlValue(prefInfo->resolutionPopup);
|
||||
GetResolutionFromPopupMenuItem(prefInfo->resolutionPopup, item, &prefInfo->prefWidth, &prefInfo->prefHeight, &prefInfo->prefDepth, &prefInfo->prefResFlags);
|
||||
|
||||
// Adjust refresh menu
|
||||
BuildRefreshRates(prefInfo->prefDisplayID, prefInfo->prefWidth, prefInfo->prefHeight, &prefInfo->refreshRates, prefInfo->callback);
|
||||
BuildRefreshPopupButton(prefInfo->refreshRatePopup, &prefInfo->refreshRates);
|
||||
prefInfo->freqMenuIndex = FindRefreshPopupMenuItem(&prefInfo->refreshRates, prefInfo->prefFrequency);
|
||||
if (prefInfo->freqMenuIndex == 1)
|
||||
prefInfo->prefFrequency = 0; // just in case FindRefreshPopupMenuItem didn't find prefInfo->prefFrequency
|
||||
SetControlValue (prefInfo->refreshRatePopup, prefInfo->freqMenuIndex);
|
||||
|
||||
// Disable refresh rate if NOT fullscreen
|
||||
if ((prefInfo->prefGameDisplayMode != kFullScreen) || (prefInfo->refreshRates.size() == 0))
|
||||
DisableControl (prefInfo->refreshRatePopup);
|
||||
else
|
||||
EnableControl (prefInfo->refreshRatePopup);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case kCmdRefreshRate:
|
||||
{
|
||||
// Keep prefInfo->prefFrequency updated for the other controls to reference
|
||||
prefInfo->freqMenuIndex = GetControlValue (prefInfo->refreshRatePopup);
|
||||
if (prefInfo->freqMenuIndex == 1)
|
||||
prefInfo->prefFrequency = 0;
|
||||
else
|
||||
{
|
||||
std::list<Fixed>::const_iterator iter = prefInfo->refreshRates.begin();
|
||||
for (int i = 0; i < prefInfo->freqMenuIndex-3; i++)
|
||||
iter++;
|
||||
prefInfo->prefFrequency = *iter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static DEFINE_ONE_SHOT_HANDLER_GETTER(PrefHandler)
|
||||
|
||||
OSStatus CreateGameDisplayPreferencesDialog(const GameDisplayInfo *inGDInfo,
|
||||
WindowRef *outWindow, ValidModeCallbackProc inCallback)
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
// Build up a structure to pass to the window handler we are about
|
||||
// to install. We store the window itself, as well as the original
|
||||
// states of our settings. We use this to revert if the user clicks
|
||||
// the cancel button.
|
||||
|
||||
static PrefInfo prefInfo;
|
||||
|
||||
prefInfo.prefGameDisplayMode = inGDInfo->mode;
|
||||
prefInfo.prefDisplayID = inGDInfo->displayID;
|
||||
prefInfo.prefWidth = inGDInfo->width;
|
||||
prefInfo.prefHeight = inGDInfo->height;
|
||||
prefInfo.prefDepth = inGDInfo->depth;
|
||||
prefInfo.prefFrequency = inGDInfo->frequency;
|
||||
prefInfo.prefResFlags = inGDInfo->resFlags;
|
||||
prefInfo.window = NULL;
|
||||
prefInfo.okPressed = false;
|
||||
|
||||
Boolean result;
|
||||
Boolean keyFound;
|
||||
result = CFPreferencesGetAppBooleanValue (kPref_PrefsDialogAlways, kCFPreferencesCurrentApplication, &keyFound);
|
||||
prefInfo.prefAlways = result && keyFound;
|
||||
result = CFPreferencesGetAppBooleanValue (kPref_PrefsDialogOpenAL, kCFPreferencesCurrentApplication, &keyFound);
|
||||
prefInfo.prefOpenAL = result && keyFound;
|
||||
|
||||
prefInfo.callback = inCallback;
|
||||
|
||||
// If DoPreferences is called at the start of the game, prefInfo.prefDisplayID needs to be checked
|
||||
// to see if it is still a valid display ID.
|
||||
|
||||
if (!ValidDisplayID(prefInfo.prefDisplayID))
|
||||
prefInfo.prefDisplayID = kCGDirectMainDisplay; // revert to main
|
||||
|
||||
// Fetch the dialog
|
||||
|
||||
IBNibRef aslNib;
|
||||
CFBundleRef theBundle = CFBundleGetMainBundle();
|
||||
err = CreateNibReferenceWithCFBundle(theBundle, CFSTR("ASLCore"), &aslNib);
|
||||
err = ::CreateWindowFromNib(aslNib, CFSTR( "Preferences" ), &prefInfo.window );
|
||||
if (err != noErr)
|
||||
return err;
|
||||
SetWRefCon(prefInfo.window, (long)&prefInfo);
|
||||
|
||||
// Locate all the controls
|
||||
|
||||
GetControlByID( prefInfo.window, &kFullscreenBtn, &prefInfo.fullscreenBtn ); assert(prefInfo.fullscreenBtn);
|
||||
GetControlByID( prefInfo.window, &kInAWindowBtn, &prefInfo.inAWindowBtn ); assert(prefInfo.inAWindowBtn);
|
||||
GetControlByID( prefInfo.window, &kResolutionPopup, &prefInfo.resolutionPopup ); assert(prefInfo.resolutionPopup);
|
||||
GetControlByID( prefInfo.window, &kRefreshRatePopup, &prefInfo.refreshRatePopup ); assert(prefInfo.refreshRatePopup);
|
||||
GetControlByID( prefInfo.window, &kChooseMonitorsBtn, &prefInfo.chooseMonitorsBtn ); assert(prefInfo.chooseMonitorsBtn);
|
||||
GetControlByID( prefInfo.window, &kAlwaysBtn, &prefInfo.alwaysBtn ); assert(prefInfo.alwaysBtn);
|
||||
GetControlByID( prefInfo.window, &kOpenALBtn, &prefInfo.openALBtn ); assert(prefInfo.openALBtn);
|
||||
|
||||
|
||||
|
||||
// Disable the "choose monitor" button if we've only got one to pick from
|
||||
|
||||
prefInfo.multiMonitor = CanUserPickMonitor();
|
||||
|
||||
if (!prefInfo.multiMonitor)
|
||||
{
|
||||
DisableControl (prefInfo.chooseMonitorsBtn);
|
||||
prefInfo.prefDisplayID = 0;
|
||||
}
|
||||
|
||||
// Prepare the resolutions and refresh rates popup menus
|
||||
AdjustDisplayControls(&prefInfo);
|
||||
|
||||
// Set up the controls
|
||||
|
||||
SetControlValue (prefInfo.refreshRatePopup, prefInfo.freqMenuIndex);
|
||||
SetControlValue (prefInfo.fullscreenBtn, prefInfo.prefGameDisplayMode == kFullScreen);
|
||||
SetControlValue (prefInfo.inAWindowBtn, prefInfo.prefGameDisplayMode == kWindow);
|
||||
SetControlValue (prefInfo.alwaysBtn, prefInfo.prefAlways);
|
||||
SetControlValue (prefInfo.openALBtn, prefInfo.prefOpenAL);
|
||||
|
||||
|
||||
// Create our UPP and install the handler.
|
||||
|
||||
EventTypeSpec cmdEvent = { kEventClassCommand, kEventCommandProcess };
|
||||
EventHandlerUPP handler = GetPrefHandlerUPP();
|
||||
InstallWindowEventHandler( prefInfo.window, handler, 1, &cmdEvent, &prefInfo, NULL );
|
||||
|
||||
// Position and show the window
|
||||
RepositionWindow( prefInfo.window, NULL, kWindowAlertPositionOnMainScreen );
|
||||
|
||||
if (outWindow)
|
||||
*outWindow = prefInfo.window;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// ¥ RunGameDisplayPreferencesDialog
|
||||
//------------------------------------------------------------------------------------
|
||||
// Runs the Mac-specific preferences dialog.
|
||||
|
||||
OSStatus RunGameDisplayPreferencesDialog(GameDisplayInfo *outGDInfo, WindowRef inWindow)
|
||||
{
|
||||
PrefInfo *prefInfo = (PrefInfo*)GetWRefCon(inWindow);
|
||||
|
||||
ShowWindow( inWindow );
|
||||
|
||||
// Now we run modally. We will remain here until the PrefHandler
|
||||
// calls QuitAppModalLoopForWindow if the user clicks OK or
|
||||
// Cancel.
|
||||
|
||||
RunAppModalLoopForWindow( inWindow );
|
||||
|
||||
// OK, we're done. Dispose of our window.
|
||||
// TODO: Are we supposed to uninstall event handlers?
|
||||
DisposeWindow( inWindow );
|
||||
|
||||
// Return settings to caller
|
||||
|
||||
if (prefInfo->okPressed)
|
||||
{
|
||||
outGDInfo->mode = prefInfo->prefGameDisplayMode;
|
||||
outGDInfo->width = prefInfo->prefWidth;
|
||||
outGDInfo->height = prefInfo->prefHeight;
|
||||
outGDInfo->depth = prefInfo->prefDepth;
|
||||
outGDInfo->frequency = prefInfo->prefFrequency;
|
||||
outGDInfo->resFlags = prefInfo->prefResFlags;
|
||||
outGDInfo->displayID = prefInfo->prefDisplayID;
|
||||
}
|
||||
|
||||
return prefInfo->okPressed ? noErr : userCanceledErr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
||||
|
||||
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.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef PREFERENCESDIALOG_H
|
||||
#define PREFERENCESDIALOG_H
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
enum GameDisplayMode
|
||||
{
|
||||
kInactive,
|
||||
kFullScreen,
|
||||
kWindow
|
||||
};
|
||||
|
||||
typedef long LONG;
|
||||
|
||||
typedef struct tagPOINT
|
||||
{
|
||||
LONG x;
|
||||
LONG y;
|
||||
} POINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GameDisplayMode mode; // Indicates if the game is in full screen mode or window mode.
|
||||
CGDirectDisplayID displayID; // Display used for the full screen mode.
|
||||
short width; // Width of screen and/or window.
|
||||
short height; // Height of screen and/or window.
|
||||
short depth; // Screen bit depth used for full screen mode.
|
||||
Fixed frequency; // Screen refresh rate in MHz for full screen mode. If zero, then a default will be used.
|
||||
POINT windowLoc; // Device-local coordinate of top left corner for window mode. Expressed as a Win32 POINT. Coordiantes may be CW_USEDEFAULT indicating no location has yet been established.
|
||||
unsigned long flags; // kBlankingWindow, kDontRepositionWindow, etc.
|
||||
UInt32 resFlags; // boolean bits to mark special modes for each resolution, e.g. stretched
|
||||
} GameDisplayInfo;
|
||||
|
||||
typedef bool(*ValidModeCallbackProc)(CGDirectDisplayID displayID, int width, int height, int depth, Fixed freq);
|
||||
|
||||
OSStatus CreateGameDisplayPreferencesDialog(
|
||||
const GameDisplayInfo *inGDInfo,
|
||||
WindowRef *outWindow,
|
||||
ValidModeCallbackProc inCallback = NULL);
|
||||
|
||||
OSStatus RunGameDisplayPreferencesDialog(
|
||||
GameDisplayInfo *outGDInfo,
|
||||
WindowRef inWindow);
|
||||
|
||||
#endif // PREFERENCESDIALOG_H
|
|
@ -197,9 +197,6 @@ const char *Sys_NetAdrToString( const netadr_t a ) {
|
|||
return s;
|
||||
}
|
||||
|
||||
void Sys_DoPreferences( void ) {
|
||||
}
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
// combine the args into a windows-style command line
|
||||
char cmdline[4096];
|
||||
|
|
|
@ -247,9 +247,6 @@ int Sys_ListFiles( const char *directory, const char *extension, idList<class
|
|||
// know early if we are performing a fatal error shutdown so the error message doesn't get lost
|
||||
void Sys_SetFatalError( const char *error );
|
||||
|
||||
// display perference dialog
|
||||
void Sys_DoPreferences( void );
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
|
|
|
@ -747,11 +747,3 @@ Sys_SetFatalError
|
|||
*/
|
||||
void Sys_SetFatalError( const char *error ) {
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_DoPreferences
|
||||
==================
|
||||
*/
|
||||
void Sys_DoPreferences( void ) {
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue