diff --git a/modules/05-install-remap-keys.sh b/modules/05-install-remap-keys.sh new file mode 100755 index 0000000..d075dee --- /dev/null +++ b/modules/05-install-remap-keys.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env zsh +# vi: ft=zsh + +function ensureRightAccess() { + local filesystemItem="$1" + chown root:wheel ${filesystemItem} + chmod ugo=rx ${filesystemItem} +} + +function createRemapKeysBinary() { + cat > ${remapKeysPath} <<- BINARY + #!/bin/zsh + PRODUCT_MATCHER='{"ProductID":0x7a5,"VendorID":0x45e}' + + hasMappingBeenAlreadyActivated() { + local currentModifierKeyMappings="\`hidutil property --get UserKeyMapping -m '{"ProductID":0x7a5,"VendorID":0x45e}' | grep HIDKeyboardModifierMappingDst | wc -l\`" + test "\${currentModifierKeyMappings}" -gt 1 + } + + hasMappingBeenAlreadyActivated && exit 0 + hidutil property --matching "\${PRODUCT_MATCHER}" --set '{"UserKeyMapping": [ + {"HIDKeyboardModifierMappingSrc": 0x700000065, "HIDKeyboardModifierMappingDst": 0x7000000e7}, + {"HIDKeyboardModifierMappingSrc": 0x7000000e3, "HIDKeyboardModifierMappingDst": 0x7000000e2}, + {"HIDKeyboardModifierMappingSrc": 0x7000000e2, "HIDKeyboardModifierMappingDst": 0x7000000e3} + ]}' > /dev/null 2>&1 + BINARY + ensureRightAccess ${remapKeysPath} +} + +function createXPCConsumer() { + clang -framework Foundation -x objective-c -o ${xpcConsumerPath} - <<- BINARY + #import + #include + + int main(int argc, const char * argv[]) { + @autoreleasepool { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t _Nonnull object) { + const char *event = xpc_dictionary_get_string(object, XPC_EVENT_KEY_NAME); + NSLog(@"%s", event); + dispatch_semaphore_signal(semaphore); + }); + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if(argc >= 2) { + execv(argv[1], (char **)argv+1); + } + } + } + BINARY + ensureRightAccess ${xpcConsumerPath} +} + +function createLaunchDaemon() { + cat > ${launchDaemonPath} <<- LDAEMON + + + + + Label + ${serviceName} + ProgramArguments + + ${xpcConsumerPath} + ${remapKeysPath} + + LaunchEvents + + com.apple.iokit.matching + + com.apple.device-attach + + idProduct + 1957 + idVendor + 1118 + IOProviderClass + IOUSBDevice + IOMatchLaunchStream + + + + + + + LDAEMON + ensureRightAccess ${launchDaemonPath} +} + +function enableLaunchDaemon() { + launchctl bootstrap system ${launchDaemonPath} +} + +function configure_system() { + local serviceName='de.astzweig.macos.launchdaemons.keymapper' + local dstDir='/usr/local/bin' + local xpcConsumerPath="${dstDir}/astzweig-xpc-consumer" + local remapKeysPath="${dstDir}/remap-keys" + local launchDaemonPath="/Library/LaunchDaemons/${serviceName}.plist" + [[ -d ${dstDir} ]] || { + lop -- -e "Could not install remap-keys. Directory ${dstDir} does not exist." + return 10 + } + [[ -x ${remapKeysPath} ]] || indicateActivity createRemapKeysBinary 'Create remap-keys executable' + [[ -x ${xpcConsumerPath} ]] || createXPCConsumer 'Create XPC event consuer' + [[ -f ${launchDaemonPath} ]] || createLaunchDaemon 'Create Launch Daemon' + indicateActivity enableLaunchDaemon 'Enable Launch Daemon' +} + +function getExecPrerequisites() { + cmds=( + [clang]='' + [launchctl]='' + [cp]='' + [chown]='' + [chmod]='' + ) +} + +function getUsage() { + read -r -d '' text <<- USAGE + Usage: + $cmdName show-questions [ ]... + $cmdName [-v] [-d FILE] + + Install a system wide key remapper for the Microsoft Sculpt Keyboard using + macOS nativ hidutil, in order to swap command and option key. + + Options: + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. + ---- + $cmdName 0.1.0 + Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG + License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. + USAGE + print -- ${text} +} + +if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" +fi