Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap the positions of two monitors by contextual screen id. #80

Open
twocs opened this issue Mar 24, 2022 · 10 comments
Open

Swap the positions of two monitors by contextual screen id. #80

twocs opened this issue Mar 24, 2022 · 10 comments

Comments

@twocs
Copy link

twocs commented Mar 24, 2022

I have three monitors, all the same exact model and resolution. Mac keeps reassigning the "persistent id" on wakeup, so the command cannot work (I see other open issues also related). All I want to do is swap monitor #2 with monitor #3.

I can do this with some CLI work with SED and swap the IDs in the command output, but displayplacer list is so chatty. It doesn't simply output the "command below", but it also emits instructions and a bunch of other stuff.
displayplacer list | grep displayplacer outputs two lines of possible commands:

Rotation: 0 - rotate internal screen example (may crash computer, but will be rotated after rebooting): displayplacer "id:37D8832A-2D66-02CA-B9F7-8F30A301B230 degree:90"
displayplacer "id:11AC0330-F896-4084-A952-9A27AE3D72D6 res:1920x1080 hz:75 color_depth:8 scaling:off origin:(0,0) degree:0" "id:37D8832A-2D66-02CA-B9F7-8F30A301B230 res:1728x1117 hz:120 color_depth:8 scaling:on origin:(1920,-37) degree:0" "id:CCE46CDB-1FC0-45E0-BFE9-D240990808ED res:1920x1080 hz:75 color_depth:8 scaling:off origin:(-1920,0) degree:0"
So then I can make my script
displayplacer list | grep displayplacer | tail -n1 | sed 's/11AC0330-F896-4084-A952-9A27AE3D72D6/\n/g;s/CCE46CDB-1FC0-45E0-BFE9-D240990808ED/11AC0330-F896-4084-A952-9A27AE3D72D6/g;s/\n/CCE46CDB-1FC0-45E0-BFE9-D240990808ED/g' | sed 's/displayplacer//' | xargs displayplacer

What I'd really like is a command like displayplacer swap --contextual_screen_id 2 3

Some suggestions: displayplacer list -l could listScreens(), and displayplacer list -p could limit it to printCurrentProfile() (preferably without extraneous comments like "Execute the command below to set your screens to the current arrangement"). displayplacer list --contextual-screen-ids would output contextual ids rather than the "permanent" ones that my Mac keeps switching.

Poking around I also found the undocumented commands:
displayplacer --version
displayplacer --help
Shouldn't they be in the Readme? The instructions are very brief in the Readme. Not sure what to do to get some traction on this. Sorry if this issue sounds is a bit vague but I'm really not clear on what to do.

@twocs
Copy link
Author

twocs commented Mar 24, 2022

Got a lead via this line:

In some rare cases, you may need to use contextual screen ids since the modes list changes when macOS switches GPUs

Took some time to figure out just how would you do that? Contextual screen id does not seem to be acceptable.

displayplacer "id:2 origin(-1920,0)" "id:3 origin(0,0)"

zsh: segmentation fault displayplacer "id:2 origin(-1920,0)" "id:3 origin(0,0)"

Finally I figured out it could be done like:
displayplacer "id:2 res:1920x1080 hz:75 color_depth:8 scaling:off origin:(0,0) degree:0" "id:3 res:1920x1080 hz:75 color_depth:8 scaling:off origin:(-1920,0) degree:0"
displayplacer "id:3 res:1920x1080 hz:75 color_depth:8 scaling:off origin:(0,0) degree:0" "id:2 res:1920x1080 hz:75 color_depth:8 scaling:off origin:(-1920,0) degree:0"

Apparently the res, scaling, and degree are all mandatory (even though I have no desire to change them) because this cannot work:
displayplacer "id:2 origin:(0,0)" "id:3 origin:(-1920,0)"

Interestingly I can leave a whole monitor out of the command and it works fine. Just don't forget to every time degree:0.

@westito
Copy link

westito commented Mar 27, 2022

I have the same issue. Two monitors with external dual HDMI switch. With Intel Mac the two screens always swapped, but with stored displayplacer command I could restore. But then I switched to the M1 MacBook 16 things get more strange. The screens swapped as well, BUT the display IDs swapped too!! So, when I saved the displayplacer command, it doesn't worked next time. So I have two Automator script "MonitorSet1" and "MonitorSet2". A always runs alternately. If I used "MonitorSet1" the last time, I have to run "MonitorSet2" next time, and so on. Very strange, but works. With Spotlight search I can run those very quick.

@twocs
Copy link
Author

twocs commented Mar 28, 2022

I have the same issue. Two monitors with external dual HDMI switch. With Intel Mac the two screens always swapped, but with stored displayplacer command I could restore. But then I switched to the M1 MacBook 16 things get more strange. The screens swapped as well, BUT the display IDs swapped too!! So, when I saved the displayplacer command, it doesn't worked next time. So I have two Automator script "MonitorSet1" and "MonitorSet2". A always runs alternately. If I used "MonitorSet1" the last time, I have to run "MonitorSet2" next time, and so on. Very strange, but works. With Spotlight search I can run those very quick.

