27

I'm using a MacBook Pro (Late 2011) connected to two Thunderbolt displays. The displays are chained together, and one Thunderbolt connection is made to the MacBook Pro.

I prefer to have the left monitor function as the primary display (I want the dock to live on the left). Using the Display System Preference Pane, I can set this configuration with no issues.

Every morning, I connect the displays to the MacBook Pro and I disconnect every evening.

Some days, seemingly at random, the display configuration is changed and the right monitor has the dock and menu bar instead of the left.

Is there any way to ensure the display configuration remains the same?

6
  • Just for the record, could you clarify, (1) you have the brand new current (March 2012) MBP, and I guess it is either the 15 or 17 inch? (2) you DAISY CHAIN the two monitors (the MBP has only one Thunderbolt port) ? {To be clear - there is a lot of info on the internet that supposedly you CANNOT daisy chain apple thunderbolt monitors: supposedly, with thunderbolt monitors can only be the "end" of a chain. But perhaps this rumour is complete nonsense?} (3) Finally can I ask you, to be clear all three monitors are logical displays, is that right? i.e. NOTHING is mirrored - you can wipe your mous
    – user19967
    Commented Mar 11, 2012 at 13:36
  • MBP is new/current, but from February, 17-inch. Monitors are daisy-chained. All monitors are logical displays, though I shut the MBP and don't use it's monitor when connected to the external displays.
    – jro
    Commented Mar 11, 2012 at 22:57
  • > if you DO open the MBP, do you the get three totally separate logical monitors? Yes.
    – jro
    Commented Mar 12, 2012 at 17:40
  • > when you unplug.....I only attach the chained monitors to the MBP. MBP is never opened, so it's in sleep mode when I connect it.
    – jro
    Commented Mar 12, 2012 at 17:41
  • I would hate to suggest this but have you tried (or can you try) 2 different models of external monitors?
    – databyte
    Commented Mar 13, 2012 at 19:39

8 Answers 8

7

