29 #include "../../idlib/precompiled.h"
30 #include <Carbon/Carbon.h>
38 #define kPref_PrefsDialogAlways CFSTR("PrefsDialogAlways")
39 #define kPref_PrefsDialogOpenAL CFSTR("UseOpenAL")
42 #define kAppCreator 'DOM3' // Creator type
86 static int GetScreenIndexForDisplayID( CGDirectDisplayID inDisplayID ) {
92 err = CGGetActiveDisplayList(0,
NULL, &count);
94 CGDirectDisplayID displays[
count];
95 err = CGGetActiveDisplayList(count, displays, &count);
97 for ( i = 0; i <
count; i++)
98 if (displays[i] == inDisplayID)
105 static CGDirectDisplayID GetDisplayIDForScreenIndex(
int inScreenIndex ) {
108 CGDisplayCount
count;
110 err = CGGetActiveDisplayList(0,
NULL, &count);
112 CGDirectDisplayID displays[
count];
113 err = CGGetActiveDisplayList(count, displays, &count);
115 if ( inScreenIndex >= 0 && inScreenIndex <= count )
116 return displays[inScreenIndex];
119 return (CGDirectDisplayID)r_screen;
131 unsigned char km[16];
132 const int kMacKeyCodeCommand = 0x37;
133 KeyMap *keymap = (KeyMap*)&km;
136 Boolean prefAways,
keyFound, useOpenAL;
137 prefAways = CFPreferencesGetAppBooleanValue (
kPref_PrefsDialogAlways, kCFPreferencesCurrentApplication, &keyFound );
138 bool fAlways = prefAways &&
keyFound;
140 if ( fAlways || ( km[kMacKeyCodeCommand>>3] >> ( kMacKeyCodeCommand & 7 ) ) & 1 ) {
145 int w = 800, h = 600;
158 WindowRef prefWindow;
171 if ( r_mode == -1 ) {
179 else if ( r > 1.55
f )
194 useOpenAL = CFPreferencesGetAppBooleanValue (
kPref_PrefsDialogOpenAL, kCFPreferencesCurrentApplication, &keyFound);
195 if ( keyFound && useOpenAL ) {
208 #define EnablePopupMenuItem(inControl,inMenuItem) EnableMenuItem(GetControlPopupMenuRef(inControl),inMenuItem)
209 #define DisablePopupMenuItem(inControl,inMenuItem) DisableMenuItem(GetControlPopupMenuRef(inControl),inMenuItem)
210 #define IsPopupMenuItemEnabled(inControl,inMenuItem) IsMenuItemEnabled(GetControlPopupMenuRef(inControl),inMenuItem)
223 static const ControlID kFullscreenBtn = {
'PREF', 1 };
224 static const ControlID kInAWindowBtn = {
'PREF', 2 };
225 static const ControlID kResolutionPopup = {
'PREF', 3 };
226 static const ControlID kRefreshRatePopup = {
'PREF', 4 };
227 static const ControlID kChooseMonitorsBtn = {
'PREF', 5 };
228 static const ControlID kAlwaysBtn = {
'PREF', 6 };
229 static const ControlID kOpenALBtn = {
'PREF', 7 };
239 static bool operator< (
const Res&
a,
const Res&
b)
268 static bool ValidDisplayID (CGDirectDisplayID inDisplayID)
272 CGDisplayCount
count;
274 err = CGGetActiveDisplayList(0,
NULL, &count);
277 CGDirectDisplayID displays[
count];
278 err = CGGetActiveDisplayList(count, displays, &count);
281 for ( i = 0; i <
count; i++)
282 if (displays[i] == inDisplayID)
294 if (inDisplayID == (CGDirectDisplayID)-1)
296 Res stdModes[] = { { 640, 480 }, { 800, 600 }, { 1024, 768 }, { 1152, 768 },
297 { 1280, 854 }, { 1280, 960 }, { 1280, 1024 }, { 1440, 900 } };
298 total =
sizeof(stdModes) /
sizeof(
Res);
299 for (i = 0; i < total; i++)
301 if (inCallback ==
NULL || inCallback(inDisplayID, stdModes[i].
width, stdModes[i].
height, 32, 0))
302 modes.insert(
MakeRes(stdModes[i].width, stdModes[i].height, 32) );
307 CGDirectDisplayID displayID = inDisplayID ? inDisplayID : kCGDirectMainDisplay;
308 CFArrayRef modeArrayRef = CGDisplayAvailableModes(displayID);
309 CFIndex numModes = CFArrayGetCount(modeArrayRef);
311 for (i = 0; i < numModes; i++)
313 CFDictionaryRef modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modeArrayRef, i);
316 CFNumberRef valueRef;
319 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayBitsPerPixel);
320 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
322 if (depth != 32)
continue;
324 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayWidth);
325 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
328 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayHeight);
329 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
333 CFBooleanRef boolRef;
334 if (CFDictionaryGetValueIfPresent (modeRef, kCGDisplayModeIsStretched, (
const void **)&boolRef))
335 if (CFBooleanGetValue (boolRef))
340 success = inCallback(displayID, width, height, depth, 0);
345 modes.insert(
MakeRes(width, height, depth, resFlags));
349 total = modes.size();
353 std::set<Res>::iterator it = modes.begin();
354 for (i = 0; it != modes.end(); i++)
364 static void BuildRefreshRates(CGDirectDisplayID inDisplayID,
int inWidth,
int inHeight, std::list<Fixed>* inList,
ValidModeCallbackProc inCallback)
366 CGDirectDisplayID displayID = inDisplayID ? inDisplayID : kCGDirectMainDisplay;
368 CFArrayRef modeArrayRef = CGDisplayAvailableModes(displayID);
369 CFIndex numModes = CFArrayGetCount(modeArrayRef);
373 for (
int i = 0; i < numModes; i++)
375 CFDictionaryRef modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modeArrayRef, i);
378 CFNumberRef valueRef;
381 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayBitsPerPixel);
382 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
384 if (depth != 32)
continue;
386 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayWidth);
387 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
390 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayHeight);
391 success = CFNumberGetValue(valueRef, kCFNumberLongType, &value);
394 if (width == inWidth && height == inHeight)
397 valueRef = (CFNumberRef)CFDictionaryGetValue(modeRef, kCGDisplayRefreshRate);
398 success = CFNumberGetValue(valueRef, kCFNumberDoubleType, &freqDouble);
399 Fixed freq = FloatToFixed(freqDouble);
401 success = inCallback(displayID, width, height, depth, freq);
405 inList->push_back(freq);
418 static void BuildRefreshPopupButton(ControlRef inControl, std::list<Fixed>* inList)
420 MenuRef menu = GetControlPopupMenuRef(inControl);
425 DeleteMenuItems(menu, 3, CountMenuItems(menu)-2);
427 for (std::list<Fixed>::const_iterator iter = inList->begin(); iter != inList->end(); ++iter)
429 float value = FixedToFloat(*iter);
430 CFStringRef menuString = CFStringCreateWithFormat (kCFAllocatorDefault, 0, CFSTR(
"%g Hz"), value);
431 InsertMenuItemTextWithCFString(menu, menuString, CountMenuItems(menu), 0, 0);
434 SetControlMaximum(inControl, CountMenuItems(menu));
437 static SInt32 FindRefreshPopupMenuItem(std::list<Fixed>* inList, Fixed inFrequency)
440 for (std::list<Fixed>::const_iterator iter = inList->begin(); iter != inList->end(); ++iter)
442 if (*iter == inFrequency)
449 static void BuildResolutionPopupButton(ControlRef inControl, CGDirectDisplayID inDisplayID,
ValidModeCallbackProc inCallback)
452 int count = BuildResolutionList(inDisplayID,
NULL, inCallback);
454 BuildResolutionList(inDisplayID, resList, inCallback);
457 MenuRef menu = GetControlPopupMenuRef(inControl);
460 DeleteMenuItems(menu, 1, CountMenuItems(menu));
466 CFStringRef menuString = CFStringCreateWithFormat (kCFAllocatorDefault, 0, CFSTR(
"%d x %d %@"),
467 resList[count].width, resList[count].height, (resList[count].resFlags &
kRes_Stretched) ? CFSTR(
"(Stretched)") : CFSTR(
""));
468 InsertMenuItemTextWithCFString (menu, menuString, 0, 0, 0);
469 err = SetMenuItemProperty (menu, 1,
kAppCreator,
'Res ',
sizeof(resList[count]), &resList[count]);
472 SetControlMaximum(inControl, CountMenuItems(menu));
475 static void GetResolutionFromPopupMenuItem(ControlRef inControl, MenuItemIndex inItem,
int *
outX,
int *
outY,
int *outDepth, UInt32 *outResFlags)
477 MenuRef menu = GetControlPopupMenuRef(inControl);
481 err = GetMenuItemProperty (menu, inItem,
kAppCreator,
'Res ',
sizeof(res),
NULL, &res);
491 static void AdjustResolutionPopupMenu(ControlRef inControl, CGDirectDisplayID inDisplayID,
bool isFullscreen,
int& screenwidth,
int& screenheight,
int& screendepth, UInt32& screenResFlags)
493 int screenX = INT_MAX, screenY = INT_MAX;
498 screenX = (
int)CGDisplayPixelsWide(inDisplayID);
499 screenY = (
int)CGDisplayPixelsHigh(inDisplayID);
502 MenuRef menu = GetControlPopupMenuRef(inControl);
503 int resX, resY,
depth;
505 int count = CountMenuItems(menu);
508 for( item = 1; item <=
count; item++)
510 GetResolutionFromPopupMenuItem(inControl, item, &resX, &resY, &depth, &resFlags);
512 if (screenX < resX || screenY < resY)
517 if (resX == screenwidth && resY == screenheight && depth == screendepth && resFlags == screenResFlags)
524 for(item = 1; item <=
count; item++)
529 GetResolutionFromPopupMenuItem(inControl, item, &screenwidth, &screenheight, &screendepth, &screenResFlags);
536 static void AdjustDisplayControls(
PrefInfo *prefInfo)
582 static pascal OSStatus PrefHandler( EventHandlerCallRef inHandler, EventRef inEvent,
void* inUserData )
584 #pragma unused( inHandler )
587 OSStatus
result = eventNotHandledErr;
593 GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand,
NULL,
sizeof( cmd ),
NULL, &cmd );
595 switch ( cmd.commandID )
605 prefInfo->
prefAlways ? kCFBooleanTrue : kCFBooleanFalse,
606 kCFPreferencesCurrentApplication);
609 prefInfo->
prefOpenAL ? kCFBooleanTrue : kCFBooleanFalse,
610 kCFPreferencesCurrentApplication);
612 CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
614 QuitAppModalLoopForWindow( prefInfo->
window );
618 case kHICommandCancel:
622 QuitAppModalLoopForWindow( prefInfo->
window );
644 AdjustDisplayControls(prefInfo);
653 AdjustDisplayControls(prefInfo);
688 std::list<Fixed>::const_iterator iter = prefInfo->
refreshRates.begin();
703 static DEFINE_ONE_SHOT_HANDLER_GETTER(PrefHandler)
708 OSStatus err = noErr;
729 result = CFPreferencesGetAppBooleanValue (
kPref_PrefsDialogAlways, kCFPreferencesCurrentApplication, &keyFound);
731 result = CFPreferencesGetAppBooleanValue (
kPref_PrefsDialogOpenAL, kCFPreferencesCurrentApplication, &keyFound);
746 err = CreateNibReferenceWithCFBundle(theBundle, CFSTR(
"ASLCore"), &aslNib);
747 err = ::CreateWindowFromNib(aslNib, CFSTR(
"Preferences" ), &prefInfo.
window );
775 AdjustDisplayControls(&prefInfo);
788 EventTypeSpec
cmdEvent = { kEventClassCommand, kEventCommandProcess };
789 EventHandlerUPP
handler = GetPrefHandlerUPP();
796 *outWindow = prefInfo.
window;
811 ShowWindow( inWindow );
817 RunAppModalLoopForWindow( inWindow );
821 DisposeWindow( inWindow );
836 return prefInfo->
okPressed ? noErr : userCanceledErr;
GetControlByID(prefInfo.window,&kFullscreenBtn,&prefInfo.fullscreenBtn)
virtual void SetCVarInteger(const char *name, const int value, int flags=0)=0
GLsizei const GLfloat * value
OSStatus PickMonitor(DisplayIDType *inOutDisplayID, WindowRef parentWindow)
assert(prefInfo.fullscreenBtn)
idCVarSystem * cvarSystem
Res MakeRes(int width, int height, int depth)
static WindowRef * outWindow
bool R_GetModeInfo(int *width, int *height, int mode)
virtual int GetCVarInteger(const char *name) const =0
GLuint GLenum GLenum outY
ControlRef refreshRatePopup
bool(* ValidModeCallbackProc)(CGDirectDisplayID displayID, int width, int height, int depth, Fixed freq)
GLint GLint GLsizei GLsizei GLsizei depth
#define kPref_PrefsDialogAlways
SetWRefCon(prefInfo.window,(long)&prefInfo)
InstallWindowEventHandler(prefInfo.window, handler, 1,&cmdEvent,&prefInfo, NULL)
ValidModeCallbackProc callback
#define EnablePopupMenuItem(inControl, inMenuItem)
GLuint GLuint GLsizei count
const UInt32 kRes_Stretched
OSStatus RunGameDisplayPreferencesDialog(GameDisplayInfo *outGDInfo, WindowRef inWindow)
GLubyte GLubyte GLubyte GLubyte w
ControlRef resolutionPopup
#define kPref_PrefsDialogOpenAL
SetControlValue(prefInfo.refreshRatePopup, prefInfo.freqMenuIndex)
GameDisplayMode prefGameDisplayMode
virtual void SetCVarBool(const char *name, const bool value, int flags=0)=0
#define IsPopupMenuItemEnabled(inControl, inMenuItem)
GLubyte GLubyte GLubyte a
GLenum GLsizei GLsizei height
void Sys_DoPreferences(void)
CGDirectDisplayID prefDisplayID
GLdouble GLdouble GLdouble r
static WindowRef ValidModeCallbackProc inCallback OSStatus err
ControlRef chooseMonitorsBtn
#define DisablePopupMenuItem(inControl, inMenuItem)
OSStatus CreateGameDisplayPreferencesDialog(const GameDisplayInfo *inGDInfo, WindowRef *outWindow, ValidModeCallbackProc inCallback=NULL)
idCVar r_mode("r_mode","3", CVAR_ARCHIVE|CVAR_RENDERER|CVAR_INTEGER,"video mode number")
Boolean CanUserPickMonitor(void)
virtual bool GetCVarBool(const char *name) const =0
void SetBool(const bool value)
if(!ValidDisplayID(prefInfo.prefDisplayID)) prefInfo.prefDisplayID
RepositionWindow(prefInfo.window, NULL, kWindowAlertPositionOnMainScreen)
CGDirectDisplayID displayID
std::list< Fixed > refreshRates