<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-03-21T00:03:48+00:00</updated><id>/feed.xml</id><title type="html">precondition</title><subtitle>Typing about what I type on</subtitle><entry><title type="html">QMK Heatmap Generator</title><link href="/qmk-heatmap" rel="alternate" type="text/html" title="QMK Heatmap Generator" /><published>2021-02-19T00:00:00+00:00</published><updated>2021-02-19T00:00:00+00:00</updated><id>/qmk-heatmap</id><content type="html" xml:base="/qmk-heatmap"><![CDATA[<p>Show key presses coming from:
<select id="layerSelector" onchange="displayLayer(this.value)">
<!-- The value of "All layers" is an arbitrary big number that will be converted to highestLayer+1 -->
<option value="99">All layers</option>
<option value="0">Layer 0</option>
</select></p>

<div id="keyboard">
  <canvas id="bgCanvas" width="830" height="290">
</canvas>
</div>
<div id="howToMatchMatrix" style="display: none;min-width: 100%;text-align: center;"></div>

<hr />

<pre class="highlight" id="matrixToMatch" style="display:none; line-height:16px;"></pre>
<div class="upload-btn-wrapper" id="resetMatrixBtnWrapper" style="display:none;">
  <label class="btn" for="resetInfoMatrix">Use another matrix</label>
  <button id="resetInfoMatrix" style="position:absolute" onclick="resetMatrix()"></button>
</div>
<textarea class="qmkInfoMatrix" id="infoMatrix" rows="5" placeholder="Paste the matrix layout outputted by `qmk info -m` here" onchange="reactToTextAreaChanges(document.getElementById('infoMatrix'))" enabled=""></textarea>
<div class="upload-btn-wrapper">
  <label class="btn" for="pictureFile">Upload keyboard picture</label>
  <input type="file" id="pictureFile" class="btn" />
</div>
<div class="upload-btn-wrapper" id="csvFileBtnWrapper" style="display:none;">
  <label class="btn" for="csvFile">Upload key log csv</label>
  <input type="file" id="csvFile" />
</div>

<h1 id="what-it-is">What it is</h1>
<p>This is a web-based tool to generate a pretty heatmap of your typing habits. As opposed to all the other available keyboard heatmap generators, this doesn’t merely analyse a static piece of text and overlays the letter frequency of said piece of text over a picture of the most basic row-stagger keyboard. This generator has full support for unprintable keys like backspace, modifier keys, caps lock, F-keys, arrow keys etc. Additionally, advanced QMK features such as layers, modtaps, layertaps, <a href="home-row-mods">home row mods</a>, leader keys, autoshift, and even combos are also supported.</p>

<p>Since QMK keyboards come in all shapes and sizes, you’re invited to upload your own picture of your layout/keymap. It doesn’t matter whether you use a TKL, an Atreus or a Dactyl Manuform; if it’s available on the <a href="https://config.qmk.fm/#/">QMK configurator</a>, it’s supported.</p>

<!--
Mini version of my Dactyl Manuform 5x6 for testing
┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐
│1B││1C││1D││1E││1F│                    │7A││7B││7C││7D││7E│
└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐
│2B││2C││2D││2E││2F│                    │8A││8B││8C││8D││8E│
└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐
│3B││3C││3D││3E││3F│                    │9A││9B││9C││9D││9E│
└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘
                ┌──┐┌──┐                    ┌──┐┌──┐
                │4E││4F│                    │AA││AB│
                └──┘└──┘                    └──┘└──┘
-->

<h1 id="gallery">Gallery</h1>

<p><img src="/assets/images/qmk-heatmap/precondition-dactyl-manuform-heatmap.png" alt="Precondition's Dactyl Manuform 5x6 heatmap" /></p>

<h1 id="instructions">Instructions</h1>

<p>The QMK Heatmap Generator expects:</p>
<ol>
  <li>A picture of your layout</li>
  <li>A text representation of the matrix positions of your keyboard</li>
  <li>A link between each key in the matrix to the corresponding key in the provided picture</li>
  <li>A keylog CSV file in <code class="language-plaintext highlighter-rouge">keycode,row,col,layer</code> format (<code class="language-plaintext highlighter-rouge">keycode</code> can be omitted)</li>
</ol>

<p>If you don’t have a <code class="language-plaintext highlighter-rouge">keylog.csv</code> file yet, jump to the section on “<a href="#how-to-collect-the-required-data">How to collect the required data</a>”. It is pointless to go through steps 1–3 if you don’t already have a <code class="language-plaintext highlighter-rouge">keylog.csv</code> file that contains at least 1000 entries.</p>

<h2 id="1-a-picture-of-your-layout">1. A picture of your layout</h2>
<p>The first thing you need to do is to upload a picture of your layout. It can be any image you want but for best effects, I recommend a 2D black and white picture with high contrast. Avoid blue, green, yellow, and red in your layout graphic as those are used to draw the heatmap. If you don’t already have a graphic representation of your keymap, you can use <a href="https://keyboard-layout-editor.com">keyboard-layout-editor</a> or take a screenshot from the <a href="https://config.qmk.fm/#/">QMK configurator</a>.</p>

<p>Avoid uploading a picture which separates all your different layers like in <a href="/assets/images/qmk-heatmap/keymap_layout_broken_down_by_layers.png">this example</a>. You only get to match as many keys as you have submitted in the text box for the ASCII representation of your board.</p>

<h2 id="2-a-text-representation-of-the-matrix-positions-of-your-keyboard">2. A text representation of the matrix positions of your keyboard</h2>
<p>Next, you can see a text box prompting you to paste the text representation of the matrix layout produced by <code class="language-plaintext highlighter-rouge">qmk info --matrix</code>, or <code class="language-plaintext highlighter-rouge">qmk info -m</code> in short. If you wish to obtain the pseudo-graphic layout for another board than your main (as defined by <code class="language-plaintext highlighter-rouge">qmk config</code>), you can run <code class="language-plaintext highlighter-rouge">qmk info -kb &lt;name&gt; -m</code>. For example, <code class="language-plaintext highlighter-rouge">qmk info -kb handwired/dactyl -m</code> produces the following output:</p>

<pre style="line-height:16px">
Keyboard Name: Dactyl
Manufacturer: Unknown
Website: 
Maintainer: QMK Community
Keyboard Folder: handwired/dactyl
Layouts: LAYOUT_dactyl
Size: 17 x 8
Processor: atmega32u4
Bootloader: halfkay
Matrix for "LAYOUT_dactyl":
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐
│0A││0B││0C││0D││0E││0F│                    │0G││0H││0I││0J││0K││0L│
└──┘└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐
│1A││1B││1C││1D││1E││1F│                    │1G││1H││1I││1J││1K││1L│
└──┘└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐
│2A││2B││2C││2D││2E││2F│                    │2G││2H││2I││2J││2K││2L│
└──┘└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐                    ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐
│3A││3B││3C││3D││3E││3F│                    │3G││3H││3I││3J││3K││3L│
└──┘└──┘└──┘└──┘└──┘└──┘                    └──┘└──┘└──┘└──┘└──┘└──┘
┌──┐┌──┐┌──┐┌──┐┌──┐                            ┌──┐┌──┐┌──┐┌──┐┌──┐
│4A││4B││4C││4D││4E│                            │4H││4I││4J││4K││4L│
└──┘└──┘└──┘└──┘└──┘                            └──┘└──┘└──┘└──┘└──┘
                        ┌──┐┌──┐    ┌──┐┌──┐
                        │5F││5A│    │5L││5G│
                        └──┘└──┘    └──┘└──┘
                    ┌──┐┌──┐┌──┐    ┌──┐┌──┐┌──┐
                    │5D││5C││5E│    │5H││5J││5I│
                    │  ││  │└──┘    └──┘│  ││  │
                    │  ││  │┌──┐    ┌──┐│  ││  │
                    │  ││  ││5B│    │5K││  ││  │
                    └──┘└──┘└──┘    └──┘└──┘└──┘
</pre>

<p>Only copy-paste the lines after “Matrix for …”.</p>

<p>Note: for a handwired board, there is the possibility that the actual wiring of your board differs from that of the matrix <code class="language-plaintext highlighter-rouge">qmk info -m</code> spits out. Double check that if you notice a key you rarely press gets colored in bright colors.</p>

<h2 id="3-a-link-between-each-key-in-the-matrix-to-the-corresponding-key-in-the-provided-picture">3. A link between each key in the matrix to the corresponding key in the provided picture</h2>
<p>After pasting the matrix into the text area, left click on the picture the spot that corresponds to each key in the text matrix starting from the top left corner and moving from left to right, top to bottom.</p>

<p>Watch out for columnar staggered boards like the Lily 58. The web-tool reads in the matrix line by line so the following matrix:</p>
<pre style="line-height:16px">
            ┌──┐                                  ┌──┐
        ┌──┐│0D│┌──┐┌──┐                  ┌──┐┌──┐│5C│┌──┐
┌──┐┌──┐│0C│└──┘│0E││0F│                  │5A││5B│└──┘│5D│┌──┐┌──┐
│0A││0B│└──┘┌──┐└──┘└──┘                  └──┘└──┘┌──┐└──┘│5E││5F│
└──┘└──┘┌──┐│1D│┌──┐┌──┐                  ┌──┐┌──┐│6C│┌──┐└──┘└──┘
┌──┐┌──┐│1C│└──┘│1E││1F│                  │6A││6B│└──┘│6D│┌──┐┌──┐
│1A││1B│└──┘┌──┐└──┘└──┘                  └──┘└──┘┌──┐└──┘│6E││6F│
└──┘└──┘┌──┐│2D│┌──┐┌──┐                  ┌──┐┌──┐│7C│┌──┐└──┘└──┘
┌──┐┌──┐│2C│└──┘│2E││2F│                  │7A││7B│└──┘│7D│┌──┐┌──┐
│2A││2B│└──┘┌──┐└──┘└──┘┌──┐          ┌──┐└──┘└──┘┌──┐└──┘│7E││7F│
└──┘└──┘┌──┐│3D│┌──┐┌──┐│4F│          │8A│┌──┐┌──┐│8D│┌──┐└──┘└──┘
┌──┐┌──┐│3C│└──┘│3E││3F│└──┘          └──┘│8B││8C│└──┘│8E│┌──┐┌──┐
│3A││3B│└──┘    └──┘└──┘                  └──┘└──┘    └──┘│8F││9F│
└──┘└──┘  ┌──┐┌──┐┌──┐  ┌──┐          ┌──┐  ┌──┐┌──┐┌──┐  └──┘└──┘
          │4B││4C││4D│  │4E│          │9B│  │9C││9D││9E│
          └──┘└──┘└──┘  │  │          │  │  └──┘└──┘└──┘
                        │  │          │  │
                        └──┘          └──┘
</pre>
<p>will read keys in the following order:</p>
<video controls="" width="922">
<source src="assets/images/qmk-heatmap/matching-columnar-stagger-lily58.webm" alt="0D 5C 0C 0E 0F 5A 5B 5D 0A 0B 5E 5F 1D 6C 1C 1E 1F 6A 6B 6D 1A 1B 6E 6F" type="video/webm" />
</video>

<p>Is it annoying? Yes. I’m currently working on a desktop app that makes this process a lot more convenient. In the app, you’ll be able to select a bunch of circles at once, copy, drag and paste them wherever you want, undo and redo previous actions and more, so stay tuned!</p>

<p>If you misclicked or placed the dot a few millimeters away from the true center of the keycap and it’s driving you mad, you can Shift+Left Click anywhere on the canvas to undo the last operation.</p>

<p>Click a final time on the picture after having matched all matrix positions to points on the image to save the matching pairs and finally spawn the button that will let you upload your <code class="language-plaintext highlighter-rouge">keylog.csv</code>.</p>

<h2 id="4-generating-a-heatmap">4. Generating a heatmap</h2>
<p>After having collected enough data in the expected format, you can now submit your <code class="language-plaintext highlighter-rouge">keylog.csv</code> file (the exact name of the csv file isn’t important) to the above tool in order to generate a pretty heatmap of your typing habits.</p>

<p>A heatmap overlay will appear over the keys as soon as you upload the file.</p>

<p>NOTE: Make sure the keylog file is encoded in UTF-8! Windows may create a UTF-16 file if you pipe the output of <code class="language-plaintext highlighter-rouge">hid_listen</code>.</p>

<hr />

<h1 id="how-to-collect-the-required-data">How to collect the required data</h1>

<p>To accurately modelize your typing habits, you first need to collect enough real-word data. The more, the better.</p>

<p>To avoid skewing results, don’t play typing games such <a href="https://monkeytype.com">monkeytype</a> or <a href="https://typingracer.com">typingracer</a> while logging your keystrokes. Typing random strings of words and movie quotes isn’t a good reflection of your actual keyboard usage — unless you’re into competitive typing.</p>

<p>To collect key strokes data in the expected format, there are two things you need to setup:</p>
<ol>
  <li>Keyboard firmware</li>
  <li>A program that logs what the keyboard firmware sends into a csv file</li>
</ol>

<p>(The following instructions primarily cater to users of a UNIX environment — sorry Windows users.)</p>

<h2 id="keyboard-firmware-setup">Keyboard firmware setup</h2>

<p>First off, you need to program your keyboard firmware to send your desired information to the host.</p>

<p>To do that, append the following line to <code class="language-plaintext highlighter-rouge">rules.mk</code>:</p>
<pre><code class="language-mk">CONSOLE_ENABLE = yes
</code></pre>

<p>Next, open <code class="language-plaintext highlighter-rouge">keymap.c</code> and add these lines at the top of the file. This will import the <code class="language-plaintext highlighter-rouge">uprintf</code> function that we’ll later use, but only if <code class="language-plaintext highlighter-rouge">CONSOLE_ENABLE</code> is turned on.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifdef CONSOLE_ENABLE
#include</span> <span class="cpf">"print.h"</span><span class="cp">
#endif
</span></code></pre></div></div>

<p>After including <code class="language-plaintext highlighter-rouge">print.h</code>, head to the <code class="language-plaintext highlighter-rouge">process_record_user</code> function (More info about this function can be found <a href="https://docs.qmk.fm/#/custom_quantum_functions?id=programming-the-behavior-of-any-keycode">here</a>) and write the <code class="language-plaintext highlighter-rouge">#ifdef</code> code block just after the function signature but before the switch statement:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bool</span> <span class="nf">process_record_user</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="n">keycode</span><span class="p">,</span> <span class="n">keyrecord_t</span> <span class="o">*</span><span class="n">record</span><span class="p">)</span> <span class="p">{</span>
    <span class="cp">#ifdef CONSOLE_ENABLE
</span>        <span class="k">const</span> <span class="n">bool</span> <span class="n">is_combo</span> <span class="o">=</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">COMBO_EVENT</span><span class="p">;</span>
        <span class="n">uprintf</span><span class="p">(</span><span class="s">"0x%04X,%u,%u,%u,%b,0x%02X,0x%02X,%u</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
             <span class="n">keycode</span><span class="p">,</span>
             <span class="n">is_combo</span> <span class="o">?</span> <span class="mi">254</span> <span class="o">:</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">key</span><span class="p">.</span><span class="n">row</span><span class="p">,</span>
             <span class="n">is_combo</span> <span class="o">?</span> <span class="mi">254</span> <span class="o">:</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">key</span><span class="p">.</span><span class="n">col</span><span class="p">,</span>
             <span class="n">get_highest_layer</span><span class="p">(</span><span class="n">layer_state</span><span class="p">),</span>
             <span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span><span class="p">,</span>
             <span class="n">get_mods</span><span class="p">(),</span>
             <span class="n">get_oneshot_mods</span><span class="p">(),</span>
             <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span>
             <span class="p">);</span>
    <span class="cp">#endif
</span>    <span class="k">switch</span> <span class="p">(</span><span class="n">keycode</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">//...</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This will print the hexadecimal representation of every key you press as well as its row and its column. Make sure to not leave any space between the commas and to end the string with a newline <code class="language-plaintext highlighter-rouge">\n</code>.</p>

<details>
  <summary>Additional instructions for combos</summary>
  <p>If you want to log combo key presses, there are a few more things you need to do. If you’re using the wrapper <code class="language-plaintext highlighter-rouge">[AB_ESC] = COMBO(combo_sequence, KC_ESC)</code>, there is nothing extra that you have to do. However, here’s what you have to insert in <code class="language-plaintext highlighter-rouge">processs_combo_event</code> if you use the <code class="language-plaintext highlighter-rouge">COMBO_ACTION</code> wrapper for defining (some of) your combos:</p>
  <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifdef CONSOLE_ENABLE
</span>    <span class="n">combo_t</span> <span class="o">*</span><span class="n">combo</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">key_combos</span><span class="p">[</span><span class="n">combo_index</span><span class="p">];</span>
    <span class="kt">uint8_t</span> <span class="n">idx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">uint16_t</span> <span class="n">combo_keycode</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">((</span><span class="n">combo_keycode</span> <span class="o">=</span> <span class="n">pgm_read_word</span><span class="p">(</span><span class="o">&amp;</span><span class="n">combo</span><span class="o">-&gt;</span><span class="n">keys</span><span class="p">[</span><span class="n">idx</span><span class="p">]))</span> <span class="o">!=</span> <span class="n">COMBO_END</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">uprintf</span><span class="p">(</span><span class="s">"0x%04X,%u,%u,%u,%u,0x%02X,0x%02X,0</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
            <span class="n">combo_keycode</span><span class="p">,</span>
            <span class="mi">254</span><span class="p">,</span>
            <span class="mi">254</span><span class="p">,</span>
            <span class="n">get_highest_layer</span><span class="p">(</span><span class="n">layer_state</span><span class="p">),</span>
            <span class="n">pressed</span><span class="p">,</span>
            <span class="n">get_mods</span><span class="p">(),</span>
            <span class="n">get_oneshot_mods</span><span class="p">()</span>
            <span class="cm">/* tap_count */</span>
        <span class="p">);</span>
        <span class="n">idx</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
<span class="cp">#endif
</span></code></pre></div>  </div>
  <p>As you can notice, <code class="language-plaintext highlighter-rouge">processs_combo_event</code> doesn’t actually give any meaningful information on the matrix position of combo key presses. This is why the row and column fields in the printed output are filled in with the “magic” constant value 254 (historically called <code class="language-plaintext highlighter-rouge">KEYLOC_COMBO</code>).</p>

  <p>These “missing” constant values will be automatically filled in by the QMK Heatmap Generator based on keys you’ve typed outside of combos. For example, if you have a combo involving <code class="language-plaintext highlighter-rouge">KC_A</code> and <code class="language-plaintext highlighter-rouge">KC_S</code>, executing the combo will output these two lines:</p>
  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x004,254,254,0,1,0x00,0x00,0
0x018,254,254,0,1,0x00,0x00,0
0x004,254,254,0,0,0x00,0x00,0
0x018,254,254,0,0,0x00,0x00,0
</code></pre></div>  </div>
  <p>but simply tapping those keys by themselves, one after another would produce something like:</p>

  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x004,3,2,0,1,0x00,0x00,0
0x004,3,2,0,0,0x00,0x00,0
0x018,3,3,0,1,0x00,0x00,0
0x018,3,3,0,0,0x00,0x00,0
</code></pre></div>  </div>
  <p>Based on this, we can infer that the keycode <code class="language-plaintext highlighter-rouge">0x004</code> is positionned in the third row, second column and that <code class="language-plaintext highlighter-rouge">0x018</code> is positionned in the third row, third column.</p>

  <p>Thus, if you use a key <em>exclusively</em> in combos, there won’t be any row,col information associated with that keycode in your <code class="language-plaintext highlighter-rouge">keylog.csv</code> and as such, the generator cannot infer what’s the row and column of that key and it will remain 254. This is why it helps to press every key of your keyboard at least once; to get a complete record.</p>

</details>

<p>At this stage, the keyboard firmware is ready to go and you can flash the firmware onto your board.</p>

<h2 id="host-computer-setup">Host computer setup</h2>

<p>The next steps will be about setting up the host computer to listen to what the keyboard sends and actually log that output to a csv file.</p>

<p>To listen to your keyboard, you’ll need to install <a href="https://www.pjrc.com/teensy/hid_listen.html">hid_listen</a>. There are pre-compiled binaries available for download for most operating systems except for Linux 64-bit for which you’ll need to download the source code and run <code class="language-plaintext highlighter-rouge">make</code> at the root of the downloaded <code class="language-plaintext highlighter-rouge">hid_listen/</code> folder.</p>

<p>Now, all you need to start logging key presses is to let this command run in the background while you’re using your keyboard normally:</p>

<p>UNIX system:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> ./hid_listen | egrep <span class="nt">--line-buffered</span> <span class="s2">"(0x[A-F0-9]+,)?[0-9]+,[0-9]+,[0-9]{1,2}"</span> | <span class="nb">tee</span> <span class="nt">-a</span> keylog.csv
</code></pre></div></div>

<p>Windows system (Powershell):</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">.</span><span class="n">\hid_listen.exe</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Select-String</span><span class="w"> </span><span class="nt">-Pattern</span><span class="w"> </span><span class="s2">"(0x[A-F0-9]+,)?[0-9]+,[0-9]+,[0-9]{1,2}"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Tee-Object</span><span class="w"> </span><span class="nx">keylog.csv</span><span class="w">
</span></code></pre></div></div>

<p>The output should look like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x6117,2,4,0,1,0x00,0x00,0
0x002A,10,0,0,1,0x01,0x00,0
0x002A,10,0,0,0,0x01,0x00,0
0x6117,2,4,0,0,0x01,0x00,0
0x6216,2,3,0,1,0x00,0x00,1
0x6216,2,3,0,0,0x00,0x00,1
</code></pre></div></div>

<p>Every time you press any key on your keyboard, a new line should be appended to the standard output and to the <code class="language-plaintext highlighter-rouge">keylog.csv</code> file which will be stored in the same directory as that of the <code class="language-plaintext highlighter-rouge">hid_listen</code> executable file.</p>

<p>If you don’t want to flood the standard output, you can replace <code class="language-plaintext highlighter-rouge">| tee -a</code> by <code class="language-plaintext highlighter-rouge">&gt;&gt;</code> like so:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> ./hid_listen | egrep <span class="nt">--line-buffered</span> <span class="s2">"(0x[A-F0-9]+,)?[0-9]+,[0-9]+,[0-9]{1,2}"</span> <span class="o">&gt;&gt;</span> keylog.csv
</code></pre></div></div>
<p>This will silently append <code class="language-plaintext highlighter-rouge">&lt;keycode&gt;,&lt;row&gt;,&lt;col&gt;,&lt;layer&gt;,&lt;pressed&gt;,&lt;mod_state&gt;,&lt;oneshot_mod_state&gt;,&lt;tap_count&gt;</code> to <code class="language-plaintext highlighter-rouge">keylog.csv</code> anytime you press a key on your keyboard.</p>

<h1 id="why-should-i-trust-this-web-tool-with-my-keylogging-data">Why should I trust this web-tool with my keylogging data?</h1>
<p>This entire website is static and open source, meaning none of your data gets sent to any server, all the processing happens client-side and anyone can inspect the code. More importantly, the <code class="language-plaintext highlighter-rouge">keylog.csv</code> file that you upload to the web-tool doesn’t actually contain the key<em>sym</em> you’ve typed, only the raw hexadecimal key<em>codes</em>.</p>

<p>For example, there isn’t one clear-cut keycode that will always produce “A” on screen. <code class="language-plaintext highlighter-rouge">KC_LSHIFT</code> followed by <code class="language-plaintext highlighter-rouge">KC_A</code> will produce a different keycode from <code class="language-plaintext highlighter-rouge">S(KC_A)</code> and yet produces the same final output nonetheless. Tapping <code class="language-plaintext highlighter-rouge">LGUI_T(KC_A)</code> will result in yet another hexadecimal keycode and so will <code class="language-plaintext highlighter-rouge">LT(_LAYER, KC_A)</code>. And all of that doesn’t take into account the variability of regional OS keyboard layouts. <code class="language-plaintext highlighter-rouge">0x0004</code> would get interpreted as “a” if your OS is configured to use QWERTY but for all I know, you may as well be using AZERTY, in which case that keycode will instead output “q” or, to give another example, “ф” if you use ЙЦУКЕН.</p>

<p>I have no desire to deal with that ambiguous mess.</p>

<p>The keycodes only get used to fill in the row,col values for combo actions, so if you feel particularly paranoiac, you can delete the first column of the csv file containing the hexadecimal keycode (very easy to do in any spreadsheet application) and shuffle the order of the csv lines before uploading it. All that really matters to the generator is the <code class="language-plaintext highlighter-rouge">row</code>, the <code class="language-plaintext highlighter-rouge">col</code>, and the <code class="language-plaintext highlighter-rouge">layer</code> of each key press.</p>]]></content><author><name>precondition</name></author><category term="Keyboards" /><category term="Keyboards" /><category term="Keymap" /><category term="QMK" /><summary type="html"><![CDATA[Generate a heatmap of key presses for any QMK keyboard based on real key logging data]]></summary></entry><entry><title type="html">A guide to home row mods</title><link href="/home-row-mods" rel="alternate" type="text/html" title="A guide to home row mods" /><published>2020-12-12T00:00:00+00:00</published><updated>2020-12-12T00:00:00+00:00</updated><id>/home-row-mods</id><content type="html" xml:base="/home-row-mods"><![CDATA[<p>If you’ve been browsing mechanical keyboard communities, and especially the niche that is ergonomic mechanical keyboards, you may have come across the term “home row mods” and wondered what could that mean. Well, wonder no more for I shall explain!</p>

<div style="position: relative;">
  <p><a href="#toc-skipped" class="screen-reader-only">Skip table of contents</a></p>
</div>

<ul id="markdown-toc">
  <li><a href="#what-are-home-row-mods" id="markdown-toc-what-are-home-row-mods">What are home row mods?</a></li>
  <li><a href="#why-use-home-row-mods" id="markdown-toc-why-use-home-row-mods">Why use home row mods?</a></li>
  <li><a href="#how-to-use-home-row-mods" id="markdown-toc-how-to-use-home-row-mods">How to use home row mods?</a>    <ul>
      <li><a href="#home-row-mods-order" id="markdown-toc-home-row-mods-order">Home row mods order</a>        <ul>
          <li><a href="#scga" id="markdown-toc-scga">SCGA/⇧⎈◆⎇</a></li>
          <li><a href="#gasc" id="markdown-toc-gasc">GASC/◆⎇⇧⎈</a></li>
          <li><a href="#gacs" id="markdown-toc-gacs">GACS/◆⎇⎈⇧</a></li>
          <li><a href="#cags" id="markdown-toc-cags">CAGS/⎈⎇◆⇧</a></li>
        </ul>
      </li>
      <li><a href="#implementation" id="markdown-toc-implementation">Implementation</a></li>
      <li><a href="#using-home-row-mods-with-qmk" id="markdown-toc-using-home-row-mods-with-qmk">Using home row mods with QMK</a>        <ul>
          <li><a href="#tap-hold-configuration-settings" id="markdown-toc-tap-hold-configuration-settings">Tap Hold configuration settings</a>            <ul>
              <li><a href="#default" id="markdown-toc-default">Default</a></li>
              <li><a href="#tapping-term" id="markdown-toc-tapping-term">Tapping Term</a></li>
              <li><a href="#quick-tap-term" id="markdown-toc-quick-tap-term">Quick Tap Term</a></li>
              <li><a href="#permissive-hold" id="markdown-toc-permissive-hold">Permissive Hold</a></li>
              <li><a href="#hold-on-other-key-press" id="markdown-toc-hold-on-other-key-press">Hold on Other Key Press</a></li>
              <li><a href="#retro-tapping" id="markdown-toc-retro-tapping">Retro Tapping</a></li>
              <li><a href="#retro-shift" id="markdown-toc-retro-shift">Retro Shift</a></li>
            </ul>
          </li>
          <li><a href="#getting-started-with-home-row-mods-on-qmk" id="markdown-toc-getting-started-with-home-row-mods-on-qmk">Getting started with home row mods on QMK</a></li>
          <li><a href="#qmk-home-row-mods-code-generator" id="markdown-toc-qmk-home-row-mods-code-generator">Home row mods code generator</a></li>
        </ul>
      </li>
      <li><a href="#using-home-row-mods-with-kmonad" id="markdown-toc-using-home-row-mods-with-kmonad">Using home row mods with KMonad</a>        <ul>
          <li><a href="#getting-started-with-home-row-mods-on-kmonad" id="markdown-toc-getting-started-with-home-row-mods-on-kmonad">Getting started with home row mods on KMonad</a>            <ul>
              <li><a href="#1-defcfg" id="markdown-toc-1-defcfg">1. defcfg</a></li>
              <li><a href="#2-defsrc" id="markdown-toc-2-defsrc">2. defsrc</a></li>
              <li><a href="#3-defalias" id="markdown-toc-3-defalias">3. defalias</a></li>
              <li><a href="#4-deflayer" id="markdown-toc-4-deflayer">4. deflayer</a></li>
              <li><a href="#final-result" id="markdown-toc-final-result">Final result</a></li>
            </ul>
          </li>
          <li><a href="#kmonad-home-row-mods-code-generator" id="markdown-toc-kmonad-home-row-mods-code-generator">Home row mods code generator</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="#tips-and-tricks" id="markdown-toc-tips-and-tricks">Tips &amp; Tricks</a>    <ul>
      <li><a href="#quick-swift-taps" id="markdown-toc-quick-swift-taps">Quick swift taps</a></li>
      <li><a href="#finding-the-sweet-spot" id="markdown-toc-finding-the-sweet-spot">Finding the sweet spot</a>        <ul>
          <li><a href="#tapping-term-test-area" id="markdown-toc-tapping-term-test-area">Tapping term test area</a></li>
        </ul>
      </li>
      <li><a href="#use-left-and-right-modifiers-but-beware-of-altgr" id="markdown-toc-use-left-and-right-modifiers-but-beware-of-altgr">Use left and right modifiers but beware of AltGr!</a></li>
      <li><a href="#putting-home-row-mods-on-almost-all-layers" id="markdown-toc-putting-home-row-mods-on-almost-all-layers">Putting home row mods on (almost) all layers</a></li>
      <li><a href="#disabling-home-row-mods-when-gaming" id="markdown-toc-disabling-home-row-mods-when-gaming">Disabling home row mods when gaming</a></li>
      <li><a href="#shift-thumb-keys" id="markdown-toc-shift-thumb-keys">Shift thumb keys</a></li>
      <li><a href="#use-caps-lock" id="markdown-toc-use-caps-lock">Use Caps Lock</a></li>
      <li><a href="#mechanical-switch-type" id="markdown-toc-mechanical-switch-type">Mechanical switch type</a></li>
      <li><a href="#using-non-basic-keycodes-in-mod-taps" id="markdown-toc-using-non-basic-keycodes-in-mod-taps">Using non-basic keycodes in mod-taps</a></li>
      <li><a href="#combined-mod-taps-on-the-lower-row" id="markdown-toc-combined-mod-taps-on-the-lower-row">Combined mod-taps on the lower row</a></li>
      <li><a href="#rolled-modifiers-cancellation" id="markdown-toc-rolled-modifiers-cancellation">Rolled modifiers cancellation</a></li>
      <li><a href="#using-mod-taps-in-combos" id="markdown-toc-using-mod-taps-in-combos">Using mod-taps in combos<!-- [WIP] --></a></li>
    </ul>
  </li>
  <li><a href="#alternatives" id="markdown-toc-alternatives">Alternatives</a>    <ul>
      <li><a href="#alternative-home-row-mods-layout" id="markdown-toc-alternative-home-row-mods-layout">Alternative home row mods layout</a></li>
      <li><a href="#upperlower-row-mods" id="markdown-toc-upperlower-row-mods">Upper/Lower row mods</a></li>
      <li><a href="#home-row-mod-combos" id="markdown-toc-home-row-mod-combos">Home row mod-combos</a>        <ul>
          <li><a href="#sticky-combos" id="markdown-toc-sticky-combos">Sticky Combos</a></li>
          <li><a href="#combo-misfires" id="markdown-toc-combo-misfires">Combo misfires</a></li>
        </ul>
      </li>
      <li><a href="#chording-with-thumb-keys" id="markdown-toc-chording-with-thumb-keys">Chording with thumb keys</a>        <ul>
          <li><a href="#layers" id="markdown-toc-layers">Layers</a></li>
          <li><a href="#combos" id="markdown-toc-combos">Combos</a></li>
        </ul>
      </li>
      <li><a href="#tap-dances" id="markdown-toc-tap-dances">Tap dances</a></li>
    </ul>
  </li>
  <li><a href="#summary" id="markdown-toc-summary">Summary</a></li>
  <li><a href="#tldr-table" id="markdown-toc-tldr-table">TL;DR Table</a></li>
</ul>

<div id="toc-skipped"></div>

<h1 id="what-are-home-row-mods">What are home row mods?</h1>

<p>Let’s first deconstruct the term. The “home row” refers to the middle row of alpha keys. On an English QWERTY keyboard this would be
<kbd>A</kbd><kbd>S</kbd><kbd>D</kbd><kbd>F</kbd><kbd>G</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd><kbd>;</kbd>.
This row is called the “<em>home</em> row” because if one were to follow touch typing technique, this is the row of keys on which your fingers are supposed to rest on. The bars or the dish found on <kbd>F</kbd> and <kbd>J</kbd> help to find back the home position without looking at the keyboard — this is especially important for relatively big keyboards which require you to move your hands to hit some of the keys like for example <kbd>Backspace</kbd> or the arrow keys on a classic <abbr title="Ten Key Less">TKL</abbr> and thus throw you off home position.</p>

<figure>
    
    <img src="assets/images/home-row-mods/f-j-bumps-on-keyboard.jpg" alt="Zoom in on a keyboard with grey QWERTY keycaps with the F and J keys circled in red" />
    

    <figcaption><span>Homing bars</span></figcaption>

</figure>

<p>Next is “mods”. What is meant by “mods”? In this case, “mods” refer to modifiers, that is to say <kbd>⇧ Shift</kbd>, <kbd>⎈ Control</kbd>, <kbd>⎇ Alt</kbd>, and <kbd>◆ GUI</kbd>. The last modifier in the list is also known as WinKey on Windows, Command on MacOS or Super/Meta<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> on Linux and BSD. Do not confuse the term with actual graphical user interfaces.</p>

<p>So this means that “home row mods” are about placing modifiers on the home row.</p>

<p>How can that be possible? Does this mean that the home row letters/symbols swap positions with the modifier keys? Most certainly not! You see, one of the untapped potential of modifiers that are active as long as you hold them is that they don’t do anything useful when they’re tapped (i.e. pressed and released) on their own — a notable exception is the Win/Super key which opens the start menu on Windows and Gnome as well as Alt which pops up the menu in graphical apps — but thanks to software like <a href="https://docs.qmk.fm/#/">QMK</a>, we can turn these momentary switch modifiers into dual-role keys which act as modifiers when held but act as other keys when tapped. This allows us to make more with less.</p>

<p>The name QMK gives to this functionality is “mod-tap”. Mod-taps are a subset of <a href="http://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys">dual-role keys</a>. Other software which also implement this functionality call it differently. Therefore, we really should say “home row mod-taps” but in common parlance, “home row mods” is what’s always used.</p>

<p>We now know <em>what</em> home row mods are; it is the practice of turning the home row keys into mod-taps. We have yet to figure out <em>why</em> use home row mods.</p>

<h1 id="why-use-home-row-mods">Why use home row mods?</h1>

<p>The reason why would anyone choose to use home row mods are quite simple. A keyboard is no longer used exclusively for text input. It is also used to navigate and operate a computer, launch programs, format text, execute macros, zoom in and out, change input language and so much more which goes beyond simply typing letters. Modifiers play a big role in those functions.</p>

<p>Obviously, typewriters did not have any of those functions. They could only type. The modifier keys that we use so much now were added afterwards, kind of as an afterthought, over the classic typewriter layout which plagues us to this day. It was decided to reduce the width of the spacebar in order to make space for the modifier keys that were needed for the computer age.</p>

<figure>
  <p><a href="https://genevatypewriters.blogspot.com/2010/11/variations-on-typewriter-keyboard.html">
        <img src="https://4.bp.blogspot.com/_8pq4w7Eq5-Q/TO2K1vc3MMI/AAAAAAAABiA/rr6e91NHUqc/s1600/IMG_0830.JPG" alt="A photo of an Italian QZERTY keyboard/typewriter on a Hermes Baby" title="An Italian QZERTY typewriter on a Hermes Baby" />
</a></p>
  <figcaption>
    <p>On some typewriters, the spacebar was ｒｉｄｉｃｕｌｏｕｓｌｙ ｗｉｄｅ.</p>
  </figcaption>
</figure>

<p>As a consequence, you need to do all sorts of finger gymnastics in order to trigger keyboard shortcuts. Not only are you playing Twister with your fingers, you’re straining the weakest finger the most in order to hold the necessary modifiers.</p>

<p>This approach to keyboard shortcuts presents some biomechanical issues. These chords may require hyper-extending, hyper-flexing, or splaying the fingers, and may necessitate uncomfortable static muscular loads on top of awkward hand position, especially wrist deviation. All of which can lead to cumulative trauma disorders, as explained by Vern Putz-Anderson in his book titled <em>“Cumulative trauma disorders: A manual for musculoskeletal diseases of the upper limbs”</em>, published in 1988.</p>

<p>It is in your best interest to find a solution at the risk of maybe getting RSI and Emacs pinky one day. This is especially important for programmers as most of their keyboard usage isn’t actually typing symbols but triggering commands with a plethora of different keyboard shortcuts. Though any power user of any application, not just programmers in their text editor, uses keyboard shortcuts extensively.</p>

<p>Home row mods are about the best solution to this modifier problem. The fact that there are four modifiers, each coming with a left and a right version perfectly matches the eight fingers resting on the home row. We can put a modifier under each finger and mirror it on both hands.</p>

<p>Isn’t it great to have ALL the modifiers at our finger tips? No motion, stretching or strain required. This rapid access to modifier chords is very comfortable and allows to blend the execution of keyboard shortcuts in the typing flow, whereas it previously required a context switch to stop composing text, move the hands to the corner(s) of the keyboard, trigger the desired keyboard shortcut and then find back the homing position to continue touch typing text.</p>

<p>The other benefit of having all the modifiers lined up in a row and each dedicated a specific finger is that you can trigger ANY keyboard shortcut with ease.
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>GUI</kbd>+<kbd>Alt</kbd>, also sometimes called <a href="https://stevelosh.com/blog/2012/10/a-modern-space-cadet/#s14-hyper">Hyper</a>,
is an insanity on a standard keyboard but with home row mods, it is trivial: just hold down the four fingers of your hand on the keys you’re already resting on. Dedicating a specific finger for each of the four modifier also greatly reduces the amount of repetitive motions your pinky has to execute for all the keyboard shortcuts. Home row mods are also advantageous for the thumbs, for it frees them up for something else like layer switches or <a href="pressing-e-with-the-thumb">even letters</a>. In fact, home row mods and layer thumb keys are a perfect fit. It makes it very easy to chord layers and modifiers together without forcing finger contortions or same finger utilization.</p>

<p>Finally, home row mods (or <a href="#alternatives">variations of the concept</a> which we’ll talk about later in the article) is (a part of) the secret sauce to making all those tiny keyboards without outer pinky columns that you’ve always deemed to be too small to be usable,… actually usable.</p>

<!-- Add gallery of 30%'s -->

<p>Are you convinced? If so, let’s now look at the <em>how</em>.</p>

<h1 id="how-to-use-home-row-mods">How to use home row mods?</h1>

<p>Before we can talk about the technical implementation details, let’s briefly talk about the order of home row mods.</p>

<h2 id="home-row-mods-order">Home row mods order</h2>

<p>How should you lay out the modifiers on the home row? You have multiple options.</p>

<p>To make this easier to understand, let’s agree on common terminology first.</p>

<table>
  <thead>
    <tr>
      <th>Full Modifier Name</th>
      <th>Abbreviation</th>
      <th>Symbol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Shift</td>
      <td>S</td>
      <td>⇧</td>
    </tr>
    <tr>
      <td>Control</td>
      <td>C</td>
      <td>⎈</td>
    </tr>
    <tr>
      <td>Alt/Option</td>
      <td>A</td>
      <td>⎇</td>
    </tr>
    <tr>
      <td>GUI/Win/Command</td>
      <td>G</td>
      <td>◆</td>
    </tr>
    <tr>
      <td>No modifier/mod-tap</td>
      <td>_</td>
      <td>_</td>
    </tr>
  </tbody>
</table>

<p>This means that the home row mods setup shown in the cover picture of this blog post can be written as ◆⎇⇧⎈__⎈⇧⎇◆ when using the symbols or as GASC__CSAG when using the 1-letter abbreviations. However, since the mod-taps on the right hand are symmetric to the mod-taps on the left hand, the right-hand can be omitted. Trailing underscores can also be omitted to finally produce the following notation: GASC/◆⎇⇧⎈.</p>

<p>Now that the semantics are clear, let’s talk about some interesting orders of the home row mods to give you some ideas for your own.</p>

<h3 id="scga">SCGA/⇧⎈◆⎇</h3>

<p>If one were to transpose the standardized modifiers layout into a 1D line, this would be it. It might look familiar and thus potentially easier to learn but keep in mind that, aside from the Shift modifiers, all the modifiers now use a different finger than what you’re used to.</p>

<figure>
  <p><a href="https://i.redd.it/oflfwzh5mbv01.jpg">
        <img src="https://i.redd.it/oflfwzh5mbv01.jpg" alt="Standard row-staggered keyboard with colorful accent modifier keys" />
</a></p>
  <figcaption>
    <p>Highlighted modifier keys on a standard row-staggered TKL keyboard. When reading the left corner of modifiers from top to botton, left to right, we get SCGA.</p>
  </figcaption>
</figure>

<p>Moreover, this is a poor allocation of the mods in regard to their frequency of usage. Assuming that you do not use Caps Lock or Shift Lock,<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> Shift is <em>by far</em> the most used modifier. It is generally unwise to let the pinky take on all this load. Although letting the pinky fingers deal with Shift is the option that will necessitate the least hand swaps when typing a string of capital letters. This order also positions Alt and GUI in an undeservingly good place. The index and middle fingers are the strongest of the four non-thumb fingers but Alt and GUI aren’t the most frequently used modifiers for Windows, Linux and BSD users.</p>

<h3 id="gasc">GASC/◆⎇⇧⎈</h3>

<p>This is the layout found in the cover pic of this article and what’s used in most of the examples. Compared to the SCGA order, this is much more reasonable in terms of using the strongest fingers for the most common modifiers in operating systems that are not MacOS.</p>

<p>Indeed, if you sort the four modifiers by their frequency in Windows and/or Linux, you will find: GUI &lt; Alt &lt; Control &lt; Shift.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> The observant among you will have noticed that this does not stick with GASC/◆⎇⇧⎈. Why are Control and Shift swapped? There are multiple reasons that can justify this choice:</p>
<ol>
  <li>The index finger is the finger that is responsible for the biggest amount of alpha keys so if you use the index finger to hold Shift, you’ll have to swap hands if you want to type any of the six keys — or <em>seven</em> keys if you’re on a row-stagger board and you type <kbd>C</kbd> with your left index — that the index finger is responsible for. If you’re someone who would rather not have to swap hands too much when typing capital letters, this can be interesting for you. However, do keep letter frequency in mind. In most alternative layouts, the inner index columns are populated with infrequent keys while the home row middle finger keys are assigned very common letters such as “E”.</li>
  <li>Putting Shift between Control and Alt is pretty nifty. It allows for easy chording of <kbd>Ctrl</kbd>+<kbd>Shift</kbd> and <kbd>Alt</kbd>+<kbd>Shift</kbd> (the most common combination of modifiers) by using adjacent fingers. That cannot be done with Shift placed on the index finger. Holding two modifiers that are one or two keys apart is not ideal.</li>
  <li>Concurrently to a Shift mod-tap on the home row, one may also have other Shift-like keys which are used in lieu of the home row mod to capitalize letters like for example <a href="#use-caps-lock">Caps Lock</a> or a <a href="#shift-thumb-keys">Shift thumb key</a>. By doing so, the Shift home row mod-tap is generally only used in combination with other modifiers, most frequently Control and Alt. Consequently, in light of bullet point 2, its best place is in the middle finger column.</li>
  <li>The position of GUI next to Alt allows for easy <kbd>GUI</kbd>+<kbd>Alt</kbd>+<kbd>Arrows</kbd>, a keyboard shortcut used in some DEs for switching between virtual desktops/workspaces. GUI gets put on the pinky as that’s generally the least used modifier (unless you use a tiling window manager which requires a lot of GUI keyboard shortcuts).</li>
  <li>The index fingers already have to deal with all the mouse clicking and dragging on top of all those extra inner keys it has to reach for, so you may be tempted to give it a little bit of break by sparing it from holding down a key for all your Shift needs.</li>
</ol>

<p>This works out great on ortholinear and vertically staggered keyboards but if you use a row-staggered keyboard, you may find that you’re suddenly unable to copy and paste one-handedly.</p>

<h3 id="gacs">GACS/◆⎇⎈⇧</h3>

<p>GACS is the order you come up with when you want to assign the most frequently used modifiers to the strongest and most agile fingers and the least frequently used modifiers to the weakest fingers. GACS is for those who reply to GASC’s bullet point 1 by saying that enabling a greater range of one-handed <kbd>Ctrl</kbd>+<kbd>Letter</kbd> keyboard shortcuts is more important than a greater range of one-handed capital letters you can type.</p>

<p>GACS is also, notably, the order used by the most famous QMK ergo layout involving home row mods: <a href="https://github.com/manna-harbour/qmk_firmware/tree/miryoku/users/manna-harbour_miryoku">Miryoku</a>.</p>

<p>A non-obvious advantage of having Shift on the index column is that it can help to minimize accidental capital letters when rolling keys. You can’t have accidental capital letters on inwards rolls if the last key you roll is pressed with the index finger. Obviously, that does not apply to outwards rolls but those are generally slower and it beats having Shift in the middle and risking it in both ways.</p>

<p>If you’re undecided, pick GACS/◆⎇⎈⇧, it is a solid choice.</p>

<h3 id="cags">CAGS/⎈⎇◆⇧</h3>

<p>What if you use MacOS instead? The GUI &lt; Alt &lt; Control &lt; Shift ranking is not representative of modifier usage in MacOS. It does not even use the right terms! A more appropriate ranking of modifiers by their usage in MacOS would be Ctrl &lt; Option &lt; Command &lt; Shift. A home row mods order conceived with this ranking in mind would thus be CAGS/⎈⎇◆⇧. CAGS is to MacOS as GACS is to Windows/Linux/BSD.</p>

<hr />

<p>Hopefully, these four examples give you a better idea of what goes behind the conception of an order in the way the different mod-taps are laid out on the home row. You have to account for modifier frequency, finger strength and agility but also the interplay between different modifiers and the impact of temporarily losing access to a column of keys when holding down a home row mod.</p>

<p>Naturally, this is not an exhaustive list of all possible permutations of modifiers along the eight home keys. In fact, changing the order isn’t the only thing you can do. You can lay out the mod-taps differently too. See the section on <a href="#alternative-home-row-mods-layout">alternative home row mods layouts</a>.</p>

<p>Even so, despite having written much about the different home row mods orders, in the end, it truly isn’t that important. Just pick one you like and roll with it. If you’re already used to a certain order, don’t let the above points convince you to change. When you’re starting out, the pragmatic question of how to lay out the modifiers on the home row might seem important but that impression is misplaced.</p>

<h2 id="implementation">Implementation</h2>
<p>For the best home row mods experience, I heartily recommend a QMK-powered mechanical keyboard. At the time of writing, QMK supports over 2935 keyboards! The greater part of which are DIY keyboards.</p>

<p>The following section will be about implementing home row mods in a QMK-powered keyboard with all the necessary settings to make it work well.</p>

<p>For those of you who do not have a QMK-powered board (or those who miss their home row mods when typing on laptop or on any other non-QMK keyboard), you will find a guide for implementing home row mods using <a href="https://github.com/david-janssen/kmonad">KMonad</a> just after this section on QMK.</p>

<h2 id="using-home-row-mods-with-qmk">Using home row mods with QMK</h2>

<p>As previously said, the way to create a dual-role key is to use what’s known as a “mod-tap” in QMK.
The mod-tap key, <code class="language-plaintext highlighter-rouge">MT(mod, kc)</code>, acts like a modifier when held, and a regular keycode when tapped. In other words, this is what allows us to have a key that sends “a” when you tap it, but function as a Shift or Control key when you hold it down. Note that the fact that we’ve turned <kbd>A</kbd> into a mod-tap does not make it impossible to use keyboard shortcuts involving the letter “A”. You can still do <kbd>Shift</kbd>+<kbd>A</kbd> or <kbd>Alt</kbd>+<kbd>A</kbd> just fine.
Although, depending on what modifier you decided to assign to <kbd>A</kbd>, you’ll need to use the opposite hand to combine that modifier with <kbd>A</kbd>.</p>

<!--Consider using the Miryoku order for the example instead-->
<p>Let me explain with an example. Let’s take the home row mod setup illustrated in the cover image of this blog post.</p>

<p><img src="assets/images/home-row-mods/RealisticHRM-Dark-SideLegends-GASC.png" alt="KLE render of dark blue QWERTY home row keycaps with mod icons in the center and mod name on the side of the keycaps" /></p>

<p>This setup, translated into code would look something like this:</p>

<figure class="highlight">
  <pre><code class="language-c" data-lang="c"><span class="n">MT</span><span class="p">(</span><span class="n">MOD_LGUI</span><span class="p">,</span> <span class="n">KC_A</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_LALT</span><span class="p">,</span> <span class="n">KC_S</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_LSFT</span><span class="p">,</span> <span class="n">KC_D</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_LCTL</span><span class="p">,</span> <span class="n">KC_F</span><span class="p">),</span>

<span class="n">MT</span><span class="p">(</span><span class="n">MOD_RCTL</span><span class="p">,</span> <span class="n">KC_J</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_RSFT</span><span class="p">,</span> <span class="n">KC_K</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_LALT</span><span class="p">,</span> <span class="n">KC_L</span><span class="p">),</span> <span class="n">MT</span><span class="p">(</span><span class="n">MOD_RGUI</span><span class="p">,</span> <span class="n">KC_SCLN</span><span class="p">)</span></code></pre>
</figure>

<p>Or if one were to use the shortcuts documented <a href="https://docs.qmk.fm/#/mod_tap">here</a>:</p>

<figure class="highlight">
  <pre><code class="language-js" data-lang="js"><span class="nx">LGUI_T</span><span class="p">(</span><span class="nx">KC_A</span><span class="p">),</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_S</span><span class="p">),</span> <span class="nx">LSFT_T</span><span class="p">(</span><span class="nx">KC_D</span><span class="p">),</span> <span class="nx">LCTL_T</span><span class="p">(</span><span class="nx">KC_F</span><span class="p">),</span>

<span class="nx">RCTL_T</span><span class="p">(</span><span class="nx">KC_J</span><span class="p">),</span> <span class="nx">RSFT_T</span><span class="p">(</span><span class="nx">KC_K</span><span class="p">),</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_L</span><span class="p">),</span> <span class="nx">RGUI_T</span><span class="p">(</span><span class="nx">KC_SCLN</span><span class="p">)</span></code></pre>
</figure>

<p>As you can see in this example, <kbd>A</kbd> is a <code class="language-plaintext highlighter-rouge">LGUI</code> mod-tap. This means that tapping the key will produce “a” and holding it will activate the left GUI modifier. If that was the only GUI mod-tap in your keymap, this would make it impossible to trigger the
<kbd>GUI</kbd>+<kbd>A</kbd>
keyboard shortcut. This is where mirroring all the modifiers on the other hand comes in handy. If you want to do
<kbd>GUI</kbd>+<kbd>A</kbd>, you’ll have to hold <code class="language-plaintext highlighter-rouge">MT(MOD_RGUI, KC_SCLN)</code>, i.e. the semicolon key in our example, and tap <code class="language-plaintext highlighter-rouge">MT(MOD_LGUI, KC_A)</code>, i.e. our <kbd>A</kbd> key.</p>

<p>In case you’re curious why <code class="language-plaintext highlighter-rouge">LALT</code> is used in place of <code class="language-plaintext highlighter-rouge">RALT</code> for the modifier of the <kbd>L</kbd> mod-tap key in this example, click <a href="#use-left-and-right-modifiers-but-beware-of-altgr">here</a> to jump down to the section on modifier handedness and possible gotchas with the Right Alt mod.</p>

<h3 id="tap-hold-configuration-settings">Tap Hold configuration settings</h3>
<!-- idea: add interactive text fields in each tap hold config settings sections to invite readers to get a real feel for what typing scenarios does each setting apply for. Use something along the lines of QMK configurator test's KEYUP KEYDOWN events log box -->

<p>Configuring tap hold options is a strongly recommended step for using home row mods without pulling your hair. As such, a local QMK development environment is required since the <a href="https://config.qmk.fm/#/">online configurator</a> currently does not support configuration settings. If you haven’t set up a QMK build environment yet, follow the steps outlined in <a href="https://docs.qmk.fm/#/newbs_getting_started">this guide</a>.</p>

<p>With that out of the way, here comes the most difficult part: understanding the different tap hold configuration settings.</p>

<p>I strongly advise you to attentively read through the <a href="https://docs.qmk.fm/#/tap_hold">official QMK documentation page on tap hold configuration settings</a>.</p>

<p>Once you’re done reading through this link, come back here for a more detailed explanation of each tap hold configuration setting and their relation to home row mods.</p>

<h4 id="ignore-mod-tap-interrupt" class="invisible-header">Ignore Mod-Tap Interrupt</h4>
<h4 id="default">Default</h4>

<p>Since QMK can’t read your mind, nor predict the future, it can’t decide between tap or hold in the moment when you first initially press down the physical key. Taps and holds both involve a key down event of the mod-tap key, so an additional event is needed to resolve the tap-or-hold decision.</p>

<p>In the case of default settings, the additional event is the release of the mod-tap key or the end of the tapping term, whichever happens first.</p>

<p>You can think of it like this: Been holding the mod-tap for more than the time defined in the tapping term? Activate the modifier. Pressed the key and then released it before the tapping term expired? That’s the QMK definition of a “tap”, send the letter!</p>

<p>As long as your fingers don’t linger on the keys for longer than the tapping term, you won’t get accidental mod activations.</p>

<p>The default settings are the recommended mode for home row mods.</p>

<p>If you read old posts about home row mods, you might come across comments urging you to enable <code class="language-plaintext highlighter-rouge">IGNORE_MOD_TAP_INTERRUPT</code> to use home row mods comfortably because the old default behavior of mod-taps was akin to “<a href="#hold-on-other-key-press">hold on other key press</a>” but since <a href="https://docs.qmk.fm/#/ChangeLog/20230528?id=i-m-t-i">QMK version 0.21</a>, released in 2023 May 28, the default behavior has been changed and the now obsolete <code class="language-plaintext highlighter-rouge">IGNORE_MOD_TAP_INTERRUPT</code> option removed.</p>

<h4 id="tapping-term">Tapping Term</h4>

<p>The tapping term is an important concept to grasp for home row mods. As we’ve just seen in the previous section, the tapping term is what helps to tell tap and hold apart.</p>

<p>The tapping term, in and of itself, is a very basic thing to understand. It is simply a period of time expressed in milliseconds that the user has defined. A timer starts on every key press and constantly checks whether the tapping term for that key has expired yet or not. The timer stops when the key is released. It is good to note that each pressed key is tracked by a specific, different timer, so to speak. When you press <kbd>A</kbd>, a timer starts but pressing another key like <kbd>O</kbd> does not bump up the timer that got started when you press <kbd>A</kbd>.<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">4</a></sup></p>

<p>Since a tap is defined as the act of pressing and releasing a key within <strong>tap</strong>ping term, the tapping term can be seen as the time window in which you need to release the key in order to register a tap. On the flip side, it can also be seen as the minimum amount of time a key must be held down to register a hold.</p>

<p>As such, a good tapping term that fits you is one that prevents accidental mod activations and keeps the intended mod activations snappy. It is a delicate balance.</p>

<p>The tapping term can be configured globally and per key to fit you. In general, people choose something between 150ms and 220ms, with the default QMK setting for the tapping term set at 200ms. Don’t be scared to increase or decrease your tapping term as you see fit.</p>

<p>For tips on configuring your tapping term and finding the sweet spot for you, click <a href="#finding-the-sweet-spot">here</a>.</p>

<hr />

<p>That concludes it for the <em>essential</em> tap hold configuration settings for home row mods. Don’t try to use home row mods with an insane <code class="language-plaintext highlighter-rouge">TAPPING_TERM</code>. You’ll have a bad time if you do and will come out of it thinking that “home row mods are not for me”.</p>

<p>Apart from these options, you may have noticed that QMK offers more tap hold configuration settings if you’ve read the documentation linked at the <a href="#tap-hold-configuration-settings">beginning of this section</a> — please read through those links if you haven’t yet. While non-essential, they can still be very useful and a better understanding of them can help you enable the settings that will prove beneficial to you.</p>

<h4 id="tapping-force-hold" class="invisible-header">Tapping Force Hold</h4>
<h4 id="quick-tap-term">Quick Tap Term</h4>

<p>The first in the list and an important tap hold setting for home row mods is <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code>, or as I prefer to call it <code class="language-plaintext highlighter-rouge">DOUBLE_PRESS_AUTO_REPEAT_TERM</code>.</p>

<p>Over the course of normal computer usage, you will switch back and forth between typing and triggering keyboard shortcuts. When the modifiers are on the home row, sooner or later, you will feel the need to press a home row key to type a letter and then pressing that same key in order to activate a modifier. However, the default behavior for a quick tap followed by a hold is to auto-repeat the tapping function of the mod-tap.</p>

<p>This means that if you use <code class="language-plaintext highlighter-rouge">LSFT_T(KC_L)</code> for example and you want to type “camelCase”, you will end up with “camelllllllllllllllllcase” instead. The reason is that you’re tapping <code class="language-plaintext highlighter-rouge">LSFT_T(KC_L)</code> to get “l” and then immediately after, you’re holding that same <code class="language-plaintext highlighter-rouge">LSFT_T(KC_L)</code> key to activate Shift in order to type the capital “C” of “camel<strong>C</strong>ase”.</p>

<p>This problem occurs because the second press of the mod-tap key happens before the <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code> initiated by the first tap of the mod-tap key elapses. As you can see, the name of the option is misleading because the option is not actually about quick taps but about double presses of the same key.</p>

<p>To avoid this problem, you should thus reduce the <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code> from its default value of <code class="language-plaintext highlighter-rouge">TAPPING_TERM</code> into a much smaller value, or even 0 to disable the auto-repeat feature entirely. This will have the effect of letting you activate the hold function instead, when holding a dual-role key after having tapped it. No more accidental repeats of the mod-tap letters when typing quickly!</p>

<h4 id="permissive-hold">Permissive Hold</h4>

<p>Second in the list is “permissive hold”. It is an option that adds another way to trigger the hold function of dual-role keys.</p>

<p>Permissive hold activates the modifier when another key is pressed and released while the mod-tap is held, regardless of the tapping term. It means that this option allows the user to trigger a keyboard shortcut with a mod-tap key before the end of the tapping term.</p>

<p>Consider the following case:</p>

<div class="typingScenario">

  <table>
    <thead>
      <tr>
        <th>Key</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code class="language-plaintext highlighter-rouge">RCTL_T(N)</code></td>
        <td>Down/Press</td>
      </tr>
      <tr>
        <td><code class="language-plaintext highlighter-rouge">RGUI_T(O)</code></td>
        <td>Down/Press</td>
      </tr>
      <tr>
        <td><code class="language-plaintext highlighter-rouge">RGUI_T(O)</code></td>
        <td>Up/Release</td>
      </tr>
      <tr>
        <td><code class="language-plaintext highlighter-rouge">RCTL_T(N)</code></td>
        <td>Up/Release</td>
      </tr>
    </tbody>
  </table>

  <p><img src="assets/images/home-row-mods/DarkPermissiveHoldNO.gif" alt="Doing Ctrl+O, permissive hold style, on the right half of a Squiggle with dark Colemak-DH MBK choc keycaps" title="Right half of a Squiggle keyboard with Colemak-DH" /></p>

</div>

<p>In English, this is a situation where you’re tapping <kbd>O</kbd> while holding down <kbd>N</kbd>. It can also be called a “nested tap”. If all of this happens before the end of the tapping term, the output, assuming mod-tap interrupts are ignored, would be “no”. Contrast this to the scenario when permissive hold is enabled where the output would instead be <kbd>Ctrl</kbd>+<kbd>O</kbd>.</p>

<p>As you can see, the assumption here is that if the user taps another key while holding down one or more mod-tap keys, he isn’t doing typing rolls and as such desires to trigger a keyboard shortcut instead. The tapping term is irrelevant here.</p>

<p>Consequently, this option allows the use of home row mods with a tapping term that’s much greater than 200ms. Though, people with a high tapping term aren’t the only ones who can benefit from this option. Fast typists who are used to swift taps and rolls can enable this option for snappier mod activations and thus bypass the need to wait out the tapping term for the modifiers to take effect. It is particularly useful for Shift.</p>

<p>Owing to the fact that permissive hold is… more permissive in what counts as a hold, it makes it easier to trigger mods so unintended mod activations can happen if the aforementioned case is something you frequently do when typing normally. Depending on your typing style, permissive hold might do more harm than good.</p>

<p>As with many other tap hold settings, there exists a global <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code> setting and a per-key option, aptly named <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD_PER_KEY</code>. Consult the <a href="https://docs.qmk.fm/#/tap_hold#permissive-hold">documentation</a> to figure out how to enable and configure this setting.</p>

<h4 id="hold-on-other-key-press">Hold on Other Key Press</h4>

<p>The underlying logic of “hold on other key press” is quite simple. Did another key get pressed while the user was holding down the mod-tap key? If that’s the case, this is a keyboard shortcut; apply the modifier on that pressed key. What if, instead, no key got pressed while the user was holding down the mod-tap? Well, if the user presses and releases a key by itself, without pressing any other key in between, it must mean the user wanted the tapping function of the mod-tap since there is no use to tapping a modifier key all by itself.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">5</a></sup> Simple enough right? If you want to activate the holding function, just press on another key while holding the mod-tap key.</p>

<p>Here comes the problem with that approach if one were to use home row mods. We like to imagine typing as tapping a sequence of keys all on their own, in order. However, there’s quite some overlap between the press and release of each key. Especially so when typing at high speeds. When typing the word “no” for example, we rarely press and fully release <kbd>N</kbd> <em>before</em> pressing <kbd>O</kbd>. Try it! If you’re not a hunt’n’pecker, this is how you’re most likely going to type “no”:</p>

<div class="typingScenario">

  <table>
    <thead>
      <tr>
        <th>Key</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><kbd>N</kbd></td>
        <td>Down/Press</td>
      </tr>
      <tr>
        <td><kbd>O</kbd></td>
        <td>Down/Press</td>
      </tr>
      <tr>
        <td><kbd>N</kbd></td>
        <td>Up/Release</td>
      </tr>
      <tr>
        <td><kbd>O</kbd></td>
        <td>Up/Release</td>
      </tr>
    </tbody>
  </table>

  <p><img src="assets/images/home-row-mods/DarkRollingNO.gif" alt="Typing &quot;no&quot; on the right half of a Squiggle with dark Colemak-DH MBK choc keycaps" title="Right half of a Squiggle keyboard with Colemak-DH" /></p>

</div>

<p>Now imagine if <kbd>N</kbd> and <kbd>O</kbd> were both mod-taps — it would be the case if you use home row mods on Colemak like in the animation above. With <code class="language-plaintext highlighter-rouge">HOLD_ON_OTHER_KEY_PRESS</code> settings, this is bad news. Indeed, typing involves a lot of such rolls, where you press the next letter before having fully released the previous one.</p>

<p>For that reason, <code class="language-plaintext highlighter-rouge">HOLD_ON_OTHER_KEY_PRESS</code> is strongly discouraged for home row mods.</p>

<h4 id="retro-tapping">Retro Tapping</h4>

<p>Remember how I said that there isn’t much use in pressing and releasing a modifier all by itself? Mod-taps (ab)use this property, but as it turns out mod-taps have the exact same property themselves. If you hold down a mod-tap for longer than the tapping term and then release it without having pressed any other key in between, your QMK keyboard is going to send a press and release event of the modifier to your computer; not too different from tapping a basic modifier key. If that seems wasteful for you, then let me introduce you to <em>retro tapping</em>.</p>

<p>When a mod-tap is held for a long time and released on its own, retro tap will activate the tapping function, after having released the modifier of the mod-tap.</p>

<p>To give an example, if you press and hold <code class="language-plaintext highlighter-rouge">LGUI_T(KC_A)</code> for longer than the tapping term and then release it by itself, the host computer that your QMK keyboard is connected to first sees <code class="language-plaintext highlighter-rouge">KC_LGUI</code> being pressed when you hold down the mod-tap for longer than the tapping term and then the host computer gets notified that <code class="language-plaintext highlighter-rouge">KC_LGUI</code> is released when you take your finger off <code class="language-plaintext highlighter-rouge">LGUI_T(KC_A)</code> on your keyboard. This is the default behavior for mod-taps held and released by themselves. What retro tap does is sending <code class="language-plaintext highlighter-rouge">KC_A</code> once <code class="language-plaintext highlighter-rouge">KC_LGUI</code> is released/inactive.</p>

<!--Consider putting an animation of a keyboard pressing keys and a host computer receiving scan codes-->

<p>Retro Tap thus gives another way to trigger the tapping function of mod-taps. With this option, you can get away with a very short tapping term.</p>

<p>However, this particular example highlights a potential problem with retro tap. In many popular desktop environments, the start menu is brought up by tapping the GUI key. A user of this kind of desktop environment who would like to send “a” by retro-tapping <code class="language-plaintext highlighter-rouge">LGUI_T(KC_A)</code> would accidentally open up the start menu and type “a” in its search bar.</p>

<p>What if you use another way to bring up the start menu? You’ll still have a problem with the Alt key which is used for navigating through menus of graphical applications. You can avoid accidental pop-ups of the menu when retro-tapping the alt mod-taps by disabling the functionality in the apps settings. For example in Firefox, it can be done by going in <code class="language-plaintext highlighter-rouge">about:config</code> and turning <code class="language-plaintext highlighter-rouge">ui.key.menuAccessKeyFocuses</code> to <code class="language-plaintext highlighter-rouge">false</code>. Apps rarely offer the possibility of disabling Alt’s tapping behavior though.</p>

<p>The Alt and GUI modifiers aren’t the only problem, think of the mouse too. The firmware that’s running on your keyboard cannot tell that you have clicked or scrolled the mouse wheel while holding down a mod-tap key. All it sees is that you’ve been holding down a mod-tap for more than the tapping term and released it without pressing any other key in between. As we now know, this is the cue for the firmware to activate the tapping function of the mod-tap in question if retro tap is enabled. <kbd>Ctrl</kbd>+<kbd>Left-Click</kbd> to open a link in a new tab or <kbd>Shift</kbd>+<kbd>Scrollwheel</kbd> to scroll sideways would thus be accompanied with unintended letters.</p>

<p>To counteract this, QMK lets you define a <code class="language-plaintext highlighter-rouge">DUMMY_MOD_NEUTRALIZER_KEYCODE</code> in <code class="language-plaintext highlighter-rouge">config.h</code> that will get sent in between the register and unregister events of a held mod-tap key. That way, the programs on your computer will no longer interpret the mod suppression induced by retro-tapping as a lone tap of a modifier key and will thus not falsely trigger the undesired action.</p>

<p>Naturally, for this technique to be effective, you must choose a <code class="language-plaintext highlighter-rouge">DUMMY_MOD_NEUTRALIZER_KEYCODE</code> for which no keyboard shortcuts are bound to. Recommended values are: <code class="language-plaintext highlighter-rouge">KC_RIGHT_CTRL</code> or <code class="language-plaintext highlighter-rouge">KC_F18</code>. 
Please note that <code class="language-plaintext highlighter-rouge">DUMMY_MOD_NEUTRALIZER_KEYCODE</code> must be a basic, unmodified, HID keycode so values like <code class="language-plaintext highlighter-rouge">KC_NO</code>, <code class="language-plaintext highlighter-rouge">KC_TRANSPARENT</code> or <code class="language-plaintext highlighter-rouge">KC_PIPE</code> aka <code class="language-plaintext highlighter-rouge">S(KC_BACKSLASH)</code> are not permitted.</p>

<p>By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your <code class="language-plaintext highlighter-rouge">config.h</code>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define MODS_TO_NEUTRALIZE { &lt;mod_mask_1&gt;, &lt;mod_mask_2&gt;, ... }
</span></code></pre></div></div>

<p>Examples:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL
</span>
<span class="c1">// Neutralize left alt and left GUI (Default value)</span>
<span class="cp">#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) }
</span>
<span class="c1">// Neutralize left alt, left GUI, right GUI and left Control+Shift</span>
<span class="cp">#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) }
</span></code></pre></div></div>

<h4 id="retro-shift">Retro Shift</h4>

<p>Retro Shift builds upon the functionality of Retro Tap in order to marry <a href="https://docs.qmk.fm/#/feature_auto_shift">Auto Shift</a> with <a href="https://docs.qmk.fm/#/mod_tap">mod-taps</a>.</p>

<p>Retro Shift lets you get the shifted state of a mod-tap by releasing the mod-tap key past the end of the tapping term, in a similar fashion to Auto Shift which emits the shifted state of a basic key if it’s been held down for longer than the <code class="language-plaintext highlighter-rouge">AUTO_SHIFT_TIMEOUT</code>.</p>

<p>With Auto Shift and Retro Shift, you can confidently eradicate all Shift keys from your keymap.<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">6</a></sup></p>

<p>In case you’re worried for the flaws that plague Retro Tap to be present in Retro Shift too, don’t be. As the <a href="https://github.com/manna-harbour/qmk_firmware/blob/retro-shift/docs/tap_hold.md#retro-shift">docs</a> say, “if <code class="language-plaintext highlighter-rouge">RETRO_SHIFT</code> is defined to a value, hold times greater than that value will not produce a tap on release. This enables modifiers to be held for combining with mouse clicks without generating taps on release.”</p>

<hr />

<p>That is it for all the available QMK tap hold configuration settings. In summary, there is only one essential tap hold setting: <code class="language-plaintext highlighter-rouge">TAPPING_TERM</code>. Even then, chances are that you won’t even need to tweak it since the default value will suit most users.</p>

<p>Aside from that, there exists another very commonly recommended setting: <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code>. Don’t be misled by the name, it is not about quick taps but about the behavior of the key if you double-press it within a certain time window. It is recommended to set it to 0 or another very low value.</p>

<p><code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code> can be useful if you have a very high tapping term. If you have a lower tapping term, <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code> generally produces many misfires unless you’re very consistent in your typing style so it is not recommended.</p>

<p>Though, it is nothing in comparison to the amount of misfires you’ll get with <code class="language-plaintext highlighter-rouge">HOLD_ON_OTHER_KEY_PRESS</code>. Home row mods are pretty much unusable with that option.</p>

<p>As for <code class="language-plaintext highlighter-rouge">RETRO_TAPPING</code>, it might appear appealing at first glance but it has its load of problems which make it unsuitable for home row mods.</p>

<h3 id="getting-started-with-home-row-mods-on-qmk">Getting started with home row mods on QMK</h3>

<p>Armed with all this knowledge, we can now add home row mods to our keymap and flash it onto our board.</p>

<p>Let’s start with tap hold configuration settings. Copy and paste those lines in your <code class="language-plaintext highlighter-rouge">config.h</code> file (create the file in your personal keymap folder if it’s not already present):</p>

<figure class="highlight">
  <pre><code class="language-js" data-lang="js"><span class="c1">// Configure the global tapping term (default: 200ms)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">TAPPING_TERM</span> <span class="mi">200</span>

<span class="c1">// Enable rapid switch from tap to hold, disables double tap hold auto-repeat.</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">QUICK_TAP_TERM</span> <span class="mi">0</span></code></pre>
</figure>

<p>Once that’s done, open up <code class="language-plaintext highlighter-rouge">keymap.c</code>, and convert all the home row keys into mod-tap keys. You have multiple options for doing so. In any case, it is best to use aliases as the convention is to keep all keycode names strictly under 8 characters long in order to keep a tidy, aligned and readable layout in the <code class="language-plaintext highlighter-rouge">keymap.c</code> file. This is not possible if you use something like <code class="language-plaintext highlighter-rouge">MT(mod, kc)</code> or <code class="language-plaintext highlighter-rouge">LMOD_T(kc)</code>. For example, potential aliases for US QWERTY with GASC/◆⎇⇧⎈ order could be:</p>

<figure class="highlight">
  <pre><code class="language-js" data-lang="js"><span class="c1">// Left-hand home row mods</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_A</span> <span class="nx">LGUI_T</span><span class="p">(</span><span class="nx">KC_A</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_S</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_S</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_D</span> <span class="nx">LSFT_T</span><span class="p">(</span><span class="nx">KC_D</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_F</span> <span class="nx">LCTL_T</span><span class="p">(</span><span class="nx">KC_F</span><span class="p">)</span>

<span class="c1">// Right-hand home row mods</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_J</span> <span class="nx">RCTL_T</span><span class="p">(</span><span class="nx">KC_J</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_K</span> <span class="nx">RSFT_T</span><span class="p">(</span><span class="nx">KC_K</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_L</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_L</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_SCLN</span> <span class="nx">RGUI_T</span><span class="p">(</span><span class="nx">KC_SCLN</span><span class="p">)</span></code></pre>
</figure>

<p>If you feel like <code class="language-plaintext highlighter-rouge">HOME_letter</code> is too vague, nothing prevents you from doing something like this:</p>

<figure class="highlight">
  <pre><code class="language-js" data-lang="js"><span class="c1">// Left-hand home row mods</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">GUI_A</span> <span class="nx">LGUI_T</span><span class="p">(</span><span class="nx">KC_A</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">ALT_S</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_S</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">SFT_D</span> <span class="nx">LSFT_T</span><span class="p">(</span><span class="nx">KC_D</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">CTL_F</span> <span class="nx">LCTL_T</span><span class="p">(</span><span class="nx">KC_F</span><span class="p">)</span>

<span class="c1">// Right-hand home row mods</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">CTL_J</span> <span class="nx">RCTL_T</span><span class="p">(</span><span class="nx">KC_J</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">SFT_K</span> <span class="nx">RSFT_T</span><span class="p">(</span><span class="nx">KC_K</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">ALT_L</span> <span class="nx">LALT_T</span><span class="p">(</span><span class="nx">KC_L</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">GUI_SCLN</span> <span class="nx">RGUI_T</span><span class="p">(</span><span class="nx">KC_SCLN</span><span class="p">)</span></code></pre>
</figure>

<p>Note: Do not redefine <code class="language-plaintext highlighter-rouge">SFT_T</code> because you have a <kbd>Shift</kbd>/<kbd>T</kbd> mod-tap. <code class="language-plaintext highlighter-rouge">SFT_T</code> is already in use in the core QMK code as an alias for <code class="language-plaintext highlighter-rouge">LSFT_T(kc)</code> and redefining it in your keymap will produce compile errors. You’re advised to use <code class="language-plaintext highlighter-rouge">#define SHFT_T LSFT_T(KC_T)</code> instead.</p>

<p>Afterwards, it’s just a matter of replacing all the basic <code class="language-plaintext highlighter-rouge">KC_letter</code> situated on the home row in the <code class="language-plaintext highlighter-rouge">LAYOUT</code> of your <code class="language-plaintext highlighter-rouge">keymap.c</code> with the mod-taps aliases you’ve defined.</p>

<h3 id="qmk-home-row-mods-code-generator">Home row mods code generator</h3>

<p>For your convenience, below you can find a form that you can fill in with your options in order to generate mod-tap aliases and the home row.</p>

<details>
  <summary> Additional information</summary>

  <p>For best results, make sure to use US QWERTY on your OS since the generated code uses the default QMK keycode labels which are based on US QWERTY.</p>

  <p>If your layout isn’t present in the list, select “Other” in the dropdown list and fill in all the ten characters of your home row. To accommodate layouts such as QWERTY and <a href="https://github.com/MadRabbit/halmak">Halmak</a>, a limited set of punctuation characters are accepted in the custom layout field. They are <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">.</code>, <code class="language-plaintext highlighter-rouge">,</code>, <code class="language-plaintext highlighter-rouge">/</code>, <code class="language-plaintext highlighter-rouge">\</code>, and <code class="language-plaintext highlighter-rouge">;</code>. If you wish to use <a href="#upperlower-row-mods">upper/lower row mods</a>, you can also select “Other” and fill in the text field with the upper/lower row of your keyboard layout.</p>

  <p>The order options use the notation described in the section on <a href="#home-row-mods-order">home row mods orders</a>. The leftmost modifier is the one on the pinky and the rightmost modifier is the one on the index finger (not the inner index column). If you wish to use another home row mods order, check “Other” and specify your desired order in the same notation. <a href="#alternative-home-row-mods-layout">Alternative home row mods layouts</a> are not supported, but you’re free to use <code class="language-plaintext highlighter-rouge">_</code> to omit some modifiers if you want less than 2×4 home row mods.</p>

  <p>In case you’re curious why <code class="language-plaintext highlighter-rouge">LALT</code> is used in place of <code class="language-plaintext highlighter-rouge">RALT</code> in the generated code for the right-hand Alt mod-tap, click <a href="#use-left-and-right-modifiers-but-beware-of-altgr">here</a> to jump down to the section on modifier handedness and possible gotchas with the Right Alt mod.</p>
</details>

<form style="background: #131317;border: 25px solid #131317; border-radius: 25px;">
  <p>
Select your layout<br />
<select name="layouts" onchange="showTextField('QMKLayout')">
<option value="ASDFGHJKL;" selected="">QWERTY/AZERTY/QWERTZ </option>
<option value="AOEUIDHTNS"> Dvorak</option>
<option value="ARSTDHNEIO"> Colemak vanilla</option>
<option value="ARSTGMNEIO"> Colemak DH</option>
<option value="ASHTGYNEOI"> Workman</option>
<option value="RSTHDMNAIO"> RSTHD</option>
<option value="YIEA.DSTNB"> BEAKL15</option>
<option value="OTHER" id="otherQMKLayout"> Other </option>
</select>
</p>
  <div id="customQMKLayout" style="display:none">
    <p>Specify the ten characters of the row you want to apply mod-taps to.<br />Accepted characters: <code class="language-plaintext highlighter-rouge">A–Za–z0–9.,;/\'-</code><br />
<input type="text" maxlength="10" id="customQMKLayoutInput" pattern="[A-Za-z0-9-.,;\/'\\]{10}" title="Lowercase is allowed too" /></p>
  </div>

  <p>
Enter your desired tapping term (in ms)<br />
<input type="number" name="QMKTappingTerm" min="1" value="200" />
</p>

  <p>
Select your home row mods order<br />
<select name="homeRowModsOrders" onchange="showTextField('QMKOrder')">
<option value="GASC" selected=""> GASC</option>
<option value="GACS"> GACS</option>
<option value="SCGA"> SCGA</option>
<option value="CAGS"> CAGS</option>
<option value="OTHER" id="otherQMKOrder"> Other </option>
</select>
</p>
  <div id="customQMKOrder" style="display:none">
    <p>Specify your desired <a href="#home-row-mods-order">home row mods order</a><br />Accepted characters: <code class="language-plaintext highlighter-rouge">GASC_</code><br />
<input type="text" id="customQMKOrderInput" maxlength="4" pattern="[_GgAaSsCc]{4}" title="Lowercase is allowed too." /></p>
  </div>

  <p>
Select your desired alias style<br />
<select name="aliasStyle">
<option value="HOME" selected=""> HOME</option>
<option value="MOD"> MOD</option>
</select>
</p>

  <p style="margin-bottom: 0em;">
<input type="button" onclick="generateQMKCode(form.elements)" name="submit" value="Generate" />
</p>

  <div id="QMKGeneratorErrors" style="display: none;min-width: 100%;text-align: center;background: #f006; border-radius:15px; margin-top: 1em;"></div>
</form>

<div id="generatedQMKTappingTerm" style="display:none"></div>
<div id="generatedQMKAliases" style="display:none">
  <p>Paste this at the top of your <code class="language-plaintext highlighter-rouge">keymap.c</code> file</p>
</div>
<div id="generatedQMKHomeRow" style="display:none"></div>

<p><br /></p>

<h2 id="using-home-row-mods-with-kmonad">Using home row mods with KMonad</h2>

<p><a href="#tips-and-tricks">Skip to “Tips &amp; Tricks”</a></p>

<p>Aside from QMK, <a href="https://github.com/kmonad/kmonad">KMonad</a> is another piece of software which allows the implementation of home row mods. Its greatest perk is that it does not require a special keyboard like QMK does (although Hasu’s USB-to-USB controller can turn any USB keyboard into a QMK-compatible keyboard). It’s a cross-platform application that runs on the computer, not on the keyboard chip.</p>

<p>KMonad isn’t the only computer program which features mod-taps, it’s been preceded by <a href="https://github.com/alols/xcape">xcape</a> and <a title="Space and Shift (archived link in Japanese)" href="https://web.archive.org/web/20020215203809/http://hp.vector.co.jp/authors/VA002116/sands/">SandS</a>, the very first mod-tap ever. What sets it apart though is that, unlike all those other programs, it features much more configuration options for mod-taps. On most, you’re not allowed to roll your keys and you’re limited to simply tweaking the tapping term.</p>

<p>That’s not to say that KMonad uses the same configuration options as QMK does. They’re different programs made by different people.</p>

<p>If you want to tweak the mod-tap functionality, which by the way is called a “multi-use button” in KMonad, the way to go is to use the button that fits your desired behavior. KMonad has a bunch of mod-tap buttons. The one that’s of interest for home row mods is <code class="language-plaintext highlighter-rouge">tap-hold-next-release</code>.</p>

<p><code class="language-plaintext highlighter-rouge">tap-hold-next-release</code> works best for home row mods as it reliably acts exactly like a modifier past the tapping term and activates the “tapping” button in rolling sequences. For more information on how it works and how the other multi-use buttons work, refer to the <a href="https://github.com/kmonad/kmonad/blob/master/keymap/tutorial.kbd">configuration tutorial</a>, and in particular, the <a href="https://github.com/kmonad/kmonad/blob/98317531da8b9c2f21d5cb80b748eb23ef8f6b63/keymap/tutorial.kbd#L601">section on multi-use buttons</a>.</p>

<p>As with all the other <code class="language-plaintext highlighter-rouge">-hold</code> multi-use buttons, <code class="language-plaintext highlighter-rouge">tap-hold-next-release</code> takes in three arguments:</p>

<ol>
  <li>A timeout value expressed in milliseconds which is akin to the tapping term used by QMK</li>
  <li>The “tapping” button. For home row mods, this will correspond to the home row letter.</li>
  <li>The “holding” button. For home row mods, this will correspond to the modifier.</li>
</ol>

<p>To give an example, this would be the KMonad syntax for an <kbd>A</kbd> key that acts as a GUI modifier when held, with a defined timeout hold value of 200 milliseconds.</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">lgui</span><span class="p">)</span></code></pre>
</figure>

<p>In the same spirit that we’ve defined an alias for mod-taps in the section on getting started with home row mods on QMK to make the layout more readable, we can give a short name to mod-taps in KMonad with <code class="language-plaintext highlighter-rouge">defalias</code>.</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defalias</span><span class="w"> </span><span class="n">gui_a</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">lgui</span><span class="p">))</span></code></pre>
</figure>

<p>As you may have noticed, KMonad uses a lisp-like syntax for its configuration language. For more information on how to configure KMonad, you’re invited to read through the <a href="https://github.com/kmonad/kmonad/blob/master/keymap/tutorial.kbd">configuration tutorial</a>, which has already been linked, or through the <a href="https://github.com/kmonad/kmonad/blob/master/keymap/user">public user configurations</a>.</p>

<h3 id="getting-started-with-home-row-mods-on-kmonad">Getting started with home row mods on KMonad</h3>

<p>Install <a href="https://github.com/kmonad/kmonad">KMonad</a> by following the <a href="https://github.com/david-janssen/kmonad/blob/master/doc/installation.md">installation instructions</a>. If you encounter troubleshooting issues, make sure to check out the <a href="https://github.com/david-janssen/kmonad/blob/master/doc/faq.md">FAQ</a>.</p>

<p>Once KMonad is installed on your PC, the next step is to create a new <code class="language-plaintext highlighter-rouge">.kbd</code> file. Call it however you want. This will be the configuration file that you will pass as input to KMonad when launching it.</p>

<p>The KMonad configuration file can be broken up in four main blocks:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">defcfg</code></li>
  <li><code class="language-plaintext highlighter-rouge">defsrc</code></li>
  <li><code class="language-plaintext highlighter-rouge">defalias</code> (optional)</li>
  <li><code class="language-plaintext highlighter-rouge">deflayer</code></li>
</ol>

<h4 id="1-defcfg">1. defcfg</h4>
<!-- Add mention and explanations of `cmp-seq` -->

<p>In a nutshell, this is where you tell KMonad what keyboard you want it to affect and where and how to find it in your system. Naturally, the process will look a bit different based on the OS you use. Click on the name of your operating system to be directed to the relevant instructions: <a href="https://github.com/david-janssen/kmonad/blob/2f20899630d95deed66cd8b2f0dcc3387a3e63d7/keymap/tutorial.kbd#L80...L95">Linux</a>, <a href="https://github.com/david-janssen/kmonad/blob/2f20899630d95deed66cd8b2f0dcc3387a3e63d7/keymap/tutorial.kbd#L98...L112">Windows</a>, <a href="https://github.com/david-janssen/kmonad/blob/2f20899630d95deed66cd8b2f0dcc3387a3e63d7/keymap/tutorial.kbd#L115...L128">MacOS</a>.</p>

<p>The <code class="language-plaintext highlighter-rouge">defcfg</code> code block looks like this:</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defcfg</span><span class="w">
  </span><span class="c1">;; For Linux</span><span class="w">
  </span><span class="n">input</span><span class="w">  </span><span class="p">(</span><span class="nf">device-file</span><span class="w"> </span><span class="s">"/dev/input/by-id/usb-04d9_daskeyboard-event-kbd"</span><span class="p">)</span><span class="w">
  </span><span class="n">output</span><span class="w"> </span><span class="p">(</span><span class="nf">uinput-sink</span><span class="w"> </span><span class="s">"My KMonad output"</span><span class="w">

  </span><span class="c1">;; For Windows</span><span class="w">
  </span><span class="n">input</span><span class="w">  </span><span class="p">(</span><span class="nf">low-level-hook</span><span class="p">)</span><span class="w">
  </span><span class="n">output</span><span class="w"> </span><span class="p">(</span><span class="nf">send-event-sink</span><span class="p">)</span><span class="w">

  </span><span class="c1">;; For MacOS</span><span class="w">
  </span><span class="n">input</span><span class="w">  </span><span class="p">(</span><span class="nf">iokit-name</span><span class="w"> </span><span class="s">"my-keyboard-product-string"</span><span class="p">)</span><span class="w">
  </span><span class="n">output</span><span class="w"> </span><span class="p">(</span><span class="nf">kext</span><span class="p">)</span><span class="w">

  </span><span class="c1">;; This option tells KMonad to let non-configured keys act normal</span><span class="w">
  </span><span class="n">fallthrough</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="p">)</span></code></pre>
</figure>

<h4 id="2-defsrc">2. defsrc</h4>

<p>This is where you specify the physical keys on which you want KMonad to apply. If all you want to do is add home row mods to your board and keep normal behavior for every other key, enable <code class="language-plaintext highlighter-rouge">fallthrough</code> in the <code class="language-plaintext highlighter-rouge">defcfg</code> block and paste the following <code class="language-plaintext highlighter-rouge">defsrc</code> block to your <code class="language-plaintext highlighter-rouge">.kbd</code> configuration file:</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defsrc</span><span class="w">
    </span><span class="n">a</span><span class="w">    </span><span class="n">s</span><span class="w">    </span><span class="n">d</span><span class="w">    </span><span class="n">f</span><span class="w">    </span><span class="n">g</span><span class="w">    </span><span class="n">h</span><span class="w">    </span><span class="n">j</span><span class="w">    </span><span class="n">k</span><span class="w">    </span><span class="n">l</span><span class="w">    </span><span class="c1">;</span><span class="w">
</span><span class="p">)</span></code></pre>
</figure>

