The definitive guide to screen resolution?

Mikey,
Thanks for that clarification on NSScreen - as it can return resolution of all screens, I think it will be my method of choice in AS applications. Now, if only I could find a universal method for simple Applescript…
As an aside, I now realise why Method1 (NSDisplaysDataType) doesn’t work on System 2: System Profiler doesn’t have a supported data type by this name! Opening up System Profiler, display resolution appears to be buried in a series of submenus:
Hardware → PCI/AGP Cards → ATY,RV360M11 → Display
I can access the PCI profile with

do shell script "system_profiler SPPCIDataType"

but this only returns
"PCI/AGP Cards:

TXN,PCIXXXX-00:

  Name: cardbus
  Type: cardbus
  Bus: PCI
  Slot: PC Card
  Vendor ID: 0x104c
  Device ID: 0xac56
  Revision ID: 0x0000

ATY,RV360M11:

  Type: display
  Bus: AGP
  VRAM (Total): 64 MB
  Vendor: ATI (0x1002)
  Device ID: 0x4e50
  Revision ID: 0x0000
  ROM Revision: 113-xxxxx-134

    ATY,Jasper_A:
    
      Type: display
      Display Type: LCD
      VRAM (In Use): 64 MB
    
    ATY,Jasper_B:
    
      Status: No display connected"

Does anyone have any ideas how to access display resolution with system_profiler in this instance?
Thanks,
PJ.

Model: Powerbook G4
Browser: Safari 417.8
Operating System: Mac OS X (10.3.9)

This is an admittedly ugly hack, but it should work on any system with Terminal.app installed.


property desktopBounds : 0

tell application "Terminal"
	
	-- find out if terminal is running
	set termIsRunning to false
	
	tell application "System Events"
		set termIsRunning to ((name of processes) contains "Terminal")
	end tell
	
	if termIsRunning then
		-- open our window
		do script ""
	else
		-- launch and hide Terminal	
		run
		tell application "System Events" to set visible of process "Terminal" to false
	end if
	
	-- hide our window, zoom it, get its bounds, and close it
	set win to first window
	set visible of win to false
	set zoomed of win to true
	set desktopBounds to bounds of win
	close win
	
	-- if we started terminal, then kill it
	if termIsRunning is false then
		quit
	end if
	
end tell

desktopBounds

Advantages: gives size of desktop minus dock and menubar, doesn’t require Finder to be running (e.g. for PathFinder users)
Disadvantages: Big, ugly, window flash, and requires Terminal to be installed

Ok, the original post a quite old, but here are two additional approaches:

First:

set disWidth to word 1 of (do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep Width | cut -f 2 -d '=' | cut -f 1 -d ';'") as integer
set disHeight to word 1 of (do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep Height | cut -f 2 -d '=' | cut -f 1 -d ';'") as integer

Second: install the little command line cscreen in /usr/bin

Here is a subroutine to get the parameters of all connected displays or of one specified display:

set {maxDisplay, disParam} to cscreen(0) -- 0 = all displays, >0 = specified display

on cscreen(display)
	try
		((path to startup disk as string) & "usr:bin:cscreen") as alias
	on error
		return {false, false}
	end try
	set disParam to words of (do shell script "cscreen -l")
	set maxDisplay to item 1 of disParam as integer
	if display = 0 then
		set dispList to {}
		repeat with i from 1 to maxDisplay
			copy get_param(i, disParam) to end of dispList
		end repeat
		return {maxDisplay, dispList} -- list of max. number of displays and record(s) of parameters 
	else if display is less than or equal to maxDisplay then
		return {maxDisplay, get_param(display, disParam)}
	else
		return {false, false}
	end if
end cscreen

on get_param(DIndex, d)
	set i to 14 + ((DIndex - 1) * 5)
	set DisRecord to {DNum:item i of d, DDepth:item (i + 1) of d, DWidth:item (i + 2) of d, DHeight:item (i + 3) of d, DFreq:item (i + 4) of d}
	if DFreq of DisRecord = "0" then set DFreq of DisRecord to "TFT"
	return DisRecord
end get_param

both solutions work on Panther and Tiger

To take the load off StefanK, I’ve uploaded cscreen to ScriptBuilders. I am not the author, but that’s the only way I could load it.

You should be a bit wary of downloading executables from just anywhere - they can do mean things. If you want to check this copy or a copy you have received from another source, use this script after you unpack it (the hash in the script is from a known good copy I have from an independent source, and StefanK’s also checks ā€œcleanā€ in this test):

property hash : "dc3620e75bf55c302322be13982f2222"
set CS to POSIX path of (choose file with prompt "Choose the unZipped cscreen file")
set tHash to last word of (do shell script "md5 " & CS)
if tHash = hash then
	display dialog CS & "'s check sum is correct" with icon 1
else
	display dialog "The file " & CS & " has been altered!" with icon 0
end if

To find out how to use it:

set SCR to do shell script "Posix/Path/To/cscreen -h"

and to get screen resolutions for one or more screens:

set Cur to do shell script "Posix/Path/To/cscreen -I"

Thanks, Adam, I changed the link in my post above

Thanks, Stefan! I can confirm that your first method works with Jaguar as well. :slight_smile:

I’ve been trying to reduce it to just one shell script, but I’m not an expert. The following works on both my Jaguar and Tiger machines:

tell (do shell script "w=$(defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep -w 'Width'); h=$(defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep -w 'Height'); echo $w $h;") to set screenRes to {word 3 as integer, word ((count words) div 2 + 3) as integer}

It would be great if it didn’t have to include two ā€˜defaults reads’, but I haven’t been able to work out how to get by with just one.

The ā€˜grep’ in Tiger has a ā€˜-m’ option which allows you to specify how many matches are returned. This would allow a slight simplification of the AppleScript code, but doesn’t work in Jaguar:

tell (do shell script "w=$(defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep -wm1 'Width'); h=$(defaults read /Library/Preferences/com.apple.windowserver DisplaySets | grep -wm1 'Height'); echo $w $h;") to set screenRes to {word 3 as integer, word 6 as integer}

Hi, Jacques.

Thanks! Those both work on both systems and are more compact than ā€œ and nearly twice as fast as ā€œ my effort. The ā€˜grep’ version may possibly be very slightly faster than the ā€˜awk’, but it’s too close a call to be sure. They’re still several times slower than Jon’s Commands, but since that’s apparently not going to be ported for Intel machines, I’m keeping an eye on the alternatives!

set screenRes to screen size of beginning of (screen list starting with main screen) -- Needs Jon's Commands.

Elegant as these solutions are, I still have to use cscreen because I have two screens. :mad:

No problem, Adam, this returns the values for two screens ({x1, y1, x2, y2})

tell (do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | awk '/ Height =/||/ Width =/'") to set screenRes to {word 6 as integer, word 3 as integer, word 12 as integer, word 9 as integer}

It does indeed, Stefan! :smiley:

Someday, I’ll have to revise my Code Exchange submission on dual screens

I see that the very first key in the ā€œcom.apple.windowserverā€ domain is ā€œCGSInterocitorSelectModeā€. An interocitor, of course, is an alien device from the 1954 Sci-Fi film This Island Earth. There are quite a few people having fun with it on the Net. I quite enjoyed this effort. (Follow the ā€œAbout this pageā€ link for more information.) :wink:

When I read the link you gave and look back at CGSInterocitor’s value, mine is an integer set to zero. Is that universal or does it vary from country to country? If the latter, then it’s a quite suitable name for identifying ā€œaliensā€ presuming the ā€œ0ā€ means USA.

A cursory search through Apple Docs did not find much about com.apple.windowserver, however, and nothing about CGSInterocitor, so I have no idea what it’s for.

I saw Stefan’s solution, but does this work?:

(do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | sed -Ee '/^ *(Height|Width)/!d' -e 's/[^[:digit:]]*//g'")'s paragraphs

No. It’s ā€œ0ā€ here too ā€œ and we’re not aliens. :wink:

Hi, Qwerty.

It errors in Jaguar (ā€œIllegal operationā€) but returns a list of numeric Unicode texts in Tiger. For a single screen, we’d need something like this:

tell (do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | sed -Ee '/^ *(Height|Width)/!d' -e 's/[^[:digit:]]*//g'") to set screenRes to {paragraph 2 as integer, paragraph 1 as integer}

Apparently Canadians aren’t either (I’m happy to say) :lol:

Interestingly enough, after posting that, I tried changing the value to ā€œ1ā€ to see what would happen and actually turned into an alien for a while. Fortunately, I was able to slither into a vat of dinitrogen tetrasulphide while I restored the backup and, after a good night’s sleep and a cup of tea, am apparently no worse off for the experience. But thank goodness I didn’t try the ā€œ2ā€ setting! :o

:D:lol::lol:

After fiddling around for a short while, I’ve finally settled on this. It should hopefully return a list of records, but unfortunately I’m unable to test it on more than one display.

run script ("{" & (do shell script "defaults read /Library/Preferences/com.apple.windowserver DisplaySets | sed -Ee '/^ *(Height|Width)/!d' -e 's/Height = (.*);/{height: \\1,/' -e 's/Width = (.*);/width: \\1},/' -e 's/ *$/¬/'")'s text 1 thru -3 & "}")

I presume that, as the last one died of an obscure error, this too will fail on Jaguar.

Edit: Thanks Stefan, my fault. The script has been changed.

Hi Qwerty,

starting the script with two displays I get an runtime error (Expected ", " or ā€œ}ā€ but found ā€œ{ā€.)