27

Is there a way to get the information about connected monitors and displays and their resolutions via the terminal in OS X?

I have some installations that run on multiple monitors and sometimes with a GFLW window that seem to not open if a monitor is not attached - I would like to have a check for whether a monitor is attached properly and maybe dump that to a log file, but I haven't found a programmatic way to do that without getting deep into Obj-C/Cocoa

laserpilot
  • 271
  • 1
  • 3
  • 3

3 Answers3

43

You can use system_profiler SPDisplaysDataType or defaults read /Library/Preferences/com.apple.windowserver.plist (defaults read /Library/Preferences/com.apple.windowserver.displays.plist in recent macos versions):

$ system_profiler SPDisplaysDataType
Graphics/Displays:

    NVIDIA GeForce GT 640M:

      Chipset Model: NVIDIA GeForce GT 640M
      Type: GPU
      Bus: PCIe
      PCIe Lane Width: x16
      VRAM (Total): 512 MB
      Vendor: NVIDIA (0x10de)
      Device ID: 0x0fd8
      Revision ID: 0x00a2
      ROM Revision: 3707
      Displays:
        iMac:
          Display Type: LCD
          Resolution: 1920 x 1080
          Pixel Depth: 32-Bit Color (ARGB8888)
          Main Display: Yes
          Mirror: Off
          Online: Yes
          Built-In: Yes
          Connection Type: DisplayPort

# For recent macos versions:
# $ defaults read /Library/Preferences/com.apple.windowserver.displays.plist
$ defaults read /Library/Preferences/com.apple.windowserver.plist
{
    DisplayResolutionEnabled = 1;
    DisplaySets =     (
                (
                        {
                Active = 1;
                Depth = 4;
                DisplayID = 69731456;
                DisplayProductID = 40978;
                DisplaySerialNumber = 0;
                DisplayVendorID = 1552;
                Height = 1080;
                IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/P0P2@1/IOPCI2PCIBridge/GFX0@0/NVDA,Display-A@0/NVDA";
                IOFlags = 7;
                LimitsHeight = 1080;
                LimitsOriginX = 0;
                LimitsOriginY = 0;
                LimitsWidth = 1920;
                MirrorID = 0;
                Mirrored = 0;
                Mode =                 {
                    BitsPerPixel = 32;
                    BitsPerSample = 8;
                    DepthFormat = 4;
                    Height = 1080;
                    IODisplayModeID = "-2147479552";
                    IOFlags = 7;
                    Mode = 1;
                    PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB";
                    RefreshRate = 0;
                    SamplesPerPixel = 3;
                    UsableForDesktopGUI = 1;
                    Width = 1920;
                    kCGDisplayBytesPerRow = 7680;
                    kCGDisplayHorizontalResolution = 103;
                    kCGDisplayModeIsInterlaced = 0;
                    kCGDisplayModeIsSafeForHardware = 1;
                    kCGDisplayModeIsStretched = 0;
                    kCGDisplayModeIsTelevisionOutput = 0;
                    kCGDisplayModeIsUnavailable = 0;
                    kCGDisplayModeSuitableForUI = 1;
                    kCGDisplayPixelsHigh = 1080;
                    kCGDisplayPixelsWide = 1920;
                    kCGDisplayResolution = 1;
                    kCGDisplayVerticalResolution = 103;
                };
                OriginX = 0;
                OriginY = 0;
                PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB";
                Resolution = 1;
                Unit = 0;
                UnmirroredHeight = 1080;
                UnmirroredLimitsHeight = 1080;
                UnmirroredLimitsOriginX = 0;
                UnmirroredLimitsOriginY = 0;
                UnmirroredLimitsWidth = 1920;
                UnmirroredMode =                 {
                    BitsPerPixel = 32;
                    BitsPerSample = 8;
                    DepthFormat = 4;
                    Height = 1080;
                    IODisplayModeID = "-2147479552";
                    IOFlags = 7;
                    Mode = 1;
                    PixelEncoding = "--------RRRRRRRRGGGGGGGGBBBBBBBB";
                    RefreshRate = 0;
                    SamplesPerPixel = 3;
                    UsableForDesktopGUI = 1;
                    Width = 1920;
                    kCGDisplayBytesPerRow = 7680;
                    kCGDisplayHorizontalResolution = 103;
                    kCGDisplayModeIsInterlaced = 0;
                    kCGDisplayModeIsSafeForHardware = 1;
                    kCGDisplayModeIsStretched = 0;
                    kCGDisplayModeIsTelevisionOutput = 0;
                    kCGDisplayModeIsUnavailable = 0;
                    kCGDisplayModeSuitableForUI = 1;
                    kCGDisplayPixelsHigh = 1080;
                    kCGDisplayPixelsWide = 1920;
                    kCGDisplayResolution = 1;
                    kCGDisplayVerticalResolution = 103;
                };
                UnmirroredOriginX = 0;
                UnmirroredOriginY = 0;
                UnmirroredResolution = 1;
                UnmirroredWidth = 1920;
                Width = 1920;
            }
        )
    );
    ForceOldStyleMemoryManagement = 0;
}
Fabien Sa
  • 9,135
  • 4
  • 37
  • 44
