--- nono/wx/wxmainview.cpp 2026/04/29 17:04:37 1.1.1.4 +++ nono/wx/wxmainview.cpp 2026/04/29 17:04:51 1.1.1.7 @@ -6,7 +6,6 @@ #include "wxmainview.h" #include "keyboard.h" -#include "mystring.h" #include "renderer.h" #include "scheduler.h" #include @@ -43,8 +42,6 @@ #define DONT_USE_REFRESH 1 #endif -#define TIMERID_PAINTTIMER 1 - static void wxmainview_refresh(); WXMainView *gMainView; @@ -54,7 +51,7 @@ wxBEGIN_EVENT_TABLE(WXMainView, inherite EVT_KEY_DOWN(WXMainView::OnKeyDown) EVT_KEY_UP(WXMainView::OnKeyUp) EVT_MOUSE_EVENTS(WXMainView::OnMouse) - EVT_TIMER(TIMERID_PAINTTIMER, WXMainView::OnTimer) + EVT_TIMER(wxID_ANY, WXMainView::OnTimer) wxEND_EVENT_TABLE() WXMainView::WXMainView(wxWindow *parent) @@ -74,9 +71,12 @@ WXMainView::WXMainView(wxWindow *parent) // 実画面 (ウィンドウの大きさ) DoResize(screen_scale); - paintTimer.SetOwner(this, TIMERID_PAINTTIMER); - paintTimer.Start(16); - paintRequested = true; // first paint request + // 描画を律速するためのタイマー + timer.SetOwner(this); + timer.Start(33); + + // 最初に一度描画 + Refresh(); } WXMainView::~WXMainView() @@ -103,19 +103,24 @@ WXMainView::DoRefresh() RefreshRect(wxRect(0, 0, viewwidth, viewheight), false); #endif - // PAINT イベントを投げる - // XXX んだけど mac だと投げすぎるとシステムイベントを拾えなくなってしまう - paintRequested = true; + // ここは VM Renderer が画面を更新した時に呼ばれるので、本来なら + // ここで単に Refresh() を呼んで再描画を指示すればいいのだが、 + // VM 高速モードになると、VM Renderer が高速で回ってここも高速で + // 呼ばれてしまい、その結果 Refresh() を発行しすぎて Mac では + // システムイベントが拾えなくなってしまう。 + // それを避けるため、ここではフラグを立てるだけにしておいて、 + // こちらで管理している実時間タイマーで Refresh() を律速する。 + paint_request = true; } +// タイマーイベント void WXMainView::OnTimer(wxTimerEvent& event) { - bool req = paintRequested.exchange(false); + bool req = paint_request.exchange(false); if (req) { - // PAINT イベントを投げる - wxPaintEvent *ev = new wxPaintEvent(); - QueueEvent(ev); + // 実際に再描画する + Refresh(); } } @@ -123,29 +128,27 @@ WXMainView::OnTimer(wxTimerEvent& event) void WXMainView::OnPaint(wxPaintEvent& event) { - wxClientDC dc(this); - - DoPaint(dc); -} - -// 描画実行 -void -WXMainView::DoPaint(wxDC& dc) -{ if (viewwidth == 0 || viewheight == 0) return; wxImage image(rendwidth, rendheight, ImageBuf.get(), true); - if (viewwidth != rendwidth || viewheight != rendheight) { - // wxIMAGE_QUALITY_NORMAL だと速いが、品質優先。 - image.Rescale(viewwidth, viewheight, wxIMAGE_QUALITY_HIGH); + // wxIMAGE_QUALITY_NORMAL だと速いが、ここは品質優先。 +#if _BYTE_ORDER == _BIG_ENDIAN + // XXX ..のはずだったが wxWidget 3.0.4 の QUALITY_HIGH は + // BigEndian だとバグってるようだ。QUALITY_NORMAL のほうは大丈夫。 + auto quality = wxIMAGE_QUALITY_NORMAL; +#else + auto quality = wxIMAGE_QUALITY_HIGH; +#endif + image.Rescale(viewwidth, viewheight, quality); } wxBitmap bitmap(image); wxMemoryDC memDC; memDC.SelectObject(bitmap); + wxPaintDC dc(this); wxRegion region(0, 0, viewwidth, viewheight); wxRegionIterator ri(region); for (; ri; ri++) { @@ -254,7 +257,7 @@ WXMainView::OnMouse(wxMouseEvent& event) bool rb = event.RightIsDown(); bool lb = event.LeftIsDown(); bool mb = event.MiddleIsDown(); - wxPoint pos = event.GetPosition(); + const wxPoint& pos = event.GetPosition(); int dx = 0; int dy = 0;