Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Change screen resolution in Terminal UNIX
Terminal is very useful in managing of rooms of Macs with Apple Remote Desktop. One thing I do often is change the screen resolution. To do that, I use a custom Terminal program that's based largely on Jeffrey Osterman's code posted in this Mac OS X Hints Forums thread.

It is easy to compile (you'll need Xcode to do so, however), and it supersedes the old and missing cscreen. First, here's the code:
/*
* setgetscreenres.m
* 
* juanfc 2009-04-13
* Based on newscreen
*    Created by Jeffrey Osterman on 10/30/07.
*    Copyright 2007 Jeffrey Osterman. All rights reserved. 
*    PROVIDED AS IS AND WITH NO WARRANTIES WHATSOEVER
*    http://forums.macosxhints.com/showthread.php?t=59575
*
* COMPILE:
*    c++ setgetscreenres.m -framework ApplicationServices -o setgetscreenres
* USE:
*    setgetscreenres 1440 900
*/

#include <ApplicationServices/ApplicationServices.h>

bool MyDisplaySwitchToMode (CGDirectDisplayID display, CFDictionaryRef mode);

int main (int argc, const char * argv[])
{
	int	h; 							// horizontal resolution
	int v; 							// vertical resolution
	CFDictionaryRef switchMode; 	// mode to switch to
	CGDirectDisplayID mainDisplay;  // ID of main display

	CFDictionaryRef CGDisplayCurrentMode(CGDirectDisplayID display);

	if (argc == 1) {
	    CGRect screenFrame = CGDisplayBounds(kCGDirectMainDisplay);
		CGSize screenSize  = screenFrame.size;
		printf("%d %d\n", screenSize.width, screenSize.height);
		return 0;
	}
	if (argc != 3 || !(h = atoi(argv[1])) || !(v = atoi(argv[2])) ) {
		fprintf(stderr, "ERROR: Use %s horres vertres\n", argv[0]);
		return -1;
	}

	mainDisplay = CGMainDisplayID();

	switchMode = CGDisplayBestModeForParameters(mainDisplay, 32, h, v, NULL);

	if (! MyDisplaySwitchToMode(mainDisplay, switchMode)) {
	    fprintf(stderr, "Error changing resolution to %d %d\n", h, v);
		return 1;
	}

	return 0;
}

bool MyDisplaySwitchToMode (CGDirectDisplayID display, CFDictionaryRef mode)
{
	CGDisplayConfigRef config;
	if (CGBeginDisplayConfiguration(&config) == kCGErrorSuccess) {
		CGConfigureDisplayMode(config, display, mode);
		CGCompleteDisplayConfiguration(config, kCGConfigureForSession );
		return true;
	}
	return false;
}
Save that as a pure text file named setgetscreenres.m, then compile it in Terminal using the command shown in the code (assuming you're in the directory where the file is saved):
c++ setgetscreenres.m -framework ApplicationServices -o setgetscreenres
Move this file somewhere on your user's $PATH, and then use it by typing setgetscreenres hor_res vert_res, where hor_res and vert_res are the desire horizontal and vertical resolution.

[robg adds: I compiled this, then tested it, and it works as described.]
    •    
  • Currently 2.76 / 5
  You rated: 3 / 5 (17 votes cast)
 
[58,407 views]  

Change screen resolution in Terminal | 20 comments | Create New Account
Click here to return to the 'Change screen resolution in Terminal' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Change screen resolution in Terminal
Authored by: totallyGreg on Apr 16, '09 08:51:55AM

Is it possible to switch which screen is primary (has the menu bar on top) using the ApplicationServices Framework? Because that would be useful.



[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: JavaVM on Apr 16, '09 09:06:22AM
I have written a free command line tool for changing screen res and getting information on the attached displays. It is available for download at:

http://www.osxsoft.net/

[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: osxpounder on Apr 17, '09 11:45:38AM

I see that this is your first post on this site. Welcome.



[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: Anonymous on Apr 20, '09 11:12:39AM

I see that this isn't your first post. Welcome back.



[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: JavaVM on Apr 16, '09 09:19:12AM
Apologies, the link I posted in the previous comment does not work, but the following link is okay:

http://www.mowlem-enterprises.co.uk/ScreenUtil_v1.0.zip

[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: robogobo on Apr 16, '09 01:57:22PM

What happens with these settings on a headless machine? I have a Mini doing various server tasks in my office, and it behaves strangely without a monitor attached. I can usually choose from 4 different screen resolutions when connected over VNC, but I don't know how these are determined.

On a side note, a physically connected mouse doesn't work, nor does video in iChat, unless an actual monitor is connected.



[ Reply to This | # ]
How do we set the volume via command line?
Authored by: chimerical on Apr 16, '09 06:04:02PM

How do we set the volume via command line?



[ Reply to This | # ]
How do we set the volume via command line?
Authored by: leamanc on Apr 16, '09 06:27:08PM

The only way I know of to do this is by calling AppleScript via the osascript command:

sudo osascript -e "set Volume 0"
sudo osascript -e "set Volume 10"

The first line will set your Mac's sound to mute. The last one represents maximum volume. You can use any whole number in between. I believe you can use decimals (i.e., 6.5) for finer-grained control also.



[ Reply to This | # ]
How do we set the volume via command line?
Authored by: henryhbk on Apr 17, '09 09:59:07AM

For ease you can create aliases:

alias full='sudo osascript -e "set Volume 4"'
(4 seems to max out our macs' volume)

For true hilarity, ssh into someone's mac, (assuming they aren't playing music) execute the above statement, then do :

say -v whisper "<insert funny whispered quote here>"

Sit back and watch the hilarity ensue. This works as the speaker is a shared resource between all jobs on the system, rather than the display which is not. So while you can't pop up things on the user's screen, feel free to have a mac talk to them.

---
Henry Feldman, MD
Medical Informatics
NYU School of Medicine



[ Reply to This | # ]
How do we set the volume via command line?
Authored by: chimerical on Apr 17, '09 11:34:45PM
http://xkcd.com/530

:)

also, thanks for the tips, guys!

[ Reply to This | # ]
Error in source code
Authored by: wallybear on Apr 17, '09 04:32:53AM
There is an error in the source code.
If you call the program with no arguments, it should display the current resolution settings, but it cannot because the printf parameters are wrong (they expect two integer values, but the variables are floats).
To obtain the expected output you have to substitute the following line:

printf("%d %dn", screenSize.width, screenSize.height);
with this one:

printf("%.0f %.0fn", screenSize.width, screenSize.height);



[ Reply to This | # ]
Error in source code (correction)
Authored by: wallybear on Apr 17, '09 04:48:41AM
The site killed the backslashes; here is the correct line:

printf("%d %d\n", screenSize.width, screenSize.height);

with this one:

printf("%.0f %.0f\n", screenSize.width, screenSize.height);



[ Reply to This | # ]
Modified source to manage two or more monitors
Authored by: wallybear on Apr 17, '09 04:44:57AM
I modified the source code to manage two or more monitors, and added some bonus too:
- It shows current main display resolution
- It shows current secondary displays resolution
- It shows the list of displays found, with their resolution, depth and refresh rate
- It sets the resolution of any display connected

Help is available with setgetscreenres -?

Here is the code:



/*
 * setgetscreenres.m
 * 
 * juanfc 2009-04-13
 * jawsoftware 2009-04-17
 * Based on newscreen
 *    Created by Jeffrey Osterman on 10/30/07.
 *    Copyright 2007 Jeffrey Osterman. All rights reserved. 
 *    PROVIDED AS IS AND WITH NO WARRANTIES WHATSOEVER
 *    http://forums.macosxhints.com/showthread.php?t=59575
 *
 * COMPILE:
 *    c++ setgetscreenres.m -framework ApplicationServices -o setgetscreenres
 * USE:
 *    setgetscreenres [ -l | 1..9] [ 1440 900 ]
 */

#include <ApplicationServices/ApplicationServices.h>

bool MyDisplaySwitchToMode (CGDirectDisplayID display, CFDictionaryRef mode);
void ListDisplays( CGDisplayCount dispCount, CGDirectDisplayID *dispArray );
void usage(const char *argv[]);
void GetDisplayParms(CGDirectDisplayID *dispArray,  CGDisplayCount dispNum, int *width, int *height, int *depth, int *freq);

int main (int argc, const char * argv[])
{
	int	h; 							// horizontal resolution
	int v; 							// vertical resolution
	int depth, freq;

	CFDictionaryRef switchMode; 	// mode to switch to
	CGDirectDisplayID theDisplay;  // ID of  display, display to set
	int displayNum; //display number requested by user
	
	CGDisplayCount maxDisplays = 10;
	CGDirectDisplayID onlineDspys[maxDisplays];
	CGDisplayCount dspyCnt;
	
	CGGetOnlineDisplayList (maxDisplays, onlineDspys, &dspyCnt);

	
	if (argc == 1) {
	    CGRect screenFrame = CGDisplayBounds(kCGDirectMainDisplay);
		CGSize screenSize  = screenFrame.size;
		printf("%.0f %.0f\n", screenSize.width, screenSize.height);
		return 0;
	}
	
	if (argc == 2) {
		if (! strcmp(argv[1],"-l")) {
			ListDisplays( dspyCnt, onlineDspys );
			return 0;
		}
		else if (! strcmp(argv[1],"-?")) {
			usage(argv);
			return 0;
		}
		else if (displayNum = atoi(argv[1])) {
			if (displayNum <= dspyCnt) {
				GetDisplayParms(onlineDspys, displayNum-1, &h, &v, &depth, &freq);
				printf("%d %d\n", h, v);
				return 0;
			}
			else {
				fprintf(stderr, "ERROR: display number out of bounds; displays on this mac: %d.\n", dspyCnt);
				return -1;
			}
		}
	}
	
	
	if (argc == 4 && (displayNum = atoi(argv[1])) && (h = atoi(argv[2])) && (v = atoi(argv[3])) ) {
		if (displayNum <= dspyCnt) {
			theDisplay= onlineDspys[displayNum-1];
		}
		else return -1;
	}
	else {
		if (argc != 3 || !(h = atoi(argv[1])) || !(v = atoi(argv[2])) ) {
			fprintf(stderr, "ERROR: syntax error.\n", argv[0]);
			usage(argv);
			return -1;
		}
		theDisplay = CGMainDisplayID();
	}


	switchMode = CGDisplayBestModeForParameters(theDisplay, 32, h, v, NULL);
	
	if (! MyDisplaySwitchToMode(theDisplay, switchMode)) {
	    fprintf(stderr, "Error changing resolution to %d %d\n", h, v);
		return 1;
	}
	
	return 0;
}


void ListDisplays( CGDisplayCount dispCount, CGDirectDisplayID *dispArray )
{
	int	h, v, depth, freq;
	
		printf("Displays found: %d\n", dispCount);
		for	(int i = 0 ; i < dispCount ;  i++ ) {

			GetDisplayParms(dispArray, i, &h, &v, &depth, &freq);
			printf("Display %d (id %d):  %d x %d x %d @ %dHz\n", i+1, dispArray[i], h, v, depth, freq);
		}
}


void GetDisplayParms(CGDirectDisplayID *dispArray,  CGDisplayCount dispNum, int *width, int *height, int *depth, int *freq)
{
	CFDictionaryRef currentMode = CGDisplayCurrentMode (dispArray[dispNum]);
	CFNumberRef number = CFDictionaryGetValue (currentMode, kCGDisplayRefreshRate);
	CFNumberGetValue (number, kCFNumberLongType, freq);
	number = CFDictionaryGetValue (currentMode, kCGDisplayWidth);
	CFNumberGetValue (number, kCFNumberLongType, width);
	number = CFDictionaryGetValue (currentMode, kCGDisplayHeight);
	CFNumberGetValue (number, kCFNumberLongType, height);
	number = CFDictionaryGetValue (currentMode, kCGDisplayBitsPerPixel);
	CFNumberGetValue (number, kCFNumberLongType, depth);
}

bool MyDisplaySwitchToMode (CGDirectDisplayID display, CFDictionaryRef mode)
{
	CGDisplayConfigRef config;
	if (CGBeginDisplayConfiguration(&config) == kCGErrorSuccess) {
		CGConfigureDisplayMode(config, display, mode);
		CGCompleteDisplayConfiguration(config, kCGConfigureForSession );
		return true;
	}
	return false;
}


void usage(const char *argv[])
{
	printf("\nUsage: %s [-l | 1..9 ] [ hor_res vert_res]\n\n", argv[0]);
	printf("      -l  list resolution, depth and refresh rate of all displays\n");
	printf("    1..9  display # (default: main display)\n");
	printf(" hor_res  horizontal resolution\n");
	printf("vert_res  vertical resolution\n\n");
	printf("Examples:\n");
	printf("%s 800 600      set resolution of main display to 800x600\n", argv[0]);
	printf("%s 2 800 600    set resolution of secondary display to 800x600\n", argv[0]);
	printf("%s 3            get resolution of third display\n", argv[0]);
	printf("%s -l           get resolution, bit depth and refresh rate of all displays\n\n", argv[0]);
}


[ Reply to This | # ]
Modified source to manage two or more monitors
Authored by: juanfal on Apr 17, '09 05:56:01AM
THANKS A LOT! I have found only an annoying C++ error:
$ c++ setgetscreenres.m -framework ApplicationServices -o setgetscreenres
setgetscreenres.m: In function ‘ListDisplays’:
setgetscreenres.m:104: error: ‘for’ loop initial declaration used outside C99 mode
But you can avoid it changing lines 101-104 by:
	int	h, v, depth, freq, i;
	
	printf("Displays found: %dn", dispCount);
	for	(i = 0 ; i < dispCount ;  i++ ) {


[ Reply to This | # ]
One more thing...
Authored by: wallybear on Apr 17, '09 02:49:37PM

Ouch, that's true; I didn't get that error because I compiled it under XCode, which accepts that syntax.
I used XCode to be sure it works also on 10.4 and to make it Universal. It even builds a smaller fat binary (38Kb vs. 46Kb).

The command line compiling instructions given will generate a binary only for the CPU (and System version) of the Mac used.

To compile it as Universal from command line just change the compile command to this:

c++ setgetscreenres.m -framework ApplicationServices -o setgetscreenres -arch i386 -arch ppc

...and to make it work from OS X Panther (10.3.9) or newer, just add this flag at the end of the compile command line:

-mmacosx-version-min=10.3.9

(obviously if you want to exclude OS X Panther then use: -mmacosx-version-min=10.4 )



[ Reply to This | # ]
...a small addition...
Authored by: wallybear on Apr 18, '09 07:55:34AM
Changing my ListDisplays() function with the following, we can see which display is the primary (i.e. the one with the menu bar):

void ListDisplays( CGDisplayCount dispCount, CGDirectDisplayID *dispArray )
{
	int	h, v, depth, freq, i;
	CGDirectDisplayID mainDisplay = CGMainDisplayID();
	
		printf("Displays found: %d\n", dispCount);
		for	(i = 0 ; i < dispCount ;  i++ ) {

			GetDisplayParms(dispArray, i, &h, &v, &depth, &freq);
			printf("Display %d (id %d):  %d x %d x %d @ %dHz", i+1, dispArray[i], h, v, depth, freq);
			if ( mainDisplay == dispArray[i] ) 
				printf(" (main)\n");
			else
				printf("\n");
		}
}
With this mod, the displays listing (using setgetscreenres -l) will look like this one:

Displays found: 3
Display 1 (id 180814742):  1024 x 768 x 32 @ 75Hz
Display 2 (id 188810672):  1920 x 1080 x 32 @ 60Hz (main)
Display 3 (id 160845621):  1440 x 900 x 32 @ 60Hz
stating that Display 2 is the main display.


[ Reply to This | # ]
How to turn off (sleep) a display?
Authored by: Bakerman on Jul 09, '09 07:49:37AM

Does anyone know how to reconfigure a display so that it's off/sleeping?

The reason I ask is that most of the time I use my Mac Book Pro in clamshell mode (connected to an external display) but notice it can get a bit warm with the lid closed. So I want to have the lid open but the built-in display turned off.

Why not just use the extra screen space? Mainly because the laptop is on a shelf that is too far away to be usable, but also because my 24" monitor is big enough so I might as well save my backlight.





[ Reply to This | # ]
How to turn off (sleep) a display?
Authored by: nbriders on Aug 18, '09 07:32:35AM

Hi - i have been looking for precisely this for SO long - it should be so simple to switch between built-in display, external, both easily...currently passing by the sleep mode (closing lid, waking up, opening it again) is just a pain. Please post here if you find something, and ill do the same with success.

thanks



[ Reply to This | # ]
How to turn off (sleep) a display?
Authored by: rking555 on Jul 10, '10 08:21:26PM

To put a display to sleep hold control and shift while you press eject.



[ Reply to This | # ]
Change screen resolution in Terminal
Authored by: ghay on Dec 31, '09 04:11:11AM

This would seem to work, but I have a further problem,

using a G4 headless via ARD. Use this utility to set 1280 x 1024, screen goes garbage. Presumably down to ARD expecting the old screen size.

I've tried kickstarting ARD after the change to no effect.



[ Reply to This | # ]