自作キーボードで思ったのと違う記号が出るとき
Tech自作キーボードにありがちなトラブルの一つ、「思ったのと違う記号が出る」についてまとめたい。
スキャンコード
パソコンでは文字に番号が振られている、というのは知っている人も多いだろう。例えば半角大文字「A」はUnicodeではU+0041という番号が振られている。
が、キーボードがコンピュータに送る番号は実はこれではなく、スキャンコードと呼ばれる別の体系が使用されている。
スキャンコードにもいくつかの種類があるが、ANSI/JISのいずれでもAのスキャンコードは31だ。続く32はB…ではなく、Sを意味する。なぜか?それは、QWERTY配列でAの隣がSだからだ。A, S, D, F...が31, 32, 33, 34...のように振られているのだ。
問題は記号類のスキャンコードで、ANSI仕様とJIS仕様で一致していない部分が多々あるのだ。これはいわゆる英語キーボードと日本語キーボードで記号の位置が違うことに起因する。例えばスキャンコード「27」はPの右のキーに対応するが、ここには英語キーボードだと「[」、日本語キーボードだと「@」が描いてある。キーボードがスキャンコード「27」を送信してきたとしても、それがどういうつもりなのかは受信するコンピュータ側では一意に判定することができない。
そこで、各OSでは設定画面でキーボードの種類を選択できるようになっている。↓こういうやつね。
これで、キーボードの設定が日本語(JIS 106/109)ならスキャンコード27は「@」、英語(ANSI 101/104)にした場合は「[」のつもりなんだな、とコンピュータは判断できる。
(※2024/03/29 Macのキーボード設定だが、なんか効かないことがあるっぽい?再起動とかしないとだめなのかな…)
Shiftキー
Shiftを押したときはどうだろうか。スキャンコードはキーに対応するものなので、大文字小文字の区別はない。Aのスキャンコードである31を送信するとたいていの場合、小文字のaが入力されるだろう。大文字を入力したいときはだいたい、Shiftを押しながらAを押すだろう。
Shiftキーにはまた別途スキャンコードが割り当てられていて(「左Shift」44、「右Shift」57。幸いJISでもANSIでも同じ)、押した・離したをコンピュータに伝えられるようになっている。コンピュータはそれを見て「いまShiftが押されているか」を判断し、入力する文字を大文字と小文字で切り替える。つまりAのスキャンコード31は、Shiftなしなら小文字a、Shiftありなら大文字A、を意味しているともいえる。
記号類はここでも問題で、たとえばセミコロン「;」のスキャンコードは40だが、Shiftを押しながらこのキーを押したときの意味はANSIとJISで違う。ANSI(英語キーボード)だと「:」、JIS(日本語キーボード)だと「+」だ。
スキャンコードを勘違いするとどうなるか
キーボードが送信するスキャンコードと、コンピュータが解釈するスキャンコードが違っていたらどうなるだろうか。例えば、JIS(日本語)のスキャンコードを送っているのにANSI(英語)のスキャンコードだと判断された場合、以下のようになる。
押したキー | 入力される文字 |
---|---|
^ |
= |
@ |
[ |
[ |
] |
: |
' |
半角/全角 |
` |
] |
\ |
Shift + 2(" のつもり) |
@ |
Shift + - (= のつもり) |
_ |
Shift + ^ (~ のつもり) |
+ |
Shift + @ (「`」のつもり) |
{ |
Shift + [ ({ のつもり) |
} |
Shift + ; (+ のつもり) |
: |
Shift + : (* のつもり) |
" |
Shift + ] (} のつもり) |
` |
逆にいうと、以下のように設定すればだいたい期待通りになる(もちろんキーボード設定を正しくするのが一番いいが)。
入力したい文字 | 設定するキー |
---|---|
^ |
= + |
@ |
[ { |
[ |
] } |
: |
' " |
半角/全角 |
` ~ |
] |
`\ |
" |
Shift + 2 @ |
= |
Shift + - _ |
~ |
Shift + = + |
「`」 | Shift + [ { |
{ |
Shift + ] } |
+ |
Shift + ; : |
* |
Shift + ' " |
} |
Shift + `\ |
問題は「\」で、これのJISスキャンコードは56なのだが、ANSIスキャンコードで56をもつキーが存在しないのだ。qmk_firmwareの場合はJP_BSLS、またはそのエイリアス先であるKC_INT1、またはそのエイリアス先であるKC_RO(まだ使えるのかな?)、またはその本名であるKC_INTERNATIONAL_1、またはその実際の値である0x87がこれを意味するので、ツールによってはこのどれかが使えるかもしれない。
あるいは環境によっては「¥」でうまくいくかもしれない。JISスキャンコードは13、同じくANSIには存在しないが、qmk_firmwareではJP_YEN, KC_INT3, KC_JYEN(これは古いqmkだけ?), KC_INTERNATIONAL_3, 0x89のような値になっている。
各ツールでのスキャンコード
自作キーボードの場合、どのようなスキャンコードが送信されるかは使用するツールによる。
- REMAP
- 日本語(JIS 106/109)のスキャンコードが送信される?
- VIAL
- ?
- VIA
- ?
- QMK手書き
- 基本、ANSI 101/104のキーコードが送信される
- 「Pの右のキーを押したら@が入力されるようにしたい」ときどうすればよいか
- a) キーボード設定を英語(ANSI 101/104)にし、キーマップに
S(KC_2)
と書く- ANSIキーボードではShift + 2が@なので
- b) キーボード設定を日本語(JIS 106/109)にし、
#include <keymap_japanese.h>
して、キーマップにJP_AT
と書く- その他のキーコードはkeymap_japanese.hを参照
- (余談:昔はkeymap_jp.hという名前だった)