How to disable or enable keyboard input source

keyboardshortcut

I am using macOS Catalina v10.15.7. I am using Control+Space to select text in emacs. In order to achieve I am deselecting Select the previous input source and Select the next source Input menu.

=> Settings => Keyboard => Shortcuts => Input Sources
[ ] Select the previous input source  # deselected
[ ] Select next source in input menu  # deseleced

So when I press Contol+Space not it does not open open Input Source window.

In some cases I believe if macOS crashed or if I force macOS to shutdown by pressing the power button, after opening macOS and when I press control+space it is bound to Input Source even if (Select the previous input source Select next source in input menu) are deselected under the setting.

Is it possible to change input sources's setting using a script in startup as

  • First select Select the previous input source and Select next source in input menu

  • Then deselect Select the previous input source and *Select next source in input menu


=> Settings => Keyboard => Shortcuts => Input Sources
[X] Select the previous input source  # selected
[X] Select next source in input menu  # selected

then 

[ ] Select the previous input source  # deselected
[ ] Select next source in input menu  # deseleced

  • I am using Control+Space constantly mark/unmark text in emacs, which is the default keybinding.
C-SPC Set the mark at point, and activate it (set-mark-command).

Best Answer

The example AppleScript code, show further below, was tested under macOS Catalina with Language & Region settings in System Preferences set to English/English (US) — Primary and Input Sources in System Preferences > Keyboard set to U.S.. It was tested in Script Editor as a script and tested saved as an application and added to Login Items in System Preferences > Users & Groups for the target User.

For testing purpose as an application, I saved it as Uncheck Input Sources add added it to System Preferences > Security & Privacy > Privacy > Accessibility. After which the first time I ran it manually, to see that it worked, I was asked...

  • "Uncheck Input Sources" wants access to control "System Events". Allowing control will provide access to documents and data in "System Events" and to perform actions within that app. This script needs to control other applications to run.

    Don't Allow      OK

To which I clicked: OK

I then tested it, rebooting the system a couple times and it appeared to work without issue.

NOTE: This uses UI Scripting and System Events to toggle the target checkboxes in System Preferences > Keyboard > Shortcuts > Input Sources and it is done so without showing the UI of System Preferences, however, it still has to open it and do its thing. Keep this in mind when logging in, and allow the process to complete before doing anything else. It should only take a few seconds. (Such is the nature of UI Scripting.)


Example AppleScript code:

--  # 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 is actually closing.

set i to 0
repeat while (running of ¬
    application "System Preferences") is true ¬
    or (i is equal to 20)
    delay 0.1
    set i to i + 1
end repeat
if i is equal to 20 then return

--  # Open System Preferences to the 
--  # Shortcuts tab of the Keyboard pane.

tell application "System Preferences" to ¬
    reveal anchor "shortcutsTab" of ¬
        pane id "com.apple.preference.keyboard"

--  # System Events does the navigating around the 
--  # Shortcuts tab of the Keyboard pane and toggles
--  # the state of the target keyboard shortcut
--  # checkbox so it is left unchecked.

tell application "System Events"
    
    --  # Make sure the UI is ready to be navigated.
    --  # Checks for the 'Use keyboard navigation 
    --  # to move focus between controls' checkbox.
    
    set i to 0
    repeat until (exists checkbox 1 of ¬
        tab group 1 of ¬
        window 1 of ¬
        process "System Preferences") ¬
        or (i is equal to 40)
        delay 0.05
        set i to i + 1
    end repeat
    if i is equal to 40 then return
    
    --  # Make sure 'Input Sources' exists in the
    --  # left hand pane, and if not exit the script.
    
    if not (exists (every row of ¬
        table 1 of ¬
        scroll area 1 of ¬
        splitter group 1 of ¬
        tab group 1 of ¬
        window 1 of ¬
        process "System Preferences" whose ¬
        value of static text 1 is "Input Sources")) ¬
        then return
    
    --  # Select 'Input Sources' in the left hand pane.
    --  # This is wrapped in a try statement to get
    --  # past a bug in how the select command is
    --  # interpreted and is silently eaten.
    
    try
        select (every row of ¬
            table 1 of ¬
            scroll area 1 of ¬
            splitter group 1 of ¬
            tab group 1 of ¬
            window 1 of ¬
            process "System Preferences" whose ¬
            value of static text 1 is "Input Sources")
    end try
    
    --  # make sure the target checkbox
    --  # is available before proceeding
    --  # Checks for the 'Select the  
    --  # previous input source' checkbox.
    
    set i to 0
    repeat until (exists checkbox 1 of ¬
        UI element 1 of ¬
        row 1 of ¬
        outline 1 of ¬
        scroll area 2 of ¬
        splitter group 1 of ¬
        tab group 1 of ¬
        window 1 of ¬
        process "System Preferences") ¬
        or (i is equal to 40)
        delay 0.05
        set i to i + 1
    end repeat
    if i is equal to 40 then return
    
