--- nono/wx/wxmainview.cpp 2026/04/29 17:05:08 1.1.1.11 +++ nono/wx/wxmainview.cpp 2026/04/29 17:05:16 1.1.1.13 @@ -48,7 +48,7 @@ #define DONT_USE_REFRESH 1 #endif -WXMainView *gMainView; +wxDEFINE_EVENT(NONO_EVT_MOUSEMODE, wxCommandEvent); wxBEGIN_EVENT_TABLE(WXMainView, inherited) EVT_PAINT(WXMainView::OnPaint) @@ -56,16 +56,25 @@ wxBEGIN_EVENT_TABLE(WXMainView, inherite EVT_KEY_UP(WXMainView::OnKeyUp) EVT_CHAR(WXMainView::OnChar) EVT_MOUSE_EVENTS(WXMainView::OnMouse) + EVT_MOUSE_CAPTURE_LOST(WXMainView::OnMouseCaptureLost) wxEND_EVENT_TABLE() WXMainView::WXMainView(wxWindow *parent) : inherited(parent) { + // デバイスを取得。Keyboard は NULL の可能性あり。 + keyboard = gMainApp.FindObject(OBJ_KEYBOARD); + renderer = GetRenderer(); + // 仮想画面(VM が描画する画面) - rendwidth = gRenderer->GetWidth(); - rendheight = gRenderer->GetHeight(); + rendwidth = renderer->GetWidth(); + rendheight = renderer->GetHeight(); + + renderer->Enable(); - gRenderer->Enable(); + // マウスモード変更イベント + Connect(NONO_EVT_MOUSEMODE, + wxCommandEventHandler(WXMainView::OnMouseMode), NULL, this); // VM からの通知を受け取る WXUIMessage::Connect(UIMessage::RENDER, this, @@ -75,7 +84,7 @@ WXMainView::WXMainView(wxWindow *parent) DoResize(screen_scale); // 更新間隔 - gRenderer->SetRefreshInterval(33_msec); + renderer->SetRefreshInterval(33_msec); // 最初に一度描画 Refresh(); @@ -87,7 +96,7 @@ WXMainView::~WXMainView() if (HasCapture()) { ReleaseMouse(); } - WXUIMessage::Disconnect(UIMessage::RENDER, + WXUIMessage::Disconnect(UIMessage::RENDER, this, wxCommandEventHandler(WXMainView::OnRender)); } @@ -144,7 +153,7 @@ WXMainView::OnPaint(wxPaintEvent& event) return; } - const BitmapRGB& bitmap0 = gRenderer->GetBitmap(); + const BitmapRGB& bitmap0 = renderer->GetBitmap(); BitmapRGB bitmap1; uint8 *p = const_cast(bitmap0.GetBuf()); @@ -195,6 +204,13 @@ WXMainView::GetScale() const // マウス入力 // +// マウスモード変更要求イベント +void +WXMainView::OnMouseMode(wxCommandEvent& event) +{ + SetMouseMode(event.GetInt()); +} + // マウスモード設定 void WXMainView::SetMouseMode(bool mode) @@ -209,7 +225,9 @@ WXMainView::SetMouseMode(bool mode) // マウスカーソル OFF ::wxSetCursor(wxCursor(wxCURSOR_BLANK)); - CaptureMouse(); + if (!HasCapture()) { + CaptureMouse(); + } // このウィンドウから外れないように移動を検出し続けるため、 // マウスカーソルをウィンドウ中央に移す。 @@ -219,7 +237,9 @@ WXMainView::SetMouseMode(bool mode) // マウスモードを OFF にする DMPRINTF("SetMouseMode OFF\n"); - ReleaseMouse(); + if (HasCapture()) { + ReleaseMouse(); + } // 分かりやすさのため、マウスカーソルを中央へ戻してから復帰 wxSize pt = GetClientSize() / 2; @@ -284,8 +304,14 @@ WXMainView::OnMouse(wxMouseEvent& event) #endif if (leaving) { - // タスクスイッチした時とかのための自動リリース - SetMouseMode(false); + // タスクスイッチした時とかのための自動リリース。 + // メインウィンドウの上にサブウィンドウが乗っているときも + // leaving が発生するので、メインウィンドウの外に出た場合のみ + // リリースする。 + auto sz = GetSize(); + if (pos.x < 0 || pos.x > sz.x || pos.y < 0 || pos.y > sz.y) { + SetMouseMode(false); + } } if (moving || dragging) { @@ -321,7 +347,9 @@ WXMainView::OnMouse(wxMouseEvent& event) (mb ? 'M' : '-'), (rb ? 'R' : '-')); - gKeyboard->MouseInput(dx, dy, rb, lb, mb); + if (keyboard) { + keyboard->MouseInput(dx, dy, rb, lb, mb); + } } prevlb = lb; @@ -333,6 +361,14 @@ WXMainView::OnMouse(wxMouseEvent& event) event.Skip(); } +// マウスキャプチャロスト +void +WXMainView::OnMouseCaptureLost(wxMouseCaptureLostEvent& event) +{ + // 外部要因でマウスキャプチャをロストしたので、マウスモードを抜ける。 + SetMouseMode(false); +} + // アクティベートイベント。 // この(トップレベル)ウィンドウにフォーカスが当たるか外れるかで飛んでくる。 // 実際には WXMainFrame 宛てに飛んできたイベントをこちらに転送してある。 @@ -378,6 +414,8 @@ WXMainView::OnActivate(wxActivateEvent& // // GetRawKeyFlags() は物理キー番号ようだ。GDK の hardware keycode らしいが、 // それ以上の詳細は不明。 +// o 環境 (OS か X かライブラリ?) によって異なるようだ。 +// 少なくとも NetBSD9 と Ubuntu20.04 では一部の値が異なる。 // o [SHIFT] キーの影響を受けない。 // GetKeyCode() では影響を受けた例外キーもここでは影響を受けない。 // o [SHIFT], [CTRL], [ALT] の各左右キーは違うコードになる。 @@ -423,7 +461,9 @@ WXMainView::OnKeyDown(wxKeyEvent& event) DKPRINTF("KeyDown "); int keycode = GetKeyCode(event); - gKeyboard->MakeKey(keycode); + if (keyboard) { + keyboard->MakeKey(keycode); + } } // キーを離した @@ -436,7 +476,9 @@ WXMainView::OnKeyUp(wxKeyEvent& event) DKPRINTF("KeyUp "); int keycode = GetKeyCode(event); - gKeyboard->BreakKey(keycode); + if (keyboard) { + keyboard->BreakKey(keycode); + } } // 文字による入力モード @@ -494,6 +536,7 @@ WXMainView::OnChar(wxKeyEvent& event) case WXK_F8: ukey = CC_F8; break; case WXK_F9: ukey = CC_F9; break; case WXK_F10: ukey = CC_F10; break; + case WXK_F11: ukey = CC_F10; break; default: ukey = 0; break; @@ -508,7 +551,9 @@ WXMainView::OnChar(wxKeyEvent& event) } ukey &= 0xff; - gKeyboard->CharInput(ukey); + if (keyboard) { + keyboard->CharInput(ukey); + } } // 共通キーコードを取得する。 @@ -559,6 +604,14 @@ WXMainView::GetKeyCode(wxKeyEvent& event #if defined(__WXGTK__) // wxGTK では日本語キーボードの一部のキーが論理キーコードだけでは // 判定できないようだ + // その上 raw キーコードも OS (か何か) によってところどころ体系が + // 異なるようだ。orz + // + // OS [^] [0] [_] [\] + // --------------- ----- ----- ----- ----- + // NetBSD9 0x15 0x13 0xd3 0x85 + // OpenBSD7.1 0x15 0x13 0xd3 0x85 + // Ubuntu20.04 0x15 0x13 0x61 0x84 // [0] と [SHIFT]+[^] が同じキーコードになるようだ if (keycode == KC_0) { @@ -568,12 +621,17 @@ WXMainView::GetKeyCode(wxKeyEvent& event keycode = KC_0; } } - // [\] と [_] が同じキーコードになるようだ + // [\] と [_] が同じキーコードになるようだ。 + // その時の raw は OS によって(?)異なるようだ。 if (keycode == KC_backslash) { - if (raw == 0xd3) { + switch (raw) { + case 0xd3: // NetBSD9 + case 0x61: // Ubuntu20.04 keycode = KC_underscore; - } else { + break; + default: keycode = KC_backslash; + break; } } #endif @@ -851,7 +909,7 @@ WXMainView::keycode_table[0x190] = { KC_F9, // 348 WXK_F9 KC_F10, // 349 WXK_F10 - 0, // 350 WXK_F11 + KC_F10, // 350 WXK_F11 0, // 351 WXK_F12 0, // 352 WXK_F13 0, // 353 WXK_F14