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