よくある備忘録的なにか

自作キーボード、写真メインにその他諸々と

IMEモード誤爆よさようなら !: 自作キーボードならではの解決策

この記事の主題:

今回の記事は、PCを使って日本語の文章を作成する際に発生するIMEモードミスマッチ問題について取り上げ、その解決策の一つを紹介するものです。

現在の課題: 

PCを使った文章を作成する実務的な作業では、意図した入力文字列とPC側のIMEのモードとがマッチせずに、日本語のつもりでローマ字が入力されてしまったり、逆にプログラムで英字で入力するべきところがおかしな日本語になってしまったりすること良くある。ここではこの問題をIMEモードミスマッチ問題と表記する。

このIMEモードミスマッチ問題が発生すると、誤った文字列を消去してIMEモードを設定し直し、改めて同じ文字列を打ち直すという作業が必要となり大きな時間的ロスが発生するとともに作業のストレスとフラストレーションが蓄積すると言った弊害が大きい。 そのためIMEのモードを取り違えず入力が可能なようにすることが重要な課題である。

これまでの取り組み: 

これまでIMEモードミスマッチの発生を防ぐために、マウスカーソル周辺にIMEモードを表示するようなユーティリティを導入すると言ったソフトウェア的なアプローチをとってきた。しかし個人的にはIMEモードを都度確認することが疎かになりがちで決定打にはならなかった。 Windows の場合IMEの状態がデスクトップ内でグローバルに統一されておらずアプリケーションごとにIME状態がバラバラになるというのが大きな原因ではないかと考えている。

今回の取り組み: 

IMEモードを常に把握し続けることが困難であれば、IMEモードを常に自分のコントロールの配下に置けば良いのではないか。というのが今回の取り組みの趣旨である。 その実現のために今回はキーボードのファームウェアレベルでの改善にトライした。 具体的には親指で特定のキーを押下している状態のときはIME ON、 キーを離すと自動的にIME OFFの状態になるようなファームウェアを作成した。 *1

以下にその具体的な事例を示す

前提となる環境:

  • OS :  Windows 11 (macOSLinuxについては今回は言及しないが基本的な機構は十分利用できると思う)
  • IME:  Google日本語入力  (カスタマイズの容易さから普段利用している)
  • キーボード: QMK Firmwareが利用できる自作キーボード。スペースキーが分割されていたり親指専門のモディファイアキーが装備されているものが望ましい。今回は拙作のErgotonic49を使用した *2

実際の例:

static bool lang_key_pressed = false;
static bool lang_mode = false;
static uint16_t lang_pressed_time = 0;

bool process_record_user(uint16_t keycode, keyrecord_t *record)
{
    switch (keycode)
    {
    case KC_LANG8:
        if (record->event.pressed)
        {
            lang_pressed_time = record->event.time;
            lang_key_pressed = true;
        }
        else
        {
            if (lang_key_pressed && (TIMER_DIFF_16(record->event.time, lang_pressed_time) <= TAPPING_TERM))
            {
                // TAPPING_TERM以下でリリースされたら単発キーとして処理
                tap_code(KC_BSPC);
                lang_mode = false;
            }
            else if (lang_mode)
            {
                // IME ON状態ならモードを直接入力に
                tap_code(KC_F15); // 入力中の文字列がある場合は変換
                tap_code(KC_F16); // 変換中の文字列を確定
                tap_code(KC_F17); // IMEをOFF
                lang_mode = false;
            }
            lang_key_pressed = false;
        }
        return false;
        break;
    default:
        // LANGキーが押されている間に他のキーが押されたら
        if (lang_key_pressed) {
            tap_code(KC_F14); // IME ON
            lang_mode = true;
        }
        lang_key_pressed = false;
    }
    return true;
}

解説

QMKのkeymap.c で process_record_user()関数を上書きしキープレス、リリースイベントで特殊な処理を挟み込んでいる。 (なお今回は処理するキーコードは抽象化せず直接書いている。また 個人のIME環境で各キーの動作を定義してある)

  • 短い時間で KC_LANG8 キーをタップした場合:

    KC_BSPC(BACKSPACEキー)を送信

  • 一定時間より長い間 KC_LANG8を ホールドした場合:

    日本語入力を開始可能な状態に遷移

一定時間y彫り長い間KC_LANG8をホールドした後 任意のキーが押された場合

KC_F14 を送信 (F14キーは個人環境でIME ON)
  • ホールド状態から KC_LANG8をリリースした場合:

    KC_F15,KC_F16,KC_F17を順に送信 (IME OFF処理)

IME Off処理では次のことを行っている

  •   F15:  入力途中の文字列がある場合は変換
  •   F16:  変換途中の文字列を確定
  •   F17:  IME OFF

このIME OFF処理のコンビネーションにより、よく使う入力文字であれば変換キーを使うことなく、LANGキーをリリースするだけで目的の文字列を確定させることができる。

キーボードの物理的な面: 

日本語を入力する間、キーを押下しっぱなしにするのは通常のキーボードでは難しいかもしれない。 この方策を試す場合自作キーボードでよく見る親指拡張キーがあるキーボードが望ましい。

下図はErgotonic49を用いた筆者のレイアウトである

HOLD処理とTAP処理を一つのキーにアサインしているのは貴重な親指キーを有効に活用するためである。 親指周りのキーは特等席であり、既に重要な機能が定義されていることが多いと思う。  私も親指周りのキーはSpace,Ctrl,Enter,BSなど重要なキーバインドを割り当てておりそこにIMEモードキーを割り込ませるには葛藤とトレードオフが必要であった。

評価

IMEのモードが混乱しなくなったことは非常に有用であると感じる。IMEモード誤爆がどれほどストレスであったかが改めて身にしみる。   反面、未だ慣れていないため入力の行動にもたつきが出るのは今後慣れていくしか無いところではある。  日本語文字列入力中に親指が特定のキ押下しっぱなしにしなければいけないため手にやや負担がかかる。今後IMEモードキーを専門的に利用可能なレイアウトのキーボードを設計してみるのもよいだろう。

今回紹介したIMEモードミスマッチ問題の対策は、自作キーボードを愛好している人にとってはそれほど難易度が高くないカスタマイズと思う。興味を持ったら是非トライしてみてもらいたい。

  

*1:このアイデアはねっとサーフィン中に見つけたブログサイトに記載されていた基本的なアイデアを借用しオリジナルの実装を行いました。ただ元URLがわからなくなっているので見つけたら記載します

*2:ちょっと変わったキーボードErgotonic49の解説 https://coal.hatenablog.com/entry/2021/11/01/230327