From e11699c2e958f1c008547030edc6a9bd0f7bbc82 Mon Sep 17 00:00:00 2001 From: Yong Bakos Date: Tue, 16 Aug 2016 10:55:09 -0700 Subject: [PATCH 1/9] list: Add trailing line break. --- main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 339dd42..4bc9cbe 100644 --- a/main.c +++ b/main.c @@ -20,7 +20,7 @@ #include "version.h" #include "cg_utils.h" - + // Number of modes to list per line. #define MODES_PER_LINE 3 @@ -154,7 +154,7 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { CFRangeMake(0, CFArrayGetCount(allModesSorted)), (CFComparatorFunction) _compareCFDisplayModes, NULL - ); + ); #ifndef LIST_DEBUG if(displayNum != 0) @@ -225,7 +225,7 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { ioflags & kDisplayModeValidForMirroringFlag ?1:0 ); #endif } - + printf("\n"); CFRelease(allModes); CFRelease(allModesSorted); From 8f87203f3b8c42d9e7841afb21dc0e4a68519d17 Mon Sep 17 00:00:00 2001 From: Yong Bakos Date: Tue, 16 Aug 2016 11:22:16 -0700 Subject: [PATCH 2/9] list: Add trailing line break. Executing `screenresolution list` can result in the command prompt being displayed immediately after the last resolution in the list. Add a trailing line break so the command prompt is displayed on a new line. --- main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 4bc9cbe..8fb709a 100644 --- a/main.c +++ b/main.c @@ -225,7 +225,10 @@ unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { ioflags & kDisplayModeValidForMirroringFlag ?1:0 ); #endif } - printf("\n"); + + if (numModes % MODES_PER_LINE) + printf("\n"); + CFRelease(allModes); CFRelease(allModesSorted); From 1dcdebda159c82710425744576e4f068f28aeb8c Mon Sep 17 00:00:00 2001 From: Yong Bakos Date: Tue, 16 Aug 2016 11:26:29 -0700 Subject: [PATCH 3/9] Add ignore. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..206fba7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +version.h +*.o From a2942450dcebe6177aa05b4e8e1c0a7c5d569e50 Mon Sep 17 00:00:00 2001 From: Naresh R Date: Sat, 6 Jun 2020 17:12:23 +0530 Subject: [PATCH 4/9] Avoid de-reference in _compareCFDisplayModes Currently, the _compareCFDisplayModes method uses CGDisplayModeRef* as the first and second parameters, in alignment with the CFComparatorFunction type alias declaration expecting an UnsafeRawPointer. But CGDisplayModeRef is already a pointer to CGDisplayMode and doesn't need a reference again to work as a comparator. Doing so also introduces extra referencing and dereferencing that can be avoided. Update the method signature to pass CGDisplayModeRef directly. --- cg_utils.c | 5 +---- cg_utils.h | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) 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 From cc16458aa083e7bdcc61057a5607da5a67a6b679 Mon Sep 17 00:00:00 2001 From: Naresh R Date: Sat, 6 Jun 2020 17:28:52 +0530 Subject: [PATCH 5/9] Fetch max supported mode for each monitor Newer versions of MacOS use a scaling factor (like 2x, which is the default for newer MacBooks), leading to the default mode being half the native resolution of the display. In such cases, it would be desirable to fetch the maximum resolution supported by the display (native resolution). Add a getMax option to fetch this information. --- main.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/main.c b/main.c index c4cecc6..58060d2 100644 --- a/main.c +++ b/main.c @@ -30,6 +30,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 @@ -77,6 +78,10 @@ int main(int argc, const char *argv[]) { 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++; @@ -131,6 +136,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; From c3c1e5c498cf2e1fbe37f90899a3d440305398bd Mon Sep 17 00:00:00 2001 From: Will Date: Tue, 10 Jan 2023 15:46:13 -0500 Subject: [PATCH 6/9] update Makefile to target host arch --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From c669ac9897a2776c28683bac25dae14b008ca87c Mon Sep 17 00:00:00 2001 From: Will Date: Tue, 10 Jan 2023 17:18:08 -0500 Subject: [PATCH 7/9] update error msg/add help string --- .gitignore | 1 + main.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 206fba7..acf9775 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ version.h *.o +screenreader diff --git a/main.c b/main.c index 7f800ba..56b2612 100644 --- a/main.c +++ b/main.c @@ -70,6 +70,12 @@ int main(int argc, const char *argv[]) { return 1; } + if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "?") == 0) { + printf("Usage: Run screenreader with one of the following: get, 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) { @@ -111,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, list, or set [resolution]."); exitcode++; } return exitcode > 0; From 82634c4aa8137248bdc7260e43890cffcf40a011 Mon Sep 17 00:00:00 2001 From: Will Date: Tue, 10 Jan 2023 17:27:44 -0500 Subject: [PATCH 8/9] update help strings for getMax --- main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 56b2612..f2e2efd 100644 --- a/main.c +++ b/main.c @@ -70,8 +70,8 @@ int main(int argc, const char *argv[]) { return 1; } - if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "?") == 0) { - printf("Usage: Run screenreader with one of the following: get, list, or set [resolution].\n"); + if (strcmp(argv[1], "help") == 0) { + printf("Usage: Run screenreader with one of the following: get, getMax, list, or set [resolution].\n"); return(0); } @@ -117,7 +117,7 @@ int main(int argc, const char *argv[]) { free(activeDisplays); activeDisplays = NULL; } else { - NSLog(CFSTR("%s"), "Invalid command. Run screenreader with get, list, or set [resolution]."); + NSLog(CFSTR("%s"), "Invalid command. Run screenreader with get, getMax, list, or set [resolution]."); exitcode++; } return exitcode > 0; From 1b2b330f3e1f7d277488634010e21e82a309900e Mon Sep 17 00:00:00 2001 From: Will Date: Tue, 10 Jan 2023 17:44:19 -0500 Subject: [PATCH 9/9] Update README to reflect changes --- README | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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