|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.10! root 7: //
! 8: // キーボード (基本クラス)
! 9: //
! 10:
1.1.1.5 root 11: // 物理キーボードとソフトウェアキーボードについて
12: //
13: // 物理キーボード入力 ---------->+
14: // OR --> VM Keyboard ---> VM (MFP/SIO)
15: // ソフトウェアキーボード 入力 ->+ |
16: // |
17: // ソフトウェアキーボード 表示 <-------------+
18: //
19: // 物理キーボードとソフトウェアキーボードからの入力は並列で対等とする。
20: // つまり優劣を付けず後から成立したイベントで現在の状態を上書きする。
21: // これは特に物理キーボードから [ALT]+[TAB] でウィンドウを切り替えた際に
22: // [TAB] の Make は発生するが Break が VM に届かない (そのため高速モード
23: // が抑制されたままになる) という事態をソフトウェアキーボードから復旧する
24: // ために必要。
25: //
26: // 例えば、ソフトウェアキーボードであるキーを(右クリックで)長押ししたまま
27: // (A)、物理キーボードで同じキーを押して(B)離す(C)と、まず A で Make が
28: // 成立、B は無視して (この時点ですでに Make 状態なので)、C で Break が
29: // 成立、となる。
30: // Break が成立したのでソフトウェアキーボードの描画上もキー開放になる。
31: // 逆に物理キーボードであるキーを押したまま(A)、ソフトウェアキーボードで
32: // 同じキーをクリックする、つまり押して(B)離す(C) と、まず A で Make が
33: // 成立、B は無視され、C で Break が成立までは同じだが、引き続き物理キー
34: // が押されたままならおそらくホストの動作によってもう一度 Make が入ること
35: // になる。この動作は(望ましいかどうかはともかく)仕様として許容する。
36: //
37: // また、ソフトウェアキーボードの表示は上図の通り、ソフトウェアキーボード
38: // 自身(のみ)の状態ではなく VM Keyboard 全体の現状を表示する表示器とする。
39:
40: // SHIFT キーについて
41: // 物理キーボード層、ソフトウェアキーボード層、VM の Keyboard クラスは
42: // いずれも左右の [SHIFT] キーは別個のキーとして管理しているが、X680x0 の
43: // キーボードは左右の [SHIFT] キーが独立しておらず一つのキーのように
44: // 振る舞っている(はず)。
45: //
46: // ヒューマンインタフェース的には例えば、
47: // 物理キーボードで 左[SHIFT]押下(A) -> 右[SHIFT]押下(B) -> 右[SHIFT]開放
48: // (C) -> 左[SHIFT]開放(D) の順で操作すると、A で Make が成立、B は無視
49: // ([SHIFT] はすでに押されているので)、C は無視([SHIFT] はまだ押されてる
50: // ので)、D で Break が成立、となってほしい。これは明らかに人間がそのように
51: // キーを操作しているため。
52: // 一方、ソフトウェアキーボードでは、右[SHIFT]を右クリック(押下維持)する
53: // と両方の [SHIFT] キーが点灯する。この状態で左[SHIFT] を左クリック
54: // (押下後即開放)すると、両方の [SHIFT] が開放されてほしい。これは、
55: // ユーザからはどちらのキーが押下維持で点灯していて、どちらが押されてない
56: // のに付随点灯しているかは区別できないため。
57: //
58: // このことから、
59: // o 物理キー入力は左右 [SHIFT] を区別する
60: // o ソフトウェアキーボードは左右どちらのキーに対する操作でも、内部では
61: // 左右両方の [SHIFT] を押下開放する
62: // o この結果、右 [SHIFT] と左 [SHIFT] の OR を代表値とし、
63: // MFP への通知や表示(左右の [SHIFT] は常に連動) を行う。
64: // でどうか。
65: //
66: // 物理 [SHIFT] キーを押し続けたまま、ソフトウェアキーボードから左クリック
67: // (押下後即開放) すると、物理キーを押しているにも関わらず [SHIFT] キーは
68: // 開放される。これは上述の通り仕様である。
1.1.1.9 root 69: //
70: // LUNA のキーボードは左右の SHIFT キーの区別がある。このため、 LUNA は
71: // 特別処理をする必要はない。
72: // ただしゲスト上の入力ルーチンがこの区別をしているかは別問題である。
73:
74: // 処理の流れ (SendStart まで)
75: //
76: // MakeKey(), BreakKey() までは基本的に VM スレッドに処理を渡すだけ。
77: //
78: // UI スレッド : VM スレッド
79: //
80: // キャラクタ入力 :
81: // |
82: // 直接キー入力 | :
83: // | v
84: // | CharInput() :
85: // | |
86: // +------------+ :
87: // v
88: // MakeKey()/BreakKey() :
89: // |
1.1.1.10! root 90: // | KEY_INPUT Message :
1.1.1.9 root 91: // | - - - - - - - - - - - -> KeyInputCallback()
92: // o |
93: // : MD::KeyInput()
94: // |
95: // : KeyInputCommon()
96: // |
97: // : MD::SendStart()
98: // v
99: // 機種ごとに接続先に送信
1.1.1.5 root 100:
1.1 root 101: #include "keyboard.h"
1.1.1.10! root 102: #include "config.h"
1.1.1.5 root 103: #include "scheduler.h"
1.1.1.10! root 104: #include "sync.h"
1.1.1.7 root 105: #include "uimessage.h"
1.1 root 106:
1.1.1.10! root 107: // グローバル参照用
! 108: Keyboard *gKeyboard;
1.1 root 109:
110: // コンストラクタ
111: Keyboard::Keyboard()
1.1.1.6 root 112: : inherited("Keyboard")
1.1 root 113: {
1.1.1.5 root 114: pressed.resize(KC_max);
1.1 root 115: }
116:
117: // デストラクタ
118: Keyboard::~Keyboard()
119: {
1.1.1.10! root 120: gKeyboard = NULL;
1.1 root 121: }
122:
1.1.1.10! root 123: // 初期化
! 124: bool
! 125: Keyboard::Init()
! 126: {
! 127: gScheduler->ConnectMessage(MessageID::KEY_INPUT, this,
! 128: ToMessageCallback(&Keyboard::KeyInputCallback));
! 129: return true;
! 130: }
! 131:
! 132: // 電源オン/リセット
1.1.1.5 root 133: void
1.1.1.10! root 134: Keyboard::ResetHard(bool poweron)
1.1.1.5 root 135: {
1.1.1.10! root 136: if (poweron) {
! 137: is_connected = gConfig->Find("keyboard-connect").AsInt();
! 138:
! 139: if (is_connected) {
! 140: DoConnect();
! 141: } else {
! 142: DoDisconnect();
! 143: }
! 144:
! 145: // キー通知
! 146: gSync->RequestKeyPressed(active != 0);
! 147: }
1.1.1.5 root 148:
1.1.1.10! root 149: // 内部状態をリセット
1.1.1.5 root 150: sendqueue.Clear();
1.1.1.10! root 151: }
! 152:
! 153: // 電源オフ
! 154: void
! 155: Keyboard::PowerOff()
! 156: {
! 157: // LED は全部消灯
! 158: std::fill(led.begin(), led.end(), false);
! 159:
! 160: // キーボードから手を離したことにする
1.1.1.5 root 161: std::fill(pressed.begin(), pressed.end(), false);
1.1.1.9 root 162: active = 0;
1.1.1.10! root 163:
1.1.1.5 root 164: // キーが全部解放されたので通知
1.1.1.10! root 165: gSync->RequestKeyPressed(false);
! 166:
! 167: DoDisconnect();
! 168: }
! 169:
! 170: // キーボードを接続する (外部から呼ばれる)
! 171: void
! 172: Keyboard::Connect(bool connect)
! 173: {
! 174: uint code = connect ? CC_connect : CC_disconnect;
! 175:
! 176: // ここは UI スレッドからも呼ばれるのでメッセージを送る
! 177: gScheduler->SendMessage(MessageID::KEY_INPUT, code);
1.1.1.5 root 178: }
179:
180: // キーを押した (外部から、共通キーコードで呼ばれる)
181: void
182: Keyboard::MakeKey(uint keycode)
183: {
1.1.1.10! root 184: keycode |= KC_FLAG_MAKE;
! 185:
! 186: // ここは UI スレッドからも呼ばれるのでメッセージを送る
! 187: gScheduler->SendMessage(MessageID::KEY_INPUT, keycode);
1.1.1.5 root 188: }
189:
190: // キーを離した (外部から、共通キーコードで呼ばれる)
191: void
192: Keyboard::BreakKey(uint keycode)
193: {
1.1.1.10! root 194: keycode |= KC_FLAG_BREAK;
! 195:
! 196: // ここは UI スレッドからも呼ばれるのでメッセージを送る
! 197: gScheduler->SendMessage(MessageID::KEY_INPUT, keycode);
1.1.1.5 root 198: }
199:
1.1.1.8 root 200: // 文字による入力
201: // WX での文字入力モード、CLI からの入力、ターミナルエミュレーションでの
202: // 入力によりキーボードの押し下げをエミュレートする。
203: void
204: Keyboard::CharInput(uint charcode)
205: {
206: if (charcode >= char_key.size()) {
207: return;
208: }
209:
210: uint key = char_key[charcode];
211: uint code = KC_CODE(key);
212: if ((key & KM_SHIFT)) {
213: MakeKey(KC_SHIFT_L | KC_FLAG_POST);
214: MakeKey(KC_SHIFT_R | KC_FLAG_POST);
215: } else {
216: BreakKey(KC_SHIFT_L);
217: BreakKey(KC_SHIFT_R);
218: }
219: if ((key & KM_CTRL)) {
220: MakeKey(KC_CTRL | KC_FLAG_POST);
221: } else {
222: BreakKey(KC_CTRL);
223: }
224: MakeKey(code | KC_FLAG_POST);
225: BreakKey(code);
226: if ((key & KM_CTRL)) {
227: BreakKey(KC_CTRL);
228: }
229: if ((key & KM_SHIFT)) {
230: BreakKey(KC_SHIFT_L);
231: BreakKey(KC_SHIFT_R);
232: }
233: }
234:
1.1.1.10! root 235: // キー入力メッセージコールバック
1.1.1.5 root 236: void
1.1.1.10! root 237: Keyboard::KeyInputCallback(MessageID msgid, uint32 arg)
1.1.1.5 root 238: {
1.1.1.10! root 239: uint keystat = arg;
! 240: switch (keystat) {
! 241: case CC_connect:
! 242: DoConnect();
! 243: break;
! 244: case CC_disconnect:
! 245: DoDisconnect();
! 246: break;
! 247: default:
1.1.1.5 root 248: KeyInput(keystat);
1.1.1.10! root 249: break;
! 250: }
! 251: }
! 252:
! 253: // キーボードの接続処理の実体。
! 254: void
! 255: Keyboard::DoConnect()
! 256: {
! 257: is_connected = true;
! 258:
! 259: MDConnect();
! 260:
! 261: // LED は全部消灯で初期化
! 262: std::fill(led.begin(), led.end(), false);
! 263:
! 264: // 接続されたので押しっぱなしになっているキーをスキャンして送る
! 265: for (int i = 0; i < pressed.size(); i++) {
! 266: if (pressed[i]) {
! 267: KeyInput(i | KC_FLAG_BREAK);
! 268: KeyInput(i);
! 269: }
1.1.1.5 root 270: }
1.1.1.10! root 271:
! 272: // UI に通知する
! 273: UIMessage::Post(UIMessage::KEYBOARD);
! 274: }
! 275:
! 276: void
! 277: Keyboard::DoDisconnect()
! 278: {
! 279: is_connected = false;
! 280:
! 281: // 電源が切れたので LED は全部消す
! 282: std::fill(led.begin(), led.end(), false);
! 283:
! 284: MDDisconnect();
! 285:
! 286: // UI に通知する
! 287: UIMessage::Post(UIMessage::KEYBOARD);
1.1.1.5 root 288: }
289:
1.1.1.9 root 290: // キー入力を1つ処理する。
291: // keystat が押下・開放されたキーの物理的な状態。
292: // キーを破棄したら false を返す。
1.1.1.6 root 293: bool
294: Keyboard::KeyInputCommon(uint keystat)
1.1.1.5 root 295: {
296: uint keycode = KC_CODE(keystat);
297: bool ismake = KC_IS_MAKE(keystat);
1.1.1.9 root 298: uint ledflag = KC_FLAG_LED(keystat);
1.1.1.5 root 299:
300: // 対応する機種別キーコードがなければ無視。
301: // (ここでは調べるだけでまだ変換はしない)
1.1.1.9 root 302: if (KeyToMDKey(keystat) == 0) {
1.1.1.6 root 303: return false;
1.1.1.5 root 304: }
305:
306: // このキーの状態が変化しないのなら何もしない。
307: if (IsPressed(keycode) == ismake) {
1.1.1.6 root 308: return false;
1.1.1.5 root 309: }
310:
311: // 処理することが確定したのでログ
312: // (離すほうは押すほうよりログレベルを1つ上げてある)
1.1.1.9 root 313: if (loglevel >= 1) {
314: std::string msg;
315:
316: msg += string_format("%d(", keycode);
317: msg += GetKeyName(keycode);
318: msg += ")";
319:
320: if (ledflag) {
321: // LUNA の LED キーの場合、sendstat も明示
322: if (ledflag == KC_FLAG_LED_DROP) {
323: msg += ", drop";
324: } else {
325: msg += ", send ";
326: if (ledflag == KC_FLAG_LED_MAKE) {
327: msg += "Make";
328: } else {
329: msg += "Break";
330: }
331: }
332: }
333:
334: if (ismake) {
335: putlogn( "MakeKey %s", msg.c_str());
336: } else {
337: putlog(2, "BreakKey %s", msg.c_str());
338: }
1.1.1.5 root 339: }
340:
1.1.1.10! root 341: // キーが押されてる間は VM の高速実行を抑制する。
! 342: // すべてのキーが離されたら高速モードを許可する。
1.1.1.5 root 343: pressed[keycode] = ismake;
344: if (ismake) {
1.1.1.9 root 345: Acquire();
1.1.1.5 root 346: } else {
1.1.1.9 root 347: Release();
1.1.1.5 root 348: }
349:
1.1.1.9 root 350: // キーの状態が変わったので UI に通知。
1.1.1.8 root 351: // KC_FLAG_POST が立っていればキーコードも送信 (char 入力モード用)。
352: // 通知を受け取った UI 側が IsPressed() などでキーの現状を調べることが
353: // あるため pressed[] 更新後に通知する。
1.1.1.9 root 354: // XXX LED 変更が間に合わない (see lunakbd.cpp)
1.1.1.8 root 355: uint arg;
356: if (KC_IS_POST(keystat)) {
357: arg = keycode;
358: } else {
359: arg = 0;
360: }
361: UIMessage::Post(UIMessage::KEYBOARD, arg);
362:
1.1.1.9 root 363: // LUNA の LED キー消灯はキー開放を送信
364: if (ledflag == KC_FLAG_LED_BREAK) {
365: keystat |= KC_FLAG_BREAK;
366: }
367:
1.1.1.10! root 368: // キーボードが接続されていなければここまで処理して false を返す
! 369: if (is_connected == false) {
! 370: return false;
! 371: }
! 372:
1.1.1.9 root 373: if (ledflag != KC_FLAG_LED_DROP) {
374: // 送信キューに登録
375:
376: // ここでは変換できるはず
377: uint mdkey = KeyToMDKey(keystat);
378: sendqueue.Enqueue(mdkey);
379:
380: // 機種依存のキー送信処理
381: SendStart();
382: }
1.1.1.5 root 383:
1.1.1.6 root 384: return true;
1.1.1.5 root 385: }
386:
1.1.1.9 root 387: // アクティブカウンタを 1 増やす。
388: // 0 -> 1 の遷移でスケジューラに通知する。
389: void
390: Keyboard::Acquire()
391: {
392: if (active++ == 0) {
1.1.1.10! root 393: gSync->RequestKeyPressed(true);
1.1.1.9 root 394: }
395: }
396:
397: // アクティブカウンタを 1 減らす。
398: // 1 -> 0 の遷移でスケジューラに通知する。
399: void
400: Keyboard::Release()
401: {
402: if (--active == 0) {
1.1.1.10! root 403: gSync->RequestKeyPressed(false);
1.1.1.9 root 404: }
405: }
406:
1.1 root 407: // キー名を返す (主にデバッグ用)
408: const std::string
1.1.1.6 root 409: Keyboard::GetKeyName(uint keycode)
1.1 root 410: {
1.1.1.5 root 411: if (keycode >= keyname.size()) {
412: return string_format("(keycode=0x%x, out of range)", keycode);
1.1 root 413: }
1.1.1.5 root 414: if (keyname[keycode] == NULL) {
415: return string_format("(keycode=0x%x)", keycode);
1.1 root 416: }
1.1.1.5 root 417: return std::string(keyname[keycode]);
1.1 root 418: }
419:
420: /*static*/ std::vector<const char *>
421: Keyboard::keyname {
422: "(none)", // 00
423: "BREAK", // 01
424: "COPY", // 02
425: "romaji", // 03
426: "code", // 04
427: "kigou", // 05
428: "touroku", // 06
429: "HELP", // 07
1.1.1.9 root 430: "SHIFT", // 08
1.1 root 431: "TAB", // 09
432: "CTRL", // 0a
433: "kana", // 0b
434: "SHIFT_L", // 0c
435: "SHIFT_R", // 0d
436: "CAPS", // 0e
437: "SF", // 0f
438:
439: "ESC", // 10
440: "BS", // 11
441: "enter", // 12
442: "INS", // 13
443: "space", // 14
444: "DEL", // 15
445: "XFER", // 16
446: "VALID", // 17
447: "PF11", // 18
448: "PF12", // 19
449: "PF13", // 1a
450: "PF14", // 1b
451: "up", // 1c
452: "left", // 1d
453: "right", // 1e
454: "down", // 1f
455:
456: "ROLLUP", // 20
457: "ROLLDOWN", // 21
458: "1", // 22
459: "2", // 23
460: "3", // 24
461: "4", // 25
462: "5", // 26
463: "6", // 27
464: "7", // 28
465: "8", // 29
466: "9", // 2a
467: "0", // 2b
468: "minus", // 2c
469: "circum", // 2d
470: "backslash", // 2e
1.1.1.9 root 471: NULL, // 2f
1.1 root 472:
473: "OPT1", // 30
474: "OPT2", // 31
475: "Q", // 32
476: "W", // 33
477: "E", // 34
478: "R", // 35
479: "T", // 36
480: "Y", // 37
481: "U", // 38
482: "I", // 39
483: "O", // 3a
484: "P", // 3b
485: "at", // 3c
486: "bracketleft", // 3d
487: "hira", // 3e
488: "zenkaku", // 3f
489:
1.1.1.9 root 490: "HOME", // 40
491: "UNDO", // 41
1.1 root 492: "A", // 42
493: "S", // 43
494: "D", // 44
495: "F", // 45
496: "G", // 46
497: "H", // 47
498: "J", // 48
499: "K", // 49
500: "L", // 4a
501: "semicolon", // 4b
502: "colon", // 4c
503: "bracketright", // 4d
504: NULL, // 4e
505: NULL, // 4f
506:
1.1.1.9 root 507: "XF1", // 50
508: "XF2", // 51
1.1 root 509: "Z", // 52
510: "X", // 53
511: "C", // 54
512: "V", // 55
513: "B", // 56
514: "N", // 57
515: "M", // 58
516: "comma", // 59
517: "period", // 5a
518: "slash", // 5b
519: "underscore", // 5c
1.1.1.9 root 520: "XF3", // 5d
521: "XF4", // 5e
522: "XF5", // 5f
1.1 root 523:
524: NULL, // 60
525: "PAD_plus", // 61
526: "PAD_minus", // 62
527: "PAD_7", // 63
528: "PAD_8", // 64
529: "PAD_9", // 65
530: "PAD_4", // 66
531: "PAD_5", // 67
532: "PAD_6", // 68
533: "PAD_1", // 69
534: "PAD_2", // 6a
535: "PAD_3", // 6b
536: "PAD_0", // 6c
537: "PAD_decimal", // 6d
538: "PAD_enter", // 6e
539: "PAD_CLR", // 6f
540:
541: NULL, // 70
542: NULL, // 71
543: "F1", // 72
544: "F2", // 73
545: "F3", // 74
546: "F4", // 75
547: "F5", // 76
548: "F6", // 77
549: "F7", // 78
550: "F8", // 79
551: "F9", // 7a
552: "F10", // 7b
553: "PAD_multiply", // 7c
554: "PAD_divide", // 7d
555: "PAD_equal", // 7e
556: "PAD_comma", // 7f
557: };
1.1.1.8 root 558:
559: // 文字対キーストローク表
560: // 文字による入力エミュレーションで使用。
561: /*static*/ std::vector<uint>
562: Keyboard::char_key = {
563: 0, // NONE
564: KC_A + KM_CTRL, // 0x01 ^A
565: KC_B + KM_CTRL, // 0x02 ^B
566: KC_C + KM_CTRL, // 0x03 ^C
567: KC_D + KM_CTRL, // 0x04 ^D
568: KC_E + KM_CTRL, // 0x05 ^E
569: KC_F + KM_CTRL, // 0x06 ^F
570: KC_G + KM_CTRL, // 0x07 ^G
571: KC_BS, // 0x08 ^H
572: KC_TAB, // 0x09 ^I
573: KC_J + KM_CTRL, // 0x0a ^J
574: KC_K + KM_CTRL, // 0x0b ^K
575: KC_L + KM_CTRL, // 0x0c ^L
576: KC_enter, // 0x0d ^M
577: KC_N + KM_CTRL, // 0x0e ^N
578: KC_O + KM_CTRL, // 0x0f ^O
579: KC_P + KM_CTRL, // 0x10 ^P
580: KC_Q + KM_CTRL, // 0x11 ^Q
581: KC_R + KM_CTRL, // 0x12 ^R
582: KC_S + KM_CTRL, // 0x13 ^S
583: KC_T + KM_CTRL, // 0x14 ^T
584: KC_U + KM_CTRL, // 0x15 ^U
585: KC_V + KM_CTRL, // 0x16 ^V
586: KC_W + KM_CTRL, // 0x17 ^W
587: KC_X + KM_CTRL, // 0x18 ^X
588: KC_Y + KM_CTRL, // 0x19 ^Y
589: KC_Z + KM_CTRL, // 0x1a ^Z
590:
591: KC_ESC, // 0x1b ^[
592: KC_backslash + KM_CTRL, // 0x1c ^'\'
593: KC_bracketright + KM_CTRL, // 0x1d ^]
594: KC_circum + KM_CTRL, // 0x1e ^^
595: KC_underscore + KM_CTRL, // 0x1f ^_
596:
597: KC_space, // 0x20 ' '
598: KC_1 + KM_SHIFT, // 0x21 !
599: KC_2 + KM_SHIFT, // 0x22 "
600: KC_3 + KM_SHIFT, // 0x23 #
601: KC_4 + KM_SHIFT, // 0x24 $
602: KC_5 + KM_SHIFT, // 0x25 %
603: KC_6 + KM_SHIFT, // 0x26 &
604: KC_7 + KM_SHIFT, // 0x27 '
605: KC_8 + KM_SHIFT, // 0x28 (
606: KC_9 + KM_SHIFT, // 0x29 )
607: KC_colon + KM_SHIFT, // 0x2a *
608: KC_semicolon + KM_SHIFT, // 0x2b +
609: KC_comma, // 0x2c ,
610: KC_minus, // 0x2d -
611: KC_period, // 0x2e .
612: KC_slash, // 0x2f /
613:
614: KC_0, // 0x30 0
615: KC_1, // 0x31 1
616: KC_2, // 0x32 2
617: KC_3, // 0x33 3
618: KC_4, // 0x34 4
619: KC_5, // 0x35 5
620: KC_6, // 0x36 6
621: KC_7, // 0x37 7
622: KC_8, // 0x38 8
623: KC_9, // 0x39 9
624: KC_colon, // 0x3a :
625: KC_semicolon, // 0x3b ;
626: KC_comma + KM_SHIFT, // 0x3c <
627: KC_minus + KM_SHIFT, // 0x3d =
628: KC_period + KM_SHIFT, // 0x3e >
629: KC_slash + KM_SHIFT, // 0x3f ?
630:
631: KC_at, // 0x40 @
632: KC_A + KM_SHIFT, // 0x41 A
633: KC_B + KM_SHIFT, // 0x42 B
634: KC_C + KM_SHIFT, // 0x43 C
635: KC_D + KM_SHIFT, // 0x44 D
636: KC_E + KM_SHIFT, // 0x45 E
637: KC_F + KM_SHIFT, // 0x46 F
638: KC_G + KM_SHIFT, // 0x47 G
639: KC_H + KM_SHIFT, // 0x48 H
640: KC_I + KM_SHIFT, // 0x49 I
641: KC_J + KM_SHIFT, // 0x4a J
642: KC_K + KM_SHIFT, // 0x4b K
643: KC_L + KM_SHIFT, // 0x4c L
644: KC_M + KM_SHIFT, // 0x4d M
645: KC_N + KM_SHIFT, // 0x4e N
646: KC_O + KM_SHIFT, // 0x4f O
647: KC_P + KM_SHIFT, // 0x50 P
648: KC_Q + KM_SHIFT, // 0x51 Q
649: KC_R + KM_SHIFT, // 0x52 R
650: KC_S + KM_SHIFT, // 0x53 S
651: KC_T + KM_SHIFT, // 0x54 T
652: KC_U + KM_SHIFT, // 0x55 U
653: KC_V + KM_SHIFT, // 0x56 V
654: KC_W + KM_SHIFT, // 0x57 W
655: KC_X + KM_SHIFT, // 0x58 X
656: KC_Y + KM_SHIFT, // 0x59 Y
657: KC_Z + KM_SHIFT, // 0x5a Z
658:
659: KC_bracketleft, // 0x5b [
660: KC_backslash, // 0x5c '\'
661: KC_bracketright, // 0x5d ]
662: KC_circum, // 0x5e ^
663: KC_underscore + KM_SHIFT, // 0x5f _
664:
665: KC_at + KM_SHIFT, // 0x60 `
666: KC_A, // 0x61 a
667: KC_B, // 0x62 b
668: KC_C, // 0x63 c
669: KC_D, // 0x64 d
670: KC_E, // 0x65 e
671: KC_F, // 0x66 f
672: KC_G, // 0x67 g
673: KC_H, // 0x68 h
674: KC_I, // 0x69 i
675: KC_J, // 0x6a j
676: KC_K, // 0x6b k
677: KC_L, // 0x6c l
678: KC_M, // 0x6d m
679: KC_N, // 0x6e n
680: KC_O, // 0x6f o
681: KC_P, // 0x70 p
682: KC_Q, // 0x71 q
683: KC_R, // 0x72 r
684: KC_S, // 0x73 s
685: KC_T, // 0x74 t
686: KC_U, // 0x75 u
687: KC_V, // 0x76 v
688: KC_W, // 0x77 w
689: KC_X, // 0x78 x
690: KC_Y, // 0x79 y
691: KC_Z, // 0x7a z
692:
693: KC_bracketleft + KM_SHIFT, // 0x7b {
694: KC_backslash + KM_SHIFT, // 0x7c |
695: KC_bracketright + KM_SHIFT, // 0x7d }
696: KC_circum + KM_SHIFT, // 0x7e ~
697: KC_none, // 0x7f DEL
698:
699: KC_at + KM_CTRL, // 0x80 CC_NUL
700: KC_F1, // 0x81 CC_F1
701: KC_F2, // 0x82 CC_F2
702: KC_F3, // 0x83 CC_F3
703: KC_F4, // 0x84 CC_F4
704: KC_F5, // 0x85 CC_F5
705: KC_F6, // 0x86 CC_F6
706: KC_F7, // 0x87 CC_F7
707: KC_F8, // 0x88 CC_F8
708: KC_F9, // 0x89 CC_F9
1.1.1.9 root 709: KC_F10, // 0x8a CC_F10
1.1.1.8 root 710: 0, // 0x8b
711: KC_up, // 0x8c CC_up
712: KC_left, // 0x8d CC_left
713: KC_right, // 0x8e CC_right
714: KC_down, // 0x8f CC_down
715: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.