|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2018 [email protected]
4: //
5:
6: #include "wxheader.h"
7: #include "keyboard.h"
8: #include "renderer.h"
9: #include "scheduler.h"
10: #include "wxmainview.h"
11: #include <wx/region.h>
12: #include <wx/event.h>
13: #if defined(__NetBSD__)
14: #include <sys/param.h> // __NetBSD_Version__
15: #endif
16:
17: //#define KEYDEBUG 1
1.1.1.2 ! root 18: //#define MOUSEDEBUG 1
1.1 root 19:
20: #if defined(KEYDEBUG)
1.1.1.2 ! root 21: #define DKPRINTF(...) printf(__VA_ARGS__)
1.1 root 22: #else
1.1.1.2 ! root 23: #define DKPRINTF(...) /**/
! 24: #endif
! 25:
! 26: #if defined(MOUSEDEBUG)
! 27: #define DMPRINTF(...) printf(__VA_ARGS__)
! 28: #else
! 29: #define DMPRINTF(...) /**/
1.1 root 30: #endif
31:
32: // 再描画矩形の指定方法について。
33: // DoRefresh() にて、VM スレッドが自発的に画面を更新する際は、
34: // パフォーマンスの観点からも更新矩形だけを再描画すべき。
35: // これを wxWidgets に指示するのが wxWindow::Refresh{,Rect}() であるが
36: // 一部のプラットフォームではこれを呼び出すと、アプリケーションウィンドウ
37: // 全体がささってしまい、MainView だけでなくメニューバーも含めたすべてが
38: // 再描画できなくなってしまう。仕方がないので、これらのプラットフォームでは
39: // Refresh{,Rect}() を呼ばず、再描画矩形を画面全体として運用する。
40: // ちょっと無駄なだけなので (動かないことに比べれば) 気にしない。
41: //
42: // 今のところ NetBSD 5.0 以上(と Linux (CentOS 6.3/x86_64)) が該当する。
43: #if defined(__NetBSD__) && __NetBSD_Version__ >= 500000000
44: #define DONT_USE_REFRESH 1
45: #endif
46:
47: #define TIMERID_PAINTTIMER 1
48:
49: static void wxmainview_refresh();
50:
51: WXMainView *gMainView;
52:
53: wxBEGIN_EVENT_TABLE(WXMainView, inherited)
54: EVT_PAINT(WXMainView::OnPaint)
55: EVT_KEY_DOWN(WXMainView::OnKeyDown)
56: EVT_KEY_UP(WXMainView::OnKeyUp)
1.1.1.2 ! root 57: EVT_MOUSE_EVENTS(WXMainView::OnMouse)
1.1 root 58: EVT_TIMER(TIMERID_PAINTTIMER, WXMainView::OnTimer)
59: wxEND_EVENT_TABLE()
60:
61: WXMainView::WXMainView(wxWindow *parent)
62: : inherited(parent)
63: {
64: // 仮想画面(VM が描画する画面)
65: rendwidth = gRenderer->GetWidth();
66: rendheight = gRenderer->GetHeight();
67:
68: // レンダラバッファは常に仮想画面サイズ
69: int buflen = rendwidth * rendheight * 3;
70: ImageBuf = new uint8_t[buflen];
71: memset(ImageBuf, 0x70, buflen);
72: // レンダラに通知
73: gRenderer->SetBuf(ImageBuf, wxmainview_refresh);
74:
75: // 実画面 (ウィンドウの大きさ)
76: DoResize(screen_scale);
77:
78: paintTimer.SetOwner(this, TIMERID_PAINTTIMER);
79: paintTimer.Start(16);
80: paintRequested = true; // first paint request
81: }
82:
83: WXMainView::~WXMainView()
84: {
85: delete[] ImageBuf;
86: }
87:
88: // リフレッシュ要求コールバック。
89: // VM から呼ばれるので一旦グローバル関数を経由する。
90: void
91: wxmainview_refresh(void)
92: {
93: gMainView->DoRefresh();
94: }
95:
96: // リフレッシュ要求コールバック。こっちが実体。
97: void
98: WXMainView::DoRefresh()
99: {
100: #if defined(DONT_USE_REFRESH)
101: // Refresh{,Rect}() が使えないので、再描画範囲は常に全体とする
102: #else
103: // 再描画範囲を更新矩形に限定
104: // XXX のはずだが、今の所全体
105: RefreshRect(wxRect(0, 0, viewwidth, viewheight), false);
106: #endif
107:
108: // PAINT イベントを投げる
109: // XXX んだけど mac だと投げすぎるとシステムイベントを拾えなくなってしまう
110: paintRequested = true;
111: }
112:
113: void
114: WXMainView::OnTimer(wxTimerEvent& event)
115: {
116: bool req = paintRequested.exchange(false);
117: if (req) {
118: // PAINT イベントを投げる
119: wxPaintEvent *ev = new wxPaintEvent();
120: QueueEvent(ev);
121: }
122: }
123:
124: // 描画イベント
125: void
126: WXMainView::OnPaint(wxPaintEvent& event)
127: {
128: wxClientDC dc(this);
129:
130: DoPaint(dc);
131: }
132:
133: // 描画実行
134: void
135: WXMainView::DoPaint(wxDC& dc)
136: {
137: if (viewwidth == 0 || viewheight == 0)
138: return;
139:
140: wxImage image(rendwidth, rendheight, ImageBuf, true);
141:
142: if (viewwidth != rendwidth || viewheight != rendheight) {
143: // wxIMAGE_QUALITY_NORMAL だと速いが、品質優先。
144: image.Rescale(viewwidth, viewheight, wxIMAGE_QUALITY_HIGH);
145: }
146:
147: wxBitmap bitmap(image);
148: wxMemoryDC memDC;
149: memDC.SelectObject(bitmap);
150:
151: wxRegion region(0, 0, viewwidth, viewheight);
152: wxRegionIterator ri(region);
153: for (; ri; ri++) {
154: int dx, dy, dw, dh;
155: dx = ri.GetX();
156: dy = ri.GetY();
157: dw = ri.GetWidth();
158: dh = ri.GetHeight();
159: int sx = dx;
160: int sy = dy;
161: dc.Blit(dx, dy, dw, dh, &memDC, sx, sy, wxCOPY);
162: }
163: }
164:
165: // リサイズ (UI スレッドから呼ぶこと)
166: void
167: WXMainView::DoResize(double scale)
168: {
169: screen_scale = scale;
170: int width = (double)rendwidth * scale;
171: int height = (double)rendheight * scale;
172: if (viewwidth != width || viewheight != height) {
173: // ウィンドウサイズ変更
174: viewwidth = width;
175: viewheight = height;
176: SetClientSize(viewwidth, viewheight);
177: SetMinSize(wxSize(viewwidth, viewheight));
178: }
179: }
180:
181: // 現在のスケールを返す。
182: // screen_scale は public static なので見えるんだけど一応お行儀で。
183: double
184: WXMainView::GetScale() const
185: {
186: return screen_scale;
187: }
188:
189: // 現在のスケール
190: /*static*/ double WXMainView::screen_scale;
191:
192:
193: //
1.1.1.2 ! root 194: // マウス入力
! 195: //
! 196:
! 197: // マウスモード設定
! 198: void
! 199: WXMainView::SetMouseMode(bool mode)
! 200: {
! 201: // XXX マウスモード ON にした時の座標を記憶してそこに戻るのはどうか
! 202:
! 203: mousemode = mode;
! 204: if (mousemode) {
! 205: // マウスモードを ON にする
! 206: DMPRINTF("SetMouseMode ON\n");
! 207:
! 208: // マウスカーソル OFF
! 209: ::wxSetCursor(wxCursor(wxCURSOR_BLANK));
! 210:
! 211: // このウィンドウから外れないように移動を検出し続けるため、
! 212: // マウスカーソルをウィンドウ中央に移す。
! 213: // ウィンドウとメニューバーが分離してる wxOSX のために必要。
! 214: MyWarpPointer(GetClientSize() / 2);
! 215: } else {
! 216: // マウスモードを OFF にする
! 217: DMPRINTF("SetMouseMode OFF\n");
! 218:
! 219: // 分かりやすさのため、マウスカーソルを中央へ戻してから復帰
! 220: MyWarpPointer(GetClientSize() / 2);
! 221:
! 222: // マウスカーソル ON
! 223: ::wxSetCursor(wxNullCursor);
! 224: }
! 225: }
! 226:
! 227: // マウスカーソルをクライアント座標 (x, y) に移動
! 228: void
! 229: WXMainView::MyWarpPointer(wxSize pos)
! 230: {
! 231: DMPRINTF("MyWarpPointer %d,%d\n", pos.x, pos.y);
! 232:
! 233: // この後の MDWarpPointer() でもう一度 EVT_MOTION が飛ぶので
! 234: // それを判別するためのフラグ。
! 235: motion_by_warp_pointer = true;
! 236:
! 237: WarpPointer(pos.x, pos.y);
! 238: }
! 239:
! 240: // マウスイベント
! 241: void
! 242: WXMainView::OnMouse(wxMouseEvent& event)
! 243: {
! 244: // マウスモードの時だけ処理。
! 245: // XXX 本当はイベントごと Disconnect したい
! 246: if (mousemode) {
! 247: bool leaving = event.Leaving();
! 248: bool moving = event.Moving();
! 249: // LeftDown() 等は押された時、LeftIsDown() 等は押されてる間 true。
! 250: bool rb = event.RightIsDown();
! 251: bool lb = event.LeftIsDown();
! 252: bool mb = event.MiddleIsDown();
! 253: wxPoint pos = event.GetPosition();
! 254: int dx = 0;
! 255: int dy = 0;
! 256:
! 257: DMPRINTF(
! 258: "OnMouse Button=%d %c%c%c Leave=%d (motion=%d) Moving=%d(%d,%d)\n",
! 259: event.IsButton(),
! 260: (lb ? 'L' : '-'),
! 261: (mb ? 'M' : '-'),
! 262: (rb ? 'R' : '-'),
! 263: leaving, motion_by_warp_pointer, moving, pos.x, pos.y);
! 264:
! 265: if (leaving) {
! 266: // タスクスイッチした時とかのための自動リリース
! 267: SetMouseMode(false);
! 268: }
! 269:
! 270: if (moving) {
! 271: // (My)WarpPointer() で自発的にマウスカーソルを移動させたことで
! 272: // 来る EVT_MOTION は無視する。
! 273: if (motion_by_warp_pointer) {
! 274: motion_by_warp_pointer = false;
! 275: // ここを基準点にする
! 276: prevpos = pos;
! 277: } else {
! 278: // 前回からの差を求める
! 279: dx = pos.x - prevpos.x;
! 280: dy = pos.y - prevpos.y;
! 281: prevpos = pos;
! 282:
! 283: // マウスカーソルを中心に戻す
! 284: if (dx != 0 || dy != 0) {
! 285: MyWarpPointer(GetClientSize() / 2);
! 286: }
! 287: }
! 288: }
! 289:
! 290: // VM に入力
! 291: if (dx != 0 || dy != 0 || lb || mb || rb) {
! 292: DMPRINTF(" Input dx=%d dy=%d %c%c%c\n",
! 293: dx, dy,
! 294: (lb ? 'L' : '-'),
! 295: (mb ? 'M' : '-'),
! 296: (rb ? 'R' : '-'));
! 297:
! 298: gKeyboard->MouseInput(dx, dy, rb, lb, mb);
! 299: }
! 300: }
! 301:
! 302: // EVT_LEFT_DOWN をデフォルト処理するため
! 303: event.Skip();
! 304: }
! 305:
! 306: //
1.1 root 307: // キー入力
308: //
309:
310: // wxKeyEvent でキーコードを得るためのメソッドは
311: // GetKeyCode()、GetRawKeyCode()、GetRawKeyFlags() の3つが用意されていて
312: // wxWigets の port (wxGTK、wxOSX とか) によってそれぞれ内容の定義が違う。
313: //
314: // wxGTK の場合
315: // GetKeyCode() は wxWidgets の WXK_* (/usr/pkg/include/wx-3.0/wx/defs.h)。
316: // これは左右の SHIFT が区別できないが、
317: // それ以外はだいたい使えそうではある。
318: //
319: // GetRawKeyCode() は GDK の keycode っぽい?
320: // (/usr/pkg/include/gtk-2.0/gdk/gdkkeysyms.h)。
321: // X11 の keysym から来てる? (/usr/X11R7/include/X11/keysymdef.h)。
322: // ただし [A] と [SHIFT]+[A] が違うコードを返すというか、文字コードで
323: // 表現出来る時は文字コード、みたいな感じになっているので、ここでは
324: // 使いづらい。
325: // 左右の SHIFT は区別可能。
326: // [^] と [SHIFT]+[^] もそもそも文字コードになるので '^' と '~' になる。
327: //
328: // GetRawKeyFlags() は GDK の hardware keycode らしいけど、それが何か不明。
329: // 左右の SHIFT は違うコードを返す。
330: // SHIFT を押しながらでもコードは変わらないっぽい。
331: // [^] と [SHIFT]+[^] は同じコードを返す。
332: //
333: // wxOSX の場合
334: // GetKeyCode()
335: // これは左右の SHIFT が区別できないが、
336: // それ以外はだいたい使えそうではある。
337: //
338: // GetRawKeyCode()
339: // [A] と [SHIFT]+[A] などは同じコードを返す。
340: // 左右の SHIFT は区別可能。
341: //
342: // GetRawKeyFlags() は状態フラグか何かのようだ。
343: //
344:
345: // キーを押した
346: void
347: WXMainView::OnKeyDown(wxKeyEvent& event)
348: {
1.1.1.2 ! root 349: DKPRINTF("KeyDown ");
1.1 root 350: int keycode = GetKeyCode(event);
351: gKeyboard->MakeKey(keycode);
1.1.1.2 ! root 352:
! 353: // メニューのアクセラレータのために必要
! 354: event.Skip();
1.1 root 355: }
356:
357: // キーを離した
358: void
359: WXMainView::OnKeyUp(wxKeyEvent& event)
360: {
1.1.1.2 ! root 361: DKPRINTF("KeyUp ");
1.1 root 362: int keycode = GetKeyCode(event);
363: gKeyboard->BreakKey(keycode);
364: }
365:
366: // 共通キーコードを取得する。
367: // 対応するキーがない場合は -1 を返す。
368: int
369: WXMainView::GetKeyCode(wxKeyEvent& event)
370: {
371: uint32 wxcode __unused = event.GetKeyCode();
372: uint32 rawcode __unused = event.GetRawKeyCode();
373: uint32 rawflags __unused = event.GetRawKeyFlags();
374: uint32 inp;
375: int keycode;
376:
377: #if defined(__WXGTK__)
378: // wxGTK では RawKeyFlags を使う
1.1.1.2 ! root 379: DKPRINTF("key=0x%03x raw=0x%04x <flags=0x%02x> ",
! 380: wxcode, rawcode, rawflags);
1.1 root 381: inp = rawflags;
382: #elif defined(__WXOSX__)
383: // wxOSX では RawKeyCode を使う
1.1.1.2 ! root 384: DKPRINTF("key=0x%03x <raw=0x%02x> flags=0x%06x ",
! 385: wxcode, rawcode, rawflags);
1.1 root 386: inp = rawcode;
387: #endif
388:
389: // どちらにしてもテーブルを引く
390: if (inp < countof(keycode_table)) {
391: keycode = keycode_table[inp];
392: } else {
393: keycode = KC_none;
394: }
1.1.1.2 ! root 395: DKPRINTF("keycode=%d %s\n", keycode, Keyboard::keyname[keycode]);
1.1 root 396: return keycode;
397: }
398:
399: #if defined(__WXGTK__)
400: // wxGTK の RawKeyFlags を共通キーコードに変換するテーブル。
401: /*static*/ const int
402: WXMainView::keycode_table[0xd4] = {
403: KC_none, // 0x00
404: KC_none, // 0x01
405: KC_none, // 0x02
406: KC_none, // 0x03
407: KC_none, // 0x04
408: KC_none, // 0x05
409: KC_none, // 0x06
410: KC_none, // 0x07
411: KC_none, // 0x08
412: KC_none, // 0x09
413: KC_1, // 0x0a
414: KC_2, // 0x0b
415: KC_3, // 0x0c
416: KC_4, // 0x0d
417: KC_5, // 0x0e
418: KC_6, // 0x0f
419:
420: KC_7, // 0x10
421: KC_8, // 0x11
422: KC_9, // 0x12
423: KC_0, // 0x13
424: KC_minus, // 0x14
425: KC_circum, // 0x15
426: KC_BS, // 0x16
427: KC_TAB, // 0x17
428: KC_Q, // 0x18
429: KC_W, // 0x19
430: KC_E, // 0x1a
431: KC_R, // 0x1b
432: KC_T, // 0x1c
433: KC_Y, // 0x1d
434: KC_U, // 0x1e
435: KC_I, // 0x1f
436:
437: KC_O, // 0x20
438: KC_P, // 0x21
439: KC_at, // 0x22
440: KC_bracketleft, // 0x23
441: KC_enter, // 0x24
442: KC_CTRL, // 0x25 (CTRL_L)
443: KC_A, // 0x26
444: KC_S, // 0x27
445: KC_D, // 0x28
446: KC_F, // 0x29
447: KC_G, // 0x2a
448: KC_H, // 0x2b
449: KC_J, // 0x2c
450: KC_K, // 0x2d
451: KC_L, // 0x2e
452: KC_semicolon, // 0x2f
453:
454: KC_colon, // 0x30
455: KC_ESC, // 0x31
456: KC_SHIFT_L, // 0x32 (SHIFT_L)
457: KC_bracketright,// 0x33
458: KC_Z, // 0x34
459: KC_X, // 0x35
460: KC_C, // 0x36
461: KC_V, // 0x37
462: KC_B, // 0x38
463: KC_N, // 0x39
464: KC_M, // 0x3a
465: KC_comma, // 0x3b
466: KC_period, // 0x3c
467: KC_slash, // 0x3d
468: KC_SHIFT_R, // 0x3e (SHIFT_R)
469: KC_PAD_multiply,// 0x3f
470:
471: KC_none, // 0x40
472: KC_space, // 0x41
473: KC_none, // 0x42
474: KC_F1, // 0x43
475: KC_F2, // 0x44
476: KC_F3, // 0x45
477: KC_F4, // 0x46
478: KC_F5, // 0x47
479: KC_F6, // 0x48
480: KC_F7, // 0x49
481: KC_F8, // 0x4a
482: KC_F9, // 0x4b
483: KC_F10, // 0x4c
484: KC_none, // 0x4d
485: KC_none, // 0x4e
486: KC_PAD_7, // 0x4f
487:
488: KC_PAD_8, // 0x50
489: KC_PAD_9, // 0x51
490: KC_PAD_minus, // 0x52
491: KC_PAD_4, // 0x53
492: KC_PAD_5, // 0x54
493: KC_PAD_6, // 0x55
494: KC_PAD_plus, // 0x56
495: KC_PAD_1, // 0x57
496: KC_PAD_2, // 0x58
497: KC_PAD_3, // 0x59
498: KC_PAD_0, // 0x5a
499: KC_PAD_decimal, // 0x5b
500: KC_none, // 0x5c
501: KC_none, // 0x5d
502: KC_none, // 0x5e
503: KC_none, // 0x5f
504:
505: KC_none, // 0x60
506: KC_none, // 0x61
507: KC_up, // 0x62
508: KC_none, // 0x63
509: KC_left, // 0x64
510: KC_none, // 0x65
511: KC_right, // 0x66
512: KC_none, // 0x67
513: KC_down, // 0x68
514: KC_none, // 0x69
515: KC_INS, // 0x6a
516: KC_DEL, // 0x6b
517: KC_PAD_enter, // 0x6c
518: KC_CTRL, // 0x6d (CTRL_R)
519: KC_none, // 0x6e
520: KC_none, // 0x6f
521:
522: KC_PAD_divide, // 0x70
523: KC_none, // 0x71
524: KC_none, // 0x72
525: KC_none, // 0x73
526: KC_none, // 0x74
527: KC_none, // 0x75
528: KC_none, // 0x76
529: KC_none, // 0x77
530: KC_none, // 0x78
531: KC_none, // 0x79
532: KC_none, // 0x7a
533: KC_none, // 0x7b
534: KC_none, // 0x7c
535: KC_none, // 0x7d
536: KC_none, // 0x7e
537: KC_none, // 0x7f
538:
539: KC_none, // 0x80
540: KC_none, // 0x81
541: KC_none, // 0x82
542: KC_none, // 0x83
543: KC_none, // 0x84
544: KC_backslash, // 0x85
545: KC_none, // 0x86
546: KC_none, // 0x87
547: KC_none, // 0x88
548: KC_none, // 0x89
549: KC_none, // 0x8a
550: KC_none, // 0x8b
551: KC_none, // 0x8c
552: KC_none, // 0x8d
553: KC_none, // 0x8e
554: KC_none, // 0x8f
555:
556: KC_none, KC_none, KC_none, KC_none, // 0x90
557: KC_none, KC_none, KC_none, KC_none,
558: KC_none, KC_none, KC_none, KC_none,
559: KC_none, KC_none, KC_none, KC_none,
560:
561: KC_none, KC_none, KC_none, KC_none, // 0xa0
562: KC_none, KC_none, KC_none, KC_none,
563: KC_none, KC_none, KC_none, KC_none,
564: KC_none, KC_none, KC_none, KC_none,
565:
566: KC_none, KC_none, KC_none, KC_none, // 0xb0
567: KC_none, KC_none, KC_none, KC_none,
568: KC_none, KC_none, KC_none, KC_none,
569: KC_none, KC_none, KC_none, KC_none,
570:
571: KC_none, KC_none, KC_none, KC_none, // 0xc0
572: KC_none, KC_none, KC_none, KC_none,
573: KC_none, KC_none, KC_none, KC_none,
574: KC_none, KC_none, KC_none, KC_none,
575:
576: KC_none, // 0xd0
577: KC_none, // 0xd1
578: KC_none, // 0xd2
579: KC_underscore, // 0xd3
580: };
581: #endif // __WXGTK__
582:
583: #if defined(__WXOSX__)
584: // wxOSX の RawKeyCode を共通キーコードに変換するテーブル。
585: // Mac の CAPS は押す離すで一回分の KeyDown しか来ないのでちょっと放置。
586: // [英数] と [かな] もちょっと放置。
587: /*static*/ const int
588: WXMainView::keycode_table[0x80] = {
589: KC_A, // 0x00
590: KC_S, // 0x01
591: KC_D, // 0x02
592: KC_F, // 0x03
593: KC_H, // 0x04
594: KC_G, // 0x05
595: KC_Z, // 0x06
596: KC_X, // 0x07
597: KC_C, // 0x08
598: KC_V, // 0x09
599: KC_none, // 0x0a
600: KC_B, // 0x0b
601: KC_Q, // 0x0c
602: KC_W, // 0x0d
603: KC_E, // 0x0e
604: KC_R, // 0x0f
605:
606: KC_Y, // 0x10
607: KC_T, // 0x11
608: KC_1, // 0x12
609: KC_2, // 0x13
610: KC_3, // 0x14
611: KC_4, // 0x15
612: KC_6, // 0x16
613: KC_5, // 0x17
614: KC_circum, // 0x18
615: KC_9, // 0x19
616: KC_7, // 0x1a
617: KC_minus, // 0x1b
618: KC_8, // 0x1c
619: KC_0, // 0x1d
620: KC_bracketleft, // 0x1e
621: KC_O, // 0x1f
622:
623: KC_U, // 0x20
624: KC_at, // 0x21
625: KC_I, // 0x22
626: KC_P, // 0x23
627: KC_enter, // 0x24
628: KC_L, // 0x25
629: KC_J, // 0x26
630: KC_colon, // 0x27
631: KC_K, // 0x28
632: KC_semicolon, // 0x29
633: KC_bracketright,// 0x2a
634: KC_comma, // 0x2b
635: KC_slash, // 0x2c
636: KC_N, // 0x2d
637: KC_M, // 0x2e
638: KC_period, // 0x2f
639:
640: KC_TAB, // 0x30
641: KC_space, // 0x31
642: KC_none, // 0x32
643: KC_BS, // 0x33
644: KC_none, // 0x34
645: KC_ESC, // 0x35
646: KC_none, // 0x36
647: KC_none, // 0x37
648: KC_SHIFT_L, // 0x38
649: KC_none, // 0x39
650: KC_none, // 0x3a
651: KC_CTRL, // 0x3b
652: KC_SHIFT_R, // 0x3c
653: KC_none, // 0x3d
654: KC_none, // 0x3e
655: KC_none, // 0x3f
656:
657: KC_none, // 0x40
658: KC_none, // 0x41
659: KC_none, // 0x42
660: KC_none, // 0x43
661: KC_none, // 0x44
662: KC_none, // 0x45
663: KC_none, // 0x46
664: KC_none, // 0x47
665: KC_none, // 0x48
666: KC_none, // 0x49
667: KC_none, // 0x4a
668: KC_none, // 0x4b
669: KC_none, // 0x4c
670: KC_none, // 0x4d
671: KC_none, // 0x4e
672: KC_none, // 0x4f
673:
674: KC_none, // 0x50
675: KC_none, // 0x51
676: KC_none, // 0x52
677: KC_none, // 0x53
678: KC_none, // 0x54
679: KC_none, // 0x55
680: KC_none, // 0x56
681: KC_none, // 0x57
682: KC_none, // 0x58
683: KC_none, // 0x59
684: KC_none, // 0x5a
685: KC_none, // 0x5b
686: KC_none, // 0x5c
687: KC_backslash, // 0x5d
688: KC_underscore, // 0x5e
689: KC_none, // 0x5f
690:
691: KC_F5, // 0x60
692: KC_F6, // 0x61
693: KC_F7, // 0x62
694: KC_F3, // 0x63
695: KC_F8, // 0x64
696: KC_F9, // 0x65
697: KC_none, // 0x66
698: KC_none, // 0x67 F11
699: KC_none, // 0x68
700: KC_none, // 0x69
701: KC_none, // 0x6a
702: KC_none, // 0x6b
703: KC_none, // 0x6c
704: KC_F10, // 0x6d
705: KC_none, // 0x6e
706: KC_none, // 0x6f F12
707:
708: KC_none, // 0x70
709: KC_none, // 0x71
710: KC_none, // 0x72
711: KC_none, // 0x73
712: KC_none, // 0x74
713: KC_none, // 0x75
714: KC_F4, // 0x76
715: KC_none, // 0x77
716: KC_F2, // 0x78
717: KC_none, // 0x79
718: KC_F1, // 0x7a
719: KC_left, // 0x7b
720: KC_right, // 0x7c
721: KC_down, // 0x7d
722: KC_up, // 0x7e
723: KC_none, // 0x7f
724: };
725: #endif // __WXOSX__
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.