<p>It doesn’t matter whether you’re a French speaker whose home row spells out
<kbd>Q</kbd><kbd>S</kbd><kbd>D</kbd><kbd>F</kbd><kbd>G</kbd><kbd>H</kbd><kbd>J</kbd><kbd>K</kbd><kbd>L</kbd><kbd>M</kbd>
or a Russian speaker whose home row spells out
<kbd>Ф</kbd><kbd>Ы</kbd><kbd>В</kbd><kbd>А</kbd><kbd>П</kbd><kbd>Р</kbd><kbd>О</kbd><kbd>Л</kbd><kbd>Д</kbd><kbd>Ж</kbd>,
 the above code still applies since KMonad operates at a low-level and deals with keycodes as opposed to keysyms. The <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">;</code> button names are simply labels based on US QWERTY to make configuration easier. Don’t read them as the “keys that produce, respectively, the symbols ‘a’ and ‘;’ on the screen when pressed” but rather the “home row pinky keys”.</p>

<h4 id="3-defalias">3. defalias</h4>

<p>As mentioned in the beginning of this section on KMonad, if you intend to use mod-taps/multi-use buttons, you should consider using aliases in order to keep a readable layout.</p>

<p>Aliasing all home row mods is repetitive and rather long, so I recommend using the <a href="#kmonad-home-row-mods-code-generator">KMonad code generator</a>, found further down the guide.</p>

