<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LaunchEvents on Digi Hunch</title><link>https://static.digihunch.com/tag/launchevents/</link><description>Recent content in LaunchEvents on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 01 Apr 2025 23:14:12 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/launchevents/index.xml" rel="self" type="application/rss+xml"/><item><title>Key mapping for external PC keyboard on Mac</title><link>https://static.digihunch.com/2022/11/key-mapping-on-external-pc-keyboard-on-macbook/</link><pubDate>Wed, 23 Nov 2022 10:38:00 -0400</pubDate><guid>https://static.digihunch.com/2022/11/key-mapping-on-external-pc-keyboard-on-macbook/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/key-mapping-image.webp" alt="Featured image of post Key mapping for external PC keyboard on Mac" /&gt;&lt;p class="wp-block-paragraph"&gt;This post is to document my steps to use external Windows keyboard on Mac with custom key mapping.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-background"&gt;Background&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apple&amp;#8217;s magic keyboard does not support multi-device so I have to repurpose my Logitech K810 keyboard with MacBook. Logitech K810 is and &lt;a href="https://www.pcmag.com/reviews/logitech-k810-bluetooth-illuminated-keyboard"&gt;old model&lt;/a&gt; with Windows key layout even though it also supports MacOS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The bottom row has the same number of keys as magic keyboard but with different keys. For example, magic keyboard has cmd key (aka GUI keys) besides space bar but K810 has Alt. Magic keyboard has Option key next to cmd key and K810 has Windows key on the left and Ctrl key on the right. The position of left Ctrl and FN is different on magic keyboard too. Since I rely on &lt;a href="https://static.digihunch.com/2018/02/linux-tips-and-tricks-in-shell/"&gt;shortcuts&lt;/a&gt; on Magic keyboard, I therefore decide configure key mapping on the Windows key, Alt keys and right ctrl key to match magic keyboard. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="450" src="https://static.digihunch.com/wp-content/uploads/2025/04/K810.webp" alt="" class="wp-image-12872" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/K810.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/K810-300x132.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/K810-768x338.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;K810 Layout&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a nutshell, I need to remap some keys on an external Windows keyboard connected to MacOS (Monterey).&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;What is not working&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In MacOS, you could modify keys from keyboard preference as below. However, in my case I need to keep left ctrl key and overwrite the right ctrl key. MacOS does not distinguish them unfortunately. The native method is not flexible so I did not bother.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="300" height="206" src="https://static.digihunch.com/wp-content/uploads/2025/04/macos-keyboard-pref.webp" alt="" class="wp-image-12871"/&gt;&lt;figcaption class="wp-element-caption"&gt;Use MacOS keyboard preference to modify keys&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the mean time, I hate to install a third-party application (such as &lt;a href="https://karabiner-elements.pqrs.org/"&gt;Karabiner-Elements&lt;/a&gt;) just for the purpose of key mapping. Even though I appreciate the efforts by the community, I just don&amp;#8217;t find it a neat solution for the additional dependency.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Challenges with key mapping&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I then came across a developer&amp;#8217;s &lt;a href="https://rakhesh.com/mac/using-hidutil-to-map-macos-keyboard-keys/"&gt;post&lt;/a&gt; on using a utility called hidutil to map keys. This is promising after I tested using this command to swap key a/A and b/B. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;: 0x700000004,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;: 0x700000005},{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;: 0x700000005,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;: 0x700000004}]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command above takes effect immediately, on all keyboards. In my case I only need mapping on an external keyboard, not the built-in keyboard. Luckily hidutil has &amp;#8211;matching switch where I can specify ProductID and VendorID. I can find both of them from About This Mac -&amp;gt; System Report -&amp;gt; Hardware -&amp;gt; Bluetooth:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="654" src="https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id.webp" alt="" class="wp-image-12870" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id-300x192.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id-768x491.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;Vendor ID and Product ID&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;From &lt;a href="https://developer.apple.com/library/archive/technotes/tn2450/_index.html"&gt;this&lt;/a&gt; technical note, we can find out the usage IDs of the keys in the table at the bottom of the page. Then use the Usage ID as the last two bytes of the source and destination values of the mapping expression above. For example, 0x700000004 stands for key A/a, and 0x700000005 stands for key B/b. In my case, after going through this table, my key mapping is:&lt;/p&gt;&#10;&lt;figure class="wp-block-table"&gt;&lt;table class="has-very-light-gray-to-cyan-bluish-gray-gradient-background has-background"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Source Key on K810&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Source Code on K810&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Destination Key&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Destination Code&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Left Alt&lt;/td&gt;&lt;td&gt;0x7000000E2&lt;/td&gt;&lt;td&gt;Left GUI (cmd)&lt;/td&gt;&lt;td&gt;0x7000000E3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Right Alt&lt;/td&gt;&lt;td&gt;0x7000000E6&lt;/td&gt;&lt;td&gt;Right GUI (cmd)&lt;/td&gt;&lt;td&gt;0x7000000E7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Left Win&lt;/td&gt;&lt;td&gt;0x7000000E3&lt;/td&gt;&lt;td&gt;Left Alt (option)&lt;/td&gt;&lt;td&gt;0x7000000E2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Right Ctrl&lt;/td&gt;&lt;td&gt;0x7000000E4&lt;/td&gt;&lt;td&gt;Right Alt (option)&lt;/td&gt;&lt;td&gt;0x7000000E6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fn+F12&lt;/td&gt;&lt;td&gt;0x700000045&lt;/td&gt;&lt;td&gt;Globe&lt;/td&gt;&lt;td&gt;0xFF00000003&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is even a &lt;a href="https://hidutil-generator.netlify.app/"&gt;website&lt;/a&gt; that helps you generate the usage ID. I put together a command, which is working, on the external keyboard.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E2,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E3},{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E6,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E7},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E3,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E2},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E4,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E6},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x700000045,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0xFF00000003}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The other way to confirm that key mapping is working, is to look up key mapping with the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --get &lt;span style="color:#e6db74"&gt;&amp;#34;UserKeyMapping&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To wipe out the mapping, we can use the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that we have to use the same matching expression. However, I noticed that the command only works while the bluetooth keyboard is connected. When I reboot the MacBook the mapping goes away as well.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The solution to key mapping&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Even though I could run this command after reboot using a plist file in ~/Library/LaunchAgents/, as the reference blog suggests, it will not work because I cannot guarantee the bluetooth keyboard is connected before MacOS executes it. Also, I might disconnect and re-connect the keyboard and I want to ensure that the system runs that command whenever the keyboard gets connected.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the &lt;a href="https://github.com/pqrs-org/Karabiner-Elements"&gt;Karabiner Element&lt;/a&gt; community, some developers touched on &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;this&lt;/a&gt;. Basically we can customize the plist file to tell MacOS when to fire the hidutil command, by using &amp;#8220;LaunchEvents&amp;#8221; key in the XML. There is an &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;example&lt;/a&gt; for USB keyboard. For myself, I edit the plist file to be:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;plist&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;local.hidutilKeyMapping&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;LaunchEvents&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.iokit.matching&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.bluetooth.hostController&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;IOProviderClass&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;IOBluetoothHCIController&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;idProduct&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;B319&lt;span style="color:#f92672"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;idVendor&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;046D&lt;span style="color:#f92672"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;IOMatchLaunchStream&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/bin/hidutil&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;property&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;--matching&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;--set&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;UserKeyMapping&amp;#34;: [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E2,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E6,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E3,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E4,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E6&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x700000045,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0xFF00000003&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Store the file above as ~/Library/LaunchAgents/com.local.hidutilKeyMapping.plist (create LaunchAgents directory if it doesn&amp;#8217;t exist) and then run the following to load it:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;launchctl load ~/Library/LaunchAgents/com.local.hidutilKeyMapping.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This works perfectly. The dict section (line 7 to line 23) of the file is based on &lt;a href="http://technologeeks.com/docs/launchd.pdf"&gt;this&lt;/a&gt; document as the GitHub &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;comment&lt;/a&gt; suggests. The LaunchEvents section narrows down the type of events that will trigger the program with arguments. It triggers whenever a bluetooth device with specific ProductID and VendorID connects to Mac. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We can still use hidutil command from the previous section to ensure that the custom key mapping remain in effect:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="531" src="https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1024x531.webp" alt="" class="wp-image-12869" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1024x531.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-300x155.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-768x398.webp 768w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1536x796.webp 1536w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-2048x1061.webp 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that the output above has usage values converted to decimal from hexadecimal, with destination on top and source at the bottom.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I like this solution as it is light-weight, targeting a specific event, highly customizable and resolves an issue in a very specific circumstance.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Final words&lt;/h2&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="91" src="https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout.webp" alt="" class="wp-image-12868" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout-300x27.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout-768x68.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;K380 layout&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;After all this customization effort, I came across the Logitech &lt;a href="https://www.logitech.com/en-us/products/keyboards/k380-multi-device.920-011135.html"&gt;K380&lt;/a&gt; model (current alternative to K810), whose layout is exactly the way I customized K810 to be. So I ordered the new K380 model for just $29.99 during the week of black Friday. Remembering that I had my K810 for $94.98 back in 2015, what&amp;#8217;s the point of all this&amp;#8230;.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2022/11/aws-serverless-services-and-developer-tools/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;AWS serverless services and developer tools&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2022/12/landing-zone-in-aws/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Landing Zone in AWS – An Introduction&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>