0

To activate Switch Control in Settings, I click the checkbox located in Accessibility -> Switch Control -> Enable Switch Control (at least in Catalina). If I want a program to open Switch Control and automate that process, I have to navigate through the System Preferences app (which I could do with AppleScript). It would be nice if there were a command I could run in the terminal to directly open the Switch Control Panel application. I couldn't find one in my research.

What I tried:

I followed the instructions in this answer. If it had worked as I wanted it to, I could have changed the "Switch Control" setting by editing its corresponding .plist file (sudo defaults write). When I tried this approach with the example provided in the answer (changing "Display Login Window as:" from "List of users" to "Name and password") it worked well. It didn't work when I tested it by changing the "Enable Switch Control" setting.

Following the instructions, I made a copy of the preferences folder and the enclosed plist setting files:

$ sudo cp -r /Library/Preferences before

After changing the Switch Control setting and exiting System Preferences, I made a new copy:

$ sudo cp -r /Library/Preferences after

Next, to see which files changed, I tried:

$ sudo diff -ur before after

which doesn't return any "Binary files differ" messages.

I then tried to use the Activity Monitor to find out what programs run when "Enable Switch Control" is on. I found a running application named Assistive Control (AssistiveControl in Activity Monitor).

I ran $ ps aux and I found this under the COMMAND column:

/System/Library/Input Methods/Assistive Control.app/Contents/MacOS/Assistive Control launchd -s

When I try running the command with Switch Control off in System Preferences, it doesn't do anything. When I try the command when Switch Control is on, I get this error: invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.

How can I use the command line to activate Switch Control?

It would be great if someone could help me out or give me suggestions.

2 Answers 2

0

Are you sure that the Accessibility prefs are stored in /Library, and not ~/Library (the user library)?

When I want to discover a plist key, I usually make the change in System Preferences, then sort the user Preferences folder by Modification Date. That narrows the list down to a few files, which hopefully are named usefully.

Testing with Switch control, I notice that a few relevant plists get changed:

com.apple.universalaccess.plist
com.apple.Accessibility.plist
com.apple.HIToolbox.plist
com.apple.AssistiveControl.switch.plist

However, I'm not sure what exactly gets changed, and it may be more than one thing.

0

Here is a way from the command line in, e.g., Terminal to turn on Switch Control using a shell script using AppleScript with UI Scripting to programmatically click the Enable Switch Control checkbox in: System Preferences > Accessibility > Switch Control

The example AppleScript code, shown below, was tested in Script Editor and as an executable shell script in Terminal under macOS Catalina with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.

  • 1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.

Note that the coding in this shell script assumes that Switch Control has once previously been turned on manually so as to answer the initial System Preferences is trying to unlock Accessibility preferences dialog box where you have entered your User Name and Password then clicked the Unlock button.

After setting up the shell script, and addressing settings mentioned above1, it will then be as simple as typing, e.g., esc in, e.g., Terminal to open Switch Control.

It Terminal, type the following compound command and then press enter:

f="esc"; touch "$f"; open -e "$f"; chmod +x "$f"

Copy and paste the example AppleScript code, shown below, into the opened esc document, (named for [E]nable [S]witch [C]ontrol), then save it and close the document.

You should then move the esc executable shell script to a directory that is listed within the PATH passed to the shell. I have mine in /usr/local/bin/.



Example AppleScript code:

#!/usr/bin/osascript

--  # Check to see if System Preferences is 
--  # running and if yes, then close it.
--  # 
--  # This is done so the script will not fail 
--  # if it is running and a modal sheet is 
--  # showing, hence the use of 'killall' 
--  # as 'quit' fails when done so, if it is.
--  #
--  # This is also done to allow default behaviors
--  # to be predictable from a clean occurrence.

if running of application "System Preferences" then
    try
        tell application "System Preferences" to quit
    on error
        do shell script "killall 'System Preferences'"
    end try
    delay 0.1
end if

--  # Make sure System Preferences is not running before
--  # opening it again. Otherwise there can be an issue
--  # when trying to reopen it while it's actually closing.

repeat while running of application "System Preferences" is true
    delay 0.1
end repeat

--  # Open System Preferences to the Accessibility pane.

tell application "System Preferences" to ¬
    reveal pane id "com.apple.preference.universalaccess"

--  # Use System Events to achieve the goal.

