qmk_firmware/assets/features_pointing_device.md.DP6-XwL6.js

16 lines
147 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _ as _export_sfc, c as createElementBlock, o as openBlock, a8 as createStaticVNode } from "./chunks/framework.DyMmIvSC.js";
const __pageData = JSON.parse('{"title":"Pointing Device","description":"","frontmatter":{},"headers":[],"relativePath":"features/pointing_device.md","filePath":"features/pointing_device.md"}');
const _sfc_main = { name: "features/pointing_device.md" };
const _hoisted_1 = /* @__PURE__ */ createStaticVNode('<h1 id="pointing-device" tabindex="-1">Pointing Device <a class="header-anchor" href="#pointing-device" aria-label="Permalink to &quot;Pointing Device {#pointing-device}&quot;"></a></h1><p>Pointing Device is a generic name for a feature intended to be generic: moving the system pointer around. There are certainly other options for it - like mousekeys - but this aims to be easily modifiable and hardware driven. You can implement custom keys to control functionality, or you can gather information from other peripherals and insert it directly here - let QMK handle the processing for you.</p><p>To enable Pointing Device, add the following line in your rules.mk and specify one of the driver options below.</p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_ENABLE = yes</span></span></code></pre></div><h2 id="sensor-drivers" tabindex="-1">Sensor Drivers <a class="header-anchor" href="#sensor-drivers" aria-label="Permalink to &quot;Sensor Drivers&quot;"></a></h2><p>There are a number of sensors that are supported by default. Note that only one sensor can be enabled by <code>POINTING_DEVICE_DRIVER</code> at a time. If you need to enable more than one sensor, then you need to implement it manually, using the <code>custom</code> driver.</p><h3 id="adns-5050-sensor" tabindex="-1">ADNS 5050 Sensor <a class="header-anchor" href="#adns-5050-sensor" aria-label="Permalink to &quot;ADNS 5050 Sensor&quot;"></a></h3><p>To use the ADNS 5050 sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = adns5050</span></span></code></pre></div><p>The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>ADNS5050_SCLK_PIN</code></td><td>(Required) The pin connected to the clock pin of the sensor.</td><td><code>POINTING_DEVICE_SCLK_PIN</code></td></tr><tr><td><code>ADNS5050_SDIO_PIN</code></td><td>(Required) The pin connected to the data pin of the sensor.</td><td><code>POINTING_DEVICE_SDIO_PIN</code></td></tr><tr><td><code>ADNS5050_CS_PIN</code></td><td>(Required) The pin connected to the Chip Select pin of the sensor.</td><td><code>POINTING_DEVICE_CS_PIN</code></td></tr></tbody></table><p>The CPI range is 125-1375, in increments of 125. Defaults to 500 CPI.</p><h3 id="adns-9800-sensor" tabindex="-1">ADNS 9800 Sensor <a class="header-anchor" href="#adns-9800-sensor" aria-label="Permalink to &quot;ADNS 9800 Sensor&quot;"></a></h3><p>To use the ADNS 9800 sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = adns9800</span></span></code></pre></div><p>The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>ADNS9800_CLOCK_SPEED</code></td><td>(Optional) Sets the clock speed that the sensor runs at.</td><td><code>2000000</code></td></tr><tr><td><code>ADNS9800_SPI_LSBFIRST</code></td><td>(Optional) Sets the Least/Most Significant Byte First setting for SPI.</td><td><code>false</code></td></tr><tr><td><code>ADNS9800_SPI_MODE</code></td><td>(Optional) Sets the SPI Mode for the sensor.</td><td><code>3</code></td></tr><tr><td><code>ADNS9800_SPI_DIVISOR</code></td><td>(Optional) Sets the SPI Divisor used for SPI communication.</td><td><em>varies</em></td></tr><tr><td><code>ADNS9800_CS_PIN</code></td><td>(Required) Sets the Chip Select pin connected to the sensor.</td><td><code>POINTING_DEVICE_CS_PIN</code></td></tr></tbody></table><p>The CPI range is 800-8200, in increments of 200. Defaults to 1800 CPI.</p><h3 id="analog-joystick" tabindex="-1">Analog Joystick <a class="header-anchor" href="#analog-joystick" aria-label="Permalink to &quot;Analog Joystick&quot;"></a></h3><p>To use an analog joystick to control the pointer, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = analog_joystick</span></span></code></pre></div><p>The Analog Joystick is an analog (ADC) driven sensor. There are a variety of joysticks that you can use for this.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>ANALOG_JOYSTICK_X_AXIS_PIN</code></td><td>(Required) The pin used for the vertical/X axis.</td><td><em>not defined</em></td></tr><tr><td><code>ANALOG_JOYSTICK_Y_AXIS_PIN</code></td><td>(Required) The pin used for the horizontal/Y axis.</td><td><em>not defined</em></td></tr><tr><td><code>ANALOG_JOYSTICK_AXIS_MIN</code></td><td>(Optional) Sets the lower range to be considered movement.</td><td><code>0</code></td></tr><tr><td><code>ANALOG_JOYSTICK_AXIS_MAX</code></td><td>(Optional) Sets the upper range to be considered movement.</td><td><code>1023</code></td></tr><tr><td><code>ANALOG_JOYSTICK_AUTO_AXIS</code></td><td>(Optional) Sets ranges to be considered movement automatically.</td><td><em>not defined</em></td></tr><tr><td><code>ANALOG_JOYSTICK_SPEED_REGULATOR</code></td><td>(Optional) The divisor used to slow down movement. (lower makes it faster)</td><td><code>20</code></td></tr><tr><td><code>ANALOG_JOYSTICK_READ_INTERVAL</code></td><td>(Optional) The interval in milliseconds between reads.</td><td><code>10</code></td></tr><tr><td><code>ANALOG_JOYSTICK_SPEED_MAX</code></td><td>(Optional) The maximum value used for motion.</td><td><code>2</code></td></tr><tr><td><code>ANALOG_JOYSTICK_CLICK_PIN</code></td><td>(Optional) The pin wired up to the press switch of the analog stick.</td><td><em>not defined</em></td></tr><tr><td><code>ANALOG_JOYSTICK_WEIGHTS</code></td><td>(Optional) Use custom weights for lever positions.</td><td><em>not defined</em></td></tr><tr><td><code>ANALOG_JOYSTICK_CUTOFF</code></td><td>(Optional) Cut off movement when joystick returns to start position.</td><td><em>not defined</em></td></tr></tbody></table><p>If <code>ANALOG_JOYSTICK_AUTO_AXIS</code> is used, then <code>ANALOG_JOYSTICK_AXIS_MIN</code> and <code>ANALOG_JOYSTICK_AXIS_MAX</code> are ignored.</p><p>By default analog joystick implementation uses <code>x^2</code> weighting for lever positions. <code>ANALOG_JOYSTICK_WEIGHTS</code> allows to experiment with different configurations that might feel better.</p><p>E.g. This is weights for <code>((x-0.4)^3+0.064)/0.282</code>:</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ANALOG_JOYSTICK_WEIGHTS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">7</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">12</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">13</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">14</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">17</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">18</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">19</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">19</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">21</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">22</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">22</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">22</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">22</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">23</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">24</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">26</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">26</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">26</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">27</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">28</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">28</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">29</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">29</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">30</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">31</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">32</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">33</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">34</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">35</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">36</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">37</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">38</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">40</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">41</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">43</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">44</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">46</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">48</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">49</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">51</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">53</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">56</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">58</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">60</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">62</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">65</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">68</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">70</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">73</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">76</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">79</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">82</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">85</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">89</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">92</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">96</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>You can use following JS code to generate weights for different formulas:</p><div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Array.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">Array</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">101</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">ceil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((((x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">**</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.064</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0.282</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">))))</span></span></code></pre></div><h3 id="azoteq-iqs5xx-trackpad" tabindex="-1">Azoteq IQS5XX Trackpad <a class="header-anchor" href="#azoteq-iqs5xx-trackpad" aria-label="Permalink to &quot;Azoteq IQS5XX Trackpad&quot;"></a></h3><p>To use a Azoteq IQS5XX trackpad, add this to your <code>rules.mk</code>:</p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = azoteq_iqs5xx</span></span></code></pre></div><p>This supports the IQS525, IQS550 and IQS572 controllers, with the latter two being used in the TPS43 and TPS65 trackpads.</p><h4 id="device-settings" tabindex="-1">Device settings <a class="header-anchor" href="#device-settings" aria-label="Permalink to &quot;Device settings&quot;"></a></h4><p>Specific device profiles are provided which set the required values for dimensions and resolution.</p><table><thead><tr><th>Setting</th><th>Description</th></tr></thead><tbody><tr><td><code>AZOTEQ_IQS5XX_TPS43</code></td><td>(Pick One) Sets resolution/mm to TPS43 specifications.</td></tr><tr><td><code>AZOTEQ_IQS5XX_TPS65</code></td><td>(Pick One) Sets resolution/mm to TPS65 specifications.</td></tr></tbody></table><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>If using one of the above defines you can skip to gesture settings.</p></div><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>AZOTEQ_IQS5XX_WIDTH_MM</code></td><td>(Required) Width of the trackpad sensor in millimeters.</td><td><em>not defined</em></td></tr><tr><td><code>AZOTEQ_IQS5XX_HEIGHT_MM</code></td><td>(Required) Height of the trackpad sensor in millimeters.</td><td><em>not defined</em></td></tr><tr><td><code>AZOTEQ_IQS5XX_RESOLUTION_X</code></td><td>(Optional) Specify X resolution for CPI calculation.</td><td><em>not defined</em></td></tr><tr><td><code>AZOTEQ_IQS5XX_RESOLUTION_Y</code></td><td>(Optional) Specify Y resolution for CPI calculation.</td><td><em>not defined</em></td></tr></tbody></table><p><strong><code>AZOTEQ_IQS5XX_RESOLUTION_X/Y</code></strong> fall back resolutions are provided within the driver based on controller model.</p><table><thead><tr><th>I2C Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>AZOTEQ_IQS5XX_ADDRESS</code></td><td>(Optional) Sets the I2C Address for the Azoteq trackpad</td><td><code>0xE8</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_TIMEOUT_MS</code></td><td>(Optional) The timeout for i2c communication with in milliseconds.</td><td><code>10</code></td></tr></tbody></table><h4 id="gesture-settings" tabindex="-1">Gesture settings <a class="header-anchor" href="#gesture-settings" aria-label="Permalink to &quot;Gesture settings&quot;"></a></h4><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>AZOTEQ_IQS5XX_TAP_ENABLE</code></td><td>(Optional) Enable single finger tap. (Left click)</td><td><code>true</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE</code></td><td>(Optional) Enable two finger tap. (Right click)</td><td><code>true</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE</code></td><td>(Optional) Emulates holding left click to select text.</td><td><code>false</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_X_ENABLE</code></td><td>(Optional) Enable swipe gestures X+ (Mouse Button 5) / X- (Mouse Button 4)</td><td><code>false</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_Y_ENABLE</code></td><td>(Optional) Enable swipe gestures Y+ (Mouse Button 3) / Y- (Mouse Button 6)</td><td><code>false</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_ZOOM_ENABLE</code></td><td>(Optional) Enable zoom gestures Zoom Out (Mouse Button 7) / Zoom In (Mouse Button 8)</td><td><code>false</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SCROLL_ENABLE</code></td><td>(Optional) Enable scrolling using two fingers.</td><td><code>true</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_TAP_TIME</code></td><td>(Optional) Maximum time in ms for tap to be registered.</td><td><code>150</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_TAP_DISTANCE</code></td><td>(Optional) Maximum deviation in pixels before single tap is no longer valid.</td><td><code>25</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_HOLD_TIME</code></td><td>(Optional) Minimum time in ms for press and hold.</td><td><code>300</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME</code></td><td>(Optional) Maximum time to travel initial distance before swipe is registered.</td><td><code>150</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE</code></td><td>(Optional) Minimum travel in pixels before swipe is registered.</td><td><code>300</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME</code></td><td>(Optional) Maximum time to travel consecutive distance before swipe is registered.</td><td><code>0</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE</code></td><td>(Optional) Minimum travel in pixels before a consecutive swipe is registered.</td><td><code>2000</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE</code></td><td>(Optional) Minimum travel in pixels before scroll is registered.</td><td><code>50</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE</code></td><td>(Optional) Minimum travel in pixels before zoom is registered.</td><td><code>50</code></td></tr><tr><td><code>AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE</code></td><td>(Optional) Maximum time to travel zoom distance before zoom is registered.</td><td><code>25</code></td></tr></tbody></table><h4 id="rotation-settings" tabindex="-1">Rotation settings <a class="header-anchor" href="#rotation-settings" aria-label="Permalink to &quot;Rotation settings&quot;"></a></h4><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>AZOTEQ_IQS5XX_ROTATION_90</code></td><td>(Optional) Configures hardware for 90 degree rotation.</td><td><em>not defined</em></td></tr><tr><td><code>AZOTEQ_IQS5XX_ROTATION_180</code></td><td>(Optional) Configures hardware for 180 degree rotation.</td><td><em>not defined</em></td></tr><tr><td><code>AZOTEQ_IQS5XX_ROTATION_270</code></td><td>(Optional) Configures hardware for 270 degree rotation.</td><td><em>not defined</em></td></tr></tbody></table><h3 id="cirque-trackpad" tabindex="-1">Cirque Trackpad <a class="header-anchor" href="#cirque-trackpad" aria-label="Permalink to &quot;Cirque Trackpad&quot;"></a></h3><p>To use the Cirque Trackpad sensor, add this to your <code>rules.mk</code>:</p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = cirque_pinnacle_i2c</span></span></code></pre></div><p>or</p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = cirque_pinnacle_spi</span></span></code></pre></div><p>This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported.</p><h4 id="common-settings" tabindex="-1">Common settings <a class="header-anchor" href="#common-settings" aria-label="Permalink to &quot;Common settings&quot;"></a></h4><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_DIAMETER_MM</code></td><td>(Optional) Diameter of the trackpad sensor in millimeters.</td><td><code>40</code></td></tr><tr><td><code>CIRQUE_PINNACLE_ATTENUATION</code></td><td>(Optional) Sets the attenuation of the sensor data.</td><td><code>EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X</code></td></tr><tr><td><code>CIRQUE_PINNACLE_CURVED_OVERLAY</code></td><td>(Optional) Applies settings tuned for curved overlay.</td><td><em>not defined</em></td></tr><tr><td><code>CIRQUE_PINNACLE_POSITION_MODE</code></td><td>(Optional) Mode of operation.</td><td><em>not defined</em></td></tr><tr><td><code>CIRQUE_PINNACLE_SKIP_SENSOR_CHECK</code></td><td>(Optional) Skips sensor presence check</td><td><em>not defined</em></td></tr></tbody></table><p><strong><code>CIRQUE_PINNACLE_ATTENUATION</code></strong> is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.</p><p>Default attenuation is set to 4X, although if you are using a thicker overlay (such as the curved overlay) you will want a lower attenuation such as 2X. The possible values are:</p><ul><li><code>EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X</code>: Least sensitive</li><li><code>EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_3X</code></li><li><code>EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_2X</code></li><li><code>EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_1X</code>: Most sensitive</li></ul><p><strong><code>CIRQUE_PINNACLE_POSITION_MODE</code></strong> can be <code>CIRQUE_PINNACLE_ABSOLUTE_MODE</code> or <code>CIRQUE_PINNACLE_RELATIVE_MODE</code>. Modes differ in supported features/gestures.</p><ul><li><code>CIRQUE_PINNACLE_ABSOLUTE_MODE</code>: Reports absolute x, y, z (touch pressure) coordinates and up to 5 hw buttons connected to the trackpad</li><li><code>CIRQUE_PINNACLE_RELATIVE_MODE</code>: Reports x/y deltas, scroll and up to 3 buttons (2 of them can be from taps, see gestures) connected to trackpad. Supports taps on secondary side of split. Saves about 2k of flash compared to absolute mode with all features.</li></ul><table><thead><tr><th>I2C Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_ADDR</code></td><td>(Required) Sets the I2C Address for the Cirque Trackpad</td><td><code>0x2A</code></td></tr><tr><td><code>CIRQUE_PINNACLE_TIMEOUT</code></td><td>(Optional) The timeout for i2c communication with the trackpad in milliseconds.</td><td><code>20</code></td></tr></tbody></table><table><thead><tr><th>SPI Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_CLOCK_SPEED</code></td><td>(Optional) Sets the clock speed that the sensor runs at.</td><td><code>1000000</code></td></tr><tr><td><code>CIRQUE_PINNACLE_SPI_LSBFIRST</code></td><td>(Optional) Sets the Least/Most Significant Byte First setting for SPI.</td><td><code>false</code></td></tr><tr><td><code>CIRQUE_PINNACLE_SPI_MODE</code></td><td>(Optional) Sets the SPI Mode for the sensor.</td><td><code>1</code></td></tr><tr><td><code>CIRQUE_PINNACLE_SPI_DIVISOR</code></td><td>(Optional) Sets the SPI Divisor used for SPI communication.</td><td><em>varies</em></td></tr><tr><td><code>CIRQUE_PINNACLE_SPI_CS_PIN</code></td><td>(Required) Sets the Chip Select pin connected to the sensor.</td><td><code>POINTING_DEVICE_CS_PIN</code></td></tr></tbody></table><p>Default Scaling is 1024. Actual CPI depends on trackpad diameter.</p><p>Also see the <code>POINTING_DEVICE_TASK_THROTTLE_MS</code>, which defaults to 10ms when using Cirque Pinnacle, which matches the internal update rate of the position registers (in standard configuration). Advanced configuration for pen/stylus usage might require lower values.</p><h4 id="absolute-mode-settings" tabindex="-1">Absolute mode settings <a class="header-anchor" href="#absolute-mode-settings" aria-label="Permalink to &quot;Absolute mode settings&quot;"></a></h4><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_X_LOWER</code></td><td>(Optional) The minimum reachable X value on the sensor.</td><td><code>127</code></td></tr><tr><td><code>CIRQUE_PINNACLE_X_UPPER</code></td><td>(Optional) The maximum reachable X value on the sensor.</td><td><code>1919</code></td></tr><tr><td><code>CIRQUE_PINNACLE_Y_LOWER</code></td><td>(Optional) The minimum reachable Y value on the sensor.</td><td><code>63</code></td></tr><tr><td><code>CIRQUE_PINNACLE_Y_UPPER</code></td><td>(Optional) The maximum reachable Y value on the sensor.</td><td><code>1471</code></td></tr><tr><td><code>CIRQUE_PINNACLE_REACHABLE_CALIBRATION</code></td><td>(Optional) Enable console messages to aide in calibrating above values.</td><td>not defined</td></tr></tbody></table><h4 id="absolute-mode-gestures" tabindex="-1">Absolute mode gestures <a class="header-anchor" href="#absolute-mode-gestures" aria-label="Permalink to &quot;Absolute mode gestures&quot;"></a></h4><table><thead><tr><th>Gesture Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_TAP_ENABLE</code></td><td>(Optional) Enable tap to click. This currently only works on the master side.</td><td><em>not defined</em></td></tr><tr><td><code>CIRQUE_PINNACLE_TAPPING_TERM</code></td><td>(Optional) Length of time that a touch can be to be considered a tap.</td><td><code>TAPPING_TERM</code>/<code>200</code></td></tr><tr><td><code>CIRQUE_PINNACLE_TOUCH_DEBOUNCE</code></td><td>(Optional) Length of time that a touch can be to be considered a tap.</td><td><code>TAPPING_TERM</code>/<code>200</code></td></tr></tbody></table><p><code>POINTING_DEVICE_GESTURES_SCROLL_ENABLE</code> in this mode enables circular scroll. Touch originating in outer ring can trigger scroll by moving along the perimeter. Near side triggers vertical scroll and far side triggers horizontal scroll.</p><p>Additionally, <code>POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE</code> is supported in this mode.</p><h4 id="relative-mode-gestures" tabindex="-1">Relative mode gestures <a class="header-anchor" href="#relative-mode-gestures" aria-label="Permalink to &quot;Relative mode gestures&quot;"></a></h4><table><thead><tr><th>Gesture Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>CIRQUE_PINNACLE_TAP_ENABLE</code></td><td>(Optional) Enable tap to &quot;left click&quot;. Works on both sides of a split keyboard.</td><td><em>not defined</em></td></tr><tr><td><code>CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE</code></td><td>(Optional) Tap in upper right corner (half of the finger needs to be outside of the trackpad) of the trackpad will result in &quot;right click&quot;. <code>CIRQUE_PINNACLE_TAP_ENABLE</code> must be enabled.</td><td><em>not defined</em></td></tr></tbody></table><p>Tapping term and debounce are not configurable in this mode since it&#39;s handled by trackpad internally.</p><p><code>POINTING_DEVICE_GESTURES_SCROLL_ENABLE</code> in this mode enables side scroll. Touch originating on the right side can trigger vertical scroll (IntelliSense trackpad style).</p><h3 id="paw-3204-sensor" tabindex="-1">PAW 3204 Sensor <a class="header-anchor" href="#paw-3204-sensor" aria-label="Permalink to &quot;PAW 3204 Sensor&quot;"></a></h3><p>To use the paw 3204 sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = paw3204</span></span></code></pre></div><p>The paw 3204 sensor uses a serial type protocol for communication, and requires an additional light source.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>PAW3204_SCLK_PIN</code></td><td>(Required) The pin connected to the clock pin of the sensor.</td><td><code>POINTING_DEVICE_SCLK_PIN</code></td></tr><tr><td><code>PAW3204_SDIO_PIN</code></td><td>(Required) The pin connected to the data pin of the sensor.</td><td><code>POINTING_DEVICE_SDIO_PIN</code></td></tr></tbody></table><p>The CPI range is 400-1600, with supported values of (400, 500, 600, 800, 1000, 1200 and 1600). Defaults to 1000 CPI.</p><h3 id="pimoroni-trackball" tabindex="-1">Pimoroni Trackball <a class="header-anchor" href="#pimoroni-trackball" aria-label="Permalink to &quot;Pimoroni Trackball&quot;"></a></h3><p>To use the Pimoroni Trackball module, add this to your <code>rules.mk</code>:</p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = pimoroni_trackball</span></span></code></pre></div><p>The Pimoroni Trackball module is a I2C based breakout board with an RGB enable trackball.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>PIMORONI_TRACKBALL_ADDRESS</code></td><td>(Required) Sets the I2C Address for the Pimoroni Trackball.</td><td><code>0x0A</code></td></tr><tr><td><code>PIMORONI_TRACKBALL_TIMEOUT</code></td><td>(Optional) The timeout for i2c communication with the trackball in milliseconds.</td><td><code>100</code></td></tr><tr><td><code>PIMORONI_TRACKBALL_SCALE</code></td><td>(Optional) The multiplier used to generate reports from the sensor.</td><td><code>5</code></td></tr><tr><td><code>PIMORONI_TRACKBALL_DEBOUNCE_CYCLES</code></td><td>(Optional) The number of scan cycles used for debouncing on the ball press.</td><td><code>20</code></td></tr><tr><td><code>PIMORONI_TRACKBALL_ERROR_COUNT</code></td><td>(Optional) Specifies the number of read/write errors until the sensor is disabled.</td><td><code>10</code></td></tr></tbody></table><h3 id="pmw3320-sensor" tabindex="-1">PMW3320 Sensor <a class="header-anchor" href="#pmw3320-sensor" aria-label="Permalink to &quot;PMW3320 Sensor&quot;"></a></h3><p>To use the PMW3320 sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = pmw3320</span></span></code></pre></div><p>The PMW3320 sensor uses a serial type protocol for communication, and requires an additional light source (it could work without one, but expect it to be out of service early).</p><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>PMW3320_SCLK_PIN</code></td><td>(Required) The pin connected to the clock pin of the sensor.</td><td><code>POINTING_DEVICE_SCLK_PIN</code></td></tr><tr><td><code>PMW3320_SDIO_PIN</code></td><td>(Required) The pin connected to the data pin of the sensor.</td><td><code>POINTING_DEVICE_SDIO_PIN</code></td></tr><tr><td><code>PMW3320_CS_PIN</code></td><td>(Required) The pin connected to the cable select pin of the sensor.</td><td><code>POINTING_DEVICE_CS_PIN</code></td></tr></tbody></table><p>The CPI range is 500-3500, in increments of 250. Defaults to 1000 CPI.</p><h3 id="pmw-3360-and-pmw-3389-sensor" tabindex="-1">PMW 3360 and PMW 3389 Sensor <a class="header-anchor" href="#pmw-3360-and-pmw-3389-sensor" aria-label="Permalink to &quot;PMW 3360 and PMW 3389 Sensor&quot;"></a></h3><p>This drivers supports both the PMW 3360 and PMW 3389 sensor as well as multiple sensors of the same type <em>per</em> controller, so 2 can be attached at the same side for split keyboards (or unsplit keyboards).</p><p>To use the <strong>PMW 3360</strong> sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = pmw3360</span></span></code></pre></div><p>The CPI range is 100-12000, in increments of 100. Defaults to 1600 CPI.</p><p>To use the <strong>PMW 3389</strong> sensor, add this to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = pmw3389</span></span></code></pre></div><p>The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.</p><p>Both PMW 3360 and PMW 3389 are SPI driven optical sensors, that use a built in IR LED for surface tracking. If you have different CS wiring on each half you can use <code>PMW33XX_CS_PIN_RIGHT</code> or <code>PMW33XX_CS_PINS_RIGHT</code> in combination with <code>PMW33XX_CS_PIN</code> or <code>PMW33XX_CS_PINS</code> to configure both sides independently. If <code>_RIGHT</code> values aren&#39;t provided, they default to be the same as the left ones.</p><table><thead><tr><th>Setting (<code>config.h</code>)</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>PMW33XX_CS_PIN</code></td><td>(Required) Sets the Chip Select pin connected to the sensor.</td><td><code>POINTING_DEVICE_CS_PIN</code></td></tr><tr><td><code>PMW33XX_CS_PINS</code></td><td>(Alternative) Sets the Chip Select pins connected to multiple sensors.</td><td><code>{PMW33XX_CS_PIN}</code></td></tr><tr><td><code>PMW33XX_CS_PIN_RIGHT</code></td><td>(Optional) Sets the Chip Select pin connected to the sensor on the right half.</td><td><code>PMW33XX_CS_PIN</code></td></tr><tr><td><code>PMW33XX_CS_PINS_RIGHT</code></td><td>(Optional) Sets the Chip Select pins connected to multiple sensors on the right half.</td><td><code>{PMW33XX_CS_PIN_RIGHT}</code></td></tr><tr><td><code>PMW33XX_CPI</code></td><td>(Optional) Sets counts per inch sensitivity of the sensor.</td><td><em>varies</em></td></tr><tr><td><code>PMW33XX_CLOCK_SPEED</code></td><td>(Optional) Sets the clock speed that the sensor runs at.</td><td><code>2000000</code></td></tr><tr><td><code>PMW33XX_SPI_DIVISOR</code></td><td>(Optional) Sets the SPI Divisor used for SPI communication.</td><td><em>varies</em></td></tr><tr><td><code>PMW33XX_LIFTOFF_DISTANCE</code></td><td>(Optional) Sets the lift off distance at run time</td><td><code>0x02</code></td></tr><tr><td><code>ROTATIONAL_TRANSFORM_ANGLE</code></td><td>(Optional) Allows for the sensor data to be rotated +/- 127 degrees directly in the sensor.</td><td><code>0</code></td></tr></tbody></table><p>To use multiple sensors, instead of setting <code>PMW33XX_CS_PIN</code> you need to set <code>PMW33XX_CS_PINS</code> and also handle and merge the read from this sensor in user code. Note that different (per sensor) values of CPI, speed liftoff, rotational angle or flipping of X/Y is not currently supported.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in config.h:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> PMW33XX_CS_PINS</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { B5, B6 }</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in keyboard.c:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#ifdef</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> POINTING_DEVICE_ENABLE</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_init_kb</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pmw33xx_init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // index 1 is the second device.</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pmw33xx_set_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">800</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // applies to first sensor</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pmw33xx_set_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">800</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // applies to second sensor</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_init_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Contains report from sensor #0 already, need to merge in from sensor #1</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_kb</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mouse_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pmw33xx_report_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pmw33xx_read_burst</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">report.motion.b.is_lifted </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report.motion.b.is_motion) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// From quantum/pointing_device_drivers.c</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> constrain_hid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">amt</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) ((amt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">127</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">127</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ((amt) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 127</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 127</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (amt)))</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> constrain_hid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report.delta_x);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> constrain_hid</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report.delta_y);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(mouse_report);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#endif</span></span></code></pre></div><h3 id="custom-driver" tabindex="-1">Custom Driver <a class="header-anchor" href="#custom-driver" aria-label="Permalink to &quot;Custom Driver&quot;"></a></h3><p>If you have a sensor type that isn&#39;t supported above, a custom option is available by adding the following to your <code>rules.mk</code></p><div class="language-make vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">make</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">POINTING_DEVICE_DRIVER = custom</span></span></code></pre></div><p>Using the custom driver will require implementing the following functions:</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_driver_init</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {}</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_driver_get_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mouse_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report; }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_driver_get_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">; }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_driver_set_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {}</span></span></code></pre></div><div class="warning custom-block"><p class="custom-block-title">WARNING</p><p>Ideally, new sensor hardware should be added to <code>drivers/sensors/</code> and <code>quantum/pointing_device_drivers.c</code>, but there may be cases where it&#39;s very specific to the hardware. So these functions are provided, just in case.</p></div><h2 id="common-configuration" tabindex="-1">Common Configuration <a class="header-anchor" href="#common-configuration" aria-label="Permalink to &quot;Common Configuration&quot;"></a></h2><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>MOUSE_EXTENDED_REPORT</code></td><td>(Optional) Enables support for extended mouse reports. (-32767 to 32767, instead of just -127 to 127).</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_90</code></td><td>(Optional) Rotates the X and Y data by 90 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_180</code></td><td>(Optional) Rotates the X and Y data by 180 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_270</code></td><td>(Optional) Rotates the X and Y data by 270 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_INVERT_X</code></td><td>(Optional) Inverts the X axis report.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_INVERT_Y</code></td><td>(Optional) Inverts the Y axis report.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_MOTION_PIN</code></td><td>(Optional) If supported, will only read from sensor if pin is active.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW</code></td><td>(Optional) If defined then the motion pin is active-low.</td><td><em>varies</em></td></tr><tr><td><code>POINTING_DEVICE_TASK_THROTTLE_MS</code></td><td>(Optional) Limits the frequency that the sensor is polled for motion.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE</code></td><td>(Optional) Enable inertial cursor. Cursor continues moving after a flick gesture and slows down by kinetic friction.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_GESTURES_SCROLL_ENABLE</code></td><td>(Optional) Enable scroll gesture. The gesture that activates the scroll is device dependent.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_CS_PIN</code></td><td>(Optional) Provides a default CS pin, useful for supporting multiple sensor configs.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_SDIO_PIN</code></td><td>(Optional) Provides a default SDIO pin, useful for supporting multiple sensor configs.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_SCLK_PIN</code></td><td>(Optional) Provides a default SCLK pin, useful for supporting multiple sensor configs.</td><td><em>not defined</em></td></tr></tbody></table><div class="warning custom-block"><p class="custom-block-title">WARNING</p><p>When using <code>SPLIT_POINTING_ENABLE</code> the <code>POINTING_DEVICE_MOTION_PIN</code> functionality is not supported and <code>POINTING_DEVICE_TASK_THROTTLE_MS</code> will default to <code>1</code>. Increasing this value will increase transport performance at the cost of possible mouse responsiveness.</p></div><p>The <code>POINTING_DEVICE_CS_PIN</code>, <code>POINTING_DEVICE_SDIO_PIN</code>, and <code>POINTING_DEVICE_SCLK_PIN</code> provide a convenient way to define a single pin that can be used for an interchangeable sensor config. This allows you to have a single config, without defining each device. Each sensor allows for this to be overridden with their own defines.</p><div class="warning custom-block"><p class="custom-block-title">WARNING</p><p>Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by <code>POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE</code>. e.g. PMW3360 can use Lift_Stat from Motion register. Note that <code>POINTING_DEVICE_MOTION_PIN</code> cannot be used with this feature; continuous polling of <code>get_report()</code> is needed to generate glide reports.</p></div><h2 id="split-keyboard-configuration" tabindex="-1">Split Keyboard Configuration <a class="header-anchor" href="#split-keyboard-configuration" aria-label="Permalink to &quot;Split Keyboard Configuration&quot;"></a></h2><p>The following configuration options are only available when using <code>SPLIT_POINTING_ENABLE</code> see <a href="./split_keyboard#data-sync-options">data sync options</a>. The rotation and invert <code>*_RIGHT</code> options are only used with <code>POINTING_DEVICE_COMBINED</code>. If using <code>POINTING_DEVICE_LEFT</code> or <code>POINTING_DEVICE_RIGHT</code> use the common configuration above to configure your pointing device.</p><table><thead><tr><th>Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td><code>POINTING_DEVICE_LEFT</code></td><td>Pointing device on the left side (Required - pick one only)</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_RIGHT</code></td><td>Pointing device on the right side (Required - pick one only)</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_COMBINED</code></td><td>Pointing device on both sides (Required - pick one only)</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_90_RIGHT</code></td><td>(Optional) Rotates the X and Y data by 90 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_180_RIGHT</code></td><td>(Optional) Rotates the X and Y data by 180 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_ROTATION_270_RIGHT</code></td><td>(Optional) Rotates the X and Y data by 270 degrees.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_INVERT_X_RIGHT</code></td><td>(Optional) Inverts the X axis report.</td><td><em>not defined</em></td></tr><tr><td><code>POINTING_DEVICE_INVERT_Y_RIGHT</code></td><td>(Optional) Inverts the Y axis report.</td><td><em>not defined</em></td></tr></tbody></table><div class="warning custom-block"><p class="custom-block-title">WARNING</p><p>If there is a <code>_RIGHT</code> configuration option or callback, the <a href="./pointing_device#common-configuration">common configuration</a> option will work for the left. For correct left/right detection you should setup a <a href="./split_keyboard#setting-handedness">handedness option</a>, <code>EE_HANDS</code> is usually a good option for an existing board that doesn&#39;t do handedness by hardware.</p></div><h2 id="callbacks-and-functions" tabindex="-1">Callbacks and Functions <a class="header-anchor" href="#callbacks-and-functions" aria-label="Permalink to &quot;Callbacks and Functions&quot;"></a></h2><table><thead><tr><th>Function</th><th>Description</th></tr></thead><tbody><tr><td><code>pointing_device_init_kb(void)</code></td><td>Callback to allow for keyboard level initialization. Useful for additional hardware sensors.</td></tr><tr><td><code>pointing_device_init_user(void)</code></td><td>Callback to allow for user level initialization. Useful for additional hardware sensors.</td></tr><tr><td><code>pointing_device_task_kb(mouse_report)</code></td><td>Callback that sends sensor data, so keyboard code can intercept and modify the data. Returns a mouse report.</td></tr><tr><td><code>pointing_device_task_user(mouse_report)</code></td><td>Callback that sends sensor data, so user code can intercept and modify the data. Returns a mouse report.</td></tr><tr><td><code>pointing_device_handle_buttons(buttons, pressed, button)</code></td><td>Callback to handle hardware button presses. Returns a <code>uint8_t</code>.</td></tr><tr><td><code>pointing_device_get_cpi(void)</code></td><td>Gets the current CPI/DPI setting from the sensor, if supported.</td></tr><tr><td><code>pointing_device_set_cpi(uint16_t)</code></td><td>Sets the CPI/DPI, if supported.</td></tr><tr><td><code>pointing_device_get_report(void)</code></td><td>Returns the current mouse report (as a <code>report_mouse_t</code> data structure).</td></tr><tr><td><code>pointing_device_set_report(mouse_report)</code></td><td>Sets the mouse report to the assigned <code>report_mouse_t</code> data structured passed to the function.</td></tr><tr><td><code>pointing_device_send(void)</code></td><td>Sends the current mouse report to the host system. Function can be replaced.</td></tr><tr><td><code>has_mouse_report_changed(new_report, old_report)</code></td><td>Compares the old and new <code>report_mouse_t</code> data and returns true only if it has changed.</td></tr><tr><td><code>pointing_device_adjust_by_defines(mouse_report)</code></td><td>Applies rotations and invert configurations to a raw mouse report.</td></tr></tbody></table><h2 id="split-keyboard-callbacks-and-functions" tabindex="-1">Split Keyboard Callbacks and Functions <a class="header-anchor" href="#split-keyboard-callbacks-and-functions" aria-label="Permalink to &quot;Split Keyboard Callbacks and Functions&quot;"></a></h2><p>The combined functions below are only available when using <code>SPLIT_POINTING_ENABLE</code> and <code>POINTING_DEVICE_COMBINED</code>. The 2 callbacks <code>pointing_device_task_combined_*</code> replace the single sided equivalents above. See the <a href="./pointing_device#combined-pointing-devices">combined pointing devices example</a></p><table><thead><tr><th>Function</th><th>Description</th></tr></thead><tbody><tr><td><code>pointing_device_set_shared_report(mouse_report)</code></td><td>Sets the shared mouse report to the assigned <code>report_mouse_t</code> data structured passed to the function.</td></tr><tr><td><code>pointing_device_set_cpi_on_side(bool, uint16_t)</code></td><td>Sets the CPI/DPI of one side, if supported. Passing <code>true</code> will set the left and <code>false</code> the right</td></tr><tr><td><code>pointing_device_combine_reports(left_report, right_report)</code></td><td>Returns a combined mouse_report of left_report and right_report (as a <code>report_mouse_t</code> data structure)</td></tr><tr><td><code>pointing_device_task_combined_kb(left_report, right_report)</code></td><td>Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report.</td></tr><tr><td><code>pointing_device_task_combined_user(left_report, right_report)</code></td><td>Callback, so user code can intercept and modify. Returns a combined mouse report using <code>pointing_device_combine_reports</code></td></tr><tr><td><code>pointing_device_adjust_by_defines_right(mouse_report)</code></td><td>Applies right side rotations and invert configurations to a raw mouse report.</td></tr></tbody></table><h1 id="manipulating-mouse-reports" tabindex="-1">Manipulating Mouse Reports <a class="header-anchor" href="#manipulating-mouse-reports" aria-label="Permalink to &quot;Manipulating Mouse Reports&quot;"></a></h1><p>The report_mouse_t (here &quot;mouseReport&quot;) has the following properties:</p><ul><li><code>mouseReport.x</code> - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ to the right, - to the left) on the x axis.</li><li><code>mouseReport.y</code> - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ upward, - downward) on the y axis.</li><li><code>mouseReport.v</code> - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing vertical scrolling (+ upward, - downward).</li><li><code>mouseReport.h</code> - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing horizontal scrolling (+ right, - left).</li><li><code>mouseReport.buttons</code> - this is a uint8_t in which all 8 bits are used. These bits represent the mouse button state - bit 0 is mouse button 1, and bit 7 is mouse button 8.</li></ul><p>To manually manipulate the mouse reports outside of the <code>pointing_device_task_*</code> functions, you can use:</p><ul><li><code>pointing_device_get_report()</code> - Returns the current report_mouse_t that represents the information sent to the host computer</li><li><code>pointing_device_set_report(report_mouse_t mouse_report)</code> - Overrides and saves the report_mouse_t to be sent to the host computer</li><li><code>pointing_device_send()</code> - Sends the mouse report to the host and zeroes out the report.</li></ul><p>When the mouse report is sent, the x, y, v, and h values are set to 0 (this is done in <code>pointing_device_send()</code>, which can be overridden to avoid this behavior). This way, button states persist, but movement will only occur once. For further customization, both <code>pointing_device_init</code> and <code>pointing_device_task</code> can be overridden.</p><p>Additionally, by default, <code>pointing_device_send()</code> will only send a report when the report has actually changed. This prevents it from continuously sending mouse reports, which will keep the host system awake. This behavior can be changed by creating your own <code>pointing_device_send()</code> function.</p><p>Also, you use the <code>has_mouse_report_changed(new_report, old_report)</code> function to check to see if the report has changed.</p><h2 id="examples" tabindex="-1">Examples <a class="header-anchor" href="#examples" aria-label="Permalink to &quot;Examples&quot;"></a></h2><h3 id="custom-mouse-keycode" tabindex="-1">Custom Mouse Keycode <a class="header-anchor" href="#custom-mouse-keycode" aria-label="Permalink to &quot;Custom Mouse Keycode&quot;"></a></h3><p>In this example, a custom key is used to click the mouse and scroll 127 units vertically and horizontally, then undo all of that when released - because that&#39;s a totally useful function.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">case MS_SPECIAL:</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> report_mouse_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_get_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (record</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event.pressed) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 127</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 127</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.buttons </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">|=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> MOUSE_BTN1;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // this is defined in report.h</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">127</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> -</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">127</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> currentReport.buttons </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ~</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">MOUSE_BTN1;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_set_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(currentReport);</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_send</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span></code></pre></div><p>Recall that the mouse report is set to zero (except the buttons) whenever it is sent, so the scrolling would only occur once in each case.</p><h3 id="drag-scroll-or-mouse-scroll" tabindex="-1">Drag Scroll or Mouse Scroll <a class="header-anchor" href="#drag-scroll-or-mouse-scroll" aria-label="Permalink to &quot;Drag Scroll or Mouse Scroll&quot;"></a></h3><p>A very common implementation is to use the mouse movement to scroll instead of moving the cursor on the system. This uses the <code>pointing_device_task_user</code> callback to intercept and modify the mouse report before it&#39;s sent to the host system.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">enum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> custom_keycodes {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DRAG_SCROLL </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SAFE_RANGE,</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> set_scrolling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mouse_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (set_scrolling) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> process_record_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (keycode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DRAG_SCROLL </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> record-&gt;event.pressed) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> set_scrolling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">set_scrolling;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.</p><h3 id="advanced-drag-scroll" tabindex="-1">Advanced Drag Scroll <a class="header-anchor" href="#advanced-drag-scroll" aria-label="Permalink to &quot;Advanced Drag Scroll&quot;"></a></h3><p>Sometimes, like with the Cirque trackpad, you will run into issues where the scrolling may be too fast.</p><p>Here is a slightly more advanced example of drag scrolling. You will be able to change the scroll speed based on the values in set in <code>SCROLL_DIVISOR_H</code> and <code>SCROLL_DIVISOR_V</code>. This bit of code is also set up so that instead of toggling the scrolling state with set_scrolling = !set_scrolling, the set_scrolling variable is set directly to record-&gt;event.pressed. This way, the drag scrolling will only be active while the DRAG_SCROLL button is held down.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">enum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> custom_keycodes {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DRAG_SCROLL </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SAFE_RANGE,</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> set_scrolling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Modify these values to adjust the scrolling speed</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SCROLL_DIVISOR_H</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 8.0</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SCROLL_DIVISOR_V</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 8.0</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Variables to store accumulated scroll values</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Function to handle mouse reports and perform drag scrolling</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mouse_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Check if drag scrolling is active</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (set_scrolling) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Calculate and accumulate scroll values based on mouse movement and divisors</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SCROLL_DIVISOR_H;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">float</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SCROLL_DIVISOR_V;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Assign integer parts of accumulated scroll values to the mouse report</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">int8_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)scroll_accumulated_h;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">int8_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)scroll_accumulated_v;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Update accumulated scroll values by subtracting the integer parts</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">int8_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)scroll_accumulated_h;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scroll_accumulated_v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">int8_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)scroll_accumulated_v;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Clear the X and Y values of the mouse report</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Function to handle key events and enable/disable drag scrolling</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> process_record_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (keycode) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DRAG_SCROLL:</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Toggle set_scrolling when DRAG_SCROLL key is pressed or released</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> set_scrolling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> record-&gt;event.pressed;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Function to handle layer changes and disable drag scrolling when not in AUTO_MOUSE_DEFAULT_LAYER</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> layer_state_set_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> state</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Disable set_scrolling if the current layer is not the AUTO_MOUSE_DEFAULT_LAYER</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get_highest_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(state) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AUTO_MOUSE_DEFAULT_LAYER) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> set_scrolling </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> state;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="split-examples" tabindex="-1">Split Examples <a class="header-anchor" href="#split-examples" aria-label="Permalink to &quot;Split Examples&quot;"></a></h2><p>The following examples make use the <code>SPLIT_POINTING_ENABLE</code> functionality and show how to manipulate the mouse report for a scrolling mode.</p><h3 id="single-pointing-device" tabindex="-1">Single Pointing Device <a class="header-anchor" href="#single-pointing-device" aria-label="Permalink to &quot;Single Pointing Device&quot;"></a></h3><p>The following example will work with either <code>POINTING_DEVICE_LEFT</code> or <code>POINTING_DEVICE_RIGHT</code> and enables scrolling mode while on a particular layer.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">static</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> bool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scrolling_mode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> layer_state_set_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> state</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get_highest_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(state)) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> _RAISE:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // If we&#39;re on the _RAISE layer enable scrolling mode</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scrolling_mode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_set_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (scrolling_mode) {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // check if we were scrolling before and set disable if so</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> scrolling_mode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_set_cpi</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">8000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> state;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mouse_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (scrolling_mode) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> mouse_report;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="combined-pointing-devices" tabindex="-1">Combined Pointing Devices <a class="header-anchor" href="#combined-pointing-devices" aria-label="Permalink to &quot;Combined Pointing Devices&quot;"></a></h3><p>The following example requires <code>POINTING_DEVICE_COMBINED</code> and sets the left side pointing device to scroll only.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> keyboard_post_init_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_set_cpi_on_side</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> //Set cpi on left side to a low value for slower scrolling.</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_set_cpi_on_side</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">8000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> //Set cpi on right side to a reasonable value for mousing.</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_combined_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> left_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">report_mouse_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> right_report</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.h </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.x;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.y;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> left_report.y </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_combine_reports</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(left_report, right_report);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h1 id="troubleshooting" tabindex="-1">Troubleshooting <a class="header-anchor" href="#troubleshooting" aria-label="Permalink to &quot;Troubleshooting&quot;"></a></h1><p>If you are having issues with pointing device drivers debug messages can be enabled that will give you insights in the inner workings. To enable these add to your keyboards <code>config.h</code> file:</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> POINTING_DEVICE_DEBUG</span></span></code></pre></div><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>The messages will be printed out to the <code>CONSOLE</code> output. For additional information, refer to <a href="./../faq_debug">Debugging/Troubleshooting QMK</a>.</p></div><hr><h1 id="pointing-device-auto-mouse" tabindex="-1">Automatic Mouse Layer <a class="header-anchor" href="#pointing-device-auto-mouse" aria-label="Permalink to &quot;Automatic Mouse Layer {#pointing-device-auto-mouse}&quot;"></a></h1><p>When using a pointing device combined with a keyboard the mouse buttons are often kept on a separate layer from the default keyboard layer, which requires pressing or holding a key to change layers before using the mouse. To make this easier and more efficient an additional pointing device feature may be enabled that will automatically activate a target layer as soon as the pointing device is active <em>(in motion, mouse button pressed etc.)</em> and deactivate the target layer after a set time.</p><p>Additionally if any key that is defined as a mouse key is pressed then the layer will be held as long as the key is pressed and the timer will be reset on key release. When a non-mouse key is pressed then the layer is deactivated early <em>(with some exceptions see below)</em>. Mod, mod tap, and one shot mod keys are ignored <em>(i.e. don&#39;t hold or activate layer but do not deactivate the layer either)</em> when sending a modifier keycode <em>(e.g. hold for mod tap)</em> allowing for mod keys to be used with the mouse without activating the target layer when typing.</p><p>All of the standard layer keys (tap toggling, toggle, toggle on, one_shot, layer tap, layer mod) that activate the current target layer are uniquely handled to ensure they behave as expected <em>(see layer key table below)</em>. The target layer that can be changed at any point during by calling the <code>set_auto_mouse_layer(&lt;new_target_layer&gt;);</code> function.</p><h3 id="behaviour-of-layer-keys-that-activate-the-target-layer" tabindex="-1">Behaviour of Layer keys that activate the target layer <a class="header-anchor" href="#behaviour-of-layer-keys-that-activate-the-target-layer" aria-label="Permalink to &quot;Behaviour of Layer keys that activate the target layer&quot;"></a></h3><table><thead><tr><th>Layer key as in <code>keymap.c</code></th><th>Auto Mouse specific behaviour</th></tr></thead><tbody><tr><td><code>MO(&lt;target_layer&gt;)</code></td><td>Treated as a mouse key holding the layer while pressed</td></tr><tr><td><code>LT(&lt;target_layer&gt;)</code></td><td>When tapped will be treated as non mouse key and mouse key when held</td></tr><tr><td><code>LM(&lt;target_layer&gt;)</code></td><td>Treated as a mouse key</td></tr><tr><td><code>TG(&lt;target_layer&gt;)</code></td><td>Will set flag preventing target layer deactivation or removal until pressed again</td></tr><tr><td><code>TO(&lt;target_layer&gt;)</code></td><td>Same as <code>TG(&lt;target_layer&gt;)</code></td></tr><tr><td><code>TT(&lt;target_layer&gt;)</code></td><td>Treated as a mouse key when <code>tap.count &lt; TAPPING_TOGGLE</code> and as <code>TG</code> when <code>tap.count == TAPPING_TOGGLE</code></td></tr><tr><td><code>DF(&lt;target_layer&gt;)</code></td><td>Skips auto mouse key processing similar to mod keys</td></tr><tr><td><code>OSL(&lt;target_layer&gt;)</code></td><td>Skips, but if current one shot layer is the target layer then it will prevent target layer deactivation or removal</td></tr></tbody></table><h2 id="how-to-enable" tabindex="-1">How to enable: <a class="header-anchor" href="#how-to-enable" aria-label="Permalink to &quot;How to enable:&quot;"></a></h2><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in config.h:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> POINTING_DEVICE_AUTO_MOUSE_ENABLE</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// only required if not setting mouse layer elsewhere</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">#define</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AUTO_MOUSE_DEFAULT_LAYER</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">index of your mouse layer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in keymap.c:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_init_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&lt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">mouse_layer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // only required if AUTO_MOUSE_DEFAULT_LAYER is not set to index of &lt;mouse_layer&gt;</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // always required before the auto mouse feature will work</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Because the auto mouse feature can be disabled/enabled during runtime and starts as disabled by default it must be enabled by calling <code>set_auto_mouse_enable(true);</code> somewhere in firmware before the feature will work.<br><em>Note: for setting the target layer during initialization either setting <code>AUTO_MOUSE_DEFAULT_LAYER</code> in <code>config.h</code> or calling <code>set_auto_mouse_layer(&lt;mouse_layer&gt;)</code> can be used.</em></p><h2 id="how-to-customize" tabindex="-1">How to Customize: <a class="header-anchor" href="#how-to-customize" aria-label="Permalink to &quot;How to Customize:&quot;"></a></h2><p>There are a few ways to control the auto mouse feature with both <code>config.h</code> options and functions for controlling it during runtime.</p><h3 id="config-h-options" tabindex="-1"><code>config.h</code> Options: <a class="header-anchor" href="#config-h-options" aria-label="Permalink to &quot;`config.h` Options:&quot;"></a></h3><table><thead><tr><th>Define</th><th>Description</th><th style="text-align:center;">Range</th><th style="text-align:center;">Units</th><th style="text-align:right;">Default</th></tr></thead><tbody><tr><td><code>POINTING_DEVICE_AUTO_MOUSE_ENABLE</code></td><td>(Required) Enables auto mouse layer feature</td><td style="text-align:center;"></td><td style="text-align:center;"><em>None</em></td><td style="text-align:right;"><em>Not defined</em></td></tr><tr><td><code>AUTO_MOUSE_DEFAULT_LAYER</code></td><td>(Optional) Index of layer to use as default target layer</td><td style="text-align:center;">0 - <code>LAYER_MAX</code></td><td style="text-align:center;"><em><code>uint8_t</code></em></td><td style="text-align:right;"><code>1</code></td></tr><tr><td><code>AUTO_MOUSE_TIME</code></td><td>(Optional) Time layer remains active after activation</td><td style="text-align:center;"><em>ideally</em> (250-1000)</td><td style="text-align:center;"><em>ms</em></td><td style="text-align:right;"><code>650 ms</code></td></tr><tr><td><code>AUTO_MOUSE_DELAY</code></td><td>(Optional) Lockout time after non-mouse key is pressed</td><td style="text-align:center;"><em>ideally</em> (100-1000)</td><td style="text-align:center;"><em>ms</em></td><td style="text-align:right;"><code>TAPPING_TERM</code> or <code>200 ms</code></td></tr><tr><td><code>AUTO_MOUSE_DEBOUNCE</code></td><td>(Optional) Time delay from last activation to next update</td><td style="text-align:center;"><em>ideally</em> (10 - 100)</td><td style="text-align:center;"><em>ms</em></td><td style="text-align:right;"><code>25 ms</code></td></tr><tr><td><code>AUTO_MOUSE_THRESHOLD</code></td><td>(Optional) Amount of mouse movement required to switch layers</td><td style="text-align:center;">0 -</td><td style="text-align:center;"><em>units</em></td><td style="text-align:right;"><code>10 units</code></td></tr></tbody></table><h3 id="adding-mouse-keys" tabindex="-1">Adding mouse keys <a class="header-anchor" href="#adding-mouse-keys" aria-label="Permalink to &quot;Adding mouse keys&quot;"></a></h3><p>While all default mouse keys and layer keys(for current mouse layer) are treated as mouse keys, additional Keyrecords can be added to mouse keys by adding them to the is_mouse_record_* stack.</p><h4 id="callbacks-for-setting-up-additional-key-codes-as-mouse-keys" tabindex="-1">Callbacks for setting up additional key codes as mouse keys: <a class="header-anchor" href="#callbacks-for-setting-up-additional-key-codes-as-mouse-keys" aria-label="Permalink to &quot;Callbacks for setting up additional key codes as mouse keys:&quot;"></a></h4><table><thead><tr><th>Callback</th><th>Description</th></tr></thead><tbody><tr><td><code>bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record)</code></td><td>keyboard level callback for adding mouse keys</td></tr><tr><td><code>bool is_mouse_record_user(uint16_t keycode, keyrecord_t* record)</code></td><td>user/keymap level callback for adding mouse keys</td></tr></tbody></table><h5 id="to-use-the-callback-function-to-add-mouse-keys" tabindex="-1">To use the callback function to add mouse keys: <a class="header-anchor" href="#to-use-the-callback-function-to-add-mouse-keys" aria-label="Permalink to &quot;To use the callback function to add mouse keys:&quot;"></a></h5><p>The following code will cause the enter key and all of the arrow keys to be treated as mouse keys (hold target layer while they are pressed and reset active layer timer).</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in &lt;keyboard&gt;.c:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> is_mouse_record_kb</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(keycode) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> KC_ENT:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> KC_RIGHT ... KC_UP:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> is_mouse_record_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(keycode, record);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="advanced-control" tabindex="-1">Advanced control <a class="header-anchor" href="#advanced-control" aria-label="Permalink to &quot;Advanced control&quot;"></a></h2><p>There are several functions that allow for more advanced interaction with the auto mouse feature allowing for greater control.</p><h3 id="functions-to-control-auto-mouse-enable-and-target-layer" tabindex="-1">Functions to control auto mouse enable and target layer: <a class="header-anchor" href="#functions-to-control-auto-mouse-enable-and-target-layer" aria-label="Permalink to &quot;Functions to control auto mouse enable and target layer:&quot;"></a></h3><table><thead><tr><th style="text-align:left;">Function</th><th>Description</th><th>Aliases</th><th style="text-align:right;">Return type</th></tr></thead><tbody><tr><td style="text-align:left;"><code>set_auto_mouse_enable(bool enable)</code></td><td>Enable or disable auto mouse (true:enable, false:disable)</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_enable(void)</code></td><td>Return auto mouse enable state (true:enabled, false:disabled)</td><td><code>AUTO_MOUSE_ENABLED</code></td><td style="text-align:right;"><code>bool</code></td></tr><tr><td style="text-align:left;"><code>set_auto_mouse_layer(uint8_t LAYER)</code></td><td>Change/set the target layer for auto mouse</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_layer(void)</code></td><td>Return auto mouse target layer index</td><td><code>AUTO_MOUSE_TARGET_LAYER</code></td><td style="text-align:right;"><code>uint8_t</code></td></tr><tr><td style="text-align:left;"><code>remove_auto_mouse_layer(layer_state_t state, bool force)</code></td><td>Return <code>state</code> with target layer removed if appropriate (ignore criteria if <code>force</code>)</td><td></td><td style="text-align:right;"><code>layer_state_t</code></td></tr><tr><td style="text-align:left;"><code>auto_mouse_layer_off(void)</code></td><td>Disable target layer if appropriate will call (makes call to <code>layer_state_set</code>)</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>auto_mouse_toggle(void)</code></td><td>Toggle on/off target toggle state (disables layer deactivation when true)</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_toggle(void)</code></td><td>Return value of toggling state variable</td><td></td><td style="text-align:right;"><code>bool</code></td></tr><tr><td style="text-align:left;"><code>set_auto_mouse_timeout(uint16_t timeout)</code></td><td>Change/set the timeout for turing off the layer</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_timeout(void)</code></td><td>Return the current timeout for turing off the layer</td><td></td><td style="text-align:right;"><code>uint16_t</code></td></tr><tr><td style="text-align:left;"><code>set_auto_mouse_debounce(uint16_t timeout)</code></td><td>Change/set the debounce for preventing layer activation</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_debounce(void)</code></td><td>Return the current debounce for preventing layer activation</td><td></td><td style="text-align:right;"><code>uint8_t</code></td></tr><tr><td style="text-align:left;"><code>is_auto_mouse_active(void)</code></td><td>Returns the active state of the auto mouse layer (eg if the layer has been triggered)</td><td></td><td style="text-align:right;"><code>bool</code></td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_key_tracker(void)</code></td><td>Gets the current count for the auto mouse key tracker.</td><td></td><td style="text-align:right;"><code>int8_t</code></td></tr><tr><td style="text-align:left;"><code>set_auto_mouse_key_tracker(int8_t key_tracker)</code></td><td>Sets/Overrides the current count for the auto mouse key tracker.</td><td></td><td style="text-align:right;"><code>void</code>(None)</td></tr></tbody></table><p><em>NOTES:</em><br> - <em>Due to the nature of how some functions work, the <code>auto_mouse_trigger_reset</code>, and <code>auto_mouse_layer_off</code> functions should never be called in the <code>layer_state_set_*</code> stack as this can cause indefinite loops.</em><br> - <em>It is recommended that <code>remove_auto_mouse_layer</code> is used in the <code>layer_state_set_*</code> stack of functions and <code>auto_mouse_layer_off</code> is used everywhere else</em><br> - <em><code>remove_auto_mouse_layer(state, false)</code> or <code>auto_mouse_layer_off()</code> should be called before any instance of <code>set_auto_mouse_enabled(false)</code> or <code>set_auto_mouse_layer(layer)</code> to ensure that the target layer will be removed appropriately before disabling auto mouse or changing target to avoid a stuck layer</em></p><h3 id="functions-for-handling-custom-key-events" tabindex="-1">Functions for handling custom key events: <a class="header-anchor" href="#functions-for-handling-custom-key-events" aria-label="Permalink to &quot;Functions for handling custom key events:&quot;"></a></h3><table><thead><tr><th style="text-align:left;">Function</th><th>Description</th><th style="text-align:right;">Return type</th></tr></thead><tbody><tr><td style="text-align:left;"><code>auto_mouse_keyevent(bool pressed)</code></td><td>Auto mouse mouse key event (true: key down, false: key up)</td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>auto_mouse_trigger_reset(bool pressed)</code></td><td>Reset auto mouse status on key down and start delay timer (non-mouse key event)</td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>auto_mouse_toggle(void)</code></td><td>Toggle on/off target toggle state (disables layer deactivation when true)</td><td style="text-align:right;"><code>void</code>(None)</td></tr><tr><td style="text-align:left;"><code>get_auto_mouse_toggle(void)</code></td><td>Return value of toggling state variable</td><td style="text-align:right;"><code>bool</code></td></tr><tr><td style="text-align:left;"><em>NOTE: Generally it would be preferable to use the <code>is_mouse_record_*</code> functions to add any additional keys that should act as mouse keys rather than adding <code>auto_mouse_keyevent(record.event-&gt;pressed)</code> to <code>process_records_*</code></em></td><td></td><td style="text-align:right;"></td></tr></tbody></table><h3 id="advanced-control-examples" tabindex="-1">Advanced control examples <a class="header-anchor" href="#advanced-control-examples" aria-label="Permalink to &quot;Advanced control examples&quot;"></a></h3><h4 id="disable-auto-mouse-on-certain-layers" tabindex="-1">Disable auto mouse on certain layers: <a class="header-anchor" href="#disable-auto-mouse-on-certain-layers" aria-label="Permalink to &quot;Disable auto mouse on certain layers:&quot;"></a></h4><p>The auto mouse feature can be disabled any time and this can be helpful if you want to disable the auto mouse feature under certain circumstances such as when particular layers are active. One issue however is the handling of the target layer, it needs to be removed appropriately <strong>before</strong> disabling auto mouse <em>(see notes under control functions above)</em>. The following function would disable the auto_mouse feature whenever the layers <code>_LAYER5</code> through <code>_LAYER7</code> are active as the top most layer <em>(ignoring target layer)</em>.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in keymap.c:</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> layer_state_set_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> state</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // checks highest layer other than target layer</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get_highest_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">remove_auto_mouse_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(state, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">))) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> _LAYER5 ... _LAYER7:</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // remove_auto_mouse_target must be called to adjust state *before* setting enable</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> state </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> remove_auto_mouse_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(state, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // recommend that any code that makes adjustment based on auto mouse layer state would go here</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> state;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h4 id="set-different-target-layer-when-a-particular-layer-is-active" tabindex="-1">Set different target layer when a particular layer is active: <a class="header-anchor" href="#set-different-target-layer-when-a-particular-layer-is-active" aria-label="Permalink to &quot;Set different target layer when a particular layer is active:&quot;"></a></h4><p>The below code will change the auto mouse layer target to <code>_MOUSE_LAYER_2</code> when <code>_DEFAULT_LAYER_2</code> is highest default layer state.</p><p><em>NOTE: that <code>auto_mouse_layer_off</code> is used here instead of <code>remove_auto_mouse_layer</code> as <code>default_layer_state_set_*</code> stack is separate from the <code>layer_state_set_*</code> stack</em>, if something similar was to be done in <code>layer_state_set_user</code>, <code>state = remove_auto_mouse_layer(state, false)</code> should be used instead.</p><p><em>ADDITIONAL NOTE: <code>AUTO_MOUSE_TARGET_LAYER</code> is checked if already set to avoid deactivating the target layer unless needed</em>.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in keymap.c</span></span>\n<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> default_layer_state_set_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">layer_state_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> state</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // switch on change in default layer need to check if target layer already set to avoid turning off layer needlessly</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get_highest_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(state)) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> _DEFAULT_LAYER_2:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ((AUTO_MOUSE_TARGET_LAYER) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> _MOUSE_LAYER_2) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auto_mouse_layer_off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(_MOUSE_LAYER_2);</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((AUTO_MOUSE_TARGET_LAYER) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> _MOUSE_LAYER_1) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auto_mouse_layer_off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_layer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(_MOUSE_LAYER_1);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> state;</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="use-custom-keys-to-control-auto-mouse" tabindex="-1">Use custom keys to control auto mouse: <a class="header-anchor" href="#use-custom-keys-to-control-auto-mouse" aria-label="Permalink to &quot;Use custom keys to control auto mouse:&quot;"></a></h3><p>Custom key records could also be created that control the auto mouse feature.<br> The code example below would create a custom key that would toggle the auto mouse feature on and off when pressed while also setting a bool that could be used to disable other code that may turn it on such as the layer code above.</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in config.h:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">enum</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user_custom_keycodes {</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AM_Toggle </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SAFE_RANGE</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// in keymap.c:</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// set up global bool to adjust other user code</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auto_mouse_tg_off </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">AUTO_MOUSE_ENABLED;</span></span>\n<span class="line"></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> process_record_user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (keycode) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // toggle auto mouse enable key</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AM_Toggle:</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(record</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">-&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event.pressed) {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // key down</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> auto_mouse_layer_off</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // disable target layer if needed</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> set_auto_mouse_enabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((AUTO_MOUSE_ENABLED) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">^</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auto_mouse_tg_off </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get_auto_mouse_enabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // do nothing on key up</span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // prevent further processing of keycode</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="customize-target-layer-activation" tabindex="-1">Customize Target Layer Activation <a class="header-anchor" href="#customize-target-layer-activation" aria-label="Permalink to &quot;Customize Target Layer Activation&quot;"></a></h2><p>Layer activation can be customized by overwriting the <code>auto_mouse_activation</code> function. This function is checked every time <code>pointing_device_task</code> is called when inactive and every <code>AUTO_MOUSE_DEBOUNCE</code> ms when active, and will evaluate pointing device level conditions that trigger target layer activation. When it returns true, the target layer will be activated barring the usual exceptions <em>(e.g. delay time has not expired)</em>.</p><p>By default it will return true if any of the <code>mouse_report</code> axes <code>x</code>,<code>y</code>,<code>h</code>,<code>v</code> are non zero, or if there is any mouse buttons active in <code>mouse_report</code>. <em>Note: The Cirque pinnacle track pad already implements a custom activation function that will activate on touchdown as well as movement all of the default conditions, currently this only works for the master side of split keyboards.</em></p><table><thead><tr><th style="text-align:left;">Function</th><th>Description</th><th style="text-align:right;">Return type</th></tr></thead><tbody><tr><td style="text-align:left;"><code>auto_mouse_activation(report_mouse_t mouse_report)</code></td><td>Overwritable function that controls target layer activation (when true)</td><td style="text-align:right;"><code>bool</code></td></tr></tbody></table><h2 id="auto-mouse-for-custom-pointing-device-task" tabindex="-1">Auto Mouse for Custom Pointing Device Task <a class="header-anchor" href="#auto-mouse-for-custom-pointing-device-task" aria-label="Permalink to &quot;Auto Mouse for Custom Pointing Device Task&quot;"></a></h2><p>When using a custom pointing device (overwriting <code>pointing_device_task</code>) the following code should be somewhere in the <code>pointing_device_task_*</code> stack:</p><div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> //...Custom pointing device task code</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // handle automatic mouse layer (needs report_mouse_t as input)</span></span>\n<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_task_auto_mouse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(local_mouse_report);</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>\n<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> //...More custom pointing device task code</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> </span></span>\n<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pointing_device_send</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>\n<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>In general the following two functions must be implemented in appropriate locations for auto mouse to function:</p><table><thead><tr><th>Function</th><th>Description</th><th style="text-align:right;">Suggested location</th></tr></thead><tbody><tr><td><code>pointing_device_task_auto_mouse(report_mouse_t mouse_report)</code></td><td>handles target layer activation and is_active status updates</td><td style="text-align:right;"><code>pointing_device_task</code> stack</td></tr><tr><td><code>process_auto_mouse(uint16_t keycode, keyrecord_t* record)</code></td><td>Keycode processing for auto mouse</td><td style="text-align:right;"><code>process_record</code> stack</td></tr></tbody></table>', 202);
const _hoisted_203 = [
_hoisted_1
];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("div", null, _hoisted_203);
}
const pointing_device = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
__pageData,
pointing_device as default
};