Annotation of nono/wx/wxmainview.cpp, revision 1.1.1.17

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.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.16  root       65:        SetName("WXMainView");
                     66: 
                     67:        // デバイスを取得。
1.1.1.13  root       68:        renderer = GetRenderer();
                     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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.