--- nono/wx/wxuimessage.cpp 2026/04/29 17:05:00 1.1.1.1 +++ nono/wx/wxuimessage.cpp 2026/04/29 17:05:48 1.1.1.5 @@ -4,50 +4,67 @@ // Licensed under nono-license.txt // +// +// UI スレッドへのメッセージ機構 (GUI 側) +// + #include "wxuimessage.h" +#include +#include // イベントタイプの定義 wxDEFINE_EVENT(NONO_EVT_UIMESSAGE, wxCommandEvent); -/*static*/ -std::array WXUIMessage::dest_table; +static std::array, UIMessage::ID_MAX> table; +static std::mutex mtx; // UIMessage を wxWidgets のイベントハンドラに接続する /*static*/ void -WXUIMessage::Connect(UIMessage::ID id, wxEvtHandler *dest, - wxObjectEventFunction function) +WXUIMessage::Connect(UIMessage::ID id, wxEvtHandler *win, + wxObjectEventFunction function) { - dest->Connect(id, NONO_EVT_UIMESSAGE, function); - dest_table[id] = dest; + std::lock_guard lock(mtx); + win->Connect(id, NONO_EVT_UIMESSAGE, function); + table[id].push_back(win); } // イベントハンドラの接続を解除する /*static*/ void -WXUIMessage::Disconnect(UIMessage::ID id, wxObjectEventFunction function) +WXUIMessage::Disconnect(UIMessage::ID id, wxEvtHandler *win, + wxObjectEventFunction function) { - wxEvtHandler *dest = dest_table[id]; - if (dest) { - dest->Disconnect(NONO_EVT_UIMESSAGE, function); - dest_table[id] = NULL; + std::lock_guard lock(mtx); + win->Disconnect(NONO_EVT_UIMESSAGE, function); + for (auto it = table[id].begin(); it != table[id].end(); ++it) { + if (*it == win) { + table[id].erase(it); + break; + } } } -// UIMessage を処理する +// UIMessage::Post() で呼ばれるコールバック関数。 /*static*/ void -WXUIMessage::Process(UIMessage::Queue& queue) +WXUIMessage::Process(uint id, int arg) { - UIMessage m; + if (id >= UIMessage::ID_MAX) { + PANIC("Invalid UIMessage %u", id); + } + std::lock_guard lock(mtx); + for (auto win : table[id]) { + wxCommandEvent ev(NONO_EVT_UIMESSAGE, id); + ev.SetInt(arg); + wxPostEvent(win, ev); + } +} - while (queue.Dequeue(&m)) { - UIMessage::ID id = m.GetID(); - if (id < 0 || id >= UIMessage::ID_MAX) { - PANIC("Invalid UIMessage %d", id); - } - auto dest = dest_table[id]; - if (dest) { - wxCommandEvent ev(NONO_EVT_UIMESSAGE, id); - ev.SetInt(m.GetArg()); - wxPostEvent(dest, ev); +// すべてのハンドラが解除されているかチェックする (開発用) +/*static*/ void +WXUIMessage::AssertAllDisconnected() +{ + for (int i = 0; i < table.size(); i++) { + if (table[i].empty() == false) { + warnx("UIMessage ID=%d not disconnected", i); } } }