Is there a way to control dual monitor relative position from terminal?

I have a weird setup for my home office that allows me to switch from a standing desk to a sitting desk. The only problem is that when I alternate positions, my laptop's external monitor switches sides. (When standing it is off to the left of my laptop, when sitting it is on the right). At the moment, every time I go from sitting to standing, or vise-versa I have to go into System Preferences -> Displays -> Arrangement and rearrange them. What I would love is some sort of terminal command that moves the 2nd monitor relative to first one. Doesn't matter how long the command is since I can just alias it.


Solution 1:

I wrote a small C program to accomplish this, as this cannot be done any other way effectively.

You'll need Xcode installed to compile it.

https://github.com/stnvh/cgorigin


#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>

#define MAX_DISPLAYS 10

static CGDisplayCount dispCount = MAX_DISPLAYS;
static CGDirectDisplayID dispOnline[MAX_DISPLAYS];

int main(int argc, const char * argv[]) {
    CGDisplayCount dispOnlineCount;
    CGDisplayErr errActive = CGGetOnlineDisplayList(dispCount, dispOnline, &dispOnlineCount);

    CGDisplayConfigRef configRef;
    CGError err = CGBeginDisplayConfiguration(&configRef);

    if(!argv[1]) {
        printf("usage: [-l | --list] [[-o | --origin] x y index] \n");
        return 1;
    }

    for(int i = 0; i < dispOnlineCount; i++) {
        if(dispOnline[i]) {
            int dispWidth = CGDisplayPixelsWide(dispOnline[i]);
            int dispHeight = CGDisplayPixelsHigh(dispOnline[i]);
            CGPoint dispOrigin = CGDisplayBounds(dispOnline[i]).origin;

            if(strcmp(argv[1], "--list") == 0 || strcmp(argv[1], "-l") == 0) {
                printf("display %d: %dx%d %ldx%ld\n", i, dispWidth, dispHeight, (long)dispOrigin.x, (long)dispOrigin.y);
            }

            if(strcmp(argv[1], "--origin") == 0 || strcmp(argv[1], "-o") == 0) {
                int posX = dispOrigin.x;
                int posY = dispOrigin.y;
                int dispInd = 1;

                if(argv[2]) {
                    posX = strtol(argv[2], NULL, 0);
                }
                if(argv[3]) {
                    posY = strtol(argv[3], NULL, 0);
                }
                if(argv[4]) {
                    long _dispInd = strtol(argv[4], NULL, 0);

                    if(_dispInd < dispOnlineCount) {
                        dispInd = _dispInd;
                    }
                }

                if(dispInd == i) {
                    err = CGConfigureDisplayOrigin(configRef, dispOnline[i], posX, posY);
                }
            }
        }
    }

    err = CGCompleteDisplayConfiguration(configRef, kCGConfigurePermanently);
    if(err != 0) NSLog(@"Error with applying configuration: %d\n", err);

    return 1;
} 

Save to a file called main.m, then run:

clang -Wall -framework Foundation -framework ApplicationServices main.m -o cgorigin

Example (from Github):

assuming we have two monitors connected, both at 1920x1080

cgorigin --origin -1920 0 # positions the second monitor to the left of the main display

cgorigin --origin 0 0 # positions the second monitor to the right of the main display

cgorigin --origin -1920 1080 0 # positions the first monitor below the second display