tell application "System Events"
    tell window 1 of application process "System Preferences"
        
        --  # Wait for target pane to be available.
        --  # The target in this case has a checkbox.
        
        my waitForUIelement(checkbox 1)
        
        --  # Ascertain the target row to select.
        
        set rowSwitchControl to the first row of ¬
            table 1 of scroll area 1 whose value of ¬
            static text 1 of UI element 1 is ¬
            "Switch Control"
        
        --  # Select the target row.
        
        select rowSwitchControl
        
        --  # Wait for target checkbox to be available.
        
        my waitForUIelement(checkbox 1 of tab group 1 of group 1)
        
        --  # Click the Enable Switch Control checkbox.
        
        click checkbox 1 of tab group 1 of group 1
        
    end tell
end tell

delay 0.02

quit application "System Preferences"


--  ## Handler(s) ##

on waitForUIelement(uiElement)
    tell application "System Events"
        tell window 1 of application process ¬
            "System Preferences"
            set i to 0
            repeat until exists uiElement
                delay 0.1
                set i to i + 1
                if i ≥ 30 then return
            end repeat
        end tell
    end tell
end waitForUIelement

Notes:

The example AppleScript code will click the target checkbox to enable Switch Control, however, as coded it does not show the UI when System Preferences is opened to do so. As a result, it will not uncheck the checkbox to disable Switch Control. That will need to be done my manually closing Switch Control.

The example AppleScript code can be modified to uncheck the checkbox to disable Switch Control, however, this will necessitate showing the UI of System Preferences. If you need it to do both and you do not mind seeing System Preferences flash on the screen for a second or two, then use the example AppleScript code show below these notes.

That said, regardless, one will see the Dock Tile bounce once in the Dock when the shell script is run and this cannot be avoided.

While this can achieve the goal of enabling Switch Control from the command line, nonetheless, UI Scripting scripting can be kludgy and prone to failure as the hierarchical UI element structure changes with updates to the OS or applications involved. In other words, what works in, e.g., macOS Catalina may need to be tweaked for use in, e.g., macOS Big Sur.



Update to toggle the state of the Enable Switch Control checkbox.

Example AppleScript code:

#!/usr/bin/osascript

--  # Check to see if System Preferences is 
--  # running and if yes, then close it.
--  # 
--  # This is done so the script will not fail 
--  # if it is running and a modal sheet is 
--  # showing, hence the use of 'killall' 
--  # as 'quit' fails when done so, if it is.
--  #
--  # This is also done to allow default behaviors
--  # to be predictable from a clean occurrence.

if running of application "System Preferences" then
    try
        tell application "System Preferences" to quit
    on error
        do shell script "killall 'System Preferences'"
    end try
    delay 0.1
end if

--  # Make sure System Preferences is not running before
--  # opening it again. Otherwise there can be an issue
--  # when trying to reopen it while it's actually closing.

repeat while running of application "System Preferences" is true
    delay 0.1
end repeat

--  # Open System Preferences to the Accessibility pane.

tell application "System Preferences" to ¬
    reveal pane id "com.apple.preference.universalaccess"

tell application "System Preferences" to activate

--  # Use System Events to achive the goal.

tell application "System Events"
    tell window 1 of application process "System Preferences"
        
        --  # Wait for target pane to be available.
        --  # The target in this case has a checkbox.
        
        my waitForUIelement(checkbox 1)
        
        --  # Ascertain the target row to select.
        
        set rowSwitchControl to the first row of ¬
            table 1 of scroll area 1 whose value of ¬
            static text 1 of UI element 1 is ¬
            "Switch Control"
        
        --  # Select the target row.
        
        select rowSwitchControl
        
        --  # Wait for target checkbox to be available.
        
        my waitForUIelement(checkbox 1 of tab group 1 of group 1)
        
        --  # Check to see if the Enable Switch Control
        --  # checkbox is checked, and if it is, then
        --  # uncheck it. Otherwise check it.       
        
        if the value of checkbox 1 of tab group 1 of group 1 is 1 then
            
            --  # The Enable Switch Control checkbox is checked.
            --  # Click the Enable Switch Control checkbox.
            
            click checkbox 1 of tab group 1 of group 1
            
            --  # Wait for OK button to be available.
            
            my waitForUIelement(button 1 of sheet 1)
            
            --  # Click the OK button..
            
            click button "OK" of sheet 1
            
        else
            --  # The Enable Switch Control checkbox is not checked.
            --  # Click the Enable Switch Control checkbox.
            
            click checkbox 1 of tab group 1 of group 1
        end if
        
    end tell
end tell

delay 0.02

quit application "System Preferences"


--  ## Handler(s) ##

on waitForUIelement(uiElement)
    tell application "System Events"
        tell window 1 of application process ¬
            "System Preferences"
            set i to 0
            repeat until exists uiElement
                delay 0.1
                set i to i + 1
                if i ≥ 30 then return
            end repeat
        end tell
    end tell
end waitForUIelement


Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

You must log in to answer this question.

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