i move my macbook pro [10.4.8] from desk to elsewhere frequently and while at desk i connect to a pc-style split keyboard – excellent for ergonomics and cheap. not giving that up. each time, i need to re-map the command and option keys using the “modifier keys” dialog of the “Keyboard” tab group of the Keyboard & Mouse Pref Pane (it’s not really practical to use a whole different keyboard layout each time).
not the biggest hassle ever, but quite tedious, and it seems it should be scriptalbe.
the solution so far… this gets me to the needed dialog no problem:
tell application "System Preferences"
activate
delay 2
end tell
tell application "System Events"
tell process "System Preferences"
click the menu item "Keyboard & Mouse" of the menu "View" of menu bar 1
delay 4
click the radio button "Keyboard" of the first tab group of window "Keyboard & Mouse"
delay 2
keystroke tab using shift down
keystroke tab using shift down
keystroke tab using shift down
keystroke tab using shift down
keystroke tab using shift down
keystroke space
end tell
end tell
however, once i’m there, doing tab-tab or shift-tab then space, then tab etc. to select the needed changes only works the first time one tests the script. successive times it runs, the focus is on a different lozenge, which throws the script off.
does anyone know a way of making those changes to modifier keys on the command line? then running that command could be scripted easily, i presume.
any suggestions are much appreciated.
Browser: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.0.7) Gecko/20060911 Camino/1.0.3
Operating System: Mac OS X (10.4)
I’m not quite clear how you want to remap the Command and Option keys. Do you want to swap them over? This does that job in OS 10.4.8 on my G5:
tell application "System Preferences"
activate
reveal anchor "keyboardTab_ModifierKeys" of pane id "com.apple.preference.keyboard"
end tell
tell application "System Events"
tell application process "System Preferences"
set optionButton to 1st pop up button of sheet 1 of front window whose value contains "Option"
set CommandButton to 1st pop up button of sheet 1 of front window whose value contains "Command"
click optionButton
key code {125, 49}
repeat until value of optionButton contains "Command"
delay 0.2
end repeat
click CommandButton
key code {126, 49}
repeat until value of CommandButton contains "Option"
delay 0.2
end repeat
key code 36
end tell
end tell
My approach is a little more “complicated”
but does the same as yours
tell application "System Preferences"
activate
reveal anchor "keyboardTab_ModifierKeys" of pane id "com.apple.preference.keyboard"
end tell
change_key(3, 1, "down")
change_key(4, 1, "up")
tell application "System Events" to click button "OK" of sheet 1 of window "Keyboard & Mouse" of process "System Preferences"
tell application "System Preferences" to quit
on change_key(theKey, step, dir)
tell application "System Events"
tell process "System Preferences"
tell window "Keyboard & Mouse"
tell pop up button theKey of sheet 1
set value of attribute "AXFocused" to true
keystroke (ASCII character 30) using option down
delay 0.5
repeat step times
if dir is "down" then
keystroke (ASCII character 31)
else
keystroke (ASCII character 30)
end if
end repeat
delay 0.5
keystroke return
end tell
end tell
end tell
end tell
end change_key
woah. i thought i might, if i were VERY lucky, get some pointers that would lead me down a path where i’d have to do a lot of digging and tweaking to maybe get it right two weeks from now. instead ya’ll come back, on a saturday afternoon no less, with the very thing that works right off the bat.
this rocks, especially since it reveals all kinds of bits i didn’t know about and may use in some other scripts.
A utility like KeyboardSee can be handy for this, Adam. If one checks the ‘keycodes’ checkbox, the hex value of each key is displayed. The arrow keys, for example, are shown as:
The values we really want to find, of course, are decimal key codes. While these aren’t displayed, conversion is a fairly trivial matter:
on dec_to_hex from l
set l to l as list
set c to "0123456789ABCDEF"
repeat with i in l
set v to i as integer
set h to ""
repeat while v > 0
set h to c's character (v mod 16 + 1) & h
set v to v div 16
end repeat
set i's contents to h
end repeat
tell l to if (count) is 1 then return beginning
l
end dec_to_hex
dec_to_hex from {123, 124, 125, 126} --> {"7B", "7C", "7D", "7E"}
So now we can simply check the keyboard layout for the resulting hex values.
To reverse the process:
on hex_to_dec from l
set l to l as list
set c to "0123456789ABCDEF"
repeat with i in l
set d to 0
repeat with v in i
if v is not in c then error "Invalid hex value: " & v
tell (offset of v in c) - 1 to set d to d * 16 + it
end repeat
set i's contents to d
end repeat
tell l to if (count) is 1 then return beginning
l
end hex_to_dec
hex_to_dec from {"7B", "7C", "7D", "7E"} --> {123, 124, 125, 126}
Very compact, to be sure ” although, to be fair, the routines suggested earlier were attempting to do slightly more (including processing a list of values).
For greater brevity, something like this could be used:
set h to "7D"
set d to 0
repeat with i in h
set d to d * 16 + (offset of i in "123456789ABCDEF")
end repeat
--> 125
Of course, if you were trying to force me into coming up with a one-liner, and the maximum value didn’t exceed 255 (as in this situation), then I might be tempted to suggest something like:
set h to "7D"
tell "123456789ABCDEF" to (my (offset of h's character 1 in it)) * 16 * ((count h) - 1) + (my (offset of h's character -1 in it))
--> 125
In terms of performance here, the former is between 160 to 200 times faster than the JavaScript technique, while the bump from the latter is more like x180 to x220…
Although I’ve come up with some good ones myself, I think Kai must be acknowledged as the grand master.
Another form of challenge is to see if you can manage to accomplish a task without defining any variables. This is an example of one that computes a short date in dd/mm/yyyy format without any defined variables (by Nigel Garvey, who must also be acknowledged as the grand master of speed):
tell {current date}
copy beginning to end
set end's month to January
tell ((beginning's year) * 10000 + (beginning - (end - 3944592)) div 2629728 * 100 + (beginning's day)) as string
text 7 thru 8 & "/" & text 5 thru 6 & "/" & text 1 thru 4
end tell
end tell
display dialog result
With regard to the problem of identifying the key that goes with the code, I came up with this, though I suspect it only works properly with British G5 keyboards “ and Tiger, of course:
Edit: I’ve now scrubbed the script that was here and posted a (hopefully) better version in the more appropriate setting of this thread of Adam’s in Code Exchange.
I’ve got one in Code Exchange for American (or English Canadian) keyboards. Not knowing of the existance of the Keyboard Server, mine is pure unadulterated brute force - I actually tried every key and wrote down the key code for it. :mad:
With respect to yours, it does indeed give wrong answers for a Keyboard Viewer (U.S.) which is the one on MM. When I understand what you’ve done, I’ll try to convert mine.
Mine’s not meant to be taken seriously “ which is why I included the wink in the preamble. It’s basically worked out by brute force, like yours. I got the names and numbers of the buttons in the Keyboard Viewer GUI and matched them to the key codes as revealed for the same machine by keyboardSee. It’s only likely to work if the Keyboard Viewer on your machine has the same GUI structure as the one on mine “ which plainly it hasn’t. Kept me amused for an hour or two, though.
From the point of view of GUI Scripting, it seems to be only necessary to know a few key codes as ‘keystroke’ seems to be the better choice in most cases.
Thanks for your kind words about the speed of my scripts. It has to be said that kai’s and one or two others’s don’t exactly hang about either…