🖱️

ZMK Input Processorチートシート

に公開

Input Processorとは

公式ドキュメントへのリンク

ZMKのInput Processorは、カーソル移動やスクロールなどのマウス入力(Input)イベント[1]を受け取り、それに基づいてさまざま処理を実行する機能。

さまざな処理とは、例えば

  • カーソルの移動やスクロールの量に倍率をかける(CPIを大きくしたり、小さくしたりする)
  • カーソル移動やスクロールの方向を変更する(XとYを入れ替えたり、x方向またはy方向を反転する)
  • カーソル移動をスクロールに変換する
  • カーソルが移動したら一定時間の間特定のレイヤーを有効化する(オートマウスレイヤー)

などが挙げられる。これ以外にも、目次に並んでいるような様々な処理が可能である。

Input Processorの利点はその汎用性にある。ZMKのinputシステムを使用して実装されているマウス入力であれば、センサー(ドライバー)が異なっても、Input Processorを使うことで同じ機能を使用できる。従来はセンサーのドライバーごとに機能を実装していたが、その手間を省くことができ、メンテナンス性の向上も期待できる。
Input Processorという名前を見て、なんだか抽象的な名前でとっつきにくいと思ったかもしれない(筆者は思った)が、この名前はその汎用性を表していると言える。

基本的な設定方法

公式ドキュメントへのリンク

例えば、&zip_xy_scaler 3 2&zip_temp_layer 5 10000という2つのInput Processorを使用するには、Input Listener(例えばtrackball_listener)に対して以下のように記述する。

#include <input/processors.dtsi>

&trackball_listener {
    input-processors = <
        &zip_xy_scaler 3 2
        &zip_temp_layer 5 10000
    >;
};
マウスキーに対してInput Processorを適用する方法

トラックボールなどの入力デバイスの他に、キーによるマウスクリック(&mkp)、カーソル移動(&mmv)、スクロール(&msc)に対するInput Listenerも用意されている。それぞれ、&mkp_input_listener&mmv_input_listener&msc_input_listenerという名前で参照できる。

Input Processorをどこに記述するべきか?

一般的に、以下のような棲み分けが推奨される。

  • .dtsiまたは.overlayファイル: ユーザーが通常変更しない、ハードウェア構成に関係したものを記述
  • .keymapファイル: ユーザーが変更し得る、ユーザーの好み次第で設定が変わるものを記述

input processorはユーザーが変更し得る設定が多いため、.keymapファイルに記述するのが適切と考えることができる。が、考え方や好みによるところではあるため、必ずしもこれが正解とは限らない。

なお、複数箇所にinput processorを記述すると、devicetreeの仕様上、どれか1つだけが有効となり、他は無効となるため、複数箇所に記述しないように要注意。

レイヤー別のInput Processor

公式ドキュメントへのリンク

以下の例では、レイヤー3でのみ&zip_xy_scaler 1 3が、レイヤー4と5でのみ&zip_xy_scaler 3 2が適用される。

#include <input/processors.dtsi>

&trackball_listener {
    input-processors = <&zip_xy_scaler 3 2>;

    snipe {
        layers = <3>;
        input-processors = <&zip_xy_scaler 1 3>;
    };

    scroller {
        layers = <4 5>;
        input-processors = <&zip_xy_to_scroll_mapper>;
    };
};

snipescrollerという名前はなんでも良く、自分に分かりやすい名前で自由に設定できる。

同じレイヤーに複数のレイヤー別Input Processorを適用する場合

通常、レイヤー別のInput Processorは最初にマッチしたものだけで処理を終了し、他はスキップされる。
スキップしないようにするには、process-next;を設定する。

#include <input/processors.dtsi>

&trackball_listener {
    input-processors = <&zip_xy_scaler 3 2>;

    scroller {
        layers = <4 5>;
        input-processors = <&zip_xy_to_scroll_mapper>;
        process-next;
    };

    fast_scroller {
        layers = <5>;
        input-processors = <&zip_scroll_scaler 3 1>;
    };
};

カーソル移動関連

カーソル移動量に倍率をかける(カーソル移動速度を大きくする/小さくする)

公式ドキュメントへのリンク

&zip_xy_scalerを使用する。
&zip_xy_scalerはパラメーターを2つ受け取り、1つ目が分子、2つ目が分母となる。
例えば、&zip_xy_scaler 3 2なら、CPIが1.5倍 (3/2倍)になり、&zip_xy_scaler 1 3とすれば0.333倍(1/3倍)になる。