OSX has to guess which monitor is which, since the EDID info is the same for both (save the serial number, presumably, but OSX doesn't appear to pay attention to that). It usually tries to set things up to the previous setup by looking at how the devices are attached in the connection tree, however with Thunderbolt the connection tree isn't as simple as it was with displayport and USB.

You should be able resolve this by attaching one monitor at a time (ie, unplug the thunderbolt connection for the third monitor, attachthe second, then plug the third back in). However that's less than ideal, especially since all your apps will go back to the main monitor, rather than how you had them set up previously.

When Apple releases a refresh of the thunderbolt display, attaching one of the old ones and one of the new ones should also resolve the problem - they won't appear to be the "same" device, and so OSX will have an easier time keeping track of which is which.

Until that happens, another thing you can try is attaching the third one with a thunderbolt extension cable. It's an active device, and may alter the connection tree enough that OSX will have an easier time keeping track of it.

If that doesn't help, your best bet will be to wait until they refresh the thunderbolt display and upgrade only one of them when they do.

1
  • 1
    I had to beat my head against OSX for several months writing a video driver. OSX is smart in most ways, and dumb in some others. The major problem being that when it's dumb there's often no easy workaround.
    – Adam Davis
    Commented Mar 20, 2012 at 17:40
12

This worked for me, credit to this answer:

https://superuser.com/a/1220526/454133

Play around with moving the "top" bar between screens in the Arrangement window. Assign it to different screens and you will notice it will solve your issue once you find the "right" screen.

So, monkeying with the menu bar in the arrangement settings will reset your displays proper. I even got screenshots.

How to move the top bar between mac windows

10

The free terminal tool I wrote, displayplacer, allows you to configure the "white bar" primary display via scripts/hotkeys.

Configure your screens how you like, drag the "white bar" to your primary screen in the macOS system settings, and then execute displayplacer list. It will output the command to run to put your screens in their current configuration. The screen with origin:(0,0) is the main display with the "white bar". Run this terminal command through a script, Automator, BetterTouchTool, etc.

This example makes the left screen the primary monitor. Execute a similar command whenever your machine randomly chooses the wrong primary display. displayplacer "id:<leftScreenId> res:1920x1080 scaling:on origin:(0,0) degree:0" "id:<rightScreenId> res:1920x1080 scaling:on origin:(1920,0) degree:0"

Also available via Homebrew brew tap jakehilborn/jakehilborn && brew install displayplacer

2
  • ive managed to use this app on an M1 mac to list the current orientation. then i put that command into an alias for zsh and i can reset my screens. next step, bind a key combe for the command. super useful tool, thanks.
    – bytejunkie
    Commented Jan 24, 2022 at 14:37
  • This is brilliant. Thank you Jake! This worked like a charm after following this github.com/jakehilborn/displayplacer/issues/… Commented Apr 24, 2022 at 21:33
8

I suffer the same problem, each morning when I come to the office about 80% of the time my Mac wrongly selects the left most TB display as primary >:@

Getting tired of going to the settings display every time, I wrote a very simple console App to swap the screens for me: "ScreenPhant" (like elephants and memory; dig :-P)

It is really too simple, but I have no time now to make it any fancier (like staying resident and monitoring display changes automatically etc.). If you just start it, it will list the displays and serials. Pass the serial of the display you want as primary and it will set it. If you rename the App like "ScreenPhant_151d050f" it will use the _[serial] for the primary display so you don't need an extra script to launch it.

You can download here: http://www.dialxs.com/dev/ScreenPhant.gz Source is available here: http://www.dialxs.com/dev/main.c

1
  • I tried to build this app, but it comes up with both displays having the same serial number. How is this possible. It is two Samsung displays S27H85x both connected using USB-C. The output from your app is: 2 displays detected display 0 = unit 0 serial 5a5a5730 (main) display 1 = unit 1 serial 5a5a5730 Program ended with exit code: 0
    – olekeh
    Commented Jun 17 at 5:52
6

I narrowed down this race condition thanks to /var/log/displaypolicy/displaypolicyd*.log and to the "Graphics/Displays" tab in "System Information" and in which order external monitors are listed there. MacOS (Mojave, Catalina 10.15.3,...) could rely on the serial numbers of the monitors seen in the latter to remember the arrangement, but it looks like macOS doesn't care about monitor serial numbers.

It's easier to reproduce this issue if you don't use daisy chaining but a dock or direct connections to the mac instead. If you connect the dock to the computer first and then the monitors to the dock second while observing /var/log/displaypolicy/displaypolicyd*.log (.log missing from the Console app for some unknown reason), you'll see macOS labels identical monitors on a first come, first serve basis, ignoring not only serial numbers but also physical connectors.

Don't get me wrong: macOS shouldn't look at the physical ports either. It should look at the serial numbers: the only thing guaranteed to never change or race or be accidentally swapped by the user.

4
  • 1
    In 10.15.7 macOS stopped remembering the orientation of a single monitor :-( 10.15.6 was remembering the orientation of a single monitor just fine.
    – MarcH
    Commented Dec 17, 2020 at 18:32
  • apple.stackexchange.com/questions/340407/…
    – MarcH
    Commented Dec 18, 2020 at 23:39
  • I don't see this log path on macOS 12 anymore... This is basically useless now I guess.
    – Fab1n
    Commented Oct 6, 2022 at 8:34
  • I just checked and these logs are still in the same place on macOS 12.6. Maybe you've been looking in /var/logs/ instead?
    – MarcH
    Commented Oct 6, 2022 at 20:40
3

Another simple workaround for this problem: keep your displays powered off, and turn them on in the same order after connecting them to your Mac.

If you only have two displays, you only need to power cycle one of them.

2

As shared in the (accepted answer above) the problem lies within multiple same-model monitors having the same EDID. Then the system cannot distinguish between both of them.

I now have solved the issue and now have different EDID for the same 2 monitor models.

The solution is simple: I now connect 1 monitor via DP and one via HDMI. Boom - I get 2 different EDIDs now. You can compare the EDIDs using ioreg -l | grep EDID. Also the AlphanumericSerialNumber is different.

Background: I have 2 Benq PD3200U connected to a TB4 Dock from Sonnettech. As the dock only has TB4 ports I use Anker HDMI to USB-C and DP to USB-C adapters, both plugged into the dock.

Previously I had plugged in 2 HDMI Cables via the mentioned adapters, one in the dock and one directly in the MBP M1P 16". This lead to switching of primary monitors as described on multiple sites and posts.

I will report back after a few days if the problem has been finally solved this way!

1
  • 2
    I must admit that sometimes the problem comes back, but way way less often. I guess it does have to do with the order in which the displays receive/process signal. The DP connected monitor always comes on first.
    – Fab1n
    Commented Oct 27, 2022 at 11:19
0

I did find this small "c" program somewhere, that switches the monitors as primary and secondary display. In the original version, I figured out that it returned the same serial number on both displays, even the displays itself had different serial numbers. I modified it to just display a list of monitors, and switched display 0 and display 1. Then I could run this only when the arrangement was wrong. This is far easier than reorganising the displays using the "display" system settings panel.

Unfortunately, I could not find the original author for it, but here is my modified version.

#include <stdio.h>
#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/IOKitLib.h>

#define MAX_DISPLAYS 32

void printDisplayInfo(io_service_t display) {
    CFDictionaryRef info = IODisplayCreateInfoDictionary(display, kIODisplayOnlyPreferredName);
    if (info) {
        // Display product name
        CFDictionaryRef names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
        if (names) {
            CFStringRef productName;
            if (CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), (const void**)&productName)) {
                char buffer[256];
                CFStringGetCString(productName, buffer, sizeof(buffer), kCFStringEncodingUTF8);
                printf("Product Name: %s\n", buffer);
            }
        }
        CFRelease(info);
    } else {
        printf("Failed to create display info dictionary.\n");
    }
}

void getDisplaySerialNumber(io_service_t display) {
    CFDataRef edidData = IORegistryEntryCreateCFProperty(display, CFSTR("IODisplayEDID"), kCFAllocatorDefault, 0);
    if (edidData) {
        const uint8_t *edidBytes = CFDataGetBytePtr(edidData);
        if (edidBytes) {
            char serialNumber[14] = {0};
            // EDID block contains ASCII serial number in descriptor 1 (bytes 54-71)
            if (edidBytes[54] == 0x00 && edidBytes[55] == 0x00 && edidBytes[56] == 0x00 && edidBytes[57] == 0xFF) {
                for (int i = 0; i < 13; i++) {
                    serialNumber[i] = (char)edidBytes[58 + i];
                }
                printf("Human-readable Serial Number: %s\n", serialNumber);
            } else {
                printf("No human-readable serial number found in EDID descriptor.\n");
            }
        }
        CFRelease(edidData);
    } else {
        printf("Failed to get EDID from display.\n");
    }
}


int main (int argc, const char ** argv) {
    
    CGDirectDisplayID activeDisplays[MAX_DISPLAYS], mainID = 99, primaryID = 99;
    uint32_t mainSerial=0, serial, primaryserial=0;
    CGDisplayErr err;
    CGDisplayCount displayCount;
    CGDisplayConfigRef config;
    
    //DEBUG argc=2; argv[1]= "151d050f";
    if( argc > 1 && strcmp(argv[1],"-h")==0 ) {
        printf("Usage: %s [<primary-serial>]\n\nNo arguments will just list your displays. Give <primary-serial> to set corresponding monitor as the main display.\n", argv[0]);
        exit(0);
    } else if( argc > 1 ) {
        sscanf(argv[1], "%x",  &primaryserial);
    } else {
        // Trick to include serial in app name so you dont need args and an extra script ;-)
        char *p=strchr(argv[0],(int)'_');
        if (p != NULL) {
            sscanf(p+1, "%x",  &primaryserial);
        }
    }
    
    err = CGGetActiveDisplayList(MAX_DISPLAYS, activeDisplays, &displayCount);
    if ( err != kCGErrorSuccess )
    {
        printf("Cannot get displays (%d)\n", err);
        exit(1);
    }
    printf("%d displays detected\n", displayCount);
    for (int i = 0; i < displayCount; i++) {/*
            serial = CGDisplaySerialNumber(activeDisplays[i]);
            uint32_t vendor = CGDisplayVendorNumber(activeDisplays[i]);
            uint32_t model = CGDisplayModelNumber(activeDisplays[i]);
            if (serial == primaryserial) {
                primaryID = i;
            }
            printf("\tdisplay %d = unit %d vendor %x model %x serial %x", i, CGDisplayUnitNumber(activeDisplays[i]), vendor, model, serial);
            if (CGDisplayIsMain(activeDisplays[i])) {
                printf(" (main)");
                mainID = i;
                mainSerial = serial;
            }
            printf("\n");*/
            io_service_t display = CGDisplayIOServicePort(activeDisplays[i]);
              printf("Display %d:\n", i);
                printDisplayInfo(display);
                getDisplaySerialNumber(display);
    }
    if( /*primaryserial != 0
       && primaryID != 99
       && mainSerial != primaryserial*/ true
       ) {
           mainID = 0;
           primaryID = 1;
           
        printf("swaping %d and %d!\n", mainID, primaryID);

        CGBeginDisplayConfiguration(&config);
        CGConfigureDisplayOrigin(config,activeDisplays[primaryID], 0, 0); //Set the second display as the new main display by positionning at 0,0
        CGConfigureDisplayOrigin(config,activeDisplays[mainID], (int)CGDisplayPixelsWide(activeDisplays[mainID])*-1, 0); //Arrangement of the old main display to the left of the new main display
        CGCompleteDisplayConfiguration(config,kCGConfigureForSession);
    }
    return 0;
}

Just open Xcode, start a new "C" command line utility, paste in the source and compile. The compiled product can be moved into you app folder, and make a shortcut on your desktop. Each time the displays has switched arrangement, just run it and it should be all good.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .