Thursday, November 21, 2024

applescript – Is it possible to change display resolution with a keyboard shortcut in Sonoma?

Is it possible to change display resolution with a keyboard shortcut in Sonoma? The answer to the same question for pre-Sonoma no longer works. I’m seeking to accomplish this as a pure Apple solution without installing any third-party programs.

Note: I have amended this at the end of the original post to report progress I have made based on the suggested answers, a keystroke script and using default write. I don’t have a working solution yet, but wanted to document my steps and progress in case it leads anyone to a working answer.

Details follow:

Is it possible to change display resolution with a keyboard shortcut? provides the following script to accomplish the question as of whatever operating system was in effect 8 years ago:

tell application "System Settings"
    reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
end tell
tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
    click radio button "Scaled" of radio group 1 of tab group 1
    click radio button 4 of radio group 1 of group 1 of tab group 1
end tell
quit application "System Settings"

However, Apple has since overhauled System Settings and running that code now gets the error:

error “System Settings got an error: Can’t get pane “com.apple.preference.displays”.” number -1728 from pane “com.apple.preference.displays”

Could someone please provide an updated script or point me to documentation on how to interact with Sonoma system settings via AppleScript?

I would like to be able to set my single 4K display to Larger text (for everything except watching 4K videos) and to More space (for watching 4K videos) using a keystroke (one for each, not looking for a toggle).

I tried starting to build a script but can’t get past opening the pane:

tell application "System Settings"
    reveal pane "Displays"
end tell

gets the error:

missing value

I would also be open to a script in the form:

do shell script "[code to set the preference]"

Update 7/31/24:

I’ve gotten partway there. I can accomplish this within AppleScript Editor but not saved as either a script or an app.

Details follow:

These are my edits to @ciegeven’s code which worked with my other settings. I suspect (but don’t know) the relevant setting might be under Keyboards, I have Keyboard Navigation turned on.

However, it only works when I have the script open for editing in AppleScript Editor and run it from there. If I save it as a script in the Library’s Script folder, it opens System Settings but doesn’t do any of the keypresses. If I save it as an app, I have to authorize it to communicate with System Events, but then I get the error that it isn’t allowed to send keypresses.

Having to open the scripts and run it from the script editor each time is no time savings from just going in and changing the system settings manually.

Anyway, here is my code for setting resolution to Larger Text, my usual setting.

tell application "System Settings"
    activate
end tell

delay 1 -- Wait for System Settings to open

tell application "System Events"
    tell process "System Settings"
        -- Use Command+F to open the search field
        keystroke "f" using {command down}
        delay 0.5
        
        -- Type "Displays" in the search field
        keystroke "Displays"
        delay 1
        
        -- Press Return to select the first search result (should be Displays)
        key code 36 -- Return key
        delay 1
        
        -- Press Tab to move to the resolution options
        key code 48 -- Tab key
        delay 1
        
        -- Press space bar
        key code 49 -- space bar to accept Larger Text
        delay 2

       -- Additional 4K code goes here
        
        -- Use Command+Q to close System Settings
        keystroke "q" using {command down}
    end tell
end tell

and here is my additional 4K code which I inserted in the 4K script:

-- Press Tab 4 x to move to the last resolution
        key code 48 -- Tab key
        delay 1
        key code 48 -- Tab key
        delay 1
        key code 48 -- Tab key
        delay 1
        key code 48 -- Tab key
        delay 1

Update 7/31/24 8:30 pm PST:

Also, based on the suggestion of @hym3242, I tried finding the preference setting.

Steps:

  1. I looked to see what plists were getting updated when I switch back and forth between Larger Text and More Space. While it appears several plists get updated on a regular basis anyway, it looked like /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist was a likely candidate.

  2. I issued the command:

defaults read /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist > /Users/[userID]/Documents/Preferences/2k.txt
  1. I changed the preference in System Settings > Display to More Space.

  2. I waited a minute in case updating the file was a cron job and not instantaneous.

  3. I issued the command:

defaults read /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist > /Users/[userID]/Documents/Preferences/4k.txt
  1. I compared the two files.

And I think I found the preference. The only difference between the two files was:

In the 2k file:

 "NSWindow Frame main" = "304 54 715 999 0 0 1920 1055 ";

and in the 4k file:

"NSWindow Frame main" = "788 1095 715 999 0 0 3840 2135 "

where 1920 1055 and 3840 2135 are the respective resolutions for Larger Text and More Space on my 4K monitor.

  1. However, when I then tried (while in Larger Text display resolution) the terminal command:
defaults write /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist "NSWindow Frame main" "788 1095 715 999 0 0 3840 2135 "

nothing happened.

So this might well be the preference, but something additional has to happen for it to take.

So the candidate AppleScript Larger Text code at this point is:

do shell script "defaults write /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist 'NSWindow Frame main' '788 1095 715 999 0 0 3840 2135 '"

and the candidate 4K code is:

do shell script "defaults write /Users/[userID]/Library/Preferences/com.apple.systempreferences.plist 'NSWindow Frame main' '788 1095 715 999 0 0 3840 2135 '"

and if I save them as run-only apps, they do update the plist correctly.

But the screen resolution doesn’t change in response to updating the plist.

I’m guessing there’s a process I need to kill, but I have no idea how I would find a name for the process so I can kill it from the script.

configd, the configuration daemon, looked like a good candidate but when I tried to quit it in Activity Monitor to test whether the resolution would switch on relaunch, I got a warning that it’s owned by root and that if I quit it my Mac might not operate correctly. So I canceled.

Even if it’s safe to quit, my script would have to be able to respond to the dialog.

Further, if my resolution is 1920 x 1055 (Larger Text) and I set “NSWindow Frame main” to “788 1095 715 999 0 0 3840 2135” and then log out and log back in, it gets set back to “304 54 715 999 0 0 1920 1055”. And there are over 400 preferences having the string “1920 1055”, although this is the only one that changes immediately when I change from Larger Text to More Space in System Settings.

**Update 8/1/24 **

And apparently it’s safe to kill configd via sudo kill configd, but:

  • Since I’m not using my admin account for by day-to-day use (and wouldn’t want to use it for viewing 4K videos), I can’t kill it from the terminal
  • While I can kill it from Activity Monitor, I have to enter my admin name and password, which would take away from the convenience of a keyboard shortcut, and
  • Worst of all, killing and relaunching configd doesn’t cause the resolution to change to agree with the value of “NSWindow Frame main”

Related Articles

Latest Articles