geerlingguy / mac-dev-playbook

Mac setup and configuration via Ansible.
Other
5.9k stars 1.76k forks source link

Automate remapping Caps Lock to Escape #22

Open geerlingguy opened 7 years ago

geerlingguy commented 7 years ago

Now that macOS 10.12.1 includes built-in remapping for Caps Lock-to-Escape, I've ditched Karabiner Elements (since that was the only thing I used it for). See: Remapping the Caps Lock key to Escape in macOS Sierra

But I'd still like to have that setting automated so I don't have to click through the Keyboard system preferences when setting up my Mac fresh.

See: Updating modifier key mappings through defaults command tool; the setting has to be set per keyboard (in my case, I have two, an 'Apple Keyboard', and an 'Apple Internal Keyboard / Trackpad', with unique IDs. I'd have to set it up (maybe in the .osx bash script in my dotfiles?) to add the mapping for each keyboard detected.

oxyc commented 7 years ago

If someone already uses khd as a hotkey daemon (it's brilliant), you can also use it to remap caps-lock.

- capslock : khd -p "- escape"
geerlingguy commented 7 years ago

Seems a lot more automate-able/configurable... but my only hesitation is the permissions required to make it work—you're giving it basically full control over keystrokes and all other parts of the accessibility layer.

oxyc commented 7 years ago

I hesitated too, but now there's no going back :D

https://twitter.com/geerlingguy/status/859526910229041154

# re-map/disable quit shortcut
cmd - q [ Firefox, iTerm2, Google Chrome ] : khd -p "cmd - w"

In case someone lands here you can disable Secure Keyboard entry for iTerm2/Terminal with:

defaults write com.apple.terminal SecureKeyboardEntry -bool false
defaults write com.googlecode.iterm2 "Secure Input" -bool false
oxyc commented 6 years ago

Quick update on khd for others reading. Seems it's been more or less abandoned in favor of skhd which doesnt support capslock and application specific mappings.

tomtastic commented 6 years ago

Hi @geerlingguy, maybe use the following for an automated key remapping solution ?

A short script remap_mac_keys to leverage MacOS native hidutil key remapping :

#!/bin/sh
# Credit to Brad Howes
FROM='"HIDKeyboardModifierMappingSrc"'
TO='"HIDKeyboardModifierMappingDst"'

ARGS=""
function Map # FROM TO
{
    CMD="${CMD:+${CMD},}{${FROM}: ${1}, ${TO}: ${2}}"
}

# Referencing :
# https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1035.41.2/IOHIDFamily/IOHIDUsageTables.h.auto.html
SECTION="0x700000064"
ESCAPE="0x700000029"
BACKQUOTE="0x700000035"
CAPS_LOCK="0x700000039"
L_SHIFT="0x7000000E1"
R_COMMAND="0x7000000E7"
L_CONTROL="0x7000000E0"

Map ${CAPS_LOCK} ${ESCAPE}
#Map ${SECTION} ${ESCAPE}
#Map ${R_COMMAND} ${SHIFT_LOCK}
#Map ${BACKQUOTE} ${L_CONTROL}

hidutil property --set "{\"UserKeyMapping\":[${CMD}]}"

A basic LaunchAgent com.user.loginscript.plist to perform the mapping at login :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>com.user.loginscript</string>
   <key>ProgramArguments</key>
   <array>
       <string>/usr/local/bin/remap_mac_keys</string>
   </array>
   <key>RunAtLoad</key>
   <true/>
</dict>
</plist>

And the following Ansible tasks to put them all in place :

- name: Copy remap_mac_keys to /usr/local/bin/
  copy:
    src: remap_mac_keys
    dest: /usr/local/bin/remap_mac_keys
    owner: root
    group: wheel
    mode: 0755
  become: yes

- name: Put LaunchAgent in place to remap keys on login
  copy:
    src: com.user.loginscript.plist
    dest: ~/Library/LaunchAgents/com.user.loginscript.plist
    mode: 0644
stale[bot] commented 4 years ago

This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution!

Please read this blog post to see the reasons why I mark issues as stale.

stale[bot] commented 4 years ago

This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details.

stale[bot] commented 3 years ago

This issue is no longer marked for closure.

geerlingguy commented 3 years ago

Reopening... I still don't have this automated :(

NicholasTD07 commented 2 years ago

Hey @geerlingguy, I'd want to say a huge thank you to you first sir! I have been trying to automate my own developer MacBook setup with Ansible and I have been following your Ansible 101 live streams for the last couple days and also this repo and your Ansible Mac collections. They have been hugely helpful for my own setup.

I have a very rough first step Ansible playbook set up, here https://github.com/NicholasTD07/ansible-macOS-playbook.

I was just wondering about whether there's a way that I can use Ansible to remap caps-lock to control and Google has taken me here 😄

It seems like there still isn't a great automation solution for this yet. Is that right?

Seems like something just has to be done by hand to please the Apple God :P

geerlingguy commented 2 years ago

@NicholasTD07 - I would imagine it has to be a plist somewhere, which would mean it is able to be automated. I just haven't had the time to go dig up where it's defined :(

NicholasTD07 commented 2 years ago

@geerlingguy Yes. Some people have done the research into that already. I think this answer looks the best https://apple.stackexchange.com/a/277544.

Basically, you can run defaults -currentHost read -g to get what has changed on your Mac in the system preferences from what I read.

nicholas.the.personal@Nicholass-MBP-2 ansible-macOS-playbook % defaults -currentHost read -g
{
    "com.apple.keyboard.modifiermapping.1118-1957-0" =     (
                {
            HIDKeyboardModifierMappingDst = 30064771300;
            HIDKeyboardModifierMappingSrc = 30064771129;
        }
    );
    "com.apple.keyboard.modifiermapping.1452-835-0" =     (
                {
            HIDKeyboardModifierMappingDst = 30064771300;
            HIDKeyboardModifierMappingSrc = 30064771129;
        }
    );
}

But notice how different keyboards have different "id"s, i.e. 1118-1957-0 vs 1452-835-0 which then "should"* be able to be read out by using ioreg -n IOHIDKeyboard -r (from this answer in that same question). But it's showing nothing for me.

Seems a bit fiddly and not very straightforward so far...

tomtastic commented 2 years ago

Why not just issue this? :

$ hidutil property --set {"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x700000029}]}
thebiblelover7 commented 2 years ago

@tomtastic thanks!

@geerlingguy That command works flawlessly... (Don't forget to quote the last section if you're on some weird shell)

thomanq commented 1 year ago

$ hidutil property --set {"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x700000029}]}

Note: Key codes can be found here: https://developer.apple.com/library/archive/technotes/tn2450/_index.html#//apple_ref/doc/uid/DTS40017618-CH1-KEY_TABLE_USAGES

andrasmaroy commented 9 months ago

I've managed to eventually solve this with Ansible. Apple realy hasn't made it easy, I've included details in https://github.com/andrasmaroy/dotfiles/commit/5815a8d137a028781a3f0cf9ccb10044301bf099.