diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..acf9775 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +version.h +*.o +screenreader diff --git a/Makefile b/Makefile index e9fc71f..1fafa1c 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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 diff --git a/README b/README index 84afa14..cd3fbe2 100644 --- a/README +++ b/README @@ -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 @@ -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 @@ -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 diff --git a/cg_utils.c b/cg_utils.c index 4fef025..899022c 100644 --- a/cg_utils.c +++ b/cg_utils.c @@ -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); diff --git a/cg_utils.h b/cg_utils.h index d050961..6a42fc8 100644 --- a/cg_utils.h +++ b/cg_utils.h @@ -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 \ No newline at end of file diff --git a/main.c b/main.c index c4cecc6..f2e2efd 100644 --- a/main.c +++ b/main.c @@ -20,8 +20,6 @@ #include "version.h" #include "cg_utils.h" -#include - // Number of modes to list per line. #define MODES_PER_LINE 3 @@ -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 @@ -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++; @@ -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; @@ -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; @@ -155,7 +200,7 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { CFRangeMake(0, CFArrayGetCount(allModesSorted)), (CFComparatorFunction) _compareCFDisplayModes, NULL - ); + ); #ifndef LIST_DEBUG if(displayNum != 0) @@ -227,6 +272,9 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { #endif } + if (numModes % MODES_PER_LINE) + printf("\n"); + CFRelease(allModes); CFRelease(allModesSorted);