15

How can I create a keyboard shortcut that flips my screen upside down?

I know how to enable this setting in System Preferences but I want to be able to bind it to a shortcut.

Is it possible to make the same keyboard shortcut revert the display back to normal orientation?

enter image description here

7
  • Just an FYI, I have built out a macOS 10.13.3 system and tested the example AppleScript code and it works as is on my system. You can reread my updated answer and see if you can get it to work on your system. If by chance it doesn't, then you need to add a screen shot of System Preferences > Displays > Display so I can at least see what the difference between your system and mine is. Mar 23, 2018 at 3:34
  • Well it's quite obvious why the script is not working for you as there is no "Rotation:" pop up button on the Display tab shown in the image you just added to the OP. So according to the image you added, rotating the Display is not an available option for you! That said, if you have the ability to rotate the Display you'll need to add the particulars of you hardware configuration and how you are actually rotating the Display. Otherwise there is not enough information to provide an alternative answer then the one I have which works by default in macOS for me as I have stated. Mar 24, 2018 at 14:13
  • @user3439894 I can cmd+alt click on the display option and it shows me rotation options
    – minseong
    Mar 24, 2018 at 14:17
  • I thought that was normal for everyone, I've never heard of anyone being shown it without cmd alt clicking
    – minseong
    Mar 24, 2018 at 14:17
  • Well for me it shows automatically, probably because I'm using a Thunderbolt display. Let me do some testing an I'll get back to you. Mar 24, 2018 at 14:24

6 Answers 6

7

I wrote a program named displayplacer that makes this easy to do via a terminal command. You could bind this to a keyboard shortcut with a program like BetterTouchTool or maybe Automator. Works with all macOS versions above 10.6.

Example to flip 180: displayplacer 'id:123467890 res:1920x1200 scaling:off origin:(0,0) degree:180'

Example to flip 0: displayplacer 'id:123467890 res:1920x1200 scaling:off origin:(0,0) degree:0'

4
  • 1
    what's id for?
    – minseong
    Apr 1, 2019 at 22:00
  • 2
    Each display has a unique ID. For example, if you have 2 monitors you'll specify that one gets rotated and the other does not. Note, displayplacer currently doesn't work well when you specify for the changes for less than all monitors plugged in. I'll be enhancing this soon. I recommend downloading the latest displayplacer binary from the repo (not the releases tab) and executing displayplacer list. At the bottom of the output you'll see your current "profile" which represents how your monitors are currently laid out. Edit this to your liking. Apr 2, 2019 at 23:36
  • Glad to hear my answer helped! Upon viewing this page it is now the first answer shown. Apr 3, 2019 at 0:57
  • 3
    This is an awesome piece of software that is able to store fully specified configuration in a command line invocation. It helpfully suggest the command to replicate the current settings (use displayplayer list). You had me at "Essentially XRandR for macOS." :-)
    – dirkjot
    Jan 23, 2020 at 17:18
14

The following has been tested under macOS Sierra 10.12.5 and macOS High Sierra 10.13.3, and works without any issue on my system.

Using the example AppleScript code, from my original answer, saved as an AppleScript application named Flip Display 180° and added to System Preferences > Security & Privacy > Privacy > Accessibility, so as to allow it to process the code, I then used an Automator service workflow, also named Flip Display 180°, to open the AppleScript application of the same name, while assigning the following keyboard shortcut: ⇧⌃⌘R

  • Note that the keyboard shortcut ⇧⌃⌘F, which worked under OS X 10.8.5, conflicted with a system default keyboard shortcut under macOS 10.12.5, macOS 10.13.3 and why I changed it. You may have to use a different keyboard shortcut and as usual you have to choose one that isn't already assigned in any application that has focus when pressed to activate this Automator service workflow.

  • I also ran the following command, in Terminal, so as not to show the Dock Tile for the AppleScript application on the Dock:

      defaults write '/Applications/Flip Display 180°.app/Contents/Info.plist' LSUIElement -bool yes
    

