Hi,
I’m currently attempting to toggle the function keys in the system settings on macOS Ventura 13.3, i can’t get it to perform a button press (Toggle).
AppleScript
tell application "System Settings"
activate
reveal pane id "com.apple.Keyboard-Settings.extension"
delay 1
tell application "System Events"
tell process "System Settings"
click UI element 12 of group 2 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window "Keyboard"
delay 1
tell outline 1 of scroll area 1 of group 1 of splitter group 1 of group 1 of sheet 1 of window "Keyboard"
select row 11
delay 0.3
tell UI element 1 of row 11
click button 1
end tell
end tell
end tell
end tell
end tell
Automator
on run {input, parameters}
-- Click the text “Keyboard”
delay 1.882038
set timeoutSeconds to 2.0
set uiScript to "click static text 1 of window \"Keyboard\" of application process \"System Settings\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” button.
delay 0.926165
set timeoutSeconds to 2.0
set uiScript to "click UI Element 12 of group 2 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window \"Keyboard\" of application process \"System Settings\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” button.
delay 1.720122
set timeoutSeconds to 2.0
set uiScript to "click UI Element 1 of UI Element 1 of row 11 of outline 1 of scroll area 1 of group 1 of splitter group 1 of group 1 of sheet 1 of window \"Keyboard\" of application process \"System Settings\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” checkbox.
delay 1.374169
set timeoutSeconds to 2.0
set uiScript to "click checkbox 1 of group 1 of scroll area 1 of group 2 of splitter group 1 of group 1 of sheet 1 of window \"Keyboard\" of application process \"System Settings\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Click the “<fill in title>” button.
delay 1.292147
set timeoutSeconds to 2.0
set uiScript to "click UI Element 2 of group 2 of splitter group 1 of group 1 of sheet 1 of window \"Keyboard\" of application process \"System Settings\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
end run
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
If I understand the code correctly, you can change the state of the function keys by using this command:
defaults write -g com.apple.keyboard.fnState 1
1 turns on F1,F2, etc. as standard function keys; 0 sets them as special-purpose keys.
And the part that I don’t know how to accomplish from the command line or AppleScript is the notification to the system that the Fn key state has been changed. In the Xcode project, that seems to be here:
Is there a way to send this notification via AppleScript or any other way?
EDIT: There seems to be a way to do this here, but I don’t pretend to understand it, or how to adapt it for this situation:
EDIT2: Unfortunately, the fntoggle utility doesn’t change the state returned by defaults read -g com.apple.keyboard.fnState - that command will always return the setting shown in System Preferences, which doesn’t change when the fntoggle utility changes the actual state.
I was able to toggle the fn function key using the shell script, but unfortunately, that doesn’t actually change its state as you previously mentioned. That’s why I opted to use the GUI way.
use AppleScript version "2.8"
use scripting additions
set fnState to do shell script "defaults read -g com.apple.keyboard.fnState"
if fnState is "0" then
do shell script "defaults write -g com.apple.keyboard.fnState 1"
set notificationTitle to "fn Function Key On"
set notificationSubtitle to "The fn function key is now ON."
else
do shell script "defaults write -g com.apple.keyboard.fnState 0"
set notificationTitle to "fn Function Key Off"
set notificationSubtitle to "The fn function key is now OFF."
end if
display notification notificationSubtitle with title notificationTitle sound name "Pop"
Yes, but as you know, the notification in the fntoggle executable isn’t the “notification” in an AppleScript that displays in the upper-right corner of the screen, but an internal notification to the system so that it puts the change into effect.
I’m not sure this is progress, but I think I very dimly see that the script to turn on Fn1, F2 act as function keys, and send the notification to the system, might look something like this (THE ALL-CAPS STRING IS MY GUESS AT WHERE I NEED TO PUT SOMETHING USEFUL):
And since I have no idea of what I’m doing, it’s probably best just to ignore me…
use framework "Foundation"
use scripting additions
property parent : class "NSObject"
do shell script "defaults write -g com.apple.keyboard.fnState 1"
set noter to current application's NSDistributedNotificationCenter's defaultCenter()
set dict to current application's NSDictionary's dictionaryOFSOMEKIND???
noter's postNotificationName:"com.apple.keyboard.fnstatedidchange" object:(missing value) userInfo:dict deliverImmediately:1