Updating modifier key mappings through defaults command tool
I am trying to automate the inital setup of my macbook, that includes installing software and changing OS X configuration to my needs.
I have tried to update the modifier keys with defaults, the code is as follow:
# The apple keyboard id (1452-567-0) should probably be modified in case you use other different model
COMPUTER_UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -E '(UUID)' | awk '{print $3}' | tr -d \"`
defaults write ~/Library/Preferences/ByHost/.GlobalPreferences.$COMPUTER_UUID com.apple.keyboard.modifiermapping.1452-567-0 '( { HIDKeyboardModifierMappingDst = 2; HIDKeyboardModifierMappingSrc = 0; } )'
The problem seems that even if the pattern is changed the System Preferences does not catch the update, not even restarting the computer.
Is there any way to perform this operation in Snow Leopard?
Thanks.
It's important for the defaults
command to use the correct "keyboard ID" in the key, it seems to be: com.apple.keyboard.modifiermapping.$VendorID-$ProductID-0
For example the internal keyboard for my MacBook Air uses: com.apple.keyboard.modifiermapping.1452-579-0
, while the external keyboard on my iMac uses com.apple.keyboard.modifiermapping.1118-219-0
How to get the correct "keyboard ID"? On the command line you can use:
ioreg -p IOUSB -c IOUSBDevice | grep -e class -e idVendor -e idProduct
to get a list of your USB devices with the relevant parameters:
[...]
+-o Natural® Ergonomic Keyboard 4000@fa140000 <class IOUSBDevice, id 0x100000452, registered, matched, active, busy 0 (115 ms), retain 12>
"idProduct" = 219
"idVendor" = 1118
My guess is that the third parameter (the "-0" part) is a "counter", in case you have more than one keyboard of the same type.
So, to switch off the CapsLock key on my external keyboard I can now use:
defaults -currentHost write -g com.apple.keyboard.modifiermapping.1118-219-0 -array-add '<dict><key>HIDKeyboardModifierMappingDst</key><integer>-1</integer><key>HIDKeyboardModifierMappingSrc</key><integer>0</integer></dict>'
And, for completeness' sake, here's a list of possible key codes to use (from Mac OS X Hints):
- None — –1
- Caps Lock — 0
- Shift (Left) — 1
- Control (Left) — 2
- Option (Left) — 3
- Command (Left) — 4
- Keypad 0 — 5
- Help — 6
- Shift (Right) — 9
- Control (Right) — 10
- Option (Right) — 11
- Command (Right) — 12
Update: thanks to Lauri Ranta here's a command that works for Bluetooth & USB keyboards:
ioreg -n IOHIDKeyboard -r | grep -e 'class IOHIDKeyboard' -e VendorID\" -e Product
which gives you slightly different output:
+-o IOHIDKeyboard <class IOHIDKeyboard, id 0x100000489, registered, matched, active, busy 0 (0 ms), retain 8>
| "Product" = "Apple Wireless Keyboard"
| "VendorID" = 1452
| "ProductID" = 570
The problem I'm having is that every time I plug my keyboard in, it gets a different ID in ioreg. All I need to do is swap the command and the apple keys.
I decided to solve this in my case the "wrong way" using AppleScript and the System Preferences GUI. It's an ugly hack, but it works! Your mileage may vary.
--The beginning of the name of the target keyboard (to type into the drop-down selection list)
set keyboardName to "natural"
--reboot system preferences to make GUI state more predictable
tell application "System Preferences"
quit
delay 1
activate
delay 1
activate
end tell
tell application "System Events"
--Bring up keyboard prefs
key code 53 --escape
keystroke "f" using command down
delay 0.5
key code 53 --escape
keystroke "keyboard"
delay 0.5
key code 36 --return
delay 1
--Open modifier keys submenu
repeat 4 times
keystroke tab using shift down
--delay 0.1
end repeat
--delay 0.1
keystroke space
delay 0.1
--Select keyboard
keystroke space
keystroke keyboardName
keystroke return
delay 0.1
--Select "option key" drop-down
repeat 3 times
keystroke tab
end repeat
delay 0.5
--Open drop-down and go to top
keystroke space
delay 0.1
repeat 4 times
key code 126 --up arrow
end repeat
--Select "command" option
repeat 3 times
key code 125 --down arrow
end repeat
delay 0.1
keystroke return
-- Select "command key" drop-down
keystroke tab
delay 0.1
--Open drop-down and go to top
keystroke space
delay 0.1
repeat 4 times
key code 126 --up arrow
end repeat
--Select "command" option
repeat 2 times
key code 125 --down arrow
end repeat
delay 0.1
keystroke return
delay 0.1
--Commit changes! phew.
keystroke return
end tell
I, too, have been unable to get defaults write
(or updating .plist files) to affect my HIDKeyboardModifierMappingSrc and HIDKeyboardModifierMappingDst settings under Snow Leopard.
I'm trying to "pre-populate" my Guest account to support my PS2-to-USB keyboard (which apparently has Option and Command swapped.) Other pages' suggestions to "log out and log back in" don't help; "logging out" of the Guest account deletes all my changes.
(I have successfully updated my "com.apple.dock" and "com.apple.menuextra.clock" plist files to customize the dock and the 24-hour clock, respectively, which makes it even more frustrating that the Keyboard Modifiers won't work...)
I've tried using "dtruss -asf" to compare what "System Preferences.app" is doing (which apparently works) to what "defaults" is doing. Nearest I can figure, I see messages along the lines of:
Foundation`+[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]+0x151
Foundation`NSKeyValueNotifyObserver+0x81
Foundation`NSKeyValueDidChange+0x1ca
Foundation`-[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:usingBlock:]+0x176
If anybody's figured out a solution that works under Snow Leopard, I'd be happy to hear it...