During a computer lab upgrade from OS X Mavericks to macOS Sierra, for which I went through the process of migrating managed preferences (MCX) to Config Profiles, I discovered that mouse button behavior wasn't being applied. Buttons were defined in a custom config profile, and if you looked at the Mouse System Preferences pane it would show all the correct settings, but all the buttons still behaved as "Primary Button" or left-click. Running defaults read
or restarting cfprefsd seemed to make no difference.
Then I noticed that if you merely clicked on one of the button settings in the Mouse pref pane, even without changing its value, the desired button behavior would suddenly start working. After some reverse engineering it was revealed that updating the user preferences cache wasn't enough, the kernel preferences cache also needed to be updated -- something the config profile on its own wasn't doing. Running this script as a LaunchAgent fixed the problem for our environment.
Note that this specifically addresses the preferences cache for the Apple wired Mighty Mouse ("com.apple.driver.AppleHIDMouse"); if you use the wireless Magic Mouse or Magic Trackpad, that uses at minimum a different preference domain and possibly also other button labels (I don't have one to test myself). Modify as needed.
#!/usr/bin/python
import CoreFoundation
from Foundation import NSBundle
import objc
# Set Button 1 aka "Primary Button"
CoreFoundation.CFPreferencesSetAppValue("Button1", 1, "com.apple.driver.AppleHIDMouse")
# Set Button 2 aka "Secondary Button"
CoreFoundation.CFPreferencesSetAppValue("Button2", 2, "com.apple.driver.AppleHIDMouse")
# Set Button 3
CoreFoundation.CFPreferencesSetAppValue("Button3", 3, "com.apple.driver.AppleHIDMouse")
# Set Button 4
CoreFoundation.CFPreferencesSetAppValue("Button4", 4, "com.apple.driver.AppleHIDMouse")
# Update user preferences cache
CoreFoundation.CFPreferencesAppSynchronize("com.apple.driver.AppleHIDMouse")
# Update kernel preferences cache
bezel_bundle = NSBundle.bundleWithPath_('/System/Library/PrivateFrameworks/BezelServices.framework')
functions = [('BSKernelPreferenceChanged', '@@'),]
objc.loadBundleFunctions(bezel_bundle, globals(), functions)
BSKernelPreferenceChanged("com.apple.driver.AppleHIDMouse")
If you are trying to get right-click or other multi-button behavior functioning on your managed Macs and are having no luck with config profiles or other previously-successful methods, give the above script a try and let us know how it goes!
Anyone have any other methods for reliably setting mouse button behavior in modern managed macOS?
References/Acknowledgements:
- BezelServices on OS X by Robert Sesek
- Reverse Engineering the OS: A Practical Guide by Michael Lynn