こんにちは、びしょ〜じょです。

最近『教皇選挙』を観ました。 お前は観たか? 観たほうがいいぞ。

内容○、画○、音響○なんで、キリスト教世界観分かるパーソンだったら更に面白く観られる気がします。

1. はじめに 材料調達部門

頭がおかしくなってキーボードを買った。

  • ファームウェアはqmk
  • いわゆる40%分割型
    • 数字キーが無い
  • ビカビカ光る
  • ホットスワップ
    • ソケットはすでに着いてるのでキースイッチ(別売)を刺すだけ

というのが特徴。 数字キーいらねえんじゃねえのとなって、こうなった。 ErgoDox EZからの乗り換えになる。

サイズ比較 図1.1. サイズ比較。手前がCorne、上の黒いのがErgoDox EZで白いのがMoonlander

キースイッチはKailhのChoc v2 Deep Sea Silent Isletという結構新しいやつを買った。

HHKBみたいな、少しザラっとしてるけど滑らかな静音リニアで気持ちがいい。 流通が少なそうなのがネック。

親指で押すキーは軽くしたいのでChoc v1のピンク軸にした。 v1とv2はソケット互換があるのでどちらも使える。一方キャップに互換はない。

めちゃ軽く手への負担は少ないが、Isletが静音すぎて相対的にカチャカチャ音が気になるのが玉に瑕。

2. qmk_firmware 小テク集

xmodmapでキーマップを変更していた10年以上前から入力の歴史は続いており(中略)(攻略)。 ErgoDox EZのキーマップをベースにした。

keyboard controller firmware for Atmel AVR and ARM USB families - Nymphium/qmk_firmware

キーボードがだいぶ小さくなったんで、マウス操作レイヤーと数字操作レイヤーを追加する。 shift+数字も変更したいので、それ用のレイヤーも追加する。

2-1. tri layer

LOWERレイヤーでの入力にshift modifierを適用したい場合、ナイーブにシフトキーだけ押すとうまくいかない。 うまくいかないんで、 layer_state_set_user関数内でupdate_tri_layer_stateを使って複数レイヤーをまたぐ場合のルールを登録する。

Documentation for QMK Firmware
ckeymap.c
layer_state_t layer_state_set_user(layer_state_t state) {
    state = update_tri_layer_state(state, _LOWER, _SHIFT, _LSHIFT);
    state = update_tri_layer_state(state, _NUM, _LOWER, _NMODS);
    return state;
}
図2.1. `update_tri_layer_state` の使い所さん

Shiftキーを押したときに_SHIFTレイヤーに移行すればよい。 このとき_SHIFTは何も登録してないレイヤーでよい。

これで、

  • _LOWERかつ_SHIFTのとき、_LSHIFTレイヤーに移行
  • _NUMかつ_LOWERのとき、_NMODSレイヤーに移行

する。 ちなむとcomboもうまくいかない。switching layer系の組み合わせもうまくいかない。 皆さんも諦めるか、smarterな解法があったら教えて下さい。

2-2. key override

QMKを触っていると人々はレイヤーがサァ! とか色気づくんだけど、modifier key+key→別のキーに変換というナイーブな機能がある。

Documentation for QMK Firmware
c keymap.c
const key_override_t *key_overrides[] = {
    &ko_make_basic(MOD_MASK_SHIFT, KC_0, JP_QUES),
};
図2.2. key overrideでShift+0→`?`を出す

Shift+0で?が出てくるようになる。 ちなみに俺は普通のキーボードでShift+0すると何が入力されるのかもう覚えてない。

2-3. マウス中クリック/ホイール

マウスホイールの中クリックを皆さん使っているか? ブラウザのリンクを中クリックすると新しいタブで開いたり、タブを中クリックするとcloseしたりする優れモノです。

qmk_firmwareはマウスエミュレーションができる。

Documentation for QMK Firmware

QMKと中クリックは人生のテーマだったんですが、

cprocess_record_user.switch in keymap.c
case MIDDLE:
    if (record->event.pressed) {
        register_code(KC_BTN3);

        WAIT_PRESSING(record);

        unregister_code(KC_BTN3);
        layer_on(_WHEEL);
    } else {
        layer_off(_WHEEL);
    }
    return false;
図2.3. 中クリック/ホイールの実装(incorrect)

プログラム2.3だと先中クリックが入力されるため、ホイール操作だけしたいのに変にリンクを開いたりしてしまい、Webサイトのスクロールできるtable of contentsでスクロールするつもりがうっかり別タブを開いてしまう事故が多々おきた。

鬼の努力は実はたった1行で解決できる。

ckeymap.c
#define MIDDLE LT(_WHEEL, KC_BTN3)
図2.4. 中クリック/ホイールの実装(correct)

これをkeymapで呼ぶだけ。

Documentation for QMK Firmware

ドキュメントはちゃんと隅々まで嫁ってことですな…w

2-4. レイヤー数増やす

cconfig.h
#undef DYNAMIC_KEYMAP_LAYER_COUNT
#define DYNAMIC_KEYMAP_LAYER_COUNT 9
図2.5. レイヤー数を増やす

はいこれです。 これを書かずに7以上のレイヤーを定義するとコンパイラが「DYNAMIC_KEYMAP_LAYER_COUNT は6や!!」と怒ってくるので、察せられます。

3. マウスtips

多分世の中には多くのqmkマウスエミュレーション愛好家がいると思うんですが、私もその一人でしてェ…。

Documentation for QMK Firmware

一旦こうなっている。

cconfig.h
#define MK_KINETIC_SPEED

#undef MOUSEKEY_DELAY
#define MOUSEKEY_DELAY 0
#undef MOUSEKEY_INITIAL_SPEED
#define MOUSEKEY_INITIAL_SPEED 80
#undef MOUSEKEY_MOVE_DELTA
#define MOUSEKEY_MOVE_DELTA 8
#undef MOUSEKEY_BASE_SPEED
#define MOUSEKEY_BASE_SPEED 2200

#undef MOUSEKEY_WHEEL_DELAY
#define MOUSEKEY_WHEEL_DELAY 3
#define MOUSEKEY_WHEEL_INTERVAL 40
#define MOUSEKEY_WHEEL_MAX_SPEED 12
#define MOUSEKEY_WHEEL_TIME_TO_MAX 16
図3.1. マウスのパラメータ〜

Kineticモードはカーソルの速度がquadratic curveで加速するため、最大速度から逆算すると初動からしばらく小さく動けるので、繊細に動かせるし遠くに動かしたいときも困らない。 MOVE_DELTAで加速度合いを変更し、BASE_SPEED まで (BASE_SPEED - INITIAL_SPEED) / MOVE_DELTA millisecかけて加速していく。

結局この辺は好みなんで快適な数値を探してください(爆)

4. おわりに

いかがでしたか?

ちなみに第1話はない。

5. おまけ

ありすぎだろ

TEXシリーズはYodaからぼちぼち買ってるので愛着がある。 奥にあるLogiのG515もG HBUという専用のソフトウェアでレイヤー機能や様々なカスタマイズができるんで使い勝手がよい。

なんとなくほしいな〜とかゲームしたいな〜となると、増えてしまうわけですね。