Hi Everyone, I’m a regular listener, but new forum participant. I wanted to share a quick automation I built that has saved me lots of time as I balance my work and personal worlds.
I have two laptops on my desk most of the time: one issued by my employer and my personal MacBook Pro. I also have a pair of 27-inch monitors that have multiple inputs (DisplayPort, HDMI, etc.). My work laptop is hooked up to the DisplayPort inputs, and my personal laptop is hooked up to the HDMI inputs. For the longest time, I’d just manually poke the input select button on each monitor until I got it to switch to the right source, but then my MacBook would be sitting during my work day with two of its screens hidden.
Here’s how I fixed that.
First, it’s important to know that most modern monitors support a protocol called Data Display Channel (DDC) (look it up on Wikipedia - as a new user I only get 2 links!). Using DDC, you can interrogate the monitor to learn all sorts of things, and you can also issue commands back. Not all monitors support it fully, and you have to have a reasonably reliable Thunderbolt/USB-C to HDMI adapter, but many cheap ones work fine (mine do).
There’s a small tool available on GitHub called ddcctl that allows you to issue DDC commands. Now, I can programmatically switch monitor inputs from work to personal and back again.
Next, I found another tool called displayplacer (also available through Homebrew). Essentially, it’s a tool to programmatically set monitor position and orientation, just like the Arrangement tab in the Displays control panel. It can control resolution, position, and rotation of all screens. It also has an option that will give you the configuration string for your current display arrangement.
Here’s how I put all this together:
Begin by installing both displayplacer and ddcctl. Some compiling will be necessary.
Now, capture the commands for the display arrangements you need.
- Arrange your displays for “personal mode”: three displays, arranged how you like. Now, run ‘’‘displayplacer list’’’ and save the last line of the output as your “personal arrangement”
- Repeat for “work mode.” For me, this is displays mirrored.
Now write two scripts. If you’re using mirrored displays, command order matters (see below)
I named my first script “monitor-work”. It looks like this:
#!/bin/bash # switch inputs to work computer while displays are still separate ddcctl -d 1 -i 15 ddcctl -d 2 -i 15 # switch to mirrored mode displayplacer "id:.........[work arrangement]"
I named my second script “monitor personal”:
#!/bin/bash # switch to separate display mode displayplacer "id:.....[personal arrangement]" # switch inputs to personal computer now that displays are again separate ddcctl -d 1 -i 17 ddcctl -d 2 -i 17
Notice that the order of
displayplacer are reversed between the two scripts. Here’s the logic: Always issue
ddcctl commands when you have separate displays active. If you try to issue
ddcctl commands when your displays are mirrored, the tool won’t be able to see the other monitors and the command will fail.
That’s about it. I mapped these scripts to a pair of buttons on my Touch Bar using BetterTouchTool, and now I can switch between having 3 work + 1 personal and 1 work + 3 personal screens in about 5 seconds. I’d love thoughts and feedback if anyone can think of ways to improve the process or take it further.