Yes, that's what's happening to me. The monitors are the same, also on the M1 MacBook 16, but the IDs swap around from monitor to monitor. One monitor will be CCE4 and the sefond is 11AC, but on wake the other monitor is CCE4 and the first monitor is 11AC. I'm sure you know which set to switch to by now, but you can also make the two into a single Automator script to swap two monitors by id like this (note: use your own IDs, not mine).
id1=CCE46CDB-1FC0-45E0-BFE9-D240990808ED && id2=11AC0330-F896-4084-A952-9A27AE3D72D6 && displayplacer list | tail -n1 | sed "s/$id1/\n/g;s/$id2/$id1/g;s/\n/$id2/g;s/displayplacer//" | xargs displayplacer

@westito
Copy link

westito commented Mar 30, 2022

I have the same issue. Two monitors with external dual HDMI switch. With Intel Mac the two screens always swapped, but with stored displayplacer command I could restore. But then I switched to the M1 MacBook 16 things get more strange. The screens swapped as well, BUT the display IDs swapped too!! So, when I saved the displayplacer command, it doesn't worked next time. So I have two Automator script "MonitorSet1" and "MonitorSet2". A always runs alternately. If I used "MonitorSet1" the last time, I have to run "MonitorSet2" next time, and so on. Very strange, but works. With Spotlight search I can run those very quick.

Yes, that's what's happening to me. The monitors are the same, also on the M1 MacBook 16, but the IDs swap around from monitor to monitor. One monitor will be CCE4 and the sefond is 11AC, but on wake the other monitor is CCE4 and the first monitor is 11AC. I'm sure you know which set to switch to by now, but you can also make the two into a single Automator script to swap two monitors by id like this (note: use your own IDs, not mine). id1=CCE46CDB-1FC0-45E0-BFE9-D240990808ED && id2=11AC0330-F896-4084-A952-9A27AE3D72D6 && displayplacer list | tail -n1 | sed "s/$id1/\n/g;s/$id2/$id1/g;s/\n/$id2/g;s/displayplacer//" | xargs displayplacer

Genius! Thank you

@ByScripts
Copy link

ByScripts commented May 5, 2022

Same case here. I have 2 identical external displays with their ID swapping randomly.

A swap command would indeed be appreciated :)

Thank you @twocs

BTW: I'm using fish shell. Here is the command I use:

begin; set -l ID1 "<first id>"; set -l ID2 "<second id>"; displayplacer list | tail -n1 | sed "s/$ID1/\n/g;s/$ID2/$ID1/g;s/\n/$ID2/g;s/displayplacer//" | xargs displayplacer; end

@PopsicleStyx
Copy link

PopsicleStyx commented Aug 28, 2022

I am not a coder and none of this stuff makes much sense. I have the same problem many of you have stated. M1 chip, 2 monitors that dont remember the arrangement, background color or screen saver after reboot, log out and sleep. I have not installed displayplacer I am hoping someone experienced can reach out and kindly guide me through it. thanks so much.

Popsi
twitch.tv.popsiclestyx@gmail.com
discord PopsicleStyx #5838

@alxw
Copy link

alxw commented Sep 9, 2022

Here's my workaround to swap position of two displays set to the same resolution (so if you have 3 displays, like a laptop built-in and 2 external, it won't swap an external with the laptop, unless they are set to the same resolution, in which case you will need additional regex customization):
Setup:

echo "displayplacer list | tail -n1 | sed 's/displayplacer //;s/id:\(.\{36\}\) res:\([0-9x]\{7,9\}\) \(.*\)id:\(.\{36\}\) res:\2/id:\4 res:\2 \3id:\1 res:\2/g' | xargs displayplacer" > swap_display.sh
chmod +x swap_display.sh

Execution:

./swap_display.sh

Works for me on an M1 Max running macOS 12.5.1 and displayplacer v1.2.0. Best of luck!

@eugeneromero
Copy link

I repurposed @alxw's command and turned it into a global shortcut, so that it's just a keypress away whenever I need it. Here's some instructions:

Create a new Shortcut in the Shortcuts app, of type "Run Shell Script", which should run this command:

/opt/homebrew/bin/displayplacer list | tail -n1 | sed 's/displayplacer //;s/id:\(.\{36\}\) res:\([0-9x]\{7,9\}\) \(.*\)id:\(.\{36\}\) res:\2/id:\4 res:\2 \3id:\1 res:\2/g' | xargs /opt/homebrew/bin/displayplacer

Leave all other options as they are. The shortcut should look like this:

image

Then, under the Settings (top right corner), check "Use as Quick Action" and "Services Menu":
image

Finally, close the Shortcut window and in the main window, rename the Shortcut to "Swap Displays":
image

Now, open System Preferences from the Apple logo on the top left corner, and go to Keyboard > Shortcuts > App Shortcuts. Press the + button to add a new shortcut, name it the exact same thing you named the Shortcut, and give it a key combination (in my case, I chose Control+Command+S).

image

Once you save it, you can now press Ctrl+Cmd+S to swap the positions of your two identical external screens.

As @alxw mentioned, if your setup is not two identical screens + the laptop display, you might have to play around with the displayplacer command, to customize it to your needs.

Hope this helps, at least until Apple decides to fix this most annoying of bugs.

@jakehilborn
Copy link
Owner

@twocs @westito @ByScripts @PopsicleStyx @alxw @eugeneromero displayplacer v1.4.0 supports addressing screens by serial id. If all of the screens in your setup have unique serial ids, this should fix the id switching issue.

Could you try out the new version and let me know if it works on your setup?

@PopsicleStyx
Copy link

PopsicleStyx commented Jun 11, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants