15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

QMKでTapとHoldのタイミングを考える

Last updated at Posted at 2022-01-24

Planckなどの40%キーボードや、それ以下のキー数のキーボードになると、組合せ(dual-role)キーが必要になって来る。SpaceのホールドでShift扱いにする SandS (Space and Shift)が代表例だ。特に親指で押すキーは激戦区で、複数の役割を持たせざるを得ない。

ただ、キーを押して、キーを離す、と文字が出る。という当たり前のことなんだけど、これが複数のキーと機能が絡みだした途端、割と複雑になっていく。きちんと整理しておかないと、後でわからなくなってしまいそうなので、知見を本稿に落とし込んでおこうと思う。

QMKの既存の方法

QMKでも関連の議論は長く、いろいろな方法が編み出された。長押しシフト複数タップなどはその一例で、確かに面白い...けど、筆者は実際に使うところまで至らなかった。

本命のSandS的な議論、「タップとホールドを使い分ける」話としては、QMKのドキュメント"Tap-Hold Configuration Options"に一番まとまっているので、ぜひ一読を。要点としては、次の3つの設定を押さえておく必要がある。

  • TAPPIG_TERM: ミリ秒で指定。これ以上押していればホールド扱い(例. Shift)
  • PERMISIVE_HOLD: TAPPING_TERM以下でも他のキーをdown/upした時点でホールド扱い
  • HOLD_ON_OTHER_KEY_PRESS: TAPPING_TERM以下でも他のキーをdownした時点でホールド扱い

キーが1つの場合

ひとつめのTAPPING_TERMが仮250msだとすると、次図のようなことになる。
timing-1.png
図の例では、「み」のキーをホールド時にShiftとして使う想定だ。SandSでも同様なので、適宜自分のキーボードに読み替えて読んでほしい。 ※ちなみに筆者はカナ打ちユーザ

通常のキーボードであれば、キーが押された段階で「み」が入力されるところ、Dual-roleになっていると、キーを押した段階ではShiftが送られて、一旦入力を待機する。次にキーが離された時点で、押下時間に応じて「み」と入力されるか、Shiftだけになるかが決まる(A, B)。

キーが2つの場合

ふたつのキーのときを考えてみる。ひとつひとつ打てば、当然それぞれのキーが入力される(C)。※ただし、TAPPING_TERMより短い場合
timing-2.png
ひとつ目のキーを押し下げたままふたつ目のキーを押すと、どうなるか。デフォルトの設定では残念ながらこれも「みわ」と入力される。ここでPERMISIVE_HOLDを有効にしておくと、「を」が出力される(D)。

ただ、問題になるのはひとつ目のキーを先に離してしまう場合だ。そうすると、これも「みわ」と入力されてしまう。なお、HOLD_ON_OTHER_KEY_PRESSが有効であれば、「を」が出力される(E)。

QMKの実装で足りない部分

PERMISIVE_HOLDでは中途半端だし、多くのOSの実装と整合しない。QMKでできる範囲としては、HOLD_ON_OTHER_KEY_PRESSを設定しておくのが自然に思える。むしろこれがデフォルトで良さそうなものだけど...、後述のようにそうも行かない理由がある。

高速に打つと、キーが重なってしまう

HOLD_ON_OTHER_KEY_PRESSで「めでたしめでたし」なら良かった。でも、実はこの設定結構使いにくい。一定以上速く打つと、直前のキーを離す前に次のキーを押してしまいがちだ。通常のキーであれば、OS側で良しなにハンドリングしてくれるので、それでも特に問題ない。問題はdual-roleキーで、HOLD_ON_OTHER_KEY_PRESSにしたことで、一瞬でもキーが重なるとホールド扱いになってしまうのだ(G)。
timing-3.png
ホールドを優先したいケースと、タップを優先したいケースがあり、どちらもキーの押下順序では区別がつかない。単押しの判断に使うTAPPIG_TERMでは、いささか長すぎてこれを基準にするのも難しい。

根本的な欠点と妥協点

これは Tap & Hold そのものの根本的な欠点で、完璧な解決方法は存在しない。論理的にも存在しない。でも、妥協点を探ることは可能で、筆者が採用したのは、TAPPIG_TERMの内側にもうひとつの基準を設けて、それ以下であればタップ扱いにするというものだ。図の例では、150msを基準にしている(H)。
timing-4.png
上図のように、文字の流れの中で考えるとすこしわかりやすい。「棲み分け(J)」と「戸を蹴る(K)」と打つとき、完全に同じテンポで打ってしまうと、途中の文字の区別がつかない。シフト側を使わない方を基本と考えるなら、前者については何も考えずに打ちたい。一方で、後者を意識的に区別することはできる。なるべくなら、打鍵のリズムを崩したくないから、押し込むタイミングはある程度一定を保ちつつ、シフトのところだけ意識的に少しホールドを長くすることで、150msを超えるようにする。

タイミング調整

前節までをまとめると、Tap&holdの理想は、次の表のようになるのではないか。

タイミング 方針 ▼▲ ▼▽▲△ ▼▽△▲
0 - 150ms タップ優先 タップ タップ ホールド
150 - 250ms ホールド優先 タップ ホールド ホールド
250ms以上 ホールドのみ ホールド ホールド ホールド

250msと150msの基準で説明してきたけど、これはあくまでも例なので、各人で調整が要る。

できれば、親指と小指で続けてキーを打ってみて、何ミリ秒程度かかっているかを計測してみてみほしい。指によっても意外なほどスピードが異なるので、それも考慮したい。大体は、親指人差し指の組み合わせが最速で、小指薬指とかは下手すると倍くらい運指に時間がかかる。

微調整

TAPPING_TERMについては、TAPPING_TERM_PER_KEYを有効にするとキーごとに調整が効く。小指だけ長めにとっておくと、少し扱いやすくなるかもしれない。

TAPPING_TERMを細かく調整したいニーズは多いようで、QMKにDynamic Tapping Termという機能も提供されている。有効にしておけば、DT_UPDT_DOWNキーを配置しておくだけで、ドライバの書き換えなしに調整ができる。

TAPPIG_TERMは2種類 (だと良かった)

QMKのTAPPIG_TERMは、設定によってタップを優先したいかホールドを優先したいかが、180度変わってしまう。今から作り直すなら、次の2つに分けてしまいたい(※願望)。

  • TAPPIG_TERM: これ以下をタップ判定 (例. 150ms)
  • HOLDING_TERM: これ以上をホールド判定 (例. 250ms)

なお、前者は、通常の運指スピードより、少しだけ大きい数字を設定する。後者は、ゆっくり目の単打より若干大きい数字を設定することを意図している。

まとめ

残念ながら、前述のような「ふたつのTAPPIG_TERM」設定が、QMKではできない。その部分については独自実装になってしまった。本来であればQMK本体に手を入れて、プルリクエストを送りたいが、様々な設定との整合性をとるのはかなり厄介だ。現状すでに複雑でイシューとドキュメントが混乱気味。そこにさらに複雑さを増す提案を入れるのも気が引ける。若干シンプルにしようという提案も出ているようなので、引き続き様子を見ていきたいと思う。

筆者はカナ打ちなので48キーがちょうどよいというか限界のキー数だけど、英数字のみなら42キーや36キーも視野に入って来る。パズルとしては30キーの配列を考えるのも楽しそうだ。


メモ

なお、もし独自実装を改めて試みるなら、TAPPING_TERMの内側ではなく、外側の処理を追加する方針のほうが、コード量を減らせそうだ。レイヤー切り替えなどにも独自実装が必要だったので、今回その手が使えなかったが、今後の課題。

追加の参考資料

15
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?