<p>For illustrative purposes, here’s the <code class="language-plaintext highlighter-rouge">defalias</code> block of a standard keymap using the GACS/◆⎇⎈⇧ order for the home row mods, and 200ms for the tapping term:</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defalias</span><span class="w">
    </span><span class="n">met_a</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">lmet</span><span class="p">)</span><span class="w">
    </span><span class="n">alt_s</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="n">lalt</span><span class="p">)</span><span class="w">
    </span><span class="n">ctl_d</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="n">lctl</span><span class="p">)</span><span class="w">
    </span><span class="n">sft_f</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">lsft</span><span class="p">)</span><span class="w">

    </span><span class="n">sft_j</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="n">rsft</span><span class="p">)</span><span class="w">
    </span><span class="n">ctl_k</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">rctl</span><span class="p">)</span><span class="w">
    </span><span class="n">alt_l</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">lalt</span><span class="p">)</span><span class="w">
    </span><span class="n">met_</span><span class="c1">; (tap-hold-next-release 200 ; rmet)</span><span class="w">
</span><span class="p">)</span></code></pre>
</figure>

<p>Note: KMonad calls the GUI modifier “Meta”, abbreviated as <code class="language-plaintext highlighter-rouge">lmet</code> and <code class="language-plaintext highlighter-rouge">rmet</code>.</p>

