Running a MacBook Pro and MacBook Air at native resolution

I wrote displaymode, a simple command line utility for changing the resolution of the main display of a macOS machine. It lets you run Retina displays at their native resolution. For a recent 15″ MacBook Pro this means 2880×1800 and for the 2018 MacBook Air Retina, 2560×1600

The repository is at https://github.com/p00ya/displaymode and you can download a binary in the releases section.

To get native resolution on the MacBook Air, run:

./displaymode t 2560 1600

and on the MacBook Pro:

./displaymode t 2880 1800

Why did I write displaymode?

I recently calibrated the displays on a MacBook Air and MacBook Pro using a colorimeter. I then went to use Han-Kwang Nienhuys excellent LCD monitor test website but quickly noticed that a bunch of the tests were broken due to the scaling used by macOS. Using the “Displays” panel from System Preferences, the default resolution on a MacBook Air is 1440×900. Given the native resolution is 2560×1600, this is a 16:9 (approximately @1.78x) scaling ratio. This non-integer ratio means that anything that starts properly aligned to a pixel grid (e.g. bitmap fonts, or dithers used for calibration tests) will be misaligned once scaled! Only one option from System Preferences is an integer ratio (1280×800, @2x), but this is an absurdly low resolution for a modern laptop.

A bit of searching pointed to using an old piece of abandonware, “ScreenUtil” or scrutil, which is only available as an ppc/i386 binary, with no source code available. However, it still runs for me under Mojave (albeit with a deprecation warning). I first tried to follow the instructions:

./scrutil s 2560 1600 32

This does change the resolution temporarily, but the resolution immediately switches back when the program exits. I suspect it was meant for scrutil’s REPL mode, whereby you’d run scrutil without any options and give it the command on stdin:

scrutil
s 2560 1600 32

Then leave it running (or ^C if something went wrong). Or perhaps Apple’s underlying APIs have changed since scrutil was written, and macOS didn’t always revert the resolution at program exit.

Nevertheless, there appears to be an alternative scrutil option that Does What I Want and sets the resolution permanently:

./scrutil t 2560 1600 32

Since ScreenUtil seems a bit sketchy (deprecation warnings, closed source, dodgy redistribution of an “All rights reserved” binary), I took a look at Apple’s Quartz Display Services APIs to see if I could replicate scrutil’s functionality. Turns out that CGConfigureDisplayWithDisplayMode is exactly what’s needed.

So I wrote displaymode – a simple drop-in replacement for the “scrutil t” functionality (I also implemented a couple of scrutil’s other options). It has the advantages:

  • open source (Apache-2.0 license)
  • binary distribution compiled for modern x86_64 mac architectures
  • does not use deprecated or private Apple APIs

Of course, the first thing you will notice after switching to the native Retina resolution is that everything is tiny. Nevertheless, I find most text is still quite legible (probably owing to its much-improved pixel alignment compensating for its much-reduced physical size). I found that if I change my Chrome default Page Zoom (from chrome://settings/?search=page+zoom) to 150% on the MacBook Air (125% on the MacBook Pro), and my Terminal font from un-antialiased 11pt Monaco to (antialiased) 18pt Menlo (14pt on the MacBook Pro), everything looks much the same physically (except bits of UI chrome like the menu bar take up much less space – a good thing in my opinion!).

3 thoughts on “Running a MacBook Pro and MacBook Air at native resolution”

  1. Great stuff. Thanks for doing it and sharing. I am exploring possibility to apply the change permanently. From the description and/or documentation of the project I didn’t find it in the options. Any ideas?

Leave a Reply

Your email address will not be published. Required fields are marked *