Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does anyone know where OSX stores the settings in System Preferences > Keyboard > Modifier Keys?

Where are these stored?!?

I'm apparently not the only one who wants to know (How can I change modifier keys in "System Preferences > Keyboard > Modifier Keys..."). I've tried watching the System Preferences app with dtruss, but that doesn't seem to be possible on 10.10.3 (which is what I'm on right now), and I'm not even sure that that would be at all useful if System Preferences is just getting settings from cfprefsd. Watching cfprefsd with dtruss doesn't seem to catch the relevant file access.

Does anyone know of an API to get this information? Something in gestalt perhaps?

like image 342
Ted Middleton Avatar asked Jun 02 '16 01:06

Ted Middleton


2 Answers

Ok - answering my own question. I threw together a little program that uses kqueues to watch file system changes. I watched my file system for modifications when I changed the setting in System Preferences, and I saw:

'/Users/ted/Library/Preferences/ByHost/.GlobalPreferences.3F1C...9C34.plist.V1Ut9hp' kevent: ident=44, filter=KQ_FILTER_VNODE, flags=KQ_EV_ADD|KQ_EV_CLEAR, fflags=KQ_NOTE_WRITE|KQ_NOTE_CHILD|KQ_NOTE_PDATAMASK

So the setting is in ~/Library/Preferences/ByHost/.GlobalPreferences.<UUID>.plist. I'm not sure what the UUID is - something do to with OpenDirectory? (UPDATE: apparently this UUID is an identifier for your machine).

Anyways, in .GlobalPreferences.<UUID>.plist, we see entries like:

<key>com.apple.keyboard.modifiermapping.1452-610-0</key>
<array>
    <dict>
        <key>HIDKeyboardModifierMappingDst</key>
        <integer>2</integer>
        <key>HIDKeyboardModifierMappingSrc</key>
        <integer>0</integer>
    </dict>
</array>

1452:610 is the decimal VID:PID for the USB keyboard/trackpad combo in my 2012 Macbook Pro, and any other keyboard that's been plugged in to my computer and has had modifier settings remapped will have a similar entry. 0 seems to be the Caps Lock key, 2 and 10 seem to be left and right CTRL, 3 and 11 seem to be left and right Option, and 4 and 12 seem to be left and right Command.

So from the above, you can see that I have my Caps Lock key mapped to left CTRL.

It looks like the settings in .GlobalPreferences.<UUID>.plist are a part of your standard user defaults. So you can get at these settings easily enough just by doing

[[NSUserDefaults standardUserDefaults] objectForKey:@"com.apple.keyboard.modifiermapping-1452-610-0"];
like image 87
Ted Middleton Avatar answered Oct 19 '22 21:10

Ted Middleton


For anyone else stumbling across this, I was looking for a way to put this in my .dotfiles when setting up new machines. All I wanted was to remap caps-lock to escape.

In Sierra 10.12 it seems the solution on this post became invalid. The documented way from Apple works for me using 10.14.6 Mojave (*with a caveat)

TL;DR;

Since Sierra 10.12, see: TN2450

# Remap caps-lock to escape
hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc":0x700000039,"HIDKeyboardModifierMappingDst":0x700000029}]}'

Before Sierra 10.12

plutil

Interestingly the solution is still correct about this file updating and saving information concerning keymapping when the user goes through the GUI to change modifier keys. However updating the keymapping info here doesn't seem to affect anything anymore.

This example uses the plutil command which is the preferred way to update plists as defaults write is deprecated according to the man page See filepath.

Also, see comparisons between the two commands and the library PlistBuddy.

#!/usr/bin/env bash

# Quit System Preferences so it doesn't muck with your settings
osascript -e 'tell application "System Preferences" to quit'

# Get your machine's UUID

__UUID__=$(
  ioreg -ad2 -c IOPlatformExpertDevice | xmllint --xpath \
  '//key[.="IOPlatformUUID"]/following-sibling::*[1]/text()' -
)

# Replace all contents of the array for the caps lock key/value pair.
plutil -replace "com\.apple\.keyboard\.modifiermapping\.1452-636-0" \
-json '[{
 "HIDKeyboardModifierMappingDst": 30064771113,
 "HIDKeyboardModifierMappingSrc": 30064771129
}]' \
~/Library/Preferences/ByHost/.GlobalPreferences.${__UUID__}.plist

# Pretty print file
plutil -p ~/Library/Preferences/ByHost/.GlobalPreferences.${__UUID__}.plist 

Since Sierra 10.12

hidutil

The new solution is much less verbose AND doesn't rely on filepath args or giving arguments types for the not very well documented plutil command.

You can see this Stack Exchange post for another explanation.

This technical doc TN2450 describes the strategies for handling this with hidutil or Xcode.

#!/usr/bin/env bash

# Quit System Preferences so it doesn't muck with your settings
osascript -e 'tell application "System Preferences" to quit'

# Remap caps-lock to escape
hidutil property --set '{
  "UserKeyMapping":[{
    "HIDKeyboardModifierMappingSrc":0x700000039,
    "HIDKeyboardModifierMappingDst":0x700000029
  }]
}'
  • Caveat this doesn't seem to change the GUI's display when you visit modifier keys in System Preferences > Keyboard. Nonetheless, it still works like a charm for the functionality.
like image 43
macc Avatar answered Oct 19 '22 22:10

macc