<h4 id="4-deflayer">4. deflayer</h4>

<p>This block is used to translate the previously declared <code class="language-plaintext highlighter-rouge">defsrc</code> block into your desired output. As such, it must follow the same structure i.e. layout and number of buttons.</p>

<p>An important thing to note is that if you want to use the aliases you’ve defined, you must prepend them with a <code class="language-plaintext highlighter-rouge">@</code>.</p>

<p>Continuing with the example we’ve been working with, what you would need to write into the <code class="language-plaintext highlighter-rouge">deflayer</code> is the following:</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">deflayer</span><span class="w"> </span><span class="n">homerowmods</span><span class="w">
    </span><span class="o">@</span><span class="n">met_a</span><span class="w">   </span><span class="o">@</span><span class="n">alt_s</span><span class="w">   </span><span class="o">@</span><span class="n">ctl_d</span><span class="w">   </span><span class="o">@</span><span class="n">sft_f</span><span class="w">   </span><span class="n">g</span><span class="w">   </span><span class="n">h</span><span class="w">   </span><span class="o">@</span><span class="n">sft_j</span><span class="w">   </span><span class="o">@</span><span class="n">ctl_k</span><span class="w">   </span><span class="o">@</span><span class="n">alt_l</span><span class="w">   </span><span class="o">@</span><span class="n">met_</span><span class="c1">;</span><span class="w">
</span><span class="p">)</span></code></pre>
</figure>

<p>Here we’ve named the layer <code class="language-plaintext highlighter-rouge">homerowmods</code> but you can name the layer whatever you want.</p>

<h4 id="final-result">Final result</h4>

<p>If we fuse together the four different blocks that we have developed in the last subsections and assume that we’re on Windows, this would be the result:</p>

<figure class="highlight">
  <pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defcfg</span><span class="w">
  </span><span class="c1">;; For Windows</span><span class="w">
  </span><span class="n">input</span><span class="w">  </span><span class="p">(</span><span class="nf">low-level-hook</span><span class="p">)</span><span class="w">
  </span><span class="n">output</span><span class="w"> </span><span class="p">(</span><span class="nf">send-event-sink</span><span class="p">)</span><span class="w">

  </span><span class="c1">;; This option tells KMonad to let non-configured keys act normal</span><span class="w">
  </span><span class="n">fallthrough</span><span class="w"> </span><span class="n">true</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="p">(</span><span class="nf">defsrc</span><span class="w">
    </span><span class="n">a</span><span class="w">    </span><span class="n">s</span><span class="w">    </span><span class="n">d</span><span class="w">    </span><span class="n">f</span><span class="w">    </span><span class="n">g</span><span class="w">    </span><span class="n">h</span><span class="w">    </span><span class="n">j</span><span class="w">    </span><span class="n">k</span><span class="w">    </span><span class="n">l</span><span class="w">    </span><span class="c1">;</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="p">(</span><span class="nf">defalias</span><span class="w">
    </span><span class="n">met_a</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">lmet</span><span class="p">)</span><span class="w">
    </span><span class="n">alt_s</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="n">lalt</span><span class="p">)</span><span class="w">
    </span><span class="n">ctl_d</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="n">lctl</span><span class="p">)</span><span class="w">
    </span><span class="n">sft_f</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">lsft</span><span class="p">)</span><span class="w">

    </span><span class="n">sft_j</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="n">rsft</span><span class="p">)</span><span class="w">
    </span><span class="n">ctl_k</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">rctl</span><span class="p">)</span><span class="w">
    </span><span class="n">alt_l</span><span class="w"> </span><span class="p">(</span><span class="nf">tap-hold-next-release</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">lalt</span><span class="p">)</span><span class="w">
    </span><span class="n">met_</span><span class="c1">; (tap-hold-next-release 200 ; rmet)</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="p">(</span><span class="nf">deflayer</span><span class="w"> </span><span class="n">homerowmods</span><span class="w">
    </span><span class="o">@</span><span class="n">met_a</span><span class="w">   </span><span class="o">@</span><span class="n">alt_s</span><span class="w">   </span><span class="o">@</span><span class="n">ctl_d</span><span class="w">   </span><span class="o">@</span><span class="n">sft_f</span><span class="w">   </span><span class="n">g</span><span class="w">   </span><span class="n">h</span><span class="w">   </span><span class="o">@</span><span class="n">sft_j</span><span class="w">   </span><span class="o">@</span><span class="n">ctl_k</span><span class="w">   </span><span class="o">@</span><span class="n">alt_l</span><span class="w">   </span><span class="o">@</span><span class="n">met_</span><span class="c1">;</span><span class="w">
</span><span class="p">)</span></code></pre>
</figure>

<p>Once your configuration file is ready, open a terminal and type in the exact name of the binary you’ve downloaded alongside the name of your config file to <a href="https://github.com/david-janssen/kmonad/blob/master/doc/faq.md#how-do-i-start-kmonad">start KMonad</a>.</p>

<p>For a more detailed explanation on everything KMonad has to offer, click <a href="https://github.com/david-janssen/kmonad/#configuration">here</a>.</p>

<h3 id="kmonad-home-row-mods-code-generator">Home row mods code generator</h3>

<p>For your convenience, below you can find a form that you can fill in with your options in order to generate mod-tap aliases and the home row.</p>

<details>
  <summary> Additional information</summary>

  <p>For best results, make sure to use US QWERTY on your OS since the generated code uses the default KMonad keycode labels which are based on US QWERTY.</p>

  <p>If your layout isn’t present in the list, select “Other” in the dropdown list and fill in all the ten characters of your home row. To accommodate layouts such as QWERTY and <a href="https://github.com/MadRabbit/halmak">Halmak</a>, a limited set of punctuation characters are accepted in the custom layout field. They are <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">.</code>, <code class="language-plaintext highlighter-rouge">,</code>, <code class="language-plaintext highlighter-rouge">/</code>, <code class="language-plaintext highlighter-rouge">\</code>, and <code class="language-plaintext highlighter-rouge">;</code>. If you wish to use <a href="#upperlower-row-mods">upper/lower row mods</a>, you can also select “Other” and fill in the text field with the upper/lower row of your keyboard layout.</p>

  <p>The order options use the notation described in the section on <a href="#home-row-mods-order">home row mods orders</a>. The leftmost modifier is the one on the pinky and the rightmost modifier is the one on the index finger (not the inner index column). If you wish to use another home row mods order, select “Other” in the dropdown list and specify your desired order in the same notation. <a href="#alternative-home-row-mods-layout">Alternative home row mods layouts</a> are not supported, but you’re free to use <code class="language-plaintext highlighter-rouge">_</code> to omit some modifiers if you want less than 2×4 home row mods.</p>

  <p>In case you’re curious why <code class="language-plaintext highlighter-rouge">LALT</code> is used in place of <code class="language-plaintext highlighter-rouge">RALT</code> in the generated code for the right-hand Alt mod-tap, click <a href="#use-left-and-right-modifiers-but-beware-of-altgr">here</a> to jump down to the section on modifier handedness and possible gotchas with the Right Alt mod.</p>
</details>

<form style="background: #131317;border: 25px solid #131317; border-radius: 25px;">
  <p>
Select your layout<br />
<select name="layouts" onchange="showTextField('KMonadLayout')">
<option value="ASDFGHJKL;" selected=""> QWERTY/AZERTY/QWERTZ</option>
<option value="AOEUIDHTNS"> Dvorak</option>
<option value="ARSTDHNEIO"> Colemak vanilla</option>
<option value="ARSTGMNEIO"> Colemak DH</option>
<option value="ASHTGYNEOI"> Workman</option>
<option value="RSTHDMNAIO"> RSTHD</option>
<option value="YIEA.DSTNB"> BEAKL15</option>
<option value="OTHER" id="otherKMonadLayout"> Other </option>
</select>
</p>
  <div id="customKMonadLayout" style="display:none">
    <p>Specify the ten characters of the row you want to apply mod-taps to.<br />Accepted characters: <code class="language-plaintext highlighter-rouge">A–Za–z0–9.,;/\'-</code><br />
<input type="text" maxlength="10" id="customKMonadLayoutInput" pattern="[A-Za-z0-9-.,;\/'\\]{10}" title="Lowercase is allowed too" /></p>
  </div>

  <p>
Enter your desired tapping term (in ms)<br />
<input type="number" name="KMonadTappingTerm" min="1" value="200" />
</p>

  <p>
Select your home row mods order<br />
<select name="homeRowModsOrders" onchange="showTextField('KMonadOrder')">
<option value="GASC"> GASC</option>
<option value="GACS" selected=""> GACS</option>
<option value="SCGA"> SCGA</option>
<option value="CAGS"> CAGS</option>
<option value="OTHER" id="otherKMonadOrder"> Other </option>
</select>
</p>
  <div id="customKMonadOrder" style="display:none">
    <p>Specify your desired <a href="#home-row-mods-order">home row mods order</a><br />Accepted characters: <code class="language-plaintext highlighter-rouge">GASC_</code><br />
<input type="text" id="customKMonadOrderInput" maxlength="4" pattern="[_GgAaSsCc]{4}" title="Lowercase is allowed too." /></p>
  </div>

  <p>
Select your desired alias style<br />
<select name="aliasStyle">
<option value="HOME"> HOME</option>
<option value="MOD" selected=""> MOD</option>
</select>
</p>

  <p style="margin-bottom: 0em;">
<input type="button" onclick="generateKMonadCode(form.elements)" name="submit" value="Generate" />
</p>

  <div id="KMonadGeneratorErrors" style="display: none;min-width: 100%;text-align: center;background: #f006; border-radius:15px; margin-top: 1em;"></div>

</form>

<div id="generatedKMonadAliases" style="display:none"></div>
<div id="generatedKMonadHomeRow" style="display:none"></div>

<h1 id="tips-and-tricks">Tips &amp; Tricks</h1>

<!-- Tips -->
<h2 id="quick-swift-taps">Quick swift taps</h2>

<p>The most important tip I can give is to get into the habit of typing with quick, swift taps. The goal is to reduce the time between press and release to the minimum. Don’t focus on pressing keys, but on <em>tapping</em> keys. Pressing and releasing should <em>feel</em> like one single action, in the same way you tap the WinKey when you want to open the start menu on Windows.</p>

<p>For some people, the transition to home row mods is little jarring because they got used to holding a key down for a little a less than the key repeat delay which is set by default to 500–1000ms on most operating systems.</p>

<p>Parallels can be made between the key repeat delay and the tapping term. In both cases, releasing the key before the delay expires will result in one single letter to be produced. In that case, it is tempting to say that a person who’s used to a key repeat delay of 500ms should crank up the default tapping term of 200ms up to 500ms. It can be seen as trading key auto-repeat for modifier activation. That will certainly help to avoid accidental mods. If the user never accidentally auto-repeats keys then he won’t accidentally activate a modifier. In theory, this all sounds good and dandy but in practice, you’ll realize that having to hold a key for ≥500ms is actually pretty long.</p>

<p>My point is that the quicker your taps are, the more you can afford to reduce the tapping term which has the consequence of letting you trigger keyboard shortcuts much more rapidly.</p>

<p>Before you get the wrong idea, I want to make it clear that I am <em>not</em> telling you to increase your WPM speed. By “swift” taps, I mean avoiding keeping keys pressed for needlessly long. Don’t linger your fingers on the keys. It’s not a matter of reducing the time it takes you to type the next character. You can take a 10s break before typing each character and achieve a dramatically low WPM but you can nonetheless tap an individual key briskly.</p>

<p>Though it is not out of the question that learning to tap swiftly may lead to faster WPM in the long run.</p>

<h2 id="finding-the-sweet-spot">Finding the sweet spot</h2>

<p>Prior to looking for tips to find the sweet spot for the tapping term, I urge you to make sure to disable “<a href="#hold-on-other-key-press">Hold on Other Key Press</a>” first. Too many people make the mistake of endlessly tweaking the tapping term in the hope that they’ll eventually find the golden number that will let them use home row mods with no accidents. You can increase or decrease the tapping term all you want but that won’t help with rolling letters if your mod-taps aren’t configured to ignore interruptions.</p>

<p>If they <em>are</em> configured to but you still get accidental alphas or modifiers occasionally, here’s what you can try.</p>

<p>First of all, when starting out with home row mods, a better baseline is a tapping term that’s too high than one that’s too low. So if you have a lot of accidental mod activations, crank up the tapping term to get into a zone where you rather have accidental alphas.</p>

<p>Once you’re there, the goal is to progressively lower the tapping term in order to get closer to your optimal setting.</p>

<p>A method you can use to gauge where you’re at is to simply try to type a text excerpt entirely in lowercase in the <a href="#tapping-term-test-area">text area found at the end of this tip</a>. It will alert you any time you activate a modifier. If you find that you get capital or missing letters all over the board, try to be more careful about the way you tap the keys (see <a href="#quick-swift-taps">quick swift taps</a>). If adapting your typing style does not help, then increase the tapping term. In case you find a particular mod-tap key to be particularly problematic, consider enabling tapping term per key and increase the tapping term for that key.</p>

<p>For <a href="https://docs.qmk.fm/#/tap_hold?id=tapping-term">per key settings</a>, it is recommended to define them relative to the global tapping term. Namely, prefer <code class="language-plaintext highlighter-rouge">return TAPPING_TERM ± offset</code> over <code class="language-plaintext highlighter-rouge">return SOME_ABSOLUTE_VALUE</code>. The reason being that, in the case of special per key terms, what matters isn’t so much the absolute value but its relation to the more widespread global setting. As you grow more comfortable with home row mods, you may find yourself able to lower the tapping term further and if you do, you’ll want to have the per-key settings move along at the risk of making them feel overly long (or short).</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint16_t</span> <span class="nf">get_tapping_term</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="n">keycode</span><span class="p">,</span> <span class="n">keyrecord_t</span> <span class="o">*</span><span class="n">record</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">switch</span> <span class="p">(</span><span class="n">keycode</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">LALT_T</span><span class="p">(</span><span class="n">KC_S</span><span class="p">):</span>
            <span class="k">return</span> <span class="mi">130</span><span class="p">;</span> <span class="c1">// Not recommended</span>
        <span class="k">case</span> <span class="n">SFT_T</span><span class="p">(</span><span class="n">KC_F</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">TAPPING_TERM</span> <span class="o">+</span> <span class="mi">50</span><span class="p">;</span> <span class="c1">// Recommended</span>
        <span class="nl">default:</span>
            <span class="k">return</span> <span class="n">TAPPING_TERM</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>That being said, it won’t take you long to get annoyed from having to edit <code class="language-plaintext highlighter-rouge">config.h</code>, recompile the firmware and flash it onto your board anytime you want to tweak the tapping term, even just slightly, during this exercise. For this exact reason, a fantastic person going by the nickname of “precondition” has created three new quantum keys that let you tweak the tapping term on the fly.</p>

<table>
  <thead>
    <tr>
      <th>Key</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DT_PRNT</code></td>
      <td>“Dynamic Tapping Term Print”: Types the current tapping term, in milliseconds</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DT_UP</code></td>
      <td>“Dynamic Tapping Term Up”: Increases the current tapping term by 5ms</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DT_DOWN</code></td>
      <td>“Dynamic Tapping Term Down”: Decreases the current tapping term by 5ms</td>
    </tr>
  </tbody>
</table>

<p>In order to use them, enable the feature in <code class="language-plaintext highlighter-rouge">rules.mk</code> with <code class="language-plaintext highlighter-rouge">DYNAMIC_TAPPING_TERM_ENABLE = yes</code>.</p>

<p>Once you can easily type long strings of lowercase letters, the next step is to practice on text containing capital letters.</p>

<p>If you get accidental superfluous characters when trying to capitalize, decrease your tapping term (or consider using <a href="#permissive-hold">permissive hold</a>).</p>

<p>Rinse and repeat until you’re satisfied.</p>

<h3 id="tapping-term-test-area">Tapping term test area</h3>

<p>Write a short story all in lowercase with home row mods. In case you accidentally trigger any of the modifiers, the corresponding modifier keys under the text area will light up in red and a short beep will be emitted to alert you.</p>

<textarea id="tappingTermTestArea" rows="5" onkeydown="processModifierPress(event)" onkeyup="processModifierRelease(event)" onfocusout="clearModifiers(event)" placeholder="once upon a time..."></textarea>

<!-- Improve the responsiveness of the modifiers row -->
<div class="modifiersRow">
    <div class="leftModifiers" style="display: flex;">
        <div class="modifierKey" id="ShiftLeft"> L Shift </div>
        <div class="modifierKey" id="ControlLeft"> L Ctrl </div>
        <div class="modifierKey" id="OSLeft"> L GUI </div>
        <div class="modifierKey" id="AltLeft"> L Alt </div>
    </div>

    <div class="modifiersRowSeparator"></div>

    <div class="rightModifiers" style="display: flex;">
        <div class="modifierKey" id="AltRight"> R Alt </div>
        <div class="modifierKey" id="OSRight"> R GUI </div>
        <div class="modifierKey" id="ControlRight"> R Ctrl </div>
        <div class="modifierKey" id="ShiftRight"> R Shift </div>
    </div>

</div>

<p><br /></p>

<h2 id="use-left-and-right-modifiers-but-beware-of-altgr">Use left and right modifiers but beware of AltGr!</h2>

<p>Let’s talk about <code class="language-plaintext highlighter-rouge">RALT</code> (Right Alt, AltGr) first.
The reason why you need to watch out for <code class="language-plaintext highlighter-rouge">RALT</code> is that while most right versions of modifiers act exactly the same as their left counterpart, this is not necessarily the case for <kbd>⎇ Alt</kbd>. Everywhere else except in the US,<sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">7</a></sup> the right Alt becomes <kbd>AltGr</kbd> which is used as a momentary layer switch to access additional symbols. Keep this in mind when composing your right hand home row mods or you might get a surprise!</p>

<p>If this odd case bothers you, you can either use American layout(s) which make(s) no distinction between left and right Alt or you can use the left version of modifiers for all the home row mods. Separating left and right modifiers, as done in the example shown at the beginning of “<a href="#using-home-row-mods-with-qmk">Using home row mods with QMK</a>” and in the output of the home row mods code generators, is not strictly necessary for a functioning setup but doing so offers some perks.</p>

<p>First of all, it allows to hop from one modifier to its counterpart fluidly. What do I mean? Let’s say you want to produce, using the home row mods setup illustrated below, capital “Q” which we’ll assume is situated on the left hand of your keyboard. To do that, imagine you first hold <code class="language-plaintext highlighter-rouge">MT(MOD_LSFT, KC_F)</code> to activate Shift but then you realize that this is the wrong Shift (proper touch typing technique advocates for the use of the opposite hand when Shifting letters).</p>

<figure>
    
    <img src="assets/images/home-row-mods/RealisticHRM-Dark-Miryoku.png" alt="KLE render of dark blue QWERTY home row keycaps with mod icons in the center and mod name on the side of the keycaps" />
    

    <figcaption><span>GACS/◆⎇⎈⇧ home row mods on US QWERTY</span></figcaption>

</figure>

<p>To remedy this, press and hold <code class="language-plaintext highlighter-rouge">MT(MOD_RSFT, KC_J)</code> without releasing your finger off <code class="language-plaintext highlighter-rouge">MT(MOD_LSFT, KC_F)</code> and then, while you’re keeping <code class="language-plaintext highlighter-rouge">MT(MOD_RSFT, KC_J)</code> pressed, release <code class="language-plaintext highlighter-rouge">MT(MOD_LSFT, KC_F)</code>.
At this stage, you’re now holding Shift with only the right hand and can now tap <kbd>Q</kbd> to produce “Q”.</p>

<p>If, instead, your <kbd>J</kbd> key was <code class="language-plaintext highlighter-rouge">MT(MOD_LSFT, KC_J)</code>, you wouldn’t be able to do that. If you hold both Shift mod-taps and then release the one on the left half of the keyboard, holding the Shift mod-tap on the right side loses all its effects when you lift up your left middle finger. It is not doing anything. So when you tap <kbd>Q</kbd> while holding the right-hand Shift mod-tap, you’ll get lowercase “q”.</p>

<!-- insert KLE gif -->

<p>The only way to properly hop modifiers when both of them are programmed to send the exact same modifier, is to fully release the wrong mod-tap you’ve first pressed before pressing and holding the correct one, on the opposite hand.</p>

<p>There is a catch though. If you realize early on that this is the incorrect hand to use the modifier with, you will instinctively fully release the incorrect mod-tap in order to hop to the correct one. If you release the incorrect mod before the tapping term, which is very likely to happen unless you’re slow at catching yourself using the wrong hand for the modifier, that will be considered as a tap by the firmware and will thus send the tap keycode, “f” in our case. Doing so thus puts you at risk of accidental alphas when hopping modifiers.</p>

<p>To recap, the problem with using the same version of Shift for both hands:</p>
<ul>
  <li>Hold left hand home row Shift</li>
  <li>Hold right hand home row Shift</li>
  <li>Let go of left hand home row Shift</li>
  <li>While holding right hand home row Shift, press random letters with left hand</li>
  <li>The letters are not capitalized</li>
</ul>

<p>Secondly, distinguishing between home row mods of the left hand from home row mods of the right hand can be useful if you want to detect typing rolls. For more info, refer to the “<a href="#rolled-modifiers-cancellation">rolled modifiers cancellation</a>” trick.</p>

<h2 id="putting-home-row-mods-on-almost-all-layers">Putting home row mods on (almost) all layers</h2>

<p>If you only have home row mods on the base layer and you desire to apply a modifier to a key that’s situated in a layer, you’ll need to follow a strict timing and sequence of key presses for it to work. First, you’ll need to keep the home row key pressed for longer than your tapping term, then activate the layer you want to access without letting go of the home row mod and finally tap the key on the layer.</p>

<p>For more freedom, you can consider turning the home row on your other layers into mod-taps too. Better yet, see if you can afford to use the normal modifier keycodes on the home row instead. For example, many people have a navigation layer momentarily activated with a thumb key with pure modifier keys on the home row of the left hand and arrow keys on the right hand.</p>

<figure>
    
    <a href="assets/images/home-row-mods/Squiggle-sample-nav-layer.png">
    
    <img src="assets/images/home-row-mods/Squiggle-sample-nav-layer.png" alt="Squiggle with dark MBK caps with legends of the navigation layer" />
    
    </a>
    

    <figcaption><span>Example of a thumb-activated navigation layer with modifiers on the left-hand home row.<br />(The dotted keys indicate <code>KC_TRNS</code>)</span></figcaption>

</figure>

<p>When porting home row mods through your layers, take a minute to consider whether you really need home row mods on a certain layer. While it may be useful on a navigation or accents layer, it’s probably not very useful to include in a symbol layer since you’re unlikely to feel the need to do <kbd>Ctrl</kbd>+<kbd>!</kbd> or <kbd>Alt</kbd>+<kbd>"</kbd>.</p>

<h2 id="disabling-home-row-mods-when-gaming">Disabling home row mods when gaming</h2>

<p>Home row mods and video games do not get along very well. It’s easy to see why. If <kbd>A</kbd>, <kbd>S</kbd>, <kbd>D</kbd> all act as modifiers when held down, you don’t risk going very far in the video game if you use <kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> to move around. There have also been reports of the tapping function of a mod-tap not working reliably with certain video games.</p>

<p>The common solution to this problem is to create a gaming layer where you get rid of the home row mods.</p>

<h2 id="shift-thumb-keys">Shift thumb keys</h2>

<p><em>Not to be confused with the <a href="https://en.wikipedia.org/wiki/Thumb-shift_keyboard">thumb-shift Japanese input method</a>.</em></p>

<p>The Shift modifier is unlike all the others. Unless it’s paired with another modifier, it feels more like a layer switch than a key we can use to execute keyboard shortcuts. In bicameral scripts, it is used to capitalize letters and even unicameral scripts which do not distinguish case such as Arabic and Korean also use Shift to access additional graphemes.</p>

<div class="img-to-hover">
  <figure>
    <p><img src="assets/images/home-row-mods/BaseArabic.jpeg" alt="Base Arabic legends on a 60% keyboard" />
<img src="assets/images/home-row-mods/ShiftArabic.jpeg" class="img-shift" alt="Shifted Arabic legends on a 60% keyboard" /></p>
    <figcaption>
      <p>A variant of the Arabic keyboard.</p>
    </figcaption>
  </figure>
</div>

<p>Being such a critical and frequently used “layer” switch key, the Shift modifier is a great candidate for a thumb key.</p>

<p>Using a thumb key bypasses some of the constraints of home row Shift. If you own an ergonomic keyboard with a good thumb cluster, you have the possibility of placing a dedicated Shift key in a comfortable position, thus freeing yourself of the inherent timing constraints of mod-taps.</p>

<p>If you dedicate a thumb key to only send Shift and nothing else, you can even do away with chording all together by using a <a href="https://docs.qmk.fm/#/one_shot_keys">One-Shot</a> Shift key. As an added benefit, One-Shot Shift also allows you to eradicate accidental overcapitalization which happens when you hold Shift for a tad too long and send two uppercase characters instead of one when capitalizing words like, for example, in the sentence: “THe Grand DUchess Anna PEtrovna oF russia”.</p>

<p>An important concern with a normal or One-Shot Shift thumb key, however, is that it requires dedicating a key to this use alone which isn’t ideal when you aim for low finger travel and/or you’re not a fan of losing the thumb home position. For those feeling concerned about this, a Shift mod-tap thumb key can still prove useful nonetheless.</p>

<p>Mod-tapping the resting home thumb key(s) gives you the same advantage as mod-tapping the home row keys: elimination of the finger/hand movement needed to activate a modifier.</p>

<p>In any case, you must be willing to trade off a layer thumb key for a Shift thumb key; a dealbreaker for some.</p>

<p>As for the question on whether to keep the Shift mod-tap on the home row, it is up to you. Some may argue that the redundant home row Shift keys are useless while others use the Shift thumb keys exclusively for uppercase letters and use the home row Shift for the rest (shifted symbols, shifted Vim commands, keyboard shortcuts, chorded combinations with other modifiers, …).</p>

<h2 id="use-caps-lock">Use Caps Lock</h2>

<p><kbd>Caps Lock</kbd> is the stuff of many jokes and is considered by many to be useless, or even annoying. However for home row mods users who do not have Shift on their pinkies or their thumbs, it is a good solution for typing strings of capital letters. It avoids the awkward back-and-forth swapping of hands that happens when keeping Shift activated by using the opposite hand in order to free the other one from holding Shift to let it type a certain key.</p>

<p>Nonetheless, it still doesn’t deserve to be placed in the outer home row position.</p>

<p>If you want to go one step further, you can check out <a href="https://docs.qmk.fm/#/feature_caps_word">Caps Word</a> which works like a caps lock key that automatically toggles off once you’re done typing a word.
If you ever used caps lock to write a MACRO_IDENTIFIER in insert mode and forgot to toggle it off before entering back into normal mode in Vim and caused subsequent havoc before realizing your mistake, this is the perfect solution.</p>

<h2 id="mechanical-switch-type">Mechanical switch type</h2>

<p>Light tactile switches or clicky switches help with making short, light, snappy taps, and the feedback masks the lag of tap on release.</p>

<!-- Tricks -->

<h2 id="using-non-basic-keycodes-in-mod-taps">Using non-basic keycodes in mod-taps</h2>

<p>As opposed to KMonad, QMK does not allow for non-basic keycodes such as shifted keycodes (e.g. <code class="language-plaintext highlighter-rouge">KC_DLR</code>) and custom keycodes in mod-taps. If you try to pass in a non-basic keycode to the <code class="language-plaintext highlighter-rouge">MT()</code> function, unexpected things will happen because it will try to cast down the special keycode you passed in as a <code class="language-plaintext highlighter-rouge">uint8_t</code> data type.</p>

<p>In the case of a keyboard shortcut such as <code class="language-plaintext highlighter-rouge">KC_DLR</code> (which is merely an alias for <code class="language-plaintext highlighter-rouge">S(KC_4)</code>) or <code class="language-plaintext highlighter-rouge">ALGR(KC_COMMA)</code> or a shortcut involving more than one modifier such as <code class="language-plaintext highlighter-rouge">S(A(KC_2))</code>, all the applied modifiers to the tapped key will be stripped, and you’ll end up with only the unmodified basic keycode upon tapping the mod-tap. Although the holding function will still function exactly as expected. Thus, tapping <code class="language-plaintext highlighter-rouge">MT(MOD_LALT, KC_DLR)</code> will produce “4” on an US QWERTY keyboard and tapping <code class="language-plaintext highlighter-rouge">RCTL_T(S(A(KC_2)))</code> will produce “2” instead of “€” on US MacOS.</p>

<p>As for custom keycodes/macros, the output you’ll get will be dependant on the position of the custom keycode in your <code class="language-plaintext highlighter-rouge">custom_keycodes</code> enum and the amount of enabled quantum keycodes. The value of <code class="language-plaintext highlighter-rouge">SAFE_RANGE</code> is determined by the <code class="language-plaintext highlighter-rouge">quantum_keycodes</code> enum found in <code class="language-plaintext highlighter-rouge">qmk_firmware/quantum/quantum_keycodes.h</code>.</p>

<p>The very first custom keycode/macro in the enum is always assigned to <code class="language-plaintext highlighter-rouge">SAFE_RANGE</code>. Trying to use it in a mod-tap may produce <code class="language-plaintext highlighter-rouge">KC_ENTER</code> on tap. The next custom keycode in your enum (which will be assigned the value of <code class="language-plaintext highlighter-rouge">SAFE_RANGE+1</code>), against all odds, will <em>not</em> produce your expected macro when tapped in the context of a mod-tap but instead may emit the <code class="language-plaintext highlighter-rouge">KC_ESCAPE</code> keycode. And on it goes down the <a href="https://github.com/qmk/qmk_firmware/blob/ccb15c2d2923903a925d253eec66fd4356ceea85/tmk_core/common/keycode.h#L77">list of keycodes</a>, <em>generally</em> starting from the punctuation block. In this situation given as an example,<code class="language-plaintext highlighter-rouge">SAFE_RANGE+5</code> will produce <code class="language-plaintext highlighter-rouge">KC_EQUAL</code>, et cetera, when casted down to <code class="language-plaintext highlighter-rouge">uint8_t</code>.</p>

<p>Naturally, this can be a little disappointing. Especially if you want to <a href="#putting-home-row-mods-on-almost-all-layers">put home row mods on something like a symbol layer</a>.</p>

<p>Fear not! As there exists a trick which doesn’t force you to give up on the idea of using non-basic keycodes in mod-taps or to recode the entire mod-tap logic from scratch.</p>

<p>The idea behind the trick is to create a mod-tap key as usual and let QMK naturally deal with the holding function of the mod-tap as well as the decision between tap and hold but override the normal tapping behavior with our custom code in <code class="language-plaintext highlighter-rouge">process_record_user</code>.</p>

<p>When creating the mod-tap key with QMK’s built-in <code class="language-plaintext highlighter-rouge">MT()</code> function, you need to choose a dummy keycode for the tapping function that you know you’ll never actually use. This can be any of the function keys in the range 13–24 or a keycode that’s unsupported by all major operating systems like <code class="language-plaintext highlighter-rouge">KC_LANG6</code> or <code class="language-plaintext highlighter-rouge">KC_CRSEL</code>, or a dummy custom keycode created solely for this purpose. Regardless of what you choose, the OS will never receive the dummy keycode from your keyboard.</p>

<p>Let’s say we want to create a mod-tap key that acts as a Command/GUI modifier on hold and sends “#” (<kbd>Shift</kbd>+<kbd>3</kbd>) on tap. Any of the following is a good candidate:</p>

<figure class="highlight">
  <pre><code class="language-js" data-lang="js"><span class="err">#</span><span class="nx">define</span> <span class="nx">GUI_HASH</span> <span class="nx">MT</span><span class="p">(</span><span class="nx">MOD_LGUI</span><span class="p">,</span> <span class="nx">KC_F23</span><span class="p">)</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">CMD_HASH</span> <span class="nx">LGUI_T</span><span class="p">(</span><span class="nx">KC_LANG6</span><span class="p">)</span>

<span class="kr">enum</span> <span class="nx">custom_keycodes</span> <span class="p">{</span>
    <span class="nx">MT_POUND</span> <span class="o">=</span> <span class="nx">SAFE_RANGE</span>
<span class="p">};</span>
<span class="err">#</span><span class="nx">define</span> <span class="nx">HOME_HASH</span> <span class="nx">CMD_T</span><span class="p">(</span><span class="nx">MT_POUND</span><span class="p">)</span></code></pre>
</figure>

<p>Note: <code class="language-plaintext highlighter-rouge">MT(MOD_LGUI, kc)</code>, <code class="language-plaintext highlighter-rouge">LGUI_T(kc)</code>, and <code class="language-plaintext highlighter-rouge">CMD_T(kc)</code> are all equivalent</p>

<p>To make things easier to read, I strongly recommend using aliases. How are you supposed to know, from cursory glance, that <code class="language-plaintext highlighter-rouge">MT(MOD_LGUI, KC_F23)</code> will actually output “#” on tap and not send <kbd>F23</kbd>?</p>

<p>It can be tempting to use <code class="language-plaintext highlighter-rouge">LGUI_T(KC_HASH)</code> and it would still work but you need to realise that <code class="language-plaintext highlighter-rouge">LGUI_T(KC_HASH)</code> is the same as <code class="language-plaintext highlighter-rouge">LGUI_T(S(KC_3))</code> which, as explained earlier, gets converted to <code class="language-plaintext highlighter-rouge">LGUI_T(KC_3)</code>. This means that if you override the default tap behavior for <code class="language-plaintext highlighter-rouge">LGUI_T(KC_HASH)</code>, you will also override the behavior of <code class="language-plaintext highlighter-rouge">LGUI_T(KC_3)</code>. For this reason, it’s not recommended to do that.</p>

<p>The next step is to write a case for our newly created special mod-tap in the switch statement of the <code class="language-plaintext highlighter-rouge">process_record_user</code> function.</p>

<figure class="highlight">
  <pre><code class="language-c" data-lang="c"><span class="k">case</span> <span class="n">HOME_HASH</span><span class="p">:</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span> <span class="o">&amp;&amp;</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// send advanced keycode, etc.</span>
      <span class="c1">// the 16 bit version of the `tap_code` function is used here</span>
      <span class="c1">// because KC_HASH is a non-basic keycode.</span>
      <span class="n">tap_code16</span><span class="p">(</span><span class="n">KC_HASH</span><span class="p">);</span>
      <span class="c1">// do not continue with default tap action</span>
      <span class="c1">// if the MT was pressed or released, but not held</span>
      <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
  <span class="p">}</span>
<span class="k">break</span><span class="p">;</span></code></pre>
</figure>

<p>Finally, all that’s left to do is to place <code class="language-plaintext highlighter-rouge">HOME_HASH</code> wherever you want it to be in your layout and flash the new keymap onto your board.</p>

<p>Note: since writing the guide, the ideas of this section have found their way into the official QMK docs: “<a href="https://docs.qmk.fm/#/mod_tap?id=intercepting-mod-taps">Intercepting Mod-Taps</a>”.</p>

<h2 id="combined-mod-taps-on-the-lower-row">Combined mod-taps on the lower row</h2>

<p>This tip is particularly useful if you use KMonad on a keyboard without N-key roll over which resort to blocking in order to prevent ghosting — QMK-compatible keyboards do not suffer from ghosting issues as they’re mostly mechanical keyboards that use diodes. If that previous sentence sounded like technical gobbledegook to you, read through <a href="https://deskthority.net/wiki/Rollover,_blocking_and_ghosting">this Deskthority wiki page</a> to learn more about what all those terms mean.</p>

<p>By concentrating all modifiers in the middle of the alpha block, you are much more likely to run into dropped key presses as a result of ghost-blocking. Namely, you may notice that you can’t do <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd> using home row mods. In such a case, a dedicated <kbd>Ctrl</kbd>+<kbd>Shift</kbd> mod-tap can prove very useful. Given the fact that this problem is most likely to happen a row staggered keyboard, you can intuitively place the combined mod-taps in between the home row mods on the lower row.</p>

<p>As illustrated here on this 60% ANSI keyboard sporting the <a href="#gacs">GACS/◆⎇⎈⇧</a> home row mods order.</p>

<p><img src="assets/images/home-row-mods/combined-lower-row-mod-taps-row-staggered.png" alt="Black 60% ANSI keyboard with side-printed QWERTY legends sporting GACS home row mods and G+A A+C C+S lower row mods" /></p>

<h2 id="rolled-modifiers-cancellation">Rolled modifiers cancellation</h2>
<p>Let’s look into the situation where one uses home row mods on a keyboard layout that favors rolls. The most famous rolls-focused keyboard layout is Colemak, so we’ll use the following home row mods setup as a case study.</p>

<figure>
    
    <img src="assets/images/home-row-mods/RealisticHRM-Dark-SideLegends-Colemak-GASC.png" alt="KLE render of dark blue Colemak home row keycaps with mod icons in the center and mod name on the side of the keycaps" />
    

    <figcaption><span>GASC/◆⎇⇧⎈ home row mods on Colemak</span></figcaption>

</figure>

<p>Let’s imagine that this Colemak user is aiming for the lowest tapping term on his Shift mod-taps in order to capitalize letters in a faster and more responsive way. He’s gone so low on the tapping term of his Shift mod-taps, that rolling over <kbd>S</kbd> and <kbd>T</kbd> produces “T” instead of the expected “st”. Same story for rolls over <kbd>E</kbd> and <kbd>N</kbd>.
If he’s otherwise happy with the tapping term of his Shift mod-taps, what can he do to help him type “The first event” rapidly and accurately without ending up with “The firT evNt” instead?</p>

<p>It is tempting to say that he should use <code class="language-plaintext highlighter-rouge">TAPPING_TERM_PER_KEY</code> and increase the tapping term of his Shift mod-taps in order to reduce the accidental mod activations but aside from the “st” and “en” bigrams, this user is satisfied with the speed of activation of Shift for every other combination of letters. Increasing the tapping term will probably help with rolling “st” and “en” but it will also ever so slightly affect every other bigram involving “s” or “e”.
This hypothetical user can either adapt himself to it or if he really wants to, he can adapt the firmware <em>to himself</em>.</p>

<p>To do so, he can use this nifty piece of code in <code class="language-plaintext highlighter-rouge">process_record_user</code> which takes advantage of the distinction between left Shift and right Shift:</p>

<figure class="highlight">
  <pre><code class="language-c" data-lang="c"><span class="n">bool</span> <span class="nf">process_record_user</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="n">keycode</span><span class="p">,</span> <span class="n">keyrecord_t</span> <span class="o">*</span><span class="n">record</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">switch</span> <span class="p">(</span><span class="n">keycode</span><span class="p">)</span> <span class="p">{</span>

    <span class="k">case</span> <span class="n">RCTL_T</span><span class="p">(</span><span class="n">KC_N</span><span class="p">):</span>
        <span class="cm">/*
        This piece of code nullifies the effect of Right Shift when tapping
        the RCTL_T(KC_N) key.
        This helps rolling over RSFT_T(KC_E) and RCTL_T(KC_N)
        to obtain the intended "en" instead of "N".
        Consequently, capital N can only be obtained by tapping RCTL_T(KC_N)
        and holding LSFT_T(KC_S) (which is the left Shift mod tap).
        */</span>

        <span class="cm">/*
        Detect the tap.
        We're only interested in overriding the tap behavior
        in a certain cicumstance. The hold behavior can stay the same.
        */</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span> <span class="o">&amp;&amp;</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// Detect right Shift</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">get_mods</span><span class="p">()</span> <span class="o">&amp;</span> <span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">))</span> <span class="p">{</span>
                <span class="c1">// temporarily disable right Shift</span>
                <span class="c1">// so that we can send KC_E and KC_N</span>
                <span class="c1">// without Shift on.</span>
                <span class="n">unregister_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">));</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">KC_E</span><span class="p">);</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">KC_N</span><span class="p">);</span>
                <span class="c1">// restore the mod state</span>
                <span class="n">add_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">));</span>
                <span class="c1">// to prevent QMK from processing RCTL_T(KC_N) as usual in our special case</span>
                <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
         <span class="cm">/*else process RCTL_T(KC_N) as usual.*/</span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>

    <span class="k">case</span> <span class="n">LCTL_T</span><span class="p">(</span><span class="n">KC_T</span><span class="p">):</span>
        <span class="cm">/*
        This piece of code nullifies the effect of Left Shift when
        tapping the LCTL_T(KC_T) key.
        This helps rolling over LSFT_T(KC_S) and LCTL_T(KC_T)
        to obtain the intended "st" instead of "T".
        Consequently, capital T can only be obtained by tapping LCTL_T(KC_T)
        and holding RSFT_T(KC_E) (which is the right Shift mod tap).
        */</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span> <span class="o">&amp;&amp;</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">get_mods</span><span class="p">()</span> <span class="o">&amp;</span> <span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">))</span> <span class="p">{</span>
                <span class="n">unregister_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">));</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">KC_S</span><span class="p">);</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">KC_T</span><span class="p">);</span>
                <span class="n">add_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">));</span>
                <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
         <span class="cm">/*else process LCTL_T(KC_T) as usual.*/</span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</figure>

<p>If you have a different setup because you neither use Colemak nor use the GASC/◆⎇⇧⎈ home row mods order, but are interested in using this trick, here are the parameters you need to change:</p>

<p>Let <code class="language-plaintext highlighter-rouge">LSFT_T(l_s_letter)</code> equal your left hand home row Shift mod-tap,
    <code class="language-plaintext highlighter-rouge">LMOD_T(l_letter)</code> equal your left hand home row non-Shift mod-tap (it can be any mod, that will depend on what you’ve put near your home row Shift mod-tap),
and vice versa for the right hand;
     <code class="language-plaintext highlighter-rouge">RSFT_T(r_s_letter)</code>,
     <code class="language-plaintext highlighter-rouge">RMOD_T(r_letter)</code>.</p>

<figure class="highlight">
  <pre><code class="language-c" data-lang="c">    <span class="k">case</span> <span class="nf">RMOD_T</span><span class="p">(</span><span class="n">r_letter</span><span class="p">)</span><span class="o">:</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span> <span class="o">&amp;&amp;</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">get_mods</span><span class="p">()</span> <span class="o">&amp;</span> <span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">))</span> <span class="p">{</span>
                <span class="n">unregister_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">));</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">r_s_letter</span><span class="p">);</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">r_letter</span><span class="p">);</span>
                <span class="n">add_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_RSHIFT</span><span class="p">));</span>
                <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>

    <span class="k">case</span> <span class="nf">LMOD_T</span><span class="p">(</span><span class="n">l_letter</span><span class="p">)</span><span class="o">:</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">record</span><span class="o">-&gt;</span><span class="n">event</span><span class="p">.</span><span class="n">pressed</span> <span class="o">&amp;&amp;</span> <span class="n">record</span><span class="o">-&gt;</span><span class="n">tap</span><span class="p">.</span><span class="n">count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">get_mods</span><span class="p">()</span> <span class="o">&amp;</span> <span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">))</span> <span class="p">{</span>
                <span class="n">unregister_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">));</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">l_s_letter</span><span class="p">);</span>
                <span class="n">tap_code</span><span class="p">(</span><span class="n">l_letter</span><span class="p">);</span>
                <span class="n">add_mods</span><span class="p">(</span><span class="n">MOD_BIT</span><span class="p">(</span><span class="n">KC_LSHIFT</span><span class="p">));</span>
                <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span></code></pre>
</figure>

<p>This trick is about cancelling the effect of home row Shift mod-tap on a nearby home row mod-tap but nothing prevents you from cancelling the effect of home row non-Shift mod-tap on another key that isn’t even a mod-tap at all. It can be generalized.</p>

<p>Sticking with the Colemak example, imagine you have repetitive accidental mod activations when doing <code class="language-plaintext highlighter-rouge">RGUI_T(KC_O)</code>+<code class="language-plaintext highlighter-rouge">KC_U</code> when rolling keys for the bigram “ou”. You can add a case in your <code class="language-plaintext highlighter-rouge">process_record_user</code> for <code class="language-plaintext highlighter-rouge">KC_U</code> where you check the mod state for <code class="language-plaintext highlighter-rouge">RGUI</code> and override the default behavior by sending “ou” instead of <kbd>GUI</kbd>+<kbd>U</kbd>.</p>

<p>That being said, I want to clarify that this trick is most definitely not necessary for an enjoyable home row mods experience.
I’ve mentioned it here just to give another example why you might want to distinguish between right hand and left hand home row mods. You don’t need to go this far.</p>

<p>However, if you desire to go even further, <a href="https://www.reddit.com/user/Manna_Harbour">Manna Harbour</a>, the creator of the <a href="https://github.com/manna-harbour/qmk_firmware/tree/miryoku/users/manna-harbour_miryoku">Miryoku</a> layout, is working on a new configuration option named “Bilateral Combinations”. This option forces you to combine mods on one hand with taps on the opposite hand. It can reduce accidental mods.  When it is enabled, the last mod-tap hold will be converted to a mod-tap tap if another key on the same hand is tapped.</p>

<p>For more information on this developing new option, consult these links:</p>

<ul>
  <li><a href="https://github.com/manna-harbour/qmk_firmware/blob/bilateral-combinations/docs/tap_hold.md#bilateral-combinations">Bilateral combinations docs</a></li>
  <li><a href="https://github.com/qmk/qmk_firmware/compare/master...manna-harbour:bilateral-combinations">Bilateral combinations code</a></li>
</ul>

<p>For yet another implementation of this trick, one can also consult Steven Hum’s “<a href="http://thedarnedestthing.com/rolling%20qmk%20modifiers">rolling qmk modifiers</a>”.</p>

<h2 id="using-mod-taps-in-combos">Using mod-taps in combos<!-- [WIP] --></h2>

<p>When defining combos that involve dual-role keys, make sure to use the full name of the dual-role key, not just its tap keycode. This is a common error.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">uint16_t</span> <span class="n">PROGMEM</span> <span class="n">A_S_COMBO</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">KC_A</span><span class="p">,</span> <span class="n">KC_S</span><span class="p">,</span> <span class="n">COMBO_END</span><span class="p">};</span> <span class="c1">// ❎ Incorrect</span>
<span class="k">const</span> <span class="kt">uint16_t</span> <span class="n">PROGMEM</span> <span class="n">A_S_COMBO</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="n">LGUI_T</span><span class="p">(</span><span class="n">KC_A</span><span class="p">),</span> <span class="n">LALT_T</span><span class="p">(</span><span class="n">KC_S</span><span class="p">),</span> <span class="n">COMBO_END</span><span class="p">};</span> <span class="c1">// ✅ Correct</span>
</code></pre></div></div>

<h1 id="alternatives">Alternatives</h1>

<p>What if none of the above work out for you? You understand what all the tap-hold configuration settings mean, you played around with them, you’ve read through all the tips and tricks and yet you still can’t get used to home row mods despite the fact that you like the concept… What else can you try?</p>

<h2 id="alternative-home-row-mods-layout">Alternative home row mods layout</h2>

<p>The classic home row mods layout places all of the mod-taps on the resting keys of a touch typer, the “home keys”, as illustrated in purple below.</p>

<p><img src="assets/images/home-row-mods/PlanckAlternative-ClassicHRM.jpeg" alt="Dark Ortholinear Planck keyboard with the ASDFJKL; keys highlighted in purple" /></p>

<p>This the optimal placement for a touch typer because that’s where they’ve learned to rest their fingers by default. As such, the finger travel to reach for any of the four modifiers is zero.</p>

<p>However, if we’re willing to stretch the definition of “home row” to not only include the resting keys but encompass the entire middle row of the keyboard, we can start to imagine alternative home row mods layouts.</p>

<p>Firstly, one could shift all the mod-taps outwards.</p>

<p><img src="assets/images/home-row-mods/PlanckAlternative-OuterStraight.jpeg" alt="Dark Ortholinear Planck keyboard with the CapsLockASDKL;' keys highlighted in purple" /></p>

<p>This is vaguely reminiscent of the <a href="https://www.itmedia.co.jp/news/articles/1912/10/news176.html">HHKB-style <kbd>Ctrl</kbd> key</a> wherein the key that would usually be <kbd>Caps Lock</kbd> on standard keyboards is mapped to <kbd>Ctrl</kbd> instead.</p>

<p>Be that as it may, two flaws are apparent with this layout:</p>

<ol>
  <li>The pinkies have double duty when it comes to modifier activation:
<kbd>A</kbd>,<kbd>;</kbd> <em>and</em> <kbd>Caps Lock</kbd>,<kbd>'</kbd></li>
  <li>In case you need to combine the two outer home row mods, the whole hand needs to shift 1u outwards from home position to let the ring finger hold down <kbd>A</kbd> or <kbd>;</kbd></li>
</ol>

<p>Therefore, it may be better to go the other way and translate the home row mods <em>inwards</em>.</p>

<p><img src="assets/images/home-row-mods/PlanckAlternative-InnerStraight.jpeg" alt="Dark Ortholinear Planck keyboard with the SDFGHJKL keys highlighted in purple" /></p>

<p>Although, the second flaw is essentially still present, the first flaw is mitigated by offloading the weak pinky fingers entirely and letting the strong index fingers deal with the extra mod-taps.</p>

<p>Now, you may think to yourself that relieving the pinkies is good and all but what if you don’t like lateral movement?</p>

<p>The fellow pinky haters behind the “Balanced Effortless Keyboard Layout” (<a href="https://deskthority.net/wiki/BEAKL">BEAKL</a>) introduced the concept of the “<a href="https://keyboard-design.com/easy-block-words.html">home block</a>” wherein the lower row index keys (<kbd>V</kbd> and <kbd>M</kbd> in the illustration) have a much more favourable score in the key effort ratings than the inner index keys of the home/middle row (<kbd>G</kbd> and <kbd>H</kbd>) because the index finger is a short finger that’s more comfortable to flex than to extend.  The same concept is at play in <a href="https://workmanlayout.org/#the-problem-with-colemak">Workman</a> and <a href="https://colemakmods.github.io/mod-dh/#colemak-problems">Colemak-DH</a>.</p>

<p>This means we can use home <em>block</em> mods.</p>

<p><img src="assets/images/home-row-mods/PlanckAlternative-DHStyle.jpeg" alt="Dark Ortholinear Planck keyboard with the SDFVMJKL keys highlighted in purple" /></p>

<p>The pinky remains unused for modifiers in this modification and pressing the fourth mod-tap with the index fingers is more comfortable but aligning modifiers vertically can be problematic.</p>

<p>Unless you have a steno-friendly keyboard<sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">8</a></sup> on which vertical combos are easy to do, you’ll struggle to combine one-handedly the index modifiers.</p>

<p>Finally, for a change, let’s talk about an alternative home row mods layout that does not suffer from a mod-tap combination problem.</p>

<p>The main reason behind the position of the mod-taps in the classic home row mods layout is that those keys are the ones you’re supposed to rest on in idle state. Yet, if you use QWERTY or any of its national derivatives on a keyboard that’s not columnar staggered, you may find yourself actually resting on those keys instead:</p>

<p><img src="assets/images/home-row-mods/PlanckAlternative-FauxColStagger.jpeg" alt="Dark Ortholinear Planck keyboard with the AWEFJIO; keys highlighted in purple" /></p>

<p>The ring and middle fingers are longer than the short pinkies and index fingers so why should you force them to be in the same horizontal line? Besides, “e”, “i”, and “o” are more common than either of “s”, “d”, “k”, or “l”.</p>

<p>Though, at this point, we’re fringing on upper row mods…</p>

<h2 id="upperlower-row-mods">Upper/Lower row mods</h2>

<p>A simple modification you can do is to translate the home row mods up or down. They remain very easy to access, and depending on the alpha layout used, accidental misfires are less likely to happen as a virtue of rarer n-grams occupying the row and thus reducing the amount of typing rolls that involve mod-tap keys.</p>

<p>For instance, translating the home row mods down is a good way to prevent accidental misfires caused by typing adjacent keys. You’re unlikely to come across a word containing “xcv”, “qkj” or “,.vbh”. Generally speaking, the lower row of keys is populated with uncommon letters and symbols. That observation does not only apply to alternative optimized layouts such Dvorak or Turkish F but also to QWERTY!</p>

<p>Naturally, this trick is helpful for reducing the occurences of misfires only if you translate the mod-taps to a row that contains less frequent keys than the home row. Translating mod-taps up on QWERTY would thus be counter-productive in this regard.</p>

<figure>
  <p><img src="https://www.7day.nl/ergowerken/blog/strijdtoetsenborden/dvorakvsqwerty.jpg" alt="Row frequency stats of QWERTY and Dvorak" /></p>
  <figcaption>
    <p>Comparison of the usage frequency of the three main rows on QWERTY and Dvorak, based on an English corpus of text.
Characteristically, QWERTY has a higher usage of the upper row than of the home row.</p>
  </figcaption>
</figure>

<h2 id="home-row-mod-combos">Home row mod-combos</h2>

<p>It’s all too easy to hold down a single key for a tad too long than desired and activate a potentially destructive action that has to be fixed afterwards. What if we require more than one single key to be pressed down? Modifiers would be activated only if a specific combination of adjacent (or not) keys was held down simultaneously. The idea behind being that it’s harder to accidentally hold down two or more keys simultaneously.</p>

<p>While there are only maybe about 4!=24 possible <a href="#home-row-mods-order">home row mods orders</a> if we restrain ourselves to the middle row and mirror the order on both hands, the number of possibilities explode if we start to consider home row mod-combos.</p>

<p><kbd>S</kbd>+<kbd>D</kbd> for left Alt, <kbd>J</kbd>+<kbd>K</kbd> for right GUI, <kbd>F</kbd>+<kbd>J</kbd> for Control, <kbd>J</kbd>+<kbd>K</kbd>+<kbd>L</kbd> for Control+Shift, …</p>

<p>However, most of the possible combinations aren’t really fit for the job. You’ll want to mirror the combo-mods on both hands for the same reason home row mod-taps are mirrored and you’ll want to be able to chord all four modifiers single-handedly.</p>

<p>You’ll run into issues if you want to paste something from your clipboard with <kbd>Ctrl</kbd>+<kbd>V</kbd> but both of your index fingers are occupied holding down <kbd>F</kbd> and <kbd>J</kbd> in order to activate Ctrl. A similar predicament happens if you want to open the task manager with <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> but your setup is such that, while you can activate Ctrl and Alt on the left hand with <kbd>D</kbd>+<kbd>F</kbd> and <kbd>S</kbd>+<kbd>F</kbd> respectively, you can’t hold down <kbd>S</kbd>+<kbd>D</kbd>+<kbd>F</kbd> for Ctrl+Alt, because that’s already used for the more common Ctrl+Shift because <kbd>S</kbd>+<kbd>D</kbd> is Shift.</p>

<p><img src="assets/images/home-row-mods/CtrlAltDel-bad-combos.png" alt="QWERTY home row with a Fn key in place of Caps Lock with a badly designed home row combo-mod setup" /></p>

<p>Consequently, you end up having to trigger Ctrl on the left hand and Alt on the right hand. Now imagine that you have put <kbd>Del</kbd> on a layer, on the right index home row key. Since your right index is too busy activating Alt in tandem with the right ring finger, there is literally no way for you to open the task manager to kill that unresponsive app. Even if you swap hands and use the left for Alt and the right for Ctrl, the problem persists. All you can do now is to resort to using the mouse and reconsider your keymap design.</p>

<p>This shows that combining home row combo-mods is a more challenging design problem than it may seem at first glance.</p>

<h3 id="sticky-combos">Sticky Combos</h3>

<p>A solution to this combination problem is to use sticky combos. Instead of momentarily activating modifiers by holding down two or more keys, you tap the keys that constitute a combo, all within combo term, and the modifier gets applied to whatever basic keycode you type next.</p>

<p>The sticky/one-shot modifier gets consumed only if the next keycode you type isn’t a layer switch or a modifier itself. This means you can combine an arbitrary amount of modifiers and layer switches sequentially.</p>

<p>If we go back over our <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> example, you can chord your combo for Ctrl, then chord your combo for Alt, with the help of sticky combos, and finally, comfortably activate the Fn layer to access <kbd>Del</kbd>.</p>

<p><img src="assets/images/home-row-mods/CtrlAltDel-sticky-combos.webp" alt="QWERTY home row with a Fn key in place of Caps Lock executing Ctrl+Alt+Del with sticky combos" /></p>

<p>Besides, this alternative presents the great benefit of having access to all modifiers on the home row without requiring to hold down keys for a prolonged amount of time. Given the fact that they’re combos, you don’t need to pay attention to the specific order in which you press the keys that compose the chord and the stickiness of the modifiers provided by the One-Shot functionality of QMK lets you sequentially combine modifiers and basic keycodes, one after another.</p>

<h3 id="combo-misfires">Combo misfires</h3>

<p>The biggest drawback with all the aforementioned points is that home row mod-combos are even more prone to misfires than home row mod-taps are. All that’s needed for a combo to fire is to register a press event for all the combo keys, in any order, within the combo term.</p>

<p>As a matter of fact, one should not be fooled by the idea that you’re less likely to press down multiple keys simultaneously than to hold a single key a tad too long. You can’t fine-tune when and how a combo activates like you can with mod-taps via tap hold configuration settings such as <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code> — Although <abbr title="Pull Request">PR</abbr> <a href="https://github.com/qmk/qmk_firmware/pull/8591">#8591</a> adds half a dozen new combo configuration settings that will be of interest for anyone looking to use home row mod-combos. Combos’ indifference to key press order also prevents you from employing advanced tricks such as <a href="#rolled-modifiers-cancellation">rolled modifiers cancellation</a> to help with accidental mods.</p>

<p>If you want to type two keys that compose a combo, you <em>must</em> wait out the end of the combo term after pressing the first key before pressing the next one. In case you haven’t defined a combo term in <code class="language-plaintext highlighter-rouge">config.h</code>, it falls back to the value of the global tapping term which will generally float around 200ms for most users. Naturally, the first and only thing you can do is to reduce the combo term to a saner value; at least under 100ms.</p>

<p>Even if you do decrease the combo term down to 70, 50 or even sub-30 milliseconds, home row mod-combos are only really viable on QWERTY. To give a striking example, let’s look at <a href="https://goo.gl/PL39c2">THE-1</a>, an alpha layout heavily based on typing rolls or “splats” as the author calls them.</p>

<figure>
  <p><a href="https://goo.gl/PL39c2">
        <img src="assets/images/home-row-mods/THE-1.png" alt="THE-1 keyboard layout on a 5x3 ortholinear keyboard based on the TextBlade" />
</a></p>
  <figcaption>
    <p>THE-1 Keyboard Layout</p>
  </figcaption>
</figure>

<p>It would be quite the challenge to use home row mod-combos on such a layout. You would either need to tap each home row key separately on its own, which kills the whole point of this layout optimizing for splats, or decrease the combo term to such a low value that it’s hard to reliably trigger the modifiers when you need them.</p>

<h2 id="chording-with-thumb-keys">Chording with thumb keys</h2>

<p>The idea is to choose a thumb key — no need for an ergonomic keyboard, the space bar would also fit the bill — with which you will chord each home key to produce a modifier.</p>

<p>There are two types of implementation possible: first with a layer switch, and second with combos.</p>

<h3 id="layers">Layers</h3>

<p>The arguably simpler and more flexible method is to use the designated thumb key as a layer key that activates a layer where the home row is composed of pure modifier keys. It can be a momentary switch, a layer-tap, a toggle, a layer tap-toggle, a one-shot layer key… Whatever you pick, the usage will boil down to this:</p>

<ol>
  <li>Press layer thumb key</li>
  <li>Activate the modifiers you need by pressing the appropriate home row keys</li>
  <li>Deactivate the layer with home row mods (keep holding down keys pressed in step 2)</li>
  <li>Tap the basic keycode onto which you wish to apply the modifier(s)</li>
  <li>Release all modifiers
<!-- Animation of the above steps --></li>
</ol>

<p>If you don’t like holding down keys, you can afford to use one-shot mods instead since the modifiers are on a layer. This approach has been popularized by <a href="https://github.com/callum-oakley/qmk_firmware/tree/master/users/callum">Callum Oakley’s userspace</a>. To make the most of this alternative approach, don’t use layer-tap keys. Only “pure” layer switching keys like <code class="language-plaintext highlighter-rouge">MO(layer)</code> remove the involvement of the tapping term.</p>

<h3 id="combos">Combos</h3>

<p>This alternative also involves combos like in <a href="#home-row-mod-combos">home row mod-combos</a> but this one is much closer to the way classic home row mods work.</p>

<p>For one, the way the mods are laid out (<a href="#home-row-mods-order">order</a>, <a href="#alternative-home-row-mods-layout">layout</a>) is essentially the same as in classic home row mods. The only big difference is that the thumb gets involved to tell when a home row key should act like a modifier and when it should act like a normal letter/number/punctuation key.</p>

<p>The usage of this implementation is less convoluted than that of the layers implementation. If you want a modifier, simply press the appropriate home row key and the designated thumb key together within combo term. Since chording with thumb keys is what informs the firmware of your desire to initiate a keyboard shortcut, the hold time is irrelevant. As soon as the firmware detects a combo, the modifier(s) get activated.</p>

<p>Ideally, the thumb key used in chords shouldn’t be a key that’s often followed or preceded by a home row key such as space. All in the spirit of reducing accidental misfires when typing normally.</p>

<p>One nifty thing about this method is that you don’t need to keep holding down all the combo keys. You can press all the keys that compose the combo to trigger it and then only keep a single combo key down to maintain the modifier active, thus freeing your other fingers.</p>

<p>Overlapping combos used to be unsupported so all you needed to define is a combo for each of the 8 modifiers; chording multiple home row mods would have automatically called all the required combos. Whereas with the new combo improvements, you will need to specify a combo for</p>

<ol>
  <li><kbd>Ctrl</kbd></li>
  <li><kbd>Alt</kbd></li>
  <li><kbd>Shift</kbd></li>
  <li><kbd>GUI</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Alt</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Shift</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Alt</kbd>+<kbd>Shift</kbd></li>
  <li><kbd>Alt</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Shift</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>GUI</kbd></li>
  <li><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>GUI</kbd></li>
</ol>

<p>Idem for the other hand. So we’re looking at 30 combos total if we assume only one-handed combinations of modifiers.
However, if we drop that constraint and wish to be very exhaustive and include the possibility to do something as insane as
<kbd>LCtrl</kbd>+<kbd>LGUI</kbd>+<kbd>LAlt</kbd>+<kbd>RAlt</kbd>+<kbd>RCtrl</kbd>+<kbd>RShift</kbd>+<kbd>RGUI</kbd>,
we would need 255 combos.</p>

<!-- ## Home row layers and modifiers on the thumb keys -->

<h2 id="tap-dances">Tap dances</h2>

<p>Tap dances can offer a figurative layer of protection against unintended mod activations. Where in mod-taps, only a hold is required, you could code a tap dance in such a way that you need to double tap and then hold a key for it to register as a modifier.</p>

<h1 id="summary">Summary</h1>
<p>In summary, home row mods are an unorthodox, innovative way to use modifiers ergonomically. With the right piece of software, it can be used on any type of keyboard, and is beneficial regardless of the physical layout.<sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">9</a></sup> It will take a bit of practice and time to get used to typing with home row mods but the pay-off is worth it.</p>

<h1 id="tldr-table">TL;DR Table</h1>

<table>
  <thead>
    <tr>
      <th>Question</th>
      <th>Answer</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>What are home row mods?</td>
      <td>Mod-taps on the home row</td>
    </tr>
    <tr>
      <td>What are mod-taps?</td>
      <td>A dual-role key that sends a basic character (lettter, punctuation, number, …) when pressed and released on its own but acts as a modifier when held down</td>
    </tr>
    <tr>
      <td>Why use home row mods?</td>
      <td>It’s a more ergonomic and efficient way to use modifiers</td>
    </tr>
    <tr>
      <td>How to use home row mods?</td>
      <td>Either use a QMK keyboard or install KMonad</td>
    </tr>
    <tr>
      <td>How to lay out the modifiers on the home row?</td>
      <td>It does not matter. If you’re undecided, you can go for <a href="#gacs">GACS/◆⎇⎈⇧</a></td>
    </tr>
    <tr>
      <td>What tap hold configuration settings should I enable?</td>
      <td>On QMK version ≥0.21, keep it default. A low <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code> can also prove useful.</td>
    </tr>
    <tr>
      <td>How do I get started with home row mods on QMK or KMonad?</td>
      <td>Go to the generator for the program you wish to use (<a href="#qmk-home-row-mods-code-generator">QMK</a>) (<a href="#kmonad-home-row-mods-code-generator">KMonad</a>), select your options and click on the button “Generate”. Follow the instructions to figure out where to paste the generated output</td>
    </tr>
    <tr>
      <td>What’s the most important tip for using home row mods?</td>
      <td>Get into the habit of typing with quick, swift taps.</td>
    </tr>
  </tbody>
</table>

<details>
  <summary>Updates Log</summary>
  <p>31 Aug 2023:</p>
  <ul>
    <li><code class="language-plaintext highlighter-rouge">DUMMY_NEUTRALIZER_KEYCODE</code> is now merged into <code class="language-plaintext highlighter-rouge">qmk:main</code> so I copy-pasted the explanation from the docs. (I am the author of that feature and its documentation so I’m not plagiarizing anyone by copy-pasting :p)</li>
  </ul>

  <p>19 Jun 2023:</p>
  <ul>
    <li>Mentioned Caps Word in the section about Caps Lock</li>
    <li>Mentioned the section about intercepting mod-taps in the official docs</li>
  </ul>

  <p>18 Jun 2023:</p>
  <ul>
    <li>Updated explanations regarding the new default behavior of modtaps.</li>
    <li>Removed outdated mentions of <code class="language-plaintext highlighter-rouge">IGNORE_MOD_TAP_INTERRUPT</code></li>
    <li>Added section on <code class="language-plaintext highlighter-rouge">HOLD_ON_OTHER_KEY_PRESS</code>.</li>
    <li>Updated Tapping Force Hold section to talk about the new equivalent Quick Tap Term instead.</li>
    <li>Removed outdated information about <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code>-like behavior automatically getting enabled if <code class="language-plaintext highlighter-rouge">TAPPING_TERM</code> ≥ 500ms.</li>
    <li>Updated supported keyboards count.</li>
  </ul>

  <p>03 Feb 2021:</p>
  <ul>
    <li>Mentioned Callum style home row mods in Alternatives&gt;Chording with thumb keys&gt;Layers</li>
  </ul>

  <p>13 Sep 2021:</p>
  <ul>
    <li>Updated KMonad links</li>
    <li>De-emphasized the importance of <code class="language-plaintext highlighter-rouge">PERMISSIVE_HOLD</code></li>
    <li>Added a footnote about the “meta” modifier</li>
    <li>Updated the count of supported QMK keyboards</li>
    <li>No need to manually check out PRs #9404 and #8591 as they’re now merged in <code class="language-plaintext highlighter-rouge">qmk:master</code></li>
  </ul>

  <p>27 Dec 2021:</p>
  <ul>
    <li>No need to manually check out PR #11036 (Dynamic Tapping Term) as it is now merged in <code class="language-plaintext highlighter-rouge">qmk:master</code>.</li>
  </ul>

  <p>6 Jan 2022:</p>
  <ul>
    <li>Added a <code class="language-plaintext highlighter-rouge">if (record-&gt;event.pressed)</code> check before each code block overriding the tap of a modtap. Code should no longer fire twice now.</li>
  </ul>

  <p>18 Mar 2023:</p>
  <ul>
    <li>Added a short note about the breaking change <code class="language-plaintext highlighter-rouge">TAPPING_FORCE_HOLD</code> → <code class="language-plaintext highlighter-rouge">QUICK_TAP_TERM</code> in QMK.</li>
  </ul>

  <p>6 Aug 2024:</p>
  <ul>
    <li>Replaced <code class="language-plaintext highlighter-rouge">DT_PRINT</code> typo by <code class="language-plaintext highlighter-rouge">DT_PRNT</code>.</li>
  </ul>
</details>

<h5 class="no_toc" id="footnotes">Footnotes</h5>

