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