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