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