Lri
  • 26,768
  • 8
  • 84
  • 82
  • 1
    Awesome! Thanks so much...just what I was looking for. Looking to make some of my applications smarter about connected displays. – laserpilot Nov 21 '13 at 16:44
  • 1
    Do you know a command to change resoluation and associated refresh rate? – Vincent Feb 23 '17 at 10:42
  • If you have a use case where you need something that executes faster than `system_profiler`, `xrandr` is a reasonable alternative - the info is less complete and relatively harder to machine-parse, but it's sufficient for some simple stuff. In my case it was for a space-swapping hotkey that I wanted to behave differently depending on whether an external monitor was connected at all. – Backgammon Sep 25 '19 at 16:38
  • 2
    For anyone struggling to ingest the output of `system_profiler` in another application: you can add a `-json` flag to format the output as json: `system_profiler SPDisplaysDataType -json` – cgenco Jan 20 '22 at 23:29
  • This is quite helpful for me. Thanks. – aisensiy Feb 10 '22 at 06:50
  • 1
    In recent versions of macOS com.apple.windowserver.plist has become com.apple.windowserver.displays.plist I have suggested an edit. – AndrewC Jul 24 '22 at 11:26
2

You can also use a command-line tool called cscreen:

# install homebrew if you don't have it already
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# install cscreen
brew install --cask cscreen

# list displays
cscreen -l

output:

DisplayID  Index     Depth     Width     Height  Refresh
       1       1        32      1440        900    60
       2       2        32      1920       1080    60
use -h to display all usage options

Note:

  • The first time you try to open the cscreen the os will not allow it because it isn't signed.
  • You have to go to Security & Privacy in System Preferences and allow it.

Homebrew package search

Milovan Tomašević
  • 6,823
  • 1
  • 50
  • 42
0

Use python for getting dictionary with data.

import Foundation, objc
import Quartz



iokit = {}

iokitBundle = objc.initFrameworkWrapper(
  "IOKit",
  frameworkIdentifier="com.apple.iokit",
  frameworkPath=objc.pathForFramework("/System/Library/Frameworks/IOKit.framework"),
  globals=globals()
)


IOKit = Foundation._functiondefines.NSBundle.bundleWithIdentifier_('com.apple.framework.IOKit')

functions = [('IOServiceGetMatchingService', b'II@'),
             ('IOServiceMatching', b'@*'),
             ("IODisplayGetFloatParameter", b'iII@o^f'),
             ("IODisplayGetIntegerRangeParameter", b'I'),
             ('IORegistryEntryCreateCFProperties', b'IIo^@@I'),
             ('IOPSCopyPowerSourcesByType', b'@I'),
             ('IODisplaySetFloatParameter', b'iII@f'),
             ("IOHIDGetActivityState", b'IBi'),
             ('IODisplayCopyFloatParameters', b'II^^{__CFDictionary}i'),
             ('IODisplaySetIntegerParameter', b'II^{__CFString=}ii'),
             ('IODisplayCreateInfoDictionary', b'^{__CFDictionary=}II'),
             ('IODisplaySetParameters', b'II^{__CFDictionary=}i')

             ]






objc._objc.loadBundleFunctions(iokitBundle, iokit, functions)
objc._objc.loadBundleFunctions(IOKit, globals(), functions)

for var in variables:
  key = "{}".format(var[0])
  if key in globals():
      iokit[key] = globals()[key]



var = iokit['IODisplayCreateInfoDictionary'](Quartz.CGDisplayIOServicePort(Quartz.CGMainDisplayID()), 0)
print(var, sep=r' ')