<!-- TODO: Add label tags to forms -->
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>“Meta” is an ambiguous modifier name. It used to be its own modifier but with the advent and domination of IBM PC-style keyboards, you won’t find a physical <kbd>Meta</kbd> key anymore but the term remained in some places even as we standardised to the 2×4 modifiers of the HID spec that we know today. Sometimes, that’s how some Linux apps call the Super/GUI modifier but in GNU Emacs, Meta actually refers to the Alt modifier by default, unless you remap it. Meanwhile, <code class="language-plaintext highlighter-rouge">xmodmap</code> and <code class="language-plaintext highlighter-rouge">xkb</code> map the level 2 of <code class="language-plaintext highlighter-rouge">&lt;LALT&gt;</code> to <code class="language-plaintext highlighter-rouge">Meta_L</code> thus meaning that Shift+Alt = Meta. The <a href="https://deskthority.net/download/file.php?id=47925">Symbolics 3600</a> keyboard features both a <kbd>Super</kbd> and a <kbd>Meta</kbd> key but no <kbd>Alt</kbd>. On the <a href="http://xahlee.info/kbd/iold51593/sail_keyboard_8cd7f.jpg">SAIL keyboard</a>, <kbd>Meta</kbd> lives alongside <kbd>Alt</kbd> with no <kbd>Super</kbd> in sight. All in all, I’m in favour of abandoning the use of this term. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Caps Lock only capitalizes letters and keeps numbers and punctuations intact whereas Shift Lock acts exactly like the Shift keys and affects all the keys. <kbd>Caps Lock</kbd>+<kbd>-</kbd> = <code class="language-plaintext highlighter-rouge">-</code> ; <kbd>Shift Lock</kbd>+<kbd>-</kbd> = <code class="language-plaintext highlighter-rouge">_</code>. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>I have to admit that I couldn’t find any hard numbers supporting this. I have yet to meet someone who disagrees with this ranking though. It’s a very reasonable guess. Every capital letter in this article involved Shift. Ctrl+ZXCV is ridiculously common and most program shortcuts are either Ctrl+Letter or Ctrl+Shift+Letter. What’s more likely to be debatable is GUI &lt; Alt. The reasoning is that, while you don’t find many programs using Alt for important keyboard shortcuts and rare are the people who use Alt to navigate through menus in graphical apps, it is much more frequently used than one might expect just because of Alt+Tab alone. As for GUI, only chorded keyboard shortcuts are considered here so if we ignore WinKey taps to open the Start Menu, we can easily imagine why GUI would end up at the bottom of the ranking. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>“Technically there is only one static <code class="language-plaintext highlighter-rouge">tapping_key</code> variable which tracks the currently processed tap/hold decision. However, events in <code class="language-plaintext highlighter-rouge">waiting_buffer</code> retain their timestamps, so when the tap/hold decision finally resolves, some other event from <code class="language-plaintext highlighter-rouge">waiting_buffer</code> may become the new <code class="language-plaintext highlighter-rouge">tapping_key</code>, and its tapping term would be counted from the moment when that key has been originally pressed. With per-key tapping term it could be possible that the tapping term for the second key has already expired by the time the first key has been handled, however. So you probably can think that every key has a separate timer (tracked using event timestamps), with an additional restriction that if multiple tap/hold keys are held at the same time, the tapping term for any of those keys cannot expire until all keys pressed before it had been handled (either the tapping terms for them had expired, or the keys had been released).” — <a href="https://github.com/sigprof">sigprof</a>, in the QMK Discord server <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>Once again, the GUI modifier on Desktop Environments such as Windows or Gnome is an exception to this. And so is the Alt modifier, which can be used as a leader key to navigate the menus of graphical applications. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>Before you go ahead and do that, do keep in mind that Shift is sometimes used by itself in applications. In many video games, Shift is used to crouch (though, that would be the least of your problems if you want to play video games with Auto Shift on…) and JetBrains IDEs have you double-tap either Shifts by themselves to open up the <a href="https://blog.jetbrains.com/idea/2020/05/when-the-shift-hits-the-fan-search-everywhere/">Search Everywhere</a> window. Make sure to also read the documentation section on <a href="https://docs.qmk.fm/#/feature_auto_shift?id=modifiers">modifiers and Auto Shift</a> first. <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>Americans seem to get a kick out of using their own standards that are different from everybody else’s. <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:9" role="doc-endnote">
      <p>For our purposes, “steno-friendly” doesn’t refer to whether a given keyboard supports N-key roll over or a steno protocol such as GeminiPR. It’s a quality of a keyboard that makes single-finger combos easier to chord. Factors that play positively in the “steno-friendliness” of a given keyboard could be flat keycaps, steno key tops, choc spacing, ortholinear or columnar stagger, light springs, … <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:10" role="doc-endnote">
      <p>Obviously, it has no benefits for a macro pad and home row mods are unfit for steno boards such as the Georgi. <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>precondition</name></author><category term="Keyboards" /><category term="Keymap" /><category term="QMK" /><summary type="html"><![CDATA[What are home row mods? What is a mod-tap? What settings do you need to use? What are the alternatives? And more in this article...]]></summary></entry><entry><title type="html">Pressing E with the thumb‽</title><link href="/pressing-e-with-the-thumb" rel="alternate" type="text/html" title="Pressing E with the thumb‽" /><published>2020-08-06T00:00:00+00:00</published><updated>2020-08-06T00:00:00+00:00</updated><id>/pressing-e-with-the-thumb</id><content type="html" xml:base="/pressing-e-with-the-thumb"><![CDATA[<p>Did you know that the letter “E” is the most common letter of the English language by a fair margin? It’s second only to space. Such an observation can also be made for the majority of European languages.</p>

<figure>
  <p><a href="https://i.redd.it/4euaismc7x301.png">
        <img src="https://i.redd.it/4euaismc7x301.png" alt="Colored map of Europe showing the most common letters in different European languages" title="The most common letters, letter pairs and letter triplets" width="1013" height="352" />
</a></p>
  <figcaption>
    <p><a href="https://i.redd.it/4euaismc7x301.png"></a><a href="https://www.reddit.com/r/europe/comments/7jsyv3/the_most_common_letters_in_different_european/">Source of the diagram</a>. Click on the picture to enlarge it.</p>
  </figcaption>
</figure>

<p>Now, consider the fact that from the dawn of typewriters to our days, <em>both</em> thumbs have been historically assigned a single key, the most important key: the spacebar. While, it’s certainly a sensible choice to let the strongest finger(s) deal with the most commonly pressed key on the keyboard, chances are that you mostly only use one of your thumbs to press the spacebar. A wide spacebar has the benefit to give the users a choice on which thumb to use. Some people always use the same thumb while some others alternate between the thumbs, using the left while gaming and using the right while typing. Meanwhile, you can also find people doing away with the thumb altogether and using the index for space instead. In any case, past some time, your spacebar is most likely going to look like this:</p>

<p><img src="https://live.staticflickr.com/7144/6705479829_b31dd82da4_n.jpg" alt="Photograph of an ABS spacebar with a shiny spot on one side" /></p>

<p>You can sense what I’m getting at. This is wasteful, why not let the second thumb press the second most commonly pressed character? That would certainly balance the load between your strongest digits.</p>

<p>Moreover, this is not the only advantage of putting <kbd>E</kbd> on the thumb. Naturally, as the most frequent letter, “E” is present in most common n-grams. This makes it hard to place “E” on the keyboard without increasing same finger utilization. A common strategy used by most alternative layouts is to isolate “E” (and other vowels in general, as vowels may be followed by any consonant whereas groups of consonants are rare) by putting punctuation and/or rare consonants around it. What better way to isolate “E” than to put it on the thumb?</p>

<p>Balanced load and greatly reduced <abbr title="Same Finger Utilization">SFU</abbr> is not all! The use of thumb keys extends the amount of home keys, the keys that each of your fingers rest on, in idle state. By placing “E” on a thumb key, you gain one free home row position and any touch typist knows that the home row is prime real estate. By extension, this also widens the range of easily reachable keys on the base layer. This is great for other languages whose alphabet is extended with accented letters. For example, in French, the letter “é”, e acute, is more frequent than “v”, “h”, “g”, “f”, “b”, “q”, “j”, “x”, “z”, “y”, “k”, and “w”<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> and yet is never put into the main alpha block as opposed to all the aforementioned letters (one notable exception is the <a href="https://bepo.fr" title="Link in French">Bépo</a> layout and all its derivatives). Aside from accented characters, one can also put punctuation, additional frequently used symbols or even a macro like a dedicated “th” key if you really want to be fancy — the digraph “th” is the descendant of what used to be a standalone letter in the English alphabet, the <a href="https://en.wikipedia.org/wiki/Thorn_(letter)">“thorn” (Þ, þ)</a>, after all!</p>

<p>Obviously, this requires to do away with big, long spacebars but these have been around for the longest time and are most likely going to stay that way into the future despite the historic trend towards smaller and smaller spacebars.</p>

<p><img src="assets/images/spacebar_timeline.png" alt="Timeline of various keyboards with reducing spacebars right up until the Plank" /></p>

<p>This is probably why, despite the long history of typing machines, the idea of putting <kbd>E</kbd> on the thumb is quite novel and rather alienating to most typists.</p>

<p>It wasn’t until 19 May 1977, when the Maltron Mark II layout, pictured below, first appeared, that a keyboard layout was designed to use thumbs to input letters.</p>

<p><img src="https://4.bp.blogspot.com/-ORP5pXO3ug4/Vk7j86BINfI/AAAAAAAABp0/sQRRyL7F3tw/s1600/89MaltronDual3d.jpg" alt="Diagram of the Maltron Mark II layout" /></p>

<p>If you’re interested, you can read the introductory paper of the Maltron layout <a href="https://www.maltron.com/lillian-malt-papers.html">here</a>.</p>

<p>However, there are, in fact, plenty of keyboards featuring <kbd>E</kbd> on their thumb keys which predate the Maltron Ergonomic Keyboard but it requires stretching the definition of <em>typing</em>. Typing consists in hitting individual keys to express individual letters but there exists other forms of text input such as <em>machine stenography</em>. Stenography has long been used to write at over 200 words per minute, faster than most people speak, with the use of <em>chords</em> on special stenotype machines with extremely light actuation force. Most stenographic theories put <kbd>E</kbd> alongside other vowels on the thumb keys. You can learn more about stenography <a href="https://www.artofchording.com/introduction/">here</a>.</p>

<p>The <a href="https://www.stenograph.com/history-writers">stenotype machines pictured below</a> were all made between 1889 and 1963, much earlier than the Maltron.</p>

<figure class="wp-block-gallery columns-3 is-cropped">
  <ul class="blocks-gallery-grid">
  <li class="blocks-gallery-item">
   <figure><img src="https://www.stenograph.com/content/files/images/MachineHistory/02anderson.jpg" alt="1889 Anderson Shorthand Typewriter" title="1889 Anderson Shorthand Typewriter" class="wp-image-18" /> </figure> 
  </li>
  <li class="blocks-gallery-item">
   <figure><img src="https://www.stenograph.com/content/files/images/MachineHistory/03ireland.jpg" alt="1911 Ireland Stenotype Shorthand Machine" title="1911 Ireland Stenotype Shorthand Machine" class="wp-image-19" /></figure>
  </li>
  <li class="blocks-gallery-item">
   <figure><img src="https://www.stenograph.com/content/files/images/MachineHistory/07stenograph.jpg" alt="1963 Stenograph Data Writer" title="1963 Stenograph Data Writer" class="wp-image-20" /></figure>
  </li>
</ul>
</figure>

<p>Outside of steno though, the adoption of letter thumb keys is nearly null. That can mostly be explained by path dependence and hardware limitations.</p>

<p>We all know that QWERTY is here to stay and that most people can’t be bothered to learn a new keyboard layout and those who do quickly face hardware limitations which prevent them from giving exotic keyboard layouts a spin. We’re thankfully past the days when Kinesis and Maltron were the only available choices for keyboards with a thumb cluster but despite the rise of DIY ergonomic mechanical keyboards, getting your hands on an ergonomic keyboard is still cost-prohibitive.</p>

<p>Consequently, since the (potential) user base is so small — “small” is an understatement —, there aren’t a whole lot of Malt-like alternatives (for the sake of argument, “Malt-like” merely means any layout which puts a letter on a thumb key). Despite the odds, there <em>are</em> Malt-like layouts out there, all very recent.</p>

<p>Logical layouts/keymaps which add <kbd>E</kbd> on the thumb:</p>

<ul>
  <li><a href="https://xsznix.wordpress.com/2016/05/16/introducing-the-rsthd-layout/">RSTHD</a>
<img src="https://xsznix.files.wordpress.com/2016/04/screen-shot-2016-04-22-at-22-40-26.png" alt="ASCII diagram of the RSTHD layout" /></li>
  <li><a href="http://www.adnw.de/index.php?n=Main.FehlerfreihheitUndDaumentasten">Malt ++</a> (link in German)
<img src="https://i.ibb.co/KDtRMq3/ADNW-white-malt.png" alt="Diagram of ADNW-optimized Malt++" /></li>
  <li><a href="https://github.com/zenaan/quick-fixes-ftfw/blob/master/keyboard/README-ZenTron.md">ZenTron</a>
<img src="https://github.com/zenaan/quick-fixes-ftfw/raw/master/keyboard/ZenTron-1210x452.png" alt="Oryx configurator of ZenTron" /></li>
  <li><a href="https://keyboard-design.com/letterlayout.html?layout=opuiany.en.ergodox">Opuiany</a>
<img src="https://keyboard-design.com/klalayouts/opuiany.en.ergodox.jpg" alt="KLE keyboard-design.com diagram of Opuiany" /></li>
  <li><a href="https://forum.bepo.fr/viewtopic.php?id=1696">FR-Godox</a> (link in French)
<img src="https://i.imgur.com/f2NDm7l.png" alt="KLE diagram of the FR-Godox on an Ergodox keyboard" /></li>
  <li><a href="https://github.com/lydell/anishtro">ANISHTRO</a>
<img src="/assets/images/ANISHTRO-KLE.png" alt="KLE diagram of the ANISHTRO v1 layout on minimal Kyria" /></li>
  <li><a href="https://github.com/zigotica/kyria">TRIA</a>
<img src="/assets/images/pressing-e-with-the-thumb/QMK_configurator_diagram_of_the_TRIA_layout_on_a_Kyria.png" alt="QMK configurator diagram of the TRIA layout on a Kyria" /></li>
</ul>

<p>Logical layouts/keymaps which add another letter (circled) on the thumb:</p>
<ul>
  <li><a href="http://thedarnedestthing.com/corne">BEAKL Zi</a> <kbd>I</kbd>
<img src="http://thedarnedestthing.com/images/chimera-beakl-si.jpg" alt="KLE diagram of the BEAKL Zi layout on a Corne" /></li>
  <li><a href="https://deskthority.net/wiki/BEAKL#P_RN">BEAKL P_RN</a> <kbd>P</kbd> <kbd>R</kbd> <kbd>N</kbd>
<img src="assets/images/BEAKL_P_RN-KLE.png" alt="Color coded KLE Diagram of the BEAKL_P_RN layout on a Preonic-style keyboard" /></li>
  <li><a href="http://thedarnedestthing.com/thumb%20h">BEAKL QIEA</a> <kbd>H</kbd>
<img src="http://thedarnedestthing.com/images/keyboard-layout-splitography-thumb-h.jpg" alt="Colored KLE diagram of the QIEA layout with H on thumb" /></li>
  <li><a href="https://keyboard-design.com/letterlayout.html?layout=x6-2h.en.ergolinear">X6.2h</a> <kbd>H</kbd> (and all the other funky layouts made by Ian Douglas of the ergolinear X family)
<img src="https://keyboard-design.com/klalayouts/x6-2h.en.ergolinear.jpg" alt="KLE keyboard-design.com diagram of X6.2h" /></li>
  <li><a href="https://keyboard-design.com/letterlayout.html?layout=einbinder-orthogonal.en.ergodox">Einbinder Orthogonal</a>
<img src="https://user-images.githubusercontent.com/12673886/116615646-e4b27f80-a93b-11eb-9bf8-5eb368a6ef62.jpg" alt="KLE keyboard-design.com diagram of einbinder-orthogonal.en.ergodox" /></li>
  <li><a href="https://keyboard-design.com/letterlayout.html?layout=einbinder-1975-mod-Ian.en.matrix">Einbinder 1975</a>
<img src="https://user-images.githubusercontent.com/12673886/116615640-e3815280-a93b-11eb-8f91-27ab6baa6c1a.jpg" alt="KLE keyboard-design.com diagram of einbinder-1975-mod-ian.en.matrix" /></li>
  <li><a href="https://qiita.com/ZeptByteS/items/6e6a3e46552dcb105948#1-beakrak-2017">BEAKRAK</a> <kbd>T</kbd> (link in Japanese)
<img src="https://keyboard-design.com/klalayouts/beakrak-mod-Ian.en.ergodox.jpg" alt="KLE keyboard-design.com diagram of BEAKRAK" /></li>
  <li><a href="https://keyboard-design.com/letterlayout.html?layout=eNNe-9640PM.en.ergodox">ENNe 9640PM</a> <kbd>T</kbd>
<img src="https://keyboard-design.com/klalayouts/eNNe-9640PM.en.ergodox.jpg" alt="KLE keyboard-design.com diagram of ENNE-9640PM" /></li>
  <li><a href="https://www.persee.fr/doc/linx_0246-8743_1991_hos_4_1_1206">Marsan</a> <kbd>C</kbd> <kbd>G</kbd> (link in French) (this one is absolutely <strong>awful</strong>. there is no space key, you have to move that little stick under àÀ from right to left with your left thumb for space, everything is wrong with this “ergonomic” keyboard but I had to include it for completeness sake)
<img src="/assets/images/pressing-e-with-the-thumb/clavier-marsan.png" alt="Patent drawing of the Marsan keyboard" /></li>
</ul>

<p>This short list will be exhaustive — leave a comment if there’s a Malt-like layout I’ve missed! — if we add in my mod to Colemak-DHm which moves <kbd>E</kbd> on the right thumb key like TRIA, as opposed to all those other layouts which put the letter on the left. I’ve always pressed space with my left thumb and I’m not going to change that habit any time soon. Additionally, <kbd>E</kbd> was on the right hand to begin with so it makes sense to keep it on the right hand.</p>

<p><img src="https://i.ibb.co/MpGN8p1/Colemak-DHm-Thumb-E.png" alt="KLE diagram on Dactyl Manuform of Colemak-DHm-E" /></p>

<p>I had recently learned and become fluid in Colemak-DHm and, while I was curious to try out <kbd>E</kbd> on thumb after @frogmouth brought up the topic of RSTHD on the <a href="https://splitkb.com">splitkb.com</a> <a href="https://discord.gg/6zFR3zE">Discord server</a>, I wasn’t too fond of the idea of learning a totally new layout right after having gotten comfortable with Colemak. Later maybe, but not now. Despite these qualms, I still like experimenting with keymaps.</p>

<p>Thus, I went ahead and replaced the classic <kbd>E</kbd> position with merely shift (since I am using home row mods, the topic of a future blog post). At first, I wanted to keep backspace on the right home thumb position so I put <kbd>E</kbd> on the key to the left of it but I very quickly understood that this was a bad idea. The thumb key in question isn’t the most comfortable thumb key to hit and required lateral movement plus a repositioning of the thumb on its home position. For some reasons, my thumbs aren’t as good as my other fingers to find the home/resting position again so that <kbd>E</kbd> position was problematic. The solution would thus be to put <kbd>E</kbd> on my home right thumb key but I didn’t want to let go of backspace so I came up with another bad idea, magnitudes worse than the previous one. What if I turned the right thumb key into a dual-function key which yields “E” on tap and backspace on hold? Needless to say, it was impossible not to overshoot backspace like that.</p>

<p>Finally, I let go of my attachment to backspace’s position and let <kbd>E</kbd> take its place, pushing backspace to the left key, the previous position of delete.
At this point, the right thumb cluster looked like this:</p>

<p><img src="https://i.ibb.co/j814TZs/e-thumb-cluster.png" alt="KLE diagram of right thumb cluster with Colemak-dhm-e" style="width: 50%;" /></p>

<p>Now, it was time to figure out how long it would take me to get back to ~80WPM using only the thumb for “E”.</p>

<p>After merely a few minutes of practicing <kbd>E</kbd> on thumb using the terminal application “<a href="https://github.com/cslarsen/wpm">wpm</a>”, I had already reached 57WPM for some sentences.</p>

<p><img src="/assets/images/pressing-e-with-the-thumb/screenshot_of_wpm_showing_57_wpm.png" alt="screenshot of wpm showing 57.0 WPM" /></p>

<p>It didn’t take long to break through the 65WPM mark.</p>

<p><img src="/assets/images/pressing-e-with-the-thumb/screenshot_of_wpm_showing_65_wpm.png" alt="screenshot of wpm showing 65.6 WPM" /></p>

<p>Then, I figured that I do not need to practice sentences with punctuations and capitalisations so much as I need to practice words containing “e” so I moved to <a href="https://monkey-type.com/">monkey-type.com</a>.
Only 32 minutes had passed since I flashed my keyboard with <kbd>E</kbd> on thumb and I am already getting real close to my goal of 80WPM.</p>

<p><img src="/assets/images/pressing-e-with-the-thumb/screenshot_of_monkey_type_showing_69_wpm.png" alt="screenshot of monkey-type showing 69WPM" /></p>

<p>At that point, I took a break and after a full day spent without any keyboard (or computer for that matter), I went back to my typing tests. This is when I reached my goal.</p>

<p><img src="/assets/images/pressing-e-with-the-thumb/screenshot_of_wpm_showing_84_wpm.png" alt="screenshot of wpm with 84.3 WPM" /></p>

<p>In fact, I even surpassed my goal.</p>

<p><img src="/assets/images/pressing-e-with-the-thumb/screenshot_of_wpm_showing_97_wpm.png" alt="screenshot of wpm with 97.9 WPM" /></p>

<p>Despite all that, I still wasn’t fully used to <kbd>E</kbd> on thumb yet. More often than not, I was still hitting the previous position of <kbd>E</kbd>. The screenshots I’ve shared here are the results of successful <em>sprints</em>, they do not really reflect the casual typing speed. Disclaimers aside, this still goes to show that it’s actually not so hard to get used to <kbd>E</kbd> on thumb, it has only taken me a few hours to get to an acceptable speed.</p>

<p>However, I still was not wholly convinced by the <kbd>E</kbd> thumb. It’s certainly nice to have a balanced load between the two thumbs but the rolls don’t feel as satisfying. Colemak wasn’t designed to take advantage of thumb keys.</p>

<p>Take for example the sentence <em>“The enter key”</em>, here’s a side by side example of writing that sentence using the two keymaps. Tapped keys are highlighted in yellow and held modifier keys in orange.</p>

<p><a href="https://ibb.co/N7FMT9v"><img src="https://i.ibb.co/0QnxsC7/The-enter-key-as-typed-on-Thumb-E-Colemak-DHm.gif" alt="The enter key, as typed on Colemak-DHm-ThumbE" border="0" /></a>
<a href="https://ibb.co/JsnJpt7"><img src="https://i.ibb.co/DR42MWC/The-enter-key-as-typed-on-Vanilla-Colemak-DHm.gif" alt="The enter key, as typed on Colemak-DHm" border="0" /></a></p>

<p>I am no carpalx scientist but the classic DHm layout fares better in my opinion.</p>

<p>The way I adapted Colemak to use <kbd>E</kbd> on thumb is only one way, there are many other potentially better ways to implement it. Colemak mods probably can’t beat keymap layouts designed around this peculiar arrangement though.</p>

<p>In the end, I gave up on the <kbd>E</kbd> thumb. If it weren’t for the fact that it didn’t feel right in conjunction with Colemak and that I’ve since moved to using the <kbd>Backspace</kbd> key extensively in combos for my hybrid steno setup (more on that topic in another upcoming article), I would have certainly kept on using it as I find the idea very sound.</p>

<p>The most important is that the people who have gone off the beaten path and dared to learn this exotic, ergonomic design are happy about it:</p>

<blockquote>
  <p>I’ve tried e on thumb with RSTHD and I think it’s the way to go. It will take me time to get used to it, though so I’ve put that particular learning curve on hiatus for the near future as I’ve been a bit busy. Things I like about it:</p>

  <ul>
    <li>Remove all conflicts in bigrams with e for free</li>
    <li>Reduce the size of the rolls for less fatigue</li>
    <li>Gain one free homerow position</li>
    <li>Gain one free of the next priority position etc. until where you put your backspace</li>
  </ul>

  <p>It feels like a lot of gain. <strong><em>— @pierrec about RSTHD</em></strong></p>
</blockquote>

<blockquote>
  <p>I like it. But I haven’t spent any time learning other layouts. It does lead to a different feel on both hands, although I’m not sure that’s any different from any other layout.</p>

  <p>I’ve tweaked mine so the left hand fingers are used slightly more than the right, and when the whole hand is taken into account the right is used more. I think this is good, some other (ergo) layouts like modDH are all on the right. It also can give you very low <abbr title="Same Finger Utilization">SFU</abbr>. However it’s not just a matter of moving something to the thumb, everything interacts, just moving a letter can lead to other issues.</p>

  <p>The downside of course is that you have used a thumb key that might otherwise have been available for a mod or layer shift. When you look at what happens in the analyzer this can mean more thumb movement if you’re not careful, which penalizes the layout. Some of this is guesswork as the analyzers (that I’ve seen) don’t have great support for layers, the patorjk one and derivatives have a start at it with AltGr so might be a good starting point for adding more.</p>

  <p>I was going to say that if someone wanted to try it, the best thing would be to just put either RSTHD or Malt in your keymap and give it a go to get the feel of it. However it’s not as straightforward as trying other layouts because whatever is on the left thumb key home has to move somewhere else. Also, you do need space on right thumb home and enter next to it (or possibly, shifted, I haven’t tried that yet) <strong><em>— @frogmouth about RSTHD</em></strong></p>
</blockquote>

<blockquote>
  <p>Qwerty 30+ years to Dvorak about 5 years ago. Then moved from a staggered to a premade ortho about 3 years ago. Coffee spill killed that, so back to the old staggered while waiting for the Kyria to arrive. This is all to let you know my fingers have been confused for a while now.</p>

  <p>My thumbs are not my smartest fingers but thumb E, in use is fantastic. It’s used so often but dedicated to its own thumb. Really a great follow through.</p>

  <p>The efficiency change from Qwerty to Dvorak was noticeable. I already feel that same sort of improvement in moving from Dvorak to RSTHD. I have no idea if I will ever change again, I don’t really see enough room left to make another leap this size in efficiency. In general, RSTHD feels much more efficient, and my RSI pain issues are reduced too.</p>

  <p>Time will tell if I can see a speed increase too. &gt;60WPM is fast enough for my cares, though, so speed is not a driving factor for alternate arrangements.</p>

  <p>If you are currently using Qwerty, it is in your best interest to find a better option. <strong><em>— @BiggerCryptoRoi about RSTHD</em></strong></p>
</blockquote>

<blockquote>
  <p>RSTHD is good, and I highly recommend it. I’m on day 5 and have broken 60 wpm after 2 hrs of 1 minute typing tests. It’s very comfortable, and it feels like the workload is spread evenly between your hands. E on the homerow takes some getting used to, and the punctuation sitting in and amongst the letters is kind of unusual, but it doesn’t get in the way at all.</p>

  <p>Seems that Colemak can type 827 words with the homerow, about 0.37% of all English words, whereas RSTHD can do 1323, which is around 0.6%. I guess that’s because you have the E on the thumb, which I’m counting as part of the homerow too</p>

  <p>Anyway yeah, long story short, typing requires very little effort because you barely need to move your hands. <strong><em>— Anonymous about RSTHD</em></strong></p>
</blockquote>

<blockquote>
  <p>Using thumb for a common letter vastly improves finger balance across the board; it helps with other languages too, in contrast with Colemak that sometimes has, for example, underutilized ‘wrx’ column or overloaded right index finger.</p>

  <p>The main point around Colemak (and similar layouts) is the so-called <em>rolling</em>, i.e., using adjacent fingers of the same hand in sequences. Well, Maltron is the original layout based on this idea; but it also relies on the keyboard’s <em>columnar</em> physical layout: offset columns as an adjustment for shorter/longer fingers, especially little fingers. “Ortholinear” layouts lack this feature, though. That’s why I recommend at <em>least</em> Atreus, or better something like Dactyl-Manuform. <strong><em>— /u/Schemik about Maltron</em></strong></p>
</blockquote>

<p><img src="assets/images/BiggerCryptoRoi-transp.png" alt="BiggerCryptoRoi's left hand Kyria with RSTHD DSA keycaps" /></p>

<p>Have you ever used such layouts? Would you be willing to try it out, or is that too weird for you? Share your thoughts!</p>

<hr />

<details>
  <summary>Updates Log</summary>

  <p>09 August 2020:</p>
  <ul>
    <li>Added FR-Godox to the list of Malt-like layouts</li>
  </ul>

  <p>03 September 2020:</p>
  <ul>
    <li>Added STRENIA and TRIA to the list of Malt-like layouts</li>
    <li>ported the blog post from WordPress.com to this Jekyll site</li>
    <li>Changed the cover picture to @Sergi’s Kyria sporting his TRIA layout</li>
    <li>Moved the old cover picture to the end of the article in addition of making it transparent.</li>
  </ul>

  <p>04 September 2020:</p>
  <ul>
    <li>Added BEAKL P_RN to the list of Malt-like layouts</li>
    <li>renamed ADNW to Malt++ (ADNW is the name of the layout optimizer algorithm used to generate the layout, not the name of the layout itself)</li>
  </ul>

  <p>09 September 2020:</p>
  <ul>
    <li>Added a testimonial from an anonymous RSTHD user</li>
    <li>Added a paragraph on the benefits of <kbd>E</kbd> on the thumb</li>
    <li>Developed a little bit on why I gave up on <kbd>E</kbd> thumb</li>
  </ul>

  <p>10 September 2020:</p>
  <ul>
    <li>Added ANISHTRO to the list of Malt-like layouts</li>
    <li>Added a mention of the “thorn” (Þ, þ) letter</li>
  </ul>

  <p>20 September 2020:</p>
  <ul>
    <li>Added BEAKL QIEA to the list of Malt-like layouts</li>
  </ul>

  <p>01 May 2021:</p>
  <ul>
    <li>Added Einbinder layouts to the list</li>
  </ul>

</details>

<!-- https://community.keyboard.io/t/maltron-layouts/98 -->
<!-- https://mathematicalmulticore.wordpress.com/category/keyboards/ -->
<!-- http://mtgap.bilfo.com/completed_keyboard.html -->
<!-- https://deskthority.net/viewtopic.php?f=2&t=23838 -->
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="https://www.sttmedia.com/characterfrequency-french">Source for French character frequency</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>precondition</name></author><category term="Keyboards" /><category term="Keymap" /><summary type="html"><![CDATA[Exploring the history and reasoning behind a radical ergonomic keyboard layout and trying it out for myself.]]></summary></entry></feed>