|
|
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.1.10! root 8: #include "config.h"
1.1 root 9: #include "keyboard.h"
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.10! root 54: EVT_CHAR(WXMainView::OnChar)
1.1.1.2 root 55: EVT_MOUSE_EVENTS(WXMainView::OnMouse)
1.1.1.5 root 56: EVT_TIMER(wxID_ANY, WXMainView::OnTimer)
1.1 root 57: wxEND_EVENT_TABLE()
58:
59: WXMainView::WXMainView(wxWindow *parent)
60: : inherited(parent)
61: {
62: // 仮想画面(VM が描画する画面)
63: rendwidth = gRenderer->GetWidth();
64: rendheight = gRenderer->GetHeight();
65:
66: // レンダラバッファは常に仮想画面サイズ
67: int buflen = rendwidth * rendheight * 3;
1.1.1.4 root 68: ImageBuf.reset(new uint8_t[buflen]);
69: memset(&ImageBuf[0], 0x70, buflen);
1.1 root 70: // レンダラに通知
1.1.1.4 root 71: gRenderer->SetBuf(ImageBuf.get(), wxmainview_refresh);
1.1 root 72:
73: // 実画面 (ウィンドウの大きさ)
74: DoResize(screen_scale);
75:
1.1.1.5 root 76: // 描画を律速するためのタイマー
77: timer.SetOwner(this);
78: timer.Start(33);
79:
80: // 最初に一度描画
81: Refresh();
1.1 root 82: }
83:
84: WXMainView::~WXMainView()
85: {
1.1.1.10! root 86: // マウスをリリースしないと Assert される
! 87: if (HasCapture()) {
! 88: ReleaseMouse();
! 89: }
! 90: }
! 91:
! 92: // (設定反映などの) 初期化
! 93: bool
! 94: WXMainView::Init()
! 95: {
! 96: // キーボードの入力モードの初期値設定
! 97: const ConfigItem& item_input = gConfig->Find("hostkbd-input");
! 98: const std::string input_mode = item_input.AsString();
! 99: if (input_mode == "char") {
! 100: SetCharInputMode(true);
! 101: } else if (input_mode == "jp") {
! 102: // 今は二択しかないのでちょっと噛み合ってないが
! 103: SetCharInputMode(false);
! 104: } else {
! 105: item_input.Err();
! 106: return false;
! 107: }
! 108:
! 109: return true;
1.1 root 110: }
111:
112: // リフレッシュ要求コールバック。
113: // VM から呼ばれるので一旦グローバル関数を経由する。
114: void
115: wxmainview_refresh(void)
116: {
117: gMainView->DoRefresh();
118: }
119:
120: // リフレッシュ要求コールバック。こっちが実体。
121: void
122: WXMainView::DoRefresh()
123: {
124: #if defined(DONT_USE_REFRESH)
125: // Refresh{,Rect}() が使えないので、再描画範囲は常に全体とする
126: #else
127: // 再描画範囲を更新矩形に限定
128: // XXX のはずだが、今の所全体
129: RefreshRect(wxRect(0, 0, viewwidth, viewheight), false);
130: #endif
131:
1.1.1.5 root 132: // ここは VM Renderer が画面を更新した時に呼ばれるので、本来なら
133: // ここで単に Refresh() を呼んで再描画を指示すればいいのだが、
134: // VM 高速モードになると、VM Renderer が高速で回ってここも高速で
135: // 呼ばれてしまい、その結果 Refresh() を発行しすぎて Mac では
136: // システムイベントが拾えなくなってしまう。
137: // それを避けるため、ここではフラグを立てるだけにしておいて、
138: // こちらで管理している実時間タイマーで Refresh() を律速する。
139: paint_request = true;
1.1 root 140: }
141:
1.1.1.5 root 142: // タイマーイベント
1.1 root 143: void
144: WXMainView::OnTimer(wxTimerEvent& event)
145: {
1.1.1.5 root 146: bool req = paint_request.exchange(false);
1.1 root 147: if (req) {
1.1.1.5 root 148: // 実際に再描画する
149: Refresh();
1.1 root 150: }
151: }
152:
153: // 描画イベント
154: void
155: WXMainView::OnPaint(wxPaintEvent& event)
156: {
157: if (viewwidth == 0 || viewheight == 0)
158: return;
159:
1.1.1.4 root 160: wxImage image(rendwidth, rendheight, ImageBuf.get(), true);
1.1 root 161: if (viewwidth != rendwidth || viewheight != rendheight) {
1.1.1.6 root 162: // wxIMAGE_QUALITY_NORMAL だと速いが、ここは品質優先。
163: #if _BYTE_ORDER == _BIG_ENDIAN
164: // XXX ..のはずだったが wxWidget 3.0.4 の QUALITY_HIGH は
165: // BigEndian だとバグってるようだ。QUALITY_NORMAL のほうは大丈夫。
166: auto quality = wxIMAGE_QUALITY_NORMAL;
167: #else
168: auto quality = wxIMAGE_QUALITY_HIGH;
169: #endif
170: image.Rescale(viewwidth, viewheight, quality);
1.1 root 171: }
172:
173: wxBitmap bitmap(image);
174: wxMemoryDC memDC;
175: memDC.SelectObject(bitmap);
176:
1.1.1.5 root 177: wxPaintDC dc(this);
1.1 root 178: wxRegion region(0, 0, viewwidth, viewheight);
179: wxRegionIterator ri(region);
180: for (; ri; ri++) {
181: int dx, dy, dw, dh;
182: dx = ri.GetX();
183: dy = ri.GetY();
184: dw = ri.GetWidth();
185: dh = ri.GetHeight();
186: int sx = dx;
187: int sy = dy;
188: dc.Blit(dx, dy, dw, dh, &memDC, sx, sy, wxCOPY);
189: }
190: }
191:
192: // リサイズ (UI スレッドから呼ぶこと)
193: void
194: WXMainView::DoResize(double scale)
195: {
196: screen_scale = scale;
197: int width = (double)rendwidth * scale;
198: int height = (double)rendheight * scale;
199: if (viewwidth != width || viewheight != height) {
200: // ウィンドウサイズ変更
201: viewwidth = width;
202: viewheight = height;
203: SetClientSize(viewwidth, viewheight);
1.1.1.8 root 204: SetMinClientSize(wxSize(viewwidth, viewheight));
1.1 root 205: }
206: }
207:
208: // 現在のスケールを返す。
209: // screen_scale は public static なので見えるんだけど一応お行儀で。
210: double
211: WXMainView::GetScale() const
212: {
213: return screen_scale;
214: }
215:
216: // 現在のスケール
217: /*static*/ double WXMainView::screen_scale;
218:
219:
220: //
1.1.1.2 root 221: // マウス入力
222: //
223:
224: // マウスモード設定
225: void
226: WXMainView::SetMouseMode(bool mode)
227: {
228: // XXX マウスモード ON にした時の座標を記憶してそこに戻るのはどうか
229:
230: mousemode = mode;
231: if (mousemode) {
232: // マウスモードを ON にする
233: DMPRINTF("SetMouseMode ON\n");
234:
235: // マウスカーソル OFF
236: ::wxSetCursor(wxCursor(wxCURSOR_BLANK));
237:
1.1.1.4 root 238: CaptureMouse();
239:
1.1.1.2 root 240: // このウィンドウから外れないように移動を検出し続けるため、
241: // マウスカーソルをウィンドウ中央に移す。
242: // ウィンドウとメニューバーが分離してる wxOSX のために必要。
243: MyWarpPointer(GetClientSize() / 2);
244: } else {
245: // マウスモードを OFF にする
246: DMPRINTF("SetMouseMode OFF\n");
247:
1.1.1.4 root 248: ReleaseMouse();
249:
1.1.1.2 root 250: // 分かりやすさのため、マウスカーソルを中央へ戻してから復帰
1.1.1.4 root 251: wxSize pt = GetClientSize() / 2;
252: WarpPointer(pt.x, pt.y);
1.1.1.2 root 253:
254: // マウスカーソル ON
255: ::wxSetCursor(wxNullCursor);
256: }
257: }
258:
259: // マウスカーソルをクライアント座標 (x, y) に移動
260: void
261: WXMainView::MyWarpPointer(wxSize pos)
262: {
263: DMPRINTF("MyWarpPointer %d,%d\n", pos.x, pos.y);
264:
265: // この後の MDWarpPointer() でもう一度 EVT_MOTION が飛ぶので
266: // それを判別するためのフラグ。
267: motion_by_warp_pointer = true;
268:
269: WarpPointer(pos.x, pos.y);
270: }
271:
272: // マウスイベント
273: void
274: WXMainView::OnMouse(wxMouseEvent& event)
275: {
276: // マウスモードの時だけ処理。
277: // XXX 本当はイベントごと Disconnect したい
278: if (mousemode) {
279: bool leaving = event.Leaving();
280: bool moving = event.Moving();
1.1.1.3 root 281: bool dragging = event.Dragging();
1.1.1.2 root 282: // LeftDown() 等は押された時、LeftIsDown() 等は押されてる間 true。
283: bool rb = event.RightIsDown();
284: bool lb = event.LeftIsDown();
285: bool mb = event.MiddleIsDown();
1.1.1.5 root 286: const wxPoint& pos = event.GetPosition();
1.1.1.2 root 287: int dx = 0;
288: int dy = 0;
289:
1.1.1.3 root 290: #if defined(MOUSEDEBUG)
291: std::string dstr = "OnMouse";
292: if (moving || dragging || motion_by_warp_pointer) {
293: dstr += string_format(" (%d,%d)", pos.x, pos.y);
294: }
295: if (moving)
296: dstr += " Moving";
297: if (dragging)
298: dstr += " Dragging";
299: if (motion_by_warp_pointer)
300: dstr += " MotionByWarp";
1.1.1.4 root 301: if (lb || mb || rb) {
1.1.1.3 root 302: dstr += string_format(" Button(%c%c%c)",
303: (lb ? 'L' : '-'),
304: (mb ? 'M' : '-'),
305: (rb ? 'R' : '-'));
306: }
307: if (leaving)
308: dstr += " Leaving";
309: printf("%s\n", dstr.c_str());
310: #endif
1.1.1.2 root 311:
312: if (leaving) {
313: // タスクスイッチした時とかのための自動リリース
314: SetMouseMode(false);
315: }
316:
1.1.1.3 root 317: if (moving || dragging) {
1.1.1.2 root 318: // (My)WarpPointer() で自発的にマウスカーソルを移動させたことで
319: // 来る EVT_MOTION は無視する。
320: if (motion_by_warp_pointer) {
321: motion_by_warp_pointer = false;
322: // ここを基準点にする
323: prevpos = pos;
324: } else {
325: // 前回からの差を求める
326: dx = pos.x - prevpos.x;
327: dy = pos.y - prevpos.y;
328: prevpos = pos;
329:
330: // マウスカーソルを中心に戻す
331: if (dx != 0 || dy != 0) {
332: MyWarpPointer(GetClientSize() / 2);
333: }
334: }
335: }
336:
337: // VM に入力
1.1.1.3 root 338: if (dx != 0 ||
339: dy != 0 ||
340: lb != prevlb ||
341: mb != prevmb ||
342: rb != prevrb )
343: {
1.1.1.2 root 344: DMPRINTF(" Input dx=%d dy=%d %c%c%c\n",
345: dx, dy,
346: (lb ? 'L' : '-'),
347: (mb ? 'M' : '-'),
348: (rb ? 'R' : '-'));
349:
350: gKeyboard->MouseInput(dx, dy, rb, lb, mb);
351: }
1.1.1.3 root 352:
353: prevlb = lb;
354: prevmb = mb;
355: prevrb = rb;
1.1.1.2 root 356: }
357:
358: // EVT_LEFT_DOWN をデフォルト処理するため
359: event.Skip();
360: }
361:
1.1.1.4 root 362: // アクティベートイベント。
363: // この(トップレベル)ウィンドウにフォーカスが当たるか外れるかで飛んでくる。
364: // 実際には WXMainFrame 宛てに飛んできたイベントをこちらに転送してある。
365: // マウスモード中にこのウィンドウからフォーカスが外れたら (例えば ALT+TAB の
366: // ようなウィンドウを切り替える操作)、マウスモードを解除するため。
367: void
368: WXMainView::OnActivate(wxActivateEvent& event)
369: {
370: // フォーカスが外れる際にマウスモード中ならマウスモードを解除
371: if (event.GetActive() == false) {
372: DMPRINTF("OnActivate FocusOut\n");
373: if (mousemode) {
374: SetMouseMode(false);
375: }
376: } else {
377: DMPRINTF("OnActivate FocusIn\n");
378: }
379: }
380:
381:
1.1.1.2 root 382: //
1.1 root 383: // キー入力
384: //
385:
386: // wxKeyEvent でキーコードを得るためのメソッドは
387: // GetKeyCode()、GetRawKeyCode()、GetRawKeyFlags() の3つが用意されていて
1.1.1.10! root 388: // wxWidgets の port (wxGTK、wxOSX とか) によってそれぞれ内容の定義が違う。
1.1 root 389: //
390: // wxGTK の場合
1.1.1.8 root 391: // GetKeyCode() が論理キーコードなのでこれをメインに使う。ただし左右 [SHIFT]
392: // のように論理キーコードだけでは区別の付かないものについては物理キー番号で
393: // ある GetRawKeyFlags() を併用する。
394: //
395: // 以下詳細。
1.1 root 396: // GetKeyCode() は wxWidgets の WXK_* (/usr/pkg/include/wx-3.0/wx/defs.h)。
1.1.1.8 root 397: // これは概ね論理キーコードであり、xorg.conf の swapcaps 設定や Xmodmap の
398: // 影響をうける。
399: // o 基本的に [SHIFT] キーの影響を受けないが、一部例外がある。
400: // - [^] (0x5e) と [SHIFT]+[^] (0x30)
401: // - [,] (0x2c) と [SHIFT]+[,] (0x3c)
402: // o [\] と [_] は同じ 0x5c になる ([SHIFT] 押しながらでも同様)。
403: // o [SHIFT], [CTRL], [ALT] の各左右キーは同じコードになる。
404: //
405: // GetRawKeyFlags() は物理キー番号ようだ。GDK の hardware keycode らしいが、
406: // それ以上の詳細は不明。
407: // o [SHIFT] キーの影響を受けない。
408: // GetKeyCode() では影響を受けた例外キーもここでは影響を受けない。
409: // o [SHIFT], [CTRL], [ALT] の各左右キーは違うコードになる。
1.1 root 410: //
411: // GetRawKeyCode() は GDK の keycode っぽい?
412: // (/usr/pkg/include/gtk-2.0/gdk/gdkkeysyms.h)。
413: // X11 の keysym から来てる? (/usr/X11R7/include/X11/keysymdef.h)。
1.1.1.8 root 414: // ただし [A] と [SHIFT]+[A] が違うコードを返すというか、文字コードで表現
415: // 出来る時は文字コード、みたいな感じになっているのでここでは使いづらい。
1.1 root 416: // 左右の SHIFT は区別可能。
417: //
418: // wxOSX の場合
419: // GetKeyCode()
1.1.1.8 root 420: // 英字キー [A] と [SHIFT]+[A] は同じコードになるが、
421: // 記号キー [1] と [SHIFT]+[1] は別になる体系のようだ。
422: // 左右の [SHIFT] は区別できない。
1.1 root 423: //
424: // GetRawKeyCode()
1.1.1.8 root 425: // これがたぶん物理キー番号。
426: // [1] と [SHIFT]+[1] は同じコードを返す。
427: // 左右の [SHIFT] は区別可能。
1.1 root 428: //
429: // GetRawKeyFlags() は状態フラグか何かのようだ。
430: //
431:
1.1.1.10! root 432: // 入力モード変更
! 433: void
! 434: WXMainView::SetCharInputMode(bool enable)
! 435: {
! 436: is_charinput = enable;
! 437: }
! 438:
1.1 root 439: // キーを押した
440: void
441: WXMainView::OnKeyDown(wxKeyEvent& event)
442: {
1.1.1.10! root 443: // メニューのアクセラレータのために必要
! 444: event.Skip();
! 445:
! 446: if (is_charinput) {
! 447: return;
! 448: }
! 449:
1.1.1.2 root 450: DKPRINTF("KeyDown ");
1.1 root 451: int keycode = GetKeyCode(event);
452: gKeyboard->MakeKey(keycode);
453: }
454:
455: // キーを離した
456: void
457: WXMainView::OnKeyUp(wxKeyEvent& event)
458: {
1.1.1.10! root 459: if (is_charinput) {
! 460: return;
! 461: }
! 462:
1.1.1.2 root 463: DKPRINTF("KeyUp ");
1.1 root 464: int keycode = GetKeyCode(event);
465: gKeyboard->BreakKey(keycode);
466: }
467:
1.1.1.10! root 468: // 文字による入力モード
! 469: void
! 470: WXMainView::OnChar(wxKeyEvent& event)
! 471: {
! 472: if (!is_charinput) {
! 473: return;
! 474: }
! 475:
! 476: uint ukey = event.GetUnicodeKey();
! 477: uint ukey_orig = ukey;
! 478: DKPRINTF("Char uni=0x%02x", ukey);
! 479: if (0x20 <= ukey && ukey < 0x7f) {
! 480: DKPRINTF(" '%c'", ukey);
! 481: }
! 482:
! 483: bool ctrl = event.ControlDown();
! 484: if (ctrl) {
! 485: DKPRINTF(" CTRL");
! 486:
! 487: // Ctrl + A .. Ctrl + Z までは 0x01(^A) .. 0x1a(^Z) の文字が来るが、
! 488: // Ctrl + 記号は記号の文字コードだけが送られてくるようだ。
! 489: // Ctrl + [ は 0x1b('^[') ではなく 0x5b('[') のような感じ。
! 490: // そこでこの場合は Ctrl キーが押されているかどうかを別途判定する。
! 491: if (0x40 <= ukey && ukey <= 0x5f) {
! 492: ukey -= 0x40;
! 493: // Ctrl+@ ('\0') はそのまま通せないので、別文字にエスケープ。
! 494: if (ukey == 0) {
! 495: ukey = CC_NUL;
! 496: }
! 497: }
! 498: }
! 499: // 文字コードが拾えなければキーコードから
! 500: if (ukey == WXK_NONE) {
! 501: uint wxkey = event.GetKeyCode();
! 502: DKPRINTF(" key=%3u(0x%03x)", wxkey, wxkey);
! 503: // 一部の特殊キーをここで対応。
! 504: // キーボード国籍による違いはないだろう。
! 505: switch (wxkey) {
! 506: case WXK_LEFT: ukey = CC_left; break;
! 507: case WXK_UP: ukey = CC_up; break;
! 508: case WXK_RIGHT: ukey = CC_right; break;
! 509: case WXK_DOWN: ukey = CC_down; break;
! 510: case WXK_F1: ukey = CC_F1; break;
! 511: case WXK_F2: ukey = CC_F2; break;
! 512: case WXK_F3: ukey = CC_F3; break;
! 513: case WXK_F4: ukey = CC_F4; break;
! 514: case WXK_F5: ukey = CC_F5; break;
! 515: case WXK_F6: ukey = CC_F6; break;
! 516: case WXK_F7: ukey = CC_F7; break;
! 517: case WXK_F8: ukey = CC_F8; break;
! 518: case WXK_F9: ukey = CC_F9; break;
! 519: case WXK_F10: ukey = CC_F10; break;
! 520: default:
! 521: ukey = 0;
! 522: break;
! 523: }
! 524: }
! 525: if (ukey != ukey_orig) {
! 526: DKPRINTF(" -> 0x%02x", ukey);
! 527: }
! 528: DKPRINTF("\n");
! 529: if (ukey == 0) {
! 530: return;
! 531: }
! 532: ukey &= 0xff;
! 533:
! 534: gKeyboard->CharInput(ukey);
! 535: }
! 536:
1.1 root 537: // 共通キーコードを取得する。
538: // 対応するキーがない場合は -1 を返す。
539: int
540: WXMainView::GetKeyCode(wxKeyEvent& event)
541: {
542: uint32 wxcode __unused = event.GetKeyCode();
543: uint32 rawcode __unused = event.GetRawKeyCode();
544: uint32 rawflags __unused = event.GetRawKeyFlags();
1.1.1.8 root 545: uint32 raw;
1.1 root 546: int keycode;
547:
1.1.1.8 root 548: // wx キーコードは10進、16進併記しないと読みづらい
549: DKPRINTF("key=%3d(0x%03x) ", wxcode, wxcode);
550: #if defined(__WXOSX__)
551: // wxOSX では raw が物理キー、flags はフラグっぽいものなので不要
552: DKPRINTF("raw=0x%02x (flags=0x%06x) ", rawcode, rawflags);
553: raw = rawcode;
554: #else
555: // wxGTK では flags が物理キー、raw は文字コードっぽいものなので不要
556: DKPRINTF("flags=0x%02x (raw=0x%04x) ", rawflags, rawcode);
557: raw = rawflags;
1.1 root 558: #endif
559:
1.1.1.8 root 560: // まず wx キーコードでテーブルを引く
561: if (wxcode < countof(keycode_table)) {
562: keycode = keycode_table[wxcode];
1.1 root 563: } else {
564: keycode = KC_none;
565: }
1.1.1.8 root 566:
567: // wx キーコードは論理キーコードなので [SHIFT] キーの左右を区別できないが
568: // ここでは左右を区別したいので、物理キー番号を見て区別する。
569: if (keycode == KC_SHIFT) {
570: #if defined(__WXOSX__)
571: if (raw == 0x3c)
572: #else
573: if (raw == 0x3e)
574: #endif
575: {
576: keycode = KC_SHIFT_R;
577: } else {
578: keycode = KC_SHIFT_L;
579: }
580: }
1.1 root 581:
582: #if defined(__WXGTK__)
1.1.1.8 root 583: // wxGTK では日本語キーボードの一部のキーが論理キーコードだけでは
584: // 判定できないようだ
1.1 root 585:
1.1.1.8 root 586: // [0] と [SHIFT]+[^] が同じキーコードになるようだ
587: if (keycode == KC_0) {
588: if (raw == 0x15) {
589: keycode = KC_circum;
590: } else {
591: keycode = KC_0;
592: }
593: }
594: // [\] と [_] が同じキーコードになるようだ
595: if (keycode == KC_backslash) {
596: if (raw == 0xd3) {
597: keycode = KC_underscore;
598: } else {
599: keycode = KC_backslash;
600: }
601: }
602: #endif
603:
1.1.1.9 root 604: DKPRINTF("keycode=%d %s\n", keycode, Keyboard::GetKeyName(keycode).c_str());
1.1.1.8 root 605: return keycode;
606: }
607:
608: // wx キーコード(WXK_*)を共通キーコードに変換するテーブル。
609: // 一部このテーブルだけでは判定できないものがある。すぐ上の GetKeyCode() 参照。
610: // 値 0 は本当は KC_none と書くべきだが、こっちのほうが読みやすいので。
611: //
612: // XXX: OSX の [CAPS] は押す離すで一回分の Down しか来ないのでちょっと放置。
613: // XXX: OSX の [英数] と [かな] もちょっと放置。
1.1 root 614: /*static*/ const int
1.1.1.8 root 615: WXMainView::keycode_table[0x190] = {
616: 0, // 0x00
617: 0, // 0x01
618: 0, // 0x02
619: 0, // 0x03
620: 0, // 0x04
621: 0, // 0x05
622: 0, // 0x06
623: 0, // 0x07
624: KC_BS, // 0x08 WXK_BACK
625: KC_TAB, // 0x09 WXK_TAB
626: 0, // 0x0a
627: 0, // 0x0b
628: 0, // 0x0c
629: KC_enter, // 0x0d WXK_RETURN
630: 0, // 0x0e
631: 0, // 0x0f
632:
633: 0, // 0x10
634: 0, // 0x11
635: 0, // 0x12
636: 0, // 0x13
637: 0, // 0x14
638: 0, // 0x15
639: 0, // 0x16
640: 0, // 0x17
641: 0, // 0x18
642: 0, // 0x19
643: 0, // 0x1a
644: KC_ESC, // 0x1b WXK_ESCAPE
645: 0, // 0x1c
646: 0, // 0x1d
647: 0, // 0x1e
648: 0, // 0x1f
649:
650: KC_space, // 0x20 WXK_SPACE
651: KC_1, // 0x21 (OSX: [SHIFT]+[1])
652: KC_2, // 0x22 (OSX: [SHIFT]+[2])
653: KC_3, // 0x23 (OSX: [SHIFT]+[3])
654: KC_4, // 0x24 (OSX: [SHIFT]+[4])
655: KC_5, // 0x25 (OSX: [SHIFT]+[5])
656: KC_6, // 0x26 (OSX: [SHIFT]+[6])
657: KC_7, // 0x27 (OSX: [SHIFT]+[7])
658: KC_8, // 0x28 (OSX: [SHIFT]+[8])
659: KC_9, // 0x29 (OSX: [SHIFT]+[9])
660: KC_colon, // 0x2a (OSX: [SHIFT]+[:])
661: KC_semicolon, // 0x2b (OSX: [SHIFT]+[;])
662: KC_comma, // 0x2c
663: KC_minus, // 0x2d
664: KC_period, // 0x2e
665: KC_slash, // 0x2f
666:
667: KC_0, // 0x30 (GTK: [0] と [SHIFT]+[^])
668: KC_1, // 0x31
669: KC_2, // 0x32
670: KC_3, // 0x33
671: KC_4, // 0x34
672: KC_5, // 0x35
673: KC_6, // 0x36
674: KC_7, // 0x37
675: KC_8, // 0x38
676: KC_9, // 0x39
677: KC_colon, // 0x3a
678: KC_semicolon, // 0x3b
679: KC_comma, // 0x3c (GTK: [,]は0x2c だが [SHIFT]+[,]は0x3c)
680: KC_minus, // 0x3d (OSX: [SHIFT]+[-])
681: KC_period, // 0x3e (OSX: [SHIFT]+[.])
682: KC_slash, // 0x3f (OSX: [SHIFT]+[/])
683:
684: KC_at, // 0x40
685: KC_A, // 0x41
686: KC_B, // 0x42
687: KC_C, // 0x43
688: KC_D, // 0x44
689: KC_E, // 0x45
690: KC_F, // 0x46
691: KC_G, // 0x47
692: KC_H, // 0x48
693: KC_I, // 0x49
694: KC_J, // 0x4a
695: KC_K, // 0x4b
696: KC_L, // 0x4c
697: KC_M, // 0x4d
698: KC_N, // 0x4e
699: KC_O, // 0x4f
700:
701: KC_P, // 0x50
702: KC_Q, // 0x51
703: KC_R, // 0x52
704: KC_S, // 0x53
705: KC_T, // 0x54
706: KC_U, // 0x55
707: KC_V, // 0x56
708: KC_W, // 0x57
709: KC_X, // 0x58
710: KC_Y, // 0x59
711: KC_Z, // 0x5a
712: KC_bracketleft, // 0x5b
713: KC_backslash, // 0x5c (GTK: [\] と [_])
714: KC_bracketright,// 0x5d
715: KC_circum, // 0x5e
716: KC_underscore, // 0x5f (OSX: [_])
717:
718: KC_at, // 0x60 (OSX: [SHIFT]+[@])
719: 0, // 0x61
720: 0, // 0x62
721: 0, // 0x63
722: 0, // 0x64
723: 0, // 0x65
724: 0, // 0x66
725: 0, // 0x67
726: 0, // 0x68
727: 0, // 0x69
728: 0, // 0x6a
729: 0, // 0x6b
730: 0, // 0x6c
731: 0, // 0x6d
732: 0, // 0x6e
733: 0, // 0x6f
734:
735: 0, // 0x70
736: 0, // 0x71
737: 0, // 0x72
738: 0, // 0x73
739: 0, // 0x74
740: 0, // 0x75
741: 0, // 0x76
742: 0, // 0x77
743: 0, // 0x78
744: 0, // 0x79
745: 0, // 0x7a
746: KC_bracketleft, // 0x7b (OSX: [SHIFT]+[[])
747: KC_backslash, // 0x7c (OSX: [SHIFT]+[\])
748: KC_bracketright,// 0x7d (OSX: [SHIFT]+[]])
749: KC_circum, // 0x7e (OSX: [SHIFT]+[^])
750: KC_DEL, // 0x7f
751:
752: 0,0,0,0, 0,0,0,0, // 0x80
753: 0,0,0,0, 0,0,0,0, // 0x88
754: 0,0,0,0, 0,0,0,0, // 0x90
755: 0,0,0,0, 0,0,0,0, // 0x98
756:
757: 0, // 0xa0
758: 0, // 0xa1
759: 0, // 0xa2
760: 0, // 0xa3
761: 0, // 0xa4
762: KC_backslash, // 0xa5 (OSX: [\])
763: 0, // 0xa6
764: 0, // 0xa7
765: 0, // 0xa8
766: 0, // 0xa9
767: 0, // 0xaa
768: 0, // 0xab
769: 0, // 0xac
770: 0, // 0xad
771: 0, // 0xae
772: 0, // 0xaf
773:
774: 0,0,0,0, 0,0,0,0, // 0xb0
775: 0,0,0,0, 0,0,0,0, // 0xb8
776:
777: 0, // 0xc0=192
778: 0, // 193 WXK_SPECIAL1
779: 0, // 194 WXK_SPECIAL2
780: 0, // 195 WXK_SPECIAL3
781: 0, // 196 WXK_SPECIAL4
782: 0, // 197 WXK_SPECIAL5
783: 0, // 198 WXK_SPECIAL6
784: 0, // 199 WXK_SPECIAL7
785:
786: 0, // 200 WXK_SPECIAL8
787: 0, // 201 WXK_SPECIAL9
788: 0, // 202 WXK_SPECIAL10
789: 0, // 203 WXK_SPECIAL11
790: 0, // 204 WXK_SPECIAL12
791: 0, // 205 WXK_SPECIAL13
792: 0, // 206 WXK_SPECIAL14
793: 0, // 207 WXK_SPECIAL15
794: 0, // 208 WXK_SPECIAL16
795: 0, // 209 WXK_SPECIAL17
796:
797: 0, // 210 WXK_SPECIAL18
798: 0, // 211 WXK_SPECIAL19
799: 0, // 212 WXK_SPECIAL20
800: 0, // 0xd5
801: 0, // 0xd6
802: 0, // 0xd7
803:
804: 0,0,0,0, 0,0,0,0, // 0xd8
805: 0,0,0,0, 0,0,0,0, // 0xe0
806: 0,0,0,0, 0,0,0,0, // 0xe8
807: 0,0,0,0, 0,0,0,0, // 0xf0
808: 0,0,0,0, 0,0,0,0, // 0xf8
809: 0,0,0,0, 0,0,0,0, // 0x100
810: 0,0,0,0, 0,0,0,0, // 0x108
811: 0,0,0,0, 0,0,0,0, // 0x110
812: 0,0,0,0, 0,0,0,0, // 0x118
813: 0,0,0,0, 0,0,0,0, // 0x120
814:
815: 0, // 0x128
816: 0, // 0x129
817: 0, // 0x12a
818: 0, // 0x12b
819: //
820: // WXK_* は10進数で定義されていて、特殊キーは 300 (=0x12c) から。
821: //
822: 0, // 300 WXK_START
823: 0, // 301 WXK_LBUTTON
824: 0, // 302 WXK_RBUTTON
825: 0, // 303 WXK_CANCEL
826: 0, // 304 WXK_MBUTTON
827: 0, // 305 WXK_CLEAR
828: KC_SHIFT, // 306 WXK_SHIFT (左右[SHIFT])
829: 0, // 307 WXK_ALT
830: KC_CTRL, // 308 WXK_CONTROL (ゲストに右[CTRL]はないので区別不要)
831: 0, // 309 WXK_MENU
832:
833: 0, // 310 WXK_PAUSE
834: 0, // 311 WXK_CAPITAL
835: 0, // 312 WXK_END
836: 0, // 313 WXK_HOME
837: KC_left, // 314 WXK_LEFT
838: KC_up, // 315 WXK_UP
839: KC_right, // 316 WXK_RIGHT
840: KC_down, // 317 WXK_DOWN
841: 0, // 318 WXK_SELECT
842: 0, // 319 WXK_PRINT
843:
844: 0, // 320 WXK_EXECUTE
845: 0, // 321 WXK_SNAPSHOT
846: KC_INS, // 322 WXK_INSERT
847: 0, // 323 WXK_HELP
848: KC_PAD_0, // 324 WXK_NUMPAD0
849: KC_PAD_1, // 325 WXK_NUMPAD1
850: KC_PAD_2, // 326 WXK_NUMPAD2
851: KC_PAD_3, // 327 WXK_NUMPAD3
852: KC_PAD_4, // 328 WXK_NUMPAD4
853: KC_PAD_5, // 329 WXK_NUMPAD5
854:
855: KC_PAD_6, // 330 WXK_NUMPAD6
856: KC_PAD_7, // 331 WXK_NUMPAD7
857: KC_PAD_8, // 332 WXK_NUMPAD8
858: KC_PAD_9, // 333 WXK_NUMPAD9
859: 0, // 334 WXK_MULTIPLY
860: 0, // 335 WXK_ADD
861: 0, // 336 WXK_SEPARATOR
862: 0, // 337 WXK_SUBTRACT
863: 0, // 338 WXK_DECIMAL
864: 0, // 339 WXK_DIVIDE
865:
866: KC_F1, // 340 WXK_F1
867: KC_F2, // 341 WXK_F2
868: KC_F3, // 342 WXK_F3
869: KC_F4, // 343 WXK_F4
870: KC_F5, // 344 WXK_F5
871: KC_F6, // 345 WXK_F6
872: KC_F7, // 346 WXK_F7
873: KC_F8, // 347 WXK_F8
874: KC_F9, // 348 WXK_F9
875: KC_F10, // 349 WXK_F10
876:
877: 0, // 350 WXK_F11
878: 0, // 351 WXK_F12
879: 0, // 352 WXK_F13
880: 0, // 353 WXK_F14
881: 0, // 354 WXK_F15
882: 0, // 355 WXK_F16
883: 0, // 356 WXK_F17
884: 0, // 357 WXK_F18
885: 0, // 358 WXK_F19
886: 0, // 359 WXK_F20
887:
888: 0, // 360 WXK_F21
889: 0, // 361 WXK_F22
890: 0, // 362 WXK_F23
891: 0, // 363 WXK_F24
892: 0, // 364 WXK_NUMLOCK
893: 0, // 365 WXK_SCROLL
894: 0, // 366 WXK_PAGEUP
895: 0, // 367 WXK_PAGEDOWN
896: 0, // 368 WXK_NUMPAD_SPACE
897: 0, // 369 WXK_NUMPAD_TAB
898:
899: KC_PAD_enter, // 370 WXK_NUMPAD_ENTER
900: 0, // 371 WXK_NUMPAD_F1
901: 0, // 372 WXK_NUMPAD_F2
902: 0, // 373 WXK_NUMPAD_F3
903: 0, // 374 WXK_NUMPAD_F4
904: 0, // 375 WXK_NUMPAD_HOME
905: 0, // 376 WXK_NUMPAD_LEFT
906: 0, // 377 WXK_NUMPAD_UP
907: 0, // 378 WXK_NUMPAD_RIGHT
908: 0, // 379 WXK_NUMPAD_DOWN
909:
910: 0, // 380 WXK_NUMPAD_PAGEUP
911: 0, // 381 WXK_NUMPAD_PAGEDOWN
912: 0, // 382 WXK_NUMPAD_END
913: 0, // 383 WXK_NUMPAD_BEGIN
914: 0, // 384 WXK_NUMPAD_INSERT
915: 0, // 385 WXK_NUMPAD_DELETE
1.1.1.10! root 916: KC_PAD_equal, // 386 WXK_NUMPAD_EQUAL
1.1.1.8 root 917: KC_PAD_multiply,// 387 WXK_NUMPAD_MULTIPLY
918: KC_PAD_plus, // 388 WXK_NUMPAD_ADD
919: 0, // 389 WXK_NUMPAD_SEPARATOR
920:
921: KC_PAD_minus, // 390 WXK_NUMPAD_SUBTRACT
922: KC_PAD_decimal, // 391 WXK_NUMPAD_DECIMAL
923: KC_PAD_divide, // 392 WXK_NUMPAD_DIVIDE
924: 0, // 393 WXK_WINDOWS_LEFT
925: 0, // 394 WXK_WINDOWS_RIGHT
926: 0, // 395 WXK_WINDOWS_MENU
927: // WXK_RAW_CONTROL は wxOSX でのみ定義してあり (wxOSX 以外では別名)、
928: // wxOSX とそれ以外とで定義済みキーの最大値が違う。そこが可変だとこの
929: // テーブルが困るので、wxOSX 以外でも常に WXK_RAW_CONTROL 分の枠は用意
930: // することにする。wxOSX 以外だと飛んでこないというだけで害はない。
931: KC_CTRL, // 396 WXK_RAW_CONTROL (OSX)
932:
933: 0, // 397
934: 0, // 398
935: 0, // 399=0x18f
1.1 root 936: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.