#include <input/processors.dtsi>

&trackball_listener {
    input-processors = <&zip_xy_scaler 3 2>;
};

x方向/y方向の片方のみに倍率をかける

x方向のみスケールするには、&zip_x_scalerを、y方向のみスケールするには&zip_y_scaler&zip_xy_scalerの代わりに用いる。

カーソル移動のXとYを入れ替える

公式ドキュメントへのリンク

&zip_xy_transform INPUT_TRANSFORM_XY_SWAPを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    input-processors = <&zip_xy_transform INPUT_TRANSFORM_XY_SWAP>;
};

カーソル移動のX方向を反転する

&zip_xy_transform INPUT_TRANSFORM_X_INVERTを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    input-processors = <&zip_xy_transform INPUT_TRANSFORM_X_INVERT>;
};

カーソル移動のY方向を反転する

&zip_xy_transform INPUT_TRANSFORM_Y_INVERTを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    input-processors = <&zip_xy_transform INPUT_TRANSFORM_Y_INVERT>;
};

カーソル移動の方向変更を組み合わせる

例えば、

  • &zip_xy_transform INPUT_TRANSFORM_XY_SWAP
  • &zip_xy_transform INPUT_TRANSFORM_X_INVERT

の2つを組み合わせるには、
&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_X_INVERT)
のように記述する。

#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    input-processors = <&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_X_INVERT)>;
};

スクロール関連

カーソル移動をスクロールに変換する

公式ドキュメントへのリンク

&zip_xy_to_scroll_mapperを使用する。

#include <input/processors.dtsi>

&trackball_listener {
    input-processors = <&zip_xy_to_scroll_mapper>;
};

通常、特定のレイヤーでのみ適用することで、通常はカーソル移動で、特定レイヤーが有効な間のみスクロールにするという使い方をする。

#include <input/processors.dtsi>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <&zip_xy_to_scroll_mapper>;
    };
};

スクロール量に倍率をかける(スクロール速度を大きくする/小さくする)

公式ドキュメントへのリンク

&zip_scroll_scalerを使用する。
&zip_scroll_scalerはパラメーターを2つ受け取り、1つ目が分子、2つ目が分母となる。
例えば、&zip_scroll_scaler 3 2なら、スクロール量が1.5倍 (3/2倍)になり、&zip_scroll_scaler 1 3とすれば0.333倍(1/3倍)になる。

#include <input/processors.dtsi>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_scaler 3 2
        >;
    };
};

x方向/y方向の片方のみに倍率をかける

x方向またはy方向のみスケールするには、以下の&zip_scroll_x_scalerまたは&zip_scroll_y_scalerを定義して、&zip_scroll_scalerの代わりに用いる。
#include <zephyr/dt-bindings/input/input-event-codes.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <zephyr/dt-bindings/input/input-event-codes.h>

/ {
    input_processors {
        zip_scroll_x_scaler: zip_scroll_x_scaler {
            compatible = "zmk,input-processor-scaler";
            #input-processor-cells = <2>;
            type = <INPUT_EV_REL>;
            codes = <INPUT_REL_HWHEEL>;
            track-remainders;
        };

        zip_scroll_y_scaler: zip_scroll_y_scaler {
            compatible = "zmk,input-processor-scaler";
            #input-processor-cells = <2>;
            type = <INPUT_EV_REL>;
            codes = <INPUT_REL_WHEEL>;
            track-remainders;
        };
    };
};

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_x_scaler 3 2
        >;
    };
};

スクロールを縦方向に限定する

&zip_scroll_x_scalerでx方向のスクロールを0倍にすれば、縦方向のスクロールのみになる。

#include <zephyr/dt-bindings/input/input-event-codes.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <zephyr/dt-bindings/input/input-event-codes.h>

/ {
    input_processors {
        zip_scroll_x_scaler: zip_scroll_x_scaler {
            compatible = "zmk,input-processor-scaler";
            #input-processor-cells = <2>;
            type = <INPUT_EV_REL>;
            codes = <INPUT_REL_HWHEEL>;
            track-remainders;
        };
    };
};

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_x_scaler 0 1
        >;
    };
};

スクロールのXとYを入れ替える

公式ドキュメントへのリンク