That said, if the UI for Displays in System Preferences in macOS High Sierra on your system different for some undisclosed reason then the example AppleScript code will need to be modified to accommodate the the differences between what works on my system and yours. If it does need to be modified, I'd imagine it wouldn't be that hard to figure out.


The following images show the relevant details:

System Preferences > Displays > Display, as shown on my system:

enter image description here

AppleScript application, named Flip Display 180°:

enter image description here

Automator service workflow, also named Flip Display 180°:

Code: open -a 'Flip Display 180°'

enter image description here

System Preferences > Security & Privacy > Privacy > Accessibility:

enter image description here

System Preferences > Keyboard > Shortcuts > Services > General > Flip Display 180°

enter image description here


For the time being I'm leaving my original answer at the bottom portion of this answer as it does work as stated under OS X 10.8.6 and may be beneficial for other users.

Original Answer:

I know you are using macOS High Sierra and maybe you can use what works for me under OS X 10.8.6.

The following example AppleScript code used in a Run AppleScript action in an Automator service workflow flips the Display 180° when I press: ⇧⌃⌘F

if running of application "System Preferences" then
    quit application "System Preferences"
    delay 1
end if

tell application "System Preferences"
    reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
    delay 1
    tell application "System Events"
        tell pop up button "Rotation:" of tab group 1 of window 1 of application process "System Preferences"
            if (value) contains "Standard" then
                click
                click menu item "180°" of menu 1
                my clickConfirmButton()
            else
                click
                click menu item "Standard" of menu 1
            end if
        end tell
    end tell
    quit
end tell

on clickConfirmButton()
    set wasClicked to false
    repeat until wasClicked
        delay 0.5
        tell application "System Events"
            try
                click button "Confirm" of sheet 1 of window 1 of application process "System Preferences"
                set wasClicked to true
            end try
        end tell
    end repeat
end clickConfirmButton
  • Note that the value of the delay commands may need to be adjusted for your system, and or additional delay commands may or may not be needed. Adjust values of and or add/remove the delay commands as appropriate.

Note: The example AppleScript code is just that and does not employ any other error handling then what's shown and is meant only to show one of many ways to accomplish a task. The onus is always upon the User to add/use appropriate error handling as needed/wanted.


Automator service workflow:

enter image description here

2
  • Your script still doesn't work for me, "System Events got an error: Can’t get pop up button \"Rotation:\" of tab group 1 of window 1 of application process \"System Preferences\"."
    – minseong
    Mar 24, 2018 at 14:01
  • Thank you, the script works wonder! I pasted it in Better Touch Tool to trigger it with a trackpad gesture.
    – Louis CAD
    Jan 24, 2019 at 21:51
2

This script has tested on macos 10.14 for Chinese users.

If you're using other language, please modify the button name to your language.

In script "LG Ultra HD" means your monitor's name, this is useful if you have more than 2 monitors, otherwise, you can replace (first window whose name is "LG Ultra HD") by window 1

if running of application "System Preferences" then
    quit application "System Preferences"
    delay 1
end if

tell application "System Preferences"
    reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
    delay 1
    tell application "System Events"
        tell pop up button "旋转:" of tab group 1 of (first window whose name is "LG Ultra HD") of application process "System Preferences"
            if (value) contains "标准" then
                click
                click menu item "270°" of menu 1
                my clickConfirmButton()
            else
                click
                click menu item "标准" of menu 1
            end if
        end tell
    end tell
    quit
end tell

on clickConfirmButton()
    set wasClicked to false
    set i to 10
    repeat until wasClicked or i ≤ 0
        delay 0.5
        tell application "System Events"
            try
                click button "确认" of sheet 1 of (first window whose name is "LG Ultra HD") of application process "System Preferences"
                set wasClicked to true
            end try
        end tell
        set i to i - 1
    end repeat
end clickConfirmButton
2
  • 1
    Could you provide a hint what those buttons mean in English? (You could create an additional account on your Mac, select English as main language and check what the button text is in English). It would make your answer much more useful.
    – jaume
    Aug 21, 2018 at 18:00
  • 2
    "旋转" means "Rotation" "标准" means "Standard" "确认" means "Confirm"
    – Vxider
    Aug 23, 2018 at 1:48
