--- nono/wx/wxmainview.cpp 2026/04/29 17:04:28 1.1 +++ nono/wx/wxmainview.cpp 2026/04/29 17:04:33 1.1.1.3 @@ -5,6 +5,7 @@ #include "wxheader.h" #include "keyboard.h" +#include "mystring.h" #include "renderer.h" #include "scheduler.h" #include "wxmainview.h" @@ -15,11 +16,18 @@ #endif //#define KEYDEBUG 1 +//#define MOUSEDEBUG 1 #if defined(KEYDEBUG) -#define DPRINTF(...) printf(__VA_ARGS__) +#define DKPRINTF(...) printf(__VA_ARGS__) #else -#define DPRINTF(...) /**/ +#define DKPRINTF(...) /**/ +#endif + +#if defined(MOUSEDEBUG) +#define DMPRINTF(...) printf(__VA_ARGS__) +#else +#define DMPRINTF(...) /**/ #endif // 再描画矩形の指定方法について。 @@ -47,6 +55,7 @@ wxBEGIN_EVENT_TABLE(WXMainView, inherite EVT_PAINT(WXMainView::OnPaint) EVT_KEY_DOWN(WXMainView::OnKeyDown) EVT_KEY_UP(WXMainView::OnKeyUp) + EVT_MOUSE_EVENTS(WXMainView::OnMouse) EVT_TIMER(TIMERID_PAINTTIMER, WXMainView::OnTimer) wxEND_EVENT_TABLE() @@ -183,6 +192,143 @@ WXMainView::GetScale() const // +// マウス入力 +// + +// マウスモード設定 +void +WXMainView::SetMouseMode(bool mode) +{ + // XXX マウスモード ON にした時の座標を記憶してそこに戻るのはどうか + + mousemode = mode; + if (mousemode) { + // マウスモードを ON にする + DMPRINTF("SetMouseMode ON\n"); + + // マウスカーソル OFF + ::wxSetCursor(wxCursor(wxCURSOR_BLANK)); + + // このウィンドウから外れないように移動を検出し続けるため、 + // マウスカーソルをウィンドウ中央に移す。 + // ウィンドウとメニューバーが分離してる wxOSX のために必要。 + MyWarpPointer(GetClientSize() / 2); + } else { + // マウスモードを OFF にする + DMPRINTF("SetMouseMode OFF\n"); + + // 分かりやすさのため、マウスカーソルを中央へ戻してから復帰 + MyWarpPointer(GetClientSize() / 2); + + // マウスカーソル ON + ::wxSetCursor(wxNullCursor); + } +} + +// マウスカーソルをクライアント座標 (x, y) に移動 +void +WXMainView::MyWarpPointer(wxSize pos) +{ + DMPRINTF("MyWarpPointer %d,%d\n", pos.x, pos.y); + + // この後の MDWarpPointer() でもう一度 EVT_MOTION が飛ぶので + // それを判別するためのフラグ。 + motion_by_warp_pointer = true; + + WarpPointer(pos.x, pos.y); +} + +// マウスイベント +void +WXMainView::OnMouse(wxMouseEvent& event) +{ + // マウスモードの時だけ処理。 + // XXX 本当はイベントごと Disconnect したい + if (mousemode) { + bool leaving = event.Leaving(); + bool moving = event.Moving(); + bool dragging = event.Dragging(); + // LeftDown() 等は押された時、LeftIsDown() 等は押されてる間 true。 + bool rb = event.RightIsDown(); + bool lb = event.LeftIsDown(); + bool mb = event.MiddleIsDown(); + wxPoint pos = event.GetPosition(); + int dx = 0; + int dy = 0; + +#if defined(MOUSEDEBUG) + std::string dstr = "OnMouse"; + if (moving || dragging || motion_by_warp_pointer) { + dstr += string_format(" (%d,%d)", pos.x, pos.y); + } + if (moving) + dstr += " Moving"; + if (dragging) + dstr += " Dragging"; + if (motion_by_warp_pointer) + dstr += " MotionByWarp"; + if (event.IsButton()) { + dstr += string_format(" Button(%c%c%c)", + (lb ? 'L' : '-'), + (mb ? 'M' : '-'), + (rb ? 'R' : '-')); + } + if (leaving) + dstr += " Leaving"; + printf("%s\n", dstr.c_str()); +#endif + + if (leaving) { + // タスクスイッチした時とかのための自動リリース + SetMouseMode(false); + } + + if (moving || dragging) { + // (My)WarpPointer() で自発的にマウスカーソルを移動させたことで + // 来る EVT_MOTION は無視する。 + if (motion_by_warp_pointer) { + motion_by_warp_pointer = false; + // ここを基準点にする + prevpos = pos; + } else { + // 前回からの差を求める + dx = pos.x - prevpos.x; + dy = pos.y - prevpos.y; + prevpos = pos; + + // マウスカーソルを中心に戻す + if (dx != 0 || dy != 0) { + MyWarpPointer(GetClientSize() / 2); + } + } + } + + // VM に入力 + if (dx != 0 || + dy != 0 || + lb != prevlb || + mb != prevmb || + rb != prevrb ) + { + DMPRINTF(" Input dx=%d dy=%d %c%c%c\n", + dx, dy, + (lb ? 'L' : '-'), + (mb ? 'M' : '-'), + (rb ? 'R' : '-')); + + gKeyboard->MouseInput(dx, dy, rb, lb, mb); + } + + prevlb = lb; + prevmb = mb; + prevrb = rb; + } + + // EVT_LEFT_DOWN をデフォルト処理するため + event.Skip(); +} + +// // キー入力 // @@ -225,16 +371,19 @@ WXMainView::GetScale() const void WXMainView::OnKeyDown(wxKeyEvent& event) { - DPRINTF("KeyDown "); + DKPRINTF("KeyDown "); int keycode = GetKeyCode(event); gKeyboard->MakeKey(keycode); + + // メニューのアクセラレータのために必要 + event.Skip(); } // キーを離した void WXMainView::OnKeyUp(wxKeyEvent& event) { - DPRINTF("KeyUp "); + DKPRINTF("KeyUp "); int keycode = GetKeyCode(event); gKeyboard->BreakKey(keycode); } @@ -252,11 +401,13 @@ WXMainView::GetKeyCode(wxKeyEvent& event #if defined(__WXGTK__) // wxGTK では RawKeyFlags を使う - DPRINTF("key=0x%03x raw=0x%04x ", wxcode, rawcode, rawflags); + DKPRINTF("key=0x%03x raw=0x%04x ", + wxcode, rawcode, rawflags); inp = rawflags; #elif defined(__WXOSX__) // wxOSX では RawKeyCode を使う - DPRINTF("key=0x%03x flags=0x%06x ", wxcode, rawcode, rawflags); + DKPRINTF("key=0x%03x flags=0x%06x ", + wxcode, rawcode, rawflags); inp = rawcode; #endif @@ -266,7 +417,7 @@ WXMainView::GetKeyCode(wxKeyEvent& event } else { keycode = KC_none; } - DPRINTF("keycode=%d %s\n", keycode, Keyboard::keyname[keycode]); + DKPRINTF("keycode=%d %s\n", keycode, Keyboard::keyname[keycode]); return keycode; }