Ok, taking both routes when needed for more complete data, but always deferring to accurate data.
It’s no longer prety, or even not ugly, but it works well and returns reasonable values in all the cases I can test here.
set mp to monitorProperties()
--With one monitor attached
--{monitor1:{Width:1440, Height:900, OriginX:0, OriginY:0}, monitor2:{Width:missing value, Height:missing value, OriginX:missing value, OriginY:missing value}, monitorCount:1}
--With two monitors attached. No update of the Display Preference pane.
--{monitor1:{Width:1440, Height:900, OriginX:missing value, OriginY:missing value}, monitor2:{Width:1024, Height:768, OriginX:missing value, OriginY:missing value}, monitorCount:2}
--With two monitors attached. With an update of the Display Preference pane.
--{monitor1:{Height:900, Width:1440, OriginX:0, OriginY:0}, monitor2:{Height:768, Width:1024, OriginX:1440, OriginY:132}, monitorCount:2}
on monitorProperties()
--system_profiler parsing
set SPDisplaysData to (do shell script "system_profiler SPDisplaysDataType")
set text item delimiters to "Displays:"
set SPDisplaysData to text item 3 of SPDisplaysData
set text item delimiters to (word 1 of SPDisplaysData)
copy text item 1 of SPDisplaysData to text item delimiters
set SPDisplaysData to text items 2 thru -1 of SPDisplaysData
set text item delimiters to ""
repeat with i from 2 to length of SPDisplaysData
if character 1 of item i of SPDisplaysData is not " " then
set monitor1 to items 2 thru (i - 1) of SPDisplaysData
set monitor2 to items (i + 1) thru -1 of SPDisplaysData
exit repeat
end if
end repeat
--END OF system_profiler parsing
SPDisplaysData
set {monitorCount, output} to {1, {}}
repeat with curList in {monitor1, monitor2}
set mainDisplay to false
curList
if item 1 of curList contains "Status: No display connected" then
return {monitor1:{Width:y as integer, Height:x as integer, OriginX:0, OriginY:0}, monitor2:{Width:missing value, Height:missing value, OriginX:missing value, OriginY:missing value}, monitorCount:monitorCount}
else
repeat with i from 1 to length of curList
set curItem to item i of curList
if curItem contains "Resolution:" then
set {y, x} to {word 2 of curItem, word 4 of curItem}
end if
if curItem contains "Main Display: Yes" then
set mainDisplay to true
end if
end repeat
end if
if mainDisplay then
set display1 to {Width:y as integer, Height:x as integer, OriginX:missing value, OriginY:missing value}
else
set monitorCount to 2
set display2 to {Width:y as integer, Height:x as integer, OriginX:missing value, OriginY:missing value}
end if
end repeat
-- If there are two monitors then use com.apple.windowserver to try to acquire Origins
set {monitor1, monitor2} to {{}, {Height:missing value, Width:missing value, OriginX:missing value, OriginY:missing value}}
set PrefFilePath to do shell script "find " & (POSIX path of ((path to preferences from user domain as Unicode text) & "ByHost:")) & " -name 'com.apple.windowserver*'"
tell application "System Events"
set wsp to item 1 of (item 1 of (get value of property list items of property list file PrefFilePath))
end tell
repeat with mon from 1 to length of wsp
set monData to item mon of wsp
if (|OriginX| of monData is 0) and (|OriginY| of monData is 0) then
set monitor1 to {Height:|Height| of monData, Width:|Width| of monData, OriginX:|OriginX| of monData, OriginY:|OriginY| of monData}
else
set monitor2 to {Height:|Height| of monData, Width:|Width| of monData, OriginX:|OriginX| of monData, OriginY:|OriginY| of monData}
end if
end repeat
set WSmp to {monitor1:monitor1, monitor2:monitor2, monitorCount:(length of wsp) as integer}
--END OF If there are two monitors then use com.apple.windowserver to try to acquire Origins
if monitorCount is monitorCount of WSmp then --If monitor count matches, compare dimensions reported by the two sources.
if (Height of display1 is (Height of monitor1 of WSmp)) and (Width of display1 is (Width of monitor1 of WSmp)) and (Height of display2 is (Height of monitor2 of WSmp)) and (Width of display2 is (Width of monitor2 of WSmp)) then
return WSmp -- All match, return windowserver data since it is most complete.
end if
end if
return {monitor1:display1, monitor2:display2, monitorCount:monitorCount} -- Not all match, return system_profiler data.
end monitorProperties