Skip to content
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version.h
*.o
screenreader
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
# -convert test target to a shell script
# -figure out of lipo is the best way to make a universal binary on cmdline

uname_m := $(shell uname -m)

PREFIX=/usr/local

ORIG_RES=1920x1200x32
Expand All @@ -17,7 +19,7 @@ VERSION=1.7dev

CC=clang
PACKAGE_BUILD=/usr/bin/pkgbuild
ARCH_FLAGS=-arch i386 -arch x86_64
ARCH_FLAGS=-arch $(uname_m)

.PHONY: build
build: screenresolution
Expand Down
11 changes: 7 additions & 4 deletions README
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
This is a tool that can be used to determine current resolution,
list available resolutions and set resolutions for active displays
on Mac OS 10.6, and possibly above. I have only tested 10.6.
on Mac OS 10.6 through at least 13.1.

I used clang for development, but the code seems to compile
just fine with gcc. The code might not be as well layed out
Expand All @@ -9,12 +9,15 @@ as it could be, feel free to send a pull request.
Build+Install
====================
Running the following commands in Terminal.app will result in
dmg with a pkg file being created if the system has Xcode 4.
dmg with a pkg file being created if the system has Xcode 4+.

git clone github.com:jhford/screenresolution
cd screenresolution
make dmg

By default, screenreader will build for the target architecture
of the host machine.

At this point, I'd recommend testing that things work! I have
written a 'test' makefile target. Because this script expects two
monitors that both use the same resolution, it mightn't work
Expand Down Expand Up @@ -42,8 +45,8 @@ install make target with DESTDIR to specify an alternate root.

Running
====================
There are three commands that this program supports: get, list
and set. All three modes operate on active displays [1].
This program supports the following commands: get, getMax, list
and set. All modes operate on active displays [1].

The get mode will show you the resolution of all active displays

Expand Down
5 changes: 1 addition & 4 deletions cg_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,8 @@ unsigned int parseStringConfig(const char *string, struct config *out) {
return rc;
}

CFComparisonResult _compareCFDisplayModes (CGDisplayModeRef *mode1Ptr, CGDisplayModeRef *mode2Ptr, void *context)
CFComparisonResult _compareCFDisplayModes (CGDisplayModeRef mode1, CGDisplayModeRef mode2, void *context)
{
CGDisplayModeRef mode1 = (CGDisplayModeRef)mode1Ptr;
CGDisplayModeRef mode2 = (CGDisplayModeRef)mode2Ptr;

size_t width1 = CGDisplayModeGetWidth(mode1);
size_t width2 = CGDisplayModeGetWidth(mode2);

Expand Down
2 changes: 1 addition & 1 deletion cg_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ unsigned int configureDisplay(CGDirectDisplayID display,
int displayNum);
unsigned int parseStringConfig(const char *string, struct config *out);
size_t bitDepth(CGDisplayModeRef mode);
CFComparisonResult _compareCFDisplayModes (CGDisplayModeRef *mode1Ptr, CGDisplayModeRef *mode2Ptr, void *context);
CFComparisonResult _compareCFDisplayModes (CGDisplayModeRef mode1, CGDisplayModeRef mode2, void *context);

#endif
56 changes: 52 additions & 4 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

#include "version.h"
#include "cg_utils.h"
#include <sys/param.h>

// Number of modes to list per line.
#define MODES_PER_LINE 3

Expand All @@ -30,6 +28,7 @@

unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum);
unsigned int listCurrentMode(CGDirectDisplayID display, int displayNum);
unsigned int listMaxSupported(CGDirectDisplayID display, int displayNum);

int main(int argc, const char *argv[]) {
// http://developer.apple.com/library/IOs/#documentation/CoreFoundation/Conceptual/CFStrings/Articles/MutableStrings.html
Expand Down Expand Up @@ -71,12 +70,22 @@ int main(int argc, const char *argv[]) {
return 1;
}

if (strcmp(argv[1], "help") == 0) {
printf("Usage: Run screenreader with one of the following: get, getMax, list, or set [resolution].\n");
return(0);
}


// This loop should probably be in another function.
for (d = 0; d < displayCount && keepgoing; d++) {
if (strcmp(argv[1], "get") == 0) {
if (!listCurrentMode(activeDisplays[d], d)) {
exitcode++;
}
} else if (strcmp(argv[1], "getMax") == 0) {
if (!listMaxSupported(activeDisplays[d], d)) {
exitcode++;
}
} else if (strcmp(argv[1], "list") == 0) {
if (!listAvailableModes(activeDisplays[d], d)) {
exitcode++;
Expand Down Expand Up @@ -108,7 +117,7 @@ int main(int argc, const char *argv[]) {
free(activeDisplays);
activeDisplays = NULL;
} else {
NSLog(CFSTR("%s"), "Incorrect command line");
NSLog(CFSTR("%s"), "Invalid command. Run screenreader with get, getMax, list, or set [resolution].");
exitcode++;
}
return exitcode > 0;
Expand All @@ -131,6 +140,42 @@ unsigned int listCurrentMode(CGDirectDisplayID display, int displayNum) {
return returncode;
}

unsigned int listMaxSupported(CGDirectDisplayID display, int displayNum) {
unsigned int returncode = 1;
CGDisplayModeRef maxSupportedMode = CGDisplayCopyDisplayMode(display);

CFStringRef keys[1] = { kCGDisplayShowDuplicateLowResolutionModes };
CFBooleanRef values[1] = { kCFBooleanTrue };
CFDictionaryRef options = CFDictionaryCreate(
kCFAllocatorDefault, (const void**) keys, (const void**) values, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, options);
if (allModes == NULL) {
NSLog(CFSTR("Error: failed trying to look up modes for display %u"), displayNum);
}

CFIndex displayModeCount = CFArrayGetCount(allModes);
for (int i = 0; i < displayModeCount; ++i) {
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
CFComparisonResult result = _compareCFDisplayModes(mode, maxSupportedMode, NULL);
if (result == kCFCompareGreaterThan) {
maxSupportedMode = CGDisplayModeRetain(mode);
}
}

NSLog(CFSTR("Display %d: %ux%ux%u@%.0f"),
displayNum,
CGDisplayModeGetWidth(maxSupportedMode),
CGDisplayModeGetHeight(maxSupportedMode),
bitDepth(maxSupportedMode),
CGDisplayModeGetRefreshRate(maxSupportedMode));

CFRelease(allModes);
CFRelease(options);
CGDisplayModeRelease(maxSupportedMode);
return returncode;
}

unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) {
unsigned int returncode = 1;
int numModes = 0;
Expand All @@ -155,7 +200,7 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) {
CFRangeMake(0, CFArrayGetCount(allModesSorted)),
(CFComparatorFunction) _compareCFDisplayModes,
NULL
);
);

#ifndef LIST_DEBUG
if(displayNum != 0)
Expand Down Expand Up @@ -227,6 +272,9 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) {
#endif
}

if (numModes % MODES_PER_LINE)
printf("\n");

CFRelease(allModes);
CFRelease(allModesSorted);

Expand Down