end tell

--  # Get the state of the target checkbox
--  # as a boolean and toggle the state 
--  # of the target checkbox accordingly.
--  # The 'Select the previous input source'
--  # checkbox.

if my cbIsChecked(1) then
    my clickCheckbox(1)
else
    my clickCheckbox(1)
    delay 0.2
    my clickCheckbox(1)
end if

--  # Get the state of the target checkbox
--  # as a boolean and toggle the state 
--  # of the target checkbox accordingly.
--  # The 'Select next source in input menu'
--  # checkbox.

if my cbIsChecked(2) then
    my clickCheckbox(2)
else
    my clickCheckbox(2)
    delay 0.2
    my clickCheckbox(2)
end if

delay 0.2

tell application "System Preferences" to quit


--  # Handler(s)


--  # Get the current state of the target checkbox.
--  # 'Select the previous input source' checkbox. (1)
--  # 'Select next source in input menu' checkbox. (2)

on cbIsChecked(rowNumber)
    tell application "System Events" to ¬
        return (value of ¬
            checkbox 1 of ¬
            UI element 1 of ¬
            row rowNumber of ¬
            outline 1 of ¬
            scroll area 2 of ¬
            splitter group 1 of ¬
            tab group 1 of ¬
            window 1 of ¬
            process "System Preferences") ¬
            as boolean
end cbIsChecked

--  # Clicks the target checkbox of the target row.
--  # Due to the requirements of the OP this is
--  # called two to four times as needed based
--  # on the current state of the target checkboxes.
--  # 'Select the previous input source' checkbox. (1)
--  # 'Select next source in input menu' checkbox. (2)

on clickCheckbox(rowNumber)
    tell application "System Events" to ¬
        click checkbox 1 of ¬
            UI element 1 of ¬
            row rowNumber of ¬
            outline 1 of ¬
            scroll area 2 of ¬
            splitter group 1 of ¬
            tab group 1 of ¬
            window 1 of ¬
            process "System Preferences"
end clickCheckbox

Because of the comments and coding style the script is very long. It ends with end clickCheckbox, so make sure you highlight all of it when copying and pasting to Script Editor for testing before saving it as an application for production purposes.


Notes:

  • As coded, the repeat loops are set to timeout after two seconds if the primary condition is not met first. If the timeout is reached, the script is stopped without any error message. This can be modified as needed/wanted/required.

  • If you do not want the icon of saved AppleScript application shown in the Dock, then in Terminal use the following command syntax while changing /path/to/$name.app in the example command '/path/to/$name.app/Contents/Info.plist' to the pathname of the saved AppleScript application:

    defaults write '/path/to/$name.app/Contents/Info.plist' LSUIElement -bool yes
    
  • For my testing purposes I used:

    defaults write '/Applications/Uncheck Input Sources.app/Contents/Info.plist' LSUIElement -bool yes
    
  • If you modify the saved AppleScript application bundle after it has already been authorized to run, then you will need to reauthorize it before the system reboots again. Go to System Preferences > Security & Privacy > Privacy > Accessibility and uncheck the checkbox for the target application and then recheck it. Then run the saved AppleScript application manually to answer OK to the dialog box that appear. The saved Safari application is now read for production use and no icon for it should appear in the Dock.


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.