🎱

僕のKeyball44のキーマップを紹介します

2024/12/14に公開

Keyball44を使いはじめて三ヶ月ほどが経過しました。仕事用のWindows環境とプライベートのmacOS環境で使いつつキーマップの試行錯誤をしてきましたが、少し落ち着いてきたので現状のキーマップについてまとめます。

レイヤ構成

レイヤをひとつ増やして5レイヤ構成にしています。

config.h
#define DYNAMIC_KEYMAP_LAYER_COUNT 5

それぞれのレイヤを以下のように使っています。

  • レイヤ0: アルファベットと各種Modifier、マウスボタン1、レイヤ1〜3の有効化
  • レイヤ1: 数字、記号、矢印
  • レイヤ2: レイヤ1の数字と記号にShiftを付加したもの、ファンクションキー、マウスボタン2
  • レイヤ3: マウスホイール左右、OS固有のショートカットキー、レイヤ4の有効化
  • レイヤ4: キーボード設定

デフォルトレイヤ(レイヤ0)

デフォルトレイヤの中央の3行x10列(左10列+右10列)の部分はqwertyの普通の配列です。この領域を慣れた配列にしているので、キーキャップを他のレイヤの割り当てを表すのに使うことができます。また、使用頻度の高いこの領域にはMod-Tapの設定は入れておらず、意図せぬHold判定による入力取りこぼしの心配なく、安心して打鍵できるようにしています。

外側のキーのHoldで他のレイヤへの切り替えができるようにしています。

  • LT(1, *)を左手親指と右手右上に配置
  • LT(2, *)を右手親指と左手左上に配置
  • 左手親指の一番はじっこにMO(3)を配置

CtrlとShiftを左右対称に配置しています。CtrlはMod-Tapで

  • 左手のaの左:Tapで Esc、HoldでCtrl
  • 右手の;の右:Tapで -、HoldでCtrl

としています。Shiftは左下、右下にMod-Tap設定せずに専用のキーを割り当てています。Tap操作でも副作用なくスクリーンセーバーの解除とかができるように。

ブラウザやエディタの表示の拡大縮小で使うので - の上に = (+) を配置してデフォルトレイヤに含めています。どちらを上にするかは悩みましたが

  • 高さをイメージすると + の方が - よりも上(温度計のイメージ)
  • レイヤ3の同じ位置にmacOSの音量調整を配置しているが Up を Down より上にしている(Down の下は Mute)
    • MacBook Airの内蔵キーボードは Mute(F10)、Down (F11)、Up (F12) の順で Up の方が中心から見て遠い
  • US101だと横並びで -+ の順で、中心から見て + の方が遠い

をふまえて上から = (+), - の順にしています。なお、

  • US101だと 0 のすぐ右が -
    • レイヤ0の p の位置にレイヤ1で 0 を割り当てている
  • JP109だと 0 のすぐ右が -で、+ はその二段下

なためか、時々逆の操作をしてしまうことがあります。そのうち慣れると思いたい。

OS検出によるAltとCmdの入れ替え

左上にTabを配置。WindowsのAlt+Tab、macOSのCmd+Tabによるアプリケーション切り替えを多用するので、OS検出してAltとCmdを切り替えるようにしています。詳細は別の記事にまとめました:

https://zenn.dev/yoichi/articles/qmk-swap-keys-by-os

ボタン1のキー割り当て

AML(auto_mouse_layer)は無効にして、デフォルトレイヤで左親指のところにマウスボタン1(KC_BTN1)を割り当てています。マウスボタンの扱いについても別の記事としてまとめています:

https://zenn.dev/yoichi/articles/keyball-and-mouse-button

TAPPING_TERM

Mod-TapのHoldと判定される閾値をデフォルトの200msから180msに変更しています。値が大きすぎるとHoldのつもりがTapになってModifierが効かなかったり、逆に小さすぎるとTapのつもりがHoldになって文字入力の取りこぼしが発生します。しばらくデフォルトのままで使っていましたが、キーボードに慣れ打鍵スピードが上がったことでModifierが効かないことが出てきたので値を少し小さくしました。

config.h
#define TAPPING_TERM 180

レイヤ1

デフォルトレイヤの次によく使うキーを配置しています。一部のキーキャップはこのレイヤのキー割り当てに合わせており、記憶だけに頼らなくてよいようにしています。

  • 数字キーをレイヤ1の上段の中央10列に1, 2, ..., 9, 0と並べている
    • 通常のキーボードの上段の数字キーと同じ並び
    • キーキャップは数字キーのものにしている。間違って一列ずれて打鍵することがあり、いざとなれば見て補正できるように
  • デフォルトレイヤに入りきらなかった記号` [ ] ' \ を押しやすい真ん中あたりに配置している
    • キーキャップはfキー以外はレイヤ1の記号に合わせている。配置を忘れても見れば確認できるように
    • f のキーキャップは突起があるのでそのまま使っているが、US101と同様に [] が隣り合っており ] の左の f の所は [ と連想できる
  • 矢印キーの配置はnethackやvimで慣れている h j k lの位置に を割り当てることで、新たに覚えることを減らしている
    • 矢印にModifierを付加したOS固有のショートカットキーをレイヤ3に配置している
  • デフォルトレイヤの ,. の位置はレイヤ1では透過としている。小数を入力するときなどでレイヤ切り替えせず入力できるように
  • 同様にレイヤ1のキー入力ミス時にレイヤ切り替えせず修正できるよう、Backspace も透過にしている
  • 親指のところにHomeとEndを割り当てているのに加え、Shiftを付加したHomeとEndを左手側に配置している
    • 行頭までのテキスト選択、行末までのテキスト選択をするときにShiftを加えた3キー同時押しをしなくていいように
    • 選択範囲調整用にはこれと合わせてレイヤ3にShift+矢印を割り当てている

レイアウトミスマッチへの対策

左手のRo(KC_INT1),¥(KC_INT3)は普段使うことはない(US配列になっている場合押しても何も入力されない)のですが、キーボード設定が日本語配列になっていた場合に _ とか | を入力できず、にっちもさっちも行かなくならないように割り当てています。詳細は別の記事にまとめました:

https://zenn.dev/yoichi/articles/keymap-that-allow-recovery-from-layout-mismatch

レイヤ2

レイヤ1の数字と記号にShiftを付加したものをレイヤ2の同じ位置に配置しています。Shiftを入れた3キー同時押しではなく2キー同時押しで入力できるように。

  • 左手側にマウスボタン1,2を配置している
  • マウスボタン4,5を一時期配置していたが、誤って破壊的操作をしてしまうことがありやめた
    • ブラウザの戻る、進むが意図せず発動し、入力中フォームの内容を失うことがあった
    • 入力デバイスとして独立したマウスのボタンではなく、キーでボタンを実現しており間違えやすい
    • ブラウザの戻る、進むは一手間かければmacOSならCmd+←、Cmd+→、WindowsならAlt+←、Alt+→で実現できる
  • ファンクションは数字と同じ並べ方で左から左手側にF1〜F5、右手側にはF6〜F10、F11を配置(左手側は下段、右手側は中段)
  • 右手側と左手側でファンクションキーの段がズレているのはレイヤ1との兼ね合いによる
    • レイヤ1とレイヤ2の記号の位置を合わせたい
    • レイヤ1において矢印キーは憶えやすく押しやすいhjklにしておきたい
    • より使うキーを押しやすい中央付近になるべく配置したい
  • F11を含めているのはアプリの全画面表示で使うため

レイヤ3

Keyballではレイヤ3でトラックボール操作すると上下スクロールができます。マウスキーを有効化した上でレイヤ3の親指キーにホイールの左右(KC_WH_L, KC_WH_R)を割り当てています。

rules.mk
# Enabled for KC_MS_WH_*
MOUSEKEY_ENABLE = yes

配置の工夫として、レイヤ1のHOME、ENDとレイヤ3のホイール左、右でレイヤキーとの位置関係が似た感じになるようにして認知負荷を下げています。

Keyballではスクロールスナップの切り替えによりトラックボールで左右スクロールもできるのですが、切り替えが面倒なのと元に戻すのを忘れて混乱することがあったので、左右スクロールはキー操作で行うことで落ち着きました。

レイヤ3の上の方にmacOS向けのショートカットキーを配置しています:

  • 最上段の Cmd+1 〜 Cmd+9 はmacOSのターミナルやブラウザのタブの切り替え用
    • 1番目のタブ、2番目のタブ、…、8番目のタブ、最後のタブ
    • タブはアプリケーションウインドウの上の方にあることから連想できるよう上段に配置
    • Shiftと(Cmd+4)を合わせるとスクリーンショットを撮れる
  • 右側のCtrl+矢印はmacOSのMission Controlとデスクトップ切り替えで使う。配置はhjklに合わせている
  • 右側の右端の方にmacOSの画面輝度調整、音量調整を割り当てている
    • Pause=Brightness Up、ScrollLock=Brightness Down

レイヤ3の下段にWindows向けのショートカットキーを配置しています:

  • 左側下段の Win+1 〜 Win+4 はWindowsでタスクバーにピン止めしたアプリの起動用
    • タスクバーは画面下に表示していることから連想できるよう下段に配置
  • 右側下段のWin+矢印はWindowsのウインドウ最大化など
    • 矢印の並びは一段上のhjklに合わせている。
    • Shiftと合わせるとウインドウの別のディスプレイへの移動

OSによらない部分:

  • レイヤ4を有効化するMO(4)を左上に配置
  • 文字列選択範囲の調整用のShift+矢印を左側に配置

IME切り替え用キー

右親指のUser 0はIMEの切り替え用にしており、OSによって発行するキーコードを切り替えています。

keymap.c
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case QK_USER_0:
            switch (detected_host_os()) {
            case OS_WINDOWS:
                if (record->event.pressed) {
                    register_code16(RALT(KC_GRV));
                } else {
                    unregister_code16(RALT(KC_GRV));
                }
                return false;
            case OS_MACOS:
                if (record->event.pressed) {
                    register_code16(G(KC_SPC));
                } else {
                    unregister_code16(G(KC_SPC));
                }
                return false;
            }
            break;
    }
    return true;
}
  • WindowsならAlt+`に、macOSならCmd+Space※になるようにprocess_record_user()で処理している
  • ※前の入力ソースを選択。macOSのデフォルトではCtrl+Spaceだが、Emacsのset-mark-commandと被るのでOS設定を変えている
  • macOSのデフォルトのショートカットCtrl+Spaceのままであれば G(KC_SPC) としている所を C(KC_SPC) とすればよいはず

OS検出によるスクロール方向の切り替え

トラックボールおよびマウスーのホイール操作のスクロール方向をWindowsとmacOSで揃えるため、スクロール方向の反転機能を実装し、OS検出して切り替えるようにしています。詳細は別の記事にまとめています:

https://zenn.dev/yoichi/articles/qmk-swap-keys-by-os

レイヤ4

キーボードの動作を変える設定系のキーはレイヤ4に配置し、レイヤ4をオンにするにはレイヤ3を経由せねばならないようにしています。デフォルトのキーマップだと設定系はレイヤ3に配置されていますが、意図せず触ってしまって動作が変わって混乱することがあり、それを避けるために到達するまでの手数を増やしました。

  • LEDを付けていないのでRGB_*は割り当てしていない
  • Swap/Unswapのキー割り当てをしているが、OS検出で切り替えしてるので普段は使わない
  • Kb何とかはKeyball固有の機能が割り当たっている。詳細は特殊キーコードを参照
  • AMLは config.h の POINTING_DEVICE_AUTO_MOUSE_ENABLE 定義を外し無効化しており、AML_* (Kb 10〜12)は割り当てしていない
  • 横スクロールはレイヤ3のマウスホイール左右を使うので普段SSNP_* (Kb 13〜15)を使うことはないが、割り当ては残している
  • ファームを改造して縦横のスクロールの向きを反転できるようにしており、それを制御するためのKb 16〜17を割り当てている
  • CPIとスクロール除数は keyball.h のデフォルト値定義を好みの値に変えており、CPI_* (Kb 2〜5) SCRL_DV* (Kb 8〜9) は割り当てているが普段は使わない
keyball.h
#ifndef KEYBALL_CPI_DEFAULT
#    define KEYBALL_CPI_DEFAULT 1600
#endif

#ifndef KEYBALL_SCROLL_DIV_DEFAULT
#    define KEYBALL_SCROLL_DIV_DEFAULT 7 // 7: 1/64 (1/2^(n-1))
#endif

まとめ

キーマップの試行錯誤をしつついろいろな工夫をしました。

  • 認知負荷を下げる:規則性や対称性で記憶、連想を補助する
    • 標準的な配列に合わせる、似せる(qwerty、数字やファンクションの並び)
    • Shift付きは次のレイヤの同じ位置に
    • キーキャップで記憶を補助
    • 左右の対称性を持たせる(Ctrl、Shift)
    • OS間の違いを吸収(Cmd <-> Alt、入力言語切り替え)
  • 操作性を担保する:無理やミスを減らす
    • Modifierを両側に配置し指使いの無理をなくす
    • Modifier付きのキーを割り当て同時押しの数を減らす
    • 別レイヤの同じキーの操作と致命的な違いを避ける
    • 破壊や混乱を招く操作の手間を増やす

具体的な対処は私の癖や環境に依存する部分がありますが、「認知負荷を下げる」、「操作性を担保する」という2つの視点はキーマップを育てる際の一般的な指針になると思います。

Discussion