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