2

I have taken user3439894's solution and modified it a bit.

The following script is a massive hack, but the general idea is sometimes the rotation tab is window 1 and sometimes it is window 2. To solve this I used a try catch block that will just try the first one and if it errors it will also try the second one. Feel free to improve this script, but I just wanted something that works.

if running of application "System Preferences" then
    quit application "System Preferences"
    delay 1
end if

tell application "System Preferences"
    reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
    delay 1
    tell application "System Events"
        try
            tell pop up button "Rotation:" of tab group 1 of window 2 of application process "System Preferences"
                if (value) contains "Standard" then
                    click
                    click menu item "270°" of menu 1
                    my clickConfirmButton()
                else
                    click
                    click menu item "Standard" of menu 1
                end if
            end tell
        on error errMsg
            tell pop up button "Rotation:" of tab group 1 of window 1 of application process "System Preferences"
                if (value) contains "Standard" then
                    click
                    click menu item "270°" of menu 1
                    my clickConfirmButton()
                else
                    click
                    click menu item "Standard" of menu 1
                end if
            end tell
        end try
    end tell
    quit
end tell

on clickConfirmButton()
    set wasClicked to false
    repeat until wasClicked
        delay 0.5
        tell application "System Events"
            try
                click button "Confirm" of sheet 1 of window 1 of application process "System Preferences"
                set wasClicked to true
            end try
        end tell
    end repeat
end clickConfirmButton

Cheers for doing 99% of the work user3439894

1

Tested on macOS 11.3 Big Sur.

Based on @Vxider's solution, with menu items translated to English.

You'll need to change both occurrences of "LG HDR 4K" to match the name of your monitor, as presented in the System Preferences window:

enter image description here

if running of application "System Preferences" then
  quit application "System Preferences"
  delay 1
end if

tell application "System Preferences"
  reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
  delay 1
  tell application "System Events"
    tell pop up button "Rotation:" of tab group 1 of (first window whose name is "LG HDR 4K") of application process "System Preferences"
      if (value) contains "Standard" then
        click
        click menu item "90°" of menu 1
        my clickConfirmButton()
      else
        click
        click menu item "Standard" of menu 1
      end if
    end tell
  end tell
  quit
end tell

on clickConfirmButton()
  set wasClicked to false
  set i to 10
  repeat until wasClicked or i ≤ 0
    delay 0.5
    tell application "System Events"
      try
        click button "Confirm" of sheet 1 of (first window whose name is "LG HDR 4K") of application process "System Preferences"
        set wasClicked to true
      end try
    end tell
    set i to i - 1
  end repeat
end clickConfirmButton
0

Based on previous solutions, I adapted the script to macOS Monterey. It works fine with my macOS 12.3.1. Enjoy it.

if running of application "System Preferences" then
    quit application "System Preferences"
    delay 1
end if

tell application "System Preferences"
    activate
    reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
    delay 1
    (*set current pane to pane id "com.apple.preference.displays"*)
    delay 1
    tell application "System Events"
        tell pop up button "Rotation:" of group 1 of window 1 of application process "System Preferences"
            if (value) contains "90°" then
                delay 1
                click
                click menu item "Standard" of menu 1
                delay 3
                display notification "Rotated to Landscape mode"
                
                (*my clickConfirmButton()*)
            else
                delay 1
                click
                click menu item "90°" of menu 1
                delay 5
                display notification "Rotated to Portrait mode"
                my clickConfirmButton()
                delay 2
            end if
        end tell
    end tell
    quit application "System Preferences"
end tell


on clickConfirmButton()
    set wasClicked to false
    set i to 10
    repeat until wasClicked or i ≤ 0
        delay 0.5
        tell application "System Events"
            try
                click button "Confirm" of sheet 1 of (first window whose name is "Displays") of application process "System Preferences"
                set wasClicked to true
            end try
        end tell
        set i to i - 1
    end repeat
end clickConfirmButton

You must log in to answer this question.

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