&zip_scroll_transform INPUT_TRANSFORM_XY_SWAPを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_transform INPUT_TRANSFORM_XY_SWAP
        >;
    };
};

スクロールのX方向を反転する

&zip_scroll_transform INPUT_TRANSFORM_X_INVERTを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_transform INPUT_TRANSFORM_X_INVERT
        >;
    };
};

スクロールのY方向を反転する

&zip_scroll_transform INPUT_TRANSFORM_Y_INVERTを用いる。
#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_transform INPUT_TRANSFORM_Y_INVERT
        >;
    };
};

スクロールの方向変更を組み合わせる

例えば、

  • &zip_scroll_transform INPUT_TRANSFORM_XY_SWAP
  • &zip_scroll_transform INPUT_TRANSFORM_X_INVERT

の2つを組み合わせるには、
&zip_scroll_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_X_INVERT)
のように記述する。

#include <dt-bindings/zmk/input_transform.h>が追加で必要なことに注意。

#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>

&trackball_listener {
    scroller {
        layers = <4>;
        input-processors = <
            &zip_xy_to_scroll_mapper
            &zip_scroll_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_X_INVERT)
        >;
    };
};

その他

カーソル移動後一定時間、特定のレイヤーを有効にする(オートマウスレイヤー)

公式ドキュメントへのリンク

以下の記事で詳しく説明しているため、そちらを参照。

https://zenn.dev/kot149/articles/zmk-auto-mouse-layer

マウスクリックをキー入力に変換する

下記の&zip_button_behaviorsは、左クリックをAキーに、右クリックをBキーに、中央クリックをCキーに変換する。

#include <input/processors.dtsi>

&zip_button_behaviors {
    bindings = <&kp A &kp B &kp C>;
};

&trackpad_listener {
    input-processors = <&zip_button_behaviors>;
};

外部モジュールのInput Processor

ここまでで紹介したInput ProcessorはZMK本体に含まれている公式のInput Processorだが、それ以外に、外部モジュールでもInput Processorを実装可能である。
ここでは設定方法については詳しくは触れないが、いくつか(特に、筆者が使用したことのあるもの)を紹介する。

なお、ここで紹介しているものが全てではない。自分の欲しい機能がこの中にない場合は、GitHubやZMKのDiscordサーバーで検索してみるとよい。また、プログラミングができる人なら自分で新たにモジュールとして作成するという手もある。

カーソル移動をキー入力に変換する

カーソル移動を矢印キーなどに変換するInput Processorを提供するモジュール。

https://github.com/te9no/zmk-input-processor-keybind

https://github.com/zettaface/zmk-input-processor-keybind

マウスジェスチャー

4方向のマウスカーソル移動で描いたジェスチャーを元に、設定したキーバインドを発行するInput Processorを提供するモジュール。

https://github.com/kot149/zmk-mouse-gesture

トラックパッドジェスチャー

タップでクリック、カーソル移動に慣性をつける、トラックパッドの外周をなぞってスクロールするなど、トラックパッド固有のジェスチャーを提供するInput Processorモジュール。

https://github.com/halfdane/zmk-input-gestures

スクロール方向を自動で縦方向/横方向にロックする

360°のスクロールを、x軸またはy軸の近い方へ自動でスナップするInput Processorを提供するモジュール。

https://github.com/kot149/zmk-scroll-snap

カーソル移動を360°任意の角度傾ける

カーソル移動に360°任意(正確には5°区切り)の角度をつけるInput Processorを提供するモジュール。
センサーを傾けて取り付けている場合やキーボードを傾けて使用している場合に、補正するために使う。
(ZMKのロータリエンコーダ用の機能もSensor Rotationという名前なのでややこしい…)

https://github.com/hsgw/zmk-feature-sensor_rotation

入力イベントのレポート頻度を制限する

入力イベントのレポート頻度を制限するInput Processorを提供するモジュール。
必要以上に高い頻度で報告することは、バッテリー消費を増やすだけでなく、無線通信において遅延が発生する原因になる。このInput Processorを用いることでそれを回避できる。

https://github.com/badjeff/zmk-input-processor-report-rate-limit

脚注
  1. 入力イベントは、ZMKのベースであるZephyrで提供されているもので、こちらにその一覧が記載されている。この中にはマウス関連のイベントの他にキー入力イベントなどもあるが、ZMK(v0.3時点)ではマウス関連のイベントのみが処理可能。 ↩︎

GitHubで編集を提案

Discussion