Created
October 24, 2010 16:33
-
-
Save atr000/643659 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gcc -framework ApplicationServices -framework CoreFoundation -framework IOKit display.c -o display | |
/* This code was based on SetDisplay from the University of Utah Student | |
* Computing Labs. | |
* The code has since been modified by Rob Braun ([email protected]) | |
* Please do not contact Utah Student Computing Labs with problems with | |
* this software. I probably introduced them. | |
*/ | |
/* | |
main.c | |
This tool sets the display resolution. This tool exists so that we | |
can set the display to a setting when the display manager says it can't, | |
mainly, when a Mac starts up and the monitor is off, or if the Mac is on | |
a KVM. | |
Copyright (c) 2002 University of Utah Student Computing Labs. | |
All Rights Reserved. | |
Permission to use, copy, modify, and distribute this software and | |
its documentation for any purpose and without fee is hereby granted, | |
provided that the above copyright notice appears in all copies and | |
that both that copyright notice and this permission notice appear | |
in supporting documentation, and that the name of The University | |
of Utah not be used in advertising or publicity pertaining to | |
distribution of the software without specific, written prior | |
permission. This software is supplied as is without expressed or | |
implied warranties of any kind. | |
WARNING: | |
In testing garbage values, I did get this to tool to change the display so that absolutely | |
nothing displayed. I don't remember what I did to get that. And I can't duplicate it anymore. | |
I could remotely control it, so I could fix it. But beware, if you can't remotely control the | |
machine and fix bad display settings, well, you might have to resort to drastic measures to fix | |
a mac with bad display settings (like boot off of a different disk and delete the display | |
preferences. | |
In other words, this tool will change the display settings regardless of what the display | |
manager says is possible. So be careful!!! | |
*/ | |
#include <ApplicationServices/ApplicationServices.h> | |
#include <CoreFoundation/CoreFoundation.h> | |
#include <IOKit/IOKitLib.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
struct myMode | |
{ | |
size_t width; | |
size_t height; | |
size_t bitsPerPixel; | |
CGRefreshRate refresh; | |
}; | |
struct myMode myMode; | |
static void setdisplay( CGDirectDisplayID dspy) | |
{ | |
CFDictionaryRef mode; | |
CFDictionaryRef originalMode; | |
boolean_t exactMatch; | |
CGDisplayErr err; // or is this suppose to be CGError??? | |
CGDisplayConfigRef configRef; | |
const void *value; | |
int no; | |
int width, height, refresh, depth; | |
originalMode = CGDisplayCurrentMode( dspy ); | |
if ( originalMode == NULL ) | |
{ | |
printf( "Display is invalid\n" ); | |
return; | |
} | |
if ( myMode.bitsPerPixel == 0 ) { | |
value = CFDictionaryGetValue(originalMode, kCGDisplayBitsPerPixel); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &myMode.bitsPerPixel); | |
} | |
if ( myMode.width == 0 ) { | |
value = CFDictionaryGetValue(originalMode, kCGDisplayWidth); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &myMode.width); | |
} | |
if ( myMode.height == 0 ) { | |
value = CFDictionaryGetValue(originalMode, kCGDisplayHeight); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &myMode.height); | |
} | |
if ( myMode.refresh == 0 ) { | |
value = CFDictionaryGetValue(originalMode, kCGDisplayRefreshRate); | |
CFNumberGetValue(value, kCFNumberDoubleType, &myMode.refresh); | |
} | |
printf( "Display 0x%x: Looking for %ld x %ld, %ld Bits Per Pixel @ %f Hz\n", (unsigned int)dspy, myMode.width, myMode.height, myMode.bitsPerPixel, myMode.refresh ); | |
mode = CGDisplayBestModeForParametersAndRefreshRate(dspy, myMode.bitsPerPixel, myMode.width, myMode.height, myMode.refresh, &exactMatch); | |
// mode = CGDisplayBestModeForParametersAndRefreshRateWithProperty(dspy, myMode.bitsPerPixel, myMode.width, myMode.height, myMode.refresh, kCGDisplayModeIsSafeForHardware, &exactMatch); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayWidth); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &width); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayHeight); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &height); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayRefreshRate); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &refresh); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayBitsPerPixel); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &depth); | |
printf( "Display 0x%x: found %ld x %ld, %ld Bits Per Pixel @ %d Hz\n", (unsigned int)dspy, width, height, depth, refresh ); | |
CGBeginDisplayConfiguration(&configRef); | |
err = CGConfigureDisplayMode(configRef, dspy, mode); | |
CGCompleteDisplayConfiguration( configRef, kCGConfigurePermanently ); | |
if ( err != CGDisplayNoErr ) | |
{ | |
printf( "Oops! Mode switch failed?!?? (%d)\n", err ); | |
} | |
} | |
static void printdisplay( CGDirectDisplayID dspy, int num ) | |
{ | |
static int firsttime = 0; | |
CFDictionaryRef originalMode; | |
uint32_t unitno, vendorno, modelno, serialno; | |
int isprimary = 0, isbuiltin = 0, n; | |
CFIndex count; | |
CFTypeID type; | |
const void *value; | |
int32_t height, width, refresh, depth; | |
originalMode = CGDisplayCurrentMode( dspy ); | |
if ( originalMode == NULL ) | |
{ | |
printf( "Display is invalid\n" ); | |
return; | |
} | |
unitno = CGDisplayUnitNumber(dspy); | |
vendorno = CGDisplayVendorNumber(dspy); | |
modelno = CGDisplayModelNumber(dspy); | |
serialno = CGDisplaySerialNumber(dspy); | |
if( CGDisplayIsMain(dspy) ) { | |
isprimary = 1; | |
} | |
if( CGDisplayIsBuiltin(dspy) ) { | |
isbuiltin = 1; | |
} | |
value = CFDictionaryGetValue(originalMode, kCGDisplayWidth); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &width); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayHeight); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &height); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayRefreshRate); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &refresh); | |
value = CFDictionaryGetValue(originalMode, kCGDisplayBitsPerPixel); | |
CFNumberGetValue(value, kCFNumberSInt32Type, &depth); | |
if( firsttime == 0 ) { | |
printf("Display Unit Width Height Depth Refresh Vendor Model Serial\n"); | |
firsttime = 1; | |
} | |
printf("%-7d %-4d %-5d %-6d %-5d %-7d %-10d %-5d %-6d", num, unitno, width, height, depth, refresh, vendorno, modelno, serialno); | |
if( isprimary ) | |
printf("\t Primary Display"); | |
if( isbuiltin ) | |
printf("\t Builtin Display"); | |
printf("\n"); | |
} | |
#define kMaxDisplays 16 | |
void usage(char *prog) | |
{ | |
printf("%s [-x width] [-y height] [-b bit depth] [-r refresh] [-d display] [-l]\n", prog); | |
printf("\t-l lists all displays and their current settings\n"); | |
printf("\tIf no display is specified (-d), the settings will be applied to all displays\n"); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
CGDirectDisplayID display[kMaxDisplays]; | |
CGDisplayCount numDisplays; | |
CGDisplayCount i; | |
CGDisplayErr err; | |
int displayno = -1; | |
int ch; | |
int listonly = 0; | |
int xset = 0, yset = 0, rset = 0, bset = 0; | |
memset(&myMode, 0, sizeof(myMode)); | |
while ((ch = getopt(argc, argv, "x:y:r:b:ld:")) != -1) { | |
switch(ch) { | |
case 'x': | |
myMode.width = atoi(optarg); | |
xset = 1; | |
break; | |
case 'y': | |
myMode.height = atoi(optarg); | |
yset = 1; | |
break; | |
case 'r': | |
myMode.refresh = atoi(optarg); | |
rset = 1; | |
break; | |
case 'b': | |
myMode.bitsPerPixel = atoi(optarg); | |
bset = 1; | |
break; | |
case 'l': | |
listonly = 1; | |
break; | |
case 'd': | |
displayno = atoi(optarg); | |
break; | |
default: | |
usage(argv[0]); | |
exit(1); | |
}; | |
} | |
if( argc == 1 ) { | |
usage(argv[0]); | |
exit(1); | |
} | |
// printf( "Width: %d Height: %d BitsPerPixel: %d Refresh rate: %d\n", (int)myMode.width, (int)myMode.height, (int)myMode.bitsPerPixel, (int)myMode.refresh ); | |
err = CGGetActiveDisplayList(kMaxDisplays, | |
display, | |
&numDisplays); | |
if ( err != CGDisplayNoErr ) | |
{ | |
printf("Cannot get displays (%d)\n", err); | |
exit( 1 ); | |
} | |
printf( "%d displays found\n", (int)numDisplays ); | |
for ( i = 0; i < numDisplays; ++i ) | |
{ | |
if( listonly ) { | |
printdisplay(display[i], i); | |
} else if( (displayno == -1) || (displayno == i) ) { | |
setdisplay(display[i]); | |
} | |
} | |
printf( "Done.\n" ); | |
exit(0); | |
} | |
static int numberForKey( CFDictionaryRef desc, CFStringRef key ) | |
{ | |
CFNumberRef value; | |
int num = 0; | |
if ( (value = CFDictionaryGetValue(desc, key)) == NULL ) | |
return 0; | |
CFNumberGetValue(value, kCFNumberIntType, &num); | |
return num; | |
} | |
static void printDesc( CFDictionaryRef desc ) | |
{ | |
char * msg; | |
if ( CFDictionaryGetValue(desc, kCGDisplayModeUsableForDesktopGUI) == kCFBooleanTrue ) | |
msg = "Supports Aqua GUI"; | |
else | |
msg = "Not for Aqua GUI"; | |
printf( "\t%d x %d,\t%d BPP,\t%d Hz\t(%s)\n", | |
numberForKey(desc, kCGDisplayWidth), | |
numberForKey(desc, kCGDisplayHeight), | |
numberForKey(desc, kCGDisplayBitsPerPixel), | |
numberForKey(desc, kCGDisplayRefreshRate), | |
msg ); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment