Keyboard Quantizer をマウスに使う

Posted on Jul 28, 2021


前にも書いた気もしますが、今は、KVM スイッチャー使って、1 セットのモニター・キーボード・マウスで複数のパソコンを切り替えながらお仕事してます。

で、ずっと気になってたのが、Windows と Mac でのマウスの挙動の違いというか、エレコム製マウス・トラックボールの Mac 用ドライバーのしょぼさ)。

もうちょっと細かく書くと、

てな感じ。

ま、作業できなくはないので、放置してたんですが、この度、せきごん氏の Keyboard Quantizer を導入して、解決できるか試してみました。

Keyboard Quantizer

Keyboard Quantizer っていうのは、キーボードやマウスのアダプターとして使うもので、このアダプター上で、キーボードなりマウスなりの入力を変換してしまいましょう、っていう製品。ユーザーがファームウェアを書き換えられないような普通のキーボードなんかでも、レイヤー機能をついかしたり、キーマップ変えたりできる、っていう代物です。

使い方はちょっと複雑でしたが、ビルドガイドにのっとり、

  1. Bootloader を焼く
  2. ホスト用のファームウェアを焼く
  3. 実際にキー改変するファームウェアを焼く

っていう、3つの行程を経て準備完了。

半年くらい前に買ったときには、マウス用のファームウェアなかった気がしますが、今は、サンプルが用意されています。

実際にやりたいこと

最初にちょっと書きましたが、やりたいことは、以下の3つ。

  1. Windows/Mac でそれぞれ別のレイヤーを作成し、ボタンでレイヤーを切り替える。
  2. Mac 用のレイヤーでは、ボタン 4 ~ ボタン 8 に、「戻る(GUI + [)」、「進む(GUI + ])」、「左作業スペース(Ctrl + LEFT)」、「レイヤー切り替え」、「右作業スペース(Ctrl + RIGHT)」をそれぞれ割り振る
  3. Mac 用のレイヤー時には、スクロールの向きを変える

ちょっと悪戦苦闘しましたが、無事実装。

1 と 2 に関しては、こんな感じで実装しています。

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = {{KC_BTN1, KC_BTN2, KC_BTN3, KC_BTN4,       KC_BTN5,       KC_NO,         TG(1),   KC_NO        }},
    [1] = {{_______, _______, _______, LGUI(KC_LBRC), LGUI(KC_RBRC), LCTL(KC_LEFT), _______, LCTL(KC_RGHT)}},
};

3 に関しては、今いるレイヤーを認識したうえで、V 方向の向きを変える、ってので実装してみました。

void mouse_report_hook(mouse_parse_result_t const* report) {

    //中略

    mouse.x += report->x;
    mouse.y += report->y;
    mouse.h += report->h;

    if (IS_LAYER_ON(1)) {
        mouse.v -= report->v;
    } else {
        mouse.v += report->v;
    }

    pointing_device_set_report(mouse);

}

ジェスチャー実装(2021-07-31 追記)

当初はスクロールの向きかえたり、ボタンに機能割り当てたり、ってのを想定してたんですが、折角なのでジェスチャーも実装してみました。

実装した機能としては、こんな感じ。

  1. 戻るボタンを押しながら、カーソルを左右に一定以上動かすと、作業スペース切り替え
  2. 戻るボタンを押しながら、カーソルを上に一定以上動かすと、Launchpad 起動して、アプリへアクセス
  3. 戻るボタンを押しながら、カーソルを下に一定以上動かすと、動作してるアプリ一覧表示
  4. 戻るボタンを押して、カーソルを動かさずにボタンを話すと、戻るボタンとして動作

具体的にはこのレポジトリを見てもらえばいいんですが、簡単に説明すると、まず、戻るボタンが押されたタイミングでフラグを立てる。

static void gesture_start(void) {
    dprint("Gesture start\n");
    gesture_wait   = true;
    gesture_move_x = 0;
    gesture_move_y = 0;
}

bool process_record_user(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {

	    // 中略

	    case GEST:
            if (record -> event.pressed) {
                gesture_start();
            } else if (gesture_wait) {
                tap_code16(LGUI(KC_LBRC));
                gesture_wait = false;
	        }
            break;

        // 中略
}

次に、マウスが動くたびに、移動距離を測定し、一定以上動いたら、各機能を発動。非常に簡単。

void process_gesture(void) {

    recognize_gesture(gesture_move_x, gesture_move_y);

    switch (gesture_id) {
        case GESTURE_UP:
	    tap_code16(LCTL(KC_UP));
	    gesture_wait = false;
	    break;
	case GESTURE_DOWN:
	    tap_code16(LCTL(KC_L));
	    gesture_wait = false;
	    break;
	case GESTURE_LEFT:
	    tap_code16(LCTL(KC_LEFT));
	    gesture_wait = false;
	    break;
	case GESTURE_RIGHT:
	    tap_code16(LCTL(KC_RGHT));
	    gesture_wait = false;
	    break;
	case GESTURE_NONE:
	    break;
	default:
	    break;
    }
}

void mouse_report_hook(mouse_parse_result_t const* report) {

    // 中略

    // Save movement to recognize gesture
    //
    if (gesture_wait) {
        gesture_move_x += report->x;
        gesture_move_y += report->y;
	    process_gesture();
    }
}

実際につかってみて

実装したとおりに動いていて、なかなかにナイスです。ちょっと高度なことも簡単に実装できますし。エレコムのあれなドライバーとはおさらばです。

ただ、Quantizer 経由だと、マウスのカーソルがちょっとカクカクになってしまいます。がくっと解像度が落ちた感じ。ファームウェアいじって改善できるんでしょうかね。 どうやら、マウス/トラックボールとの相性があるみたいです。手持ちのマウスをささっと調べてみたかぎり、こんな感じ。もし、M-DT2DR を試した人がほかにいれば、ぜひ結果教えてください!

メーカー製品結果
ELECOMM-DT1DR正常
ELECOMM-DT2DRカーソルがカクカク
LogicoolM350正常

てな感じで、今日はここまで。


comments powered by Disqus