From: John L. <jr...@us...> - 2007-08-06 22:00:37
|
Update of /cvsroot/wxlua/wxLua/modules/wxlua/src In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv15149/wxLua/modules/wxlua/src Modified Files: wxlcallb.cpp wxlstate.cpp Log Message: Move wxWindow cleanup into wxLuaWinDestroyCallback from wxLuaCallback so we only have one connected wxEVT_DESTROY Index: wxlstate.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/wxlstate.cpp,v retrieving revision 1.128 retrieving revision 1.129 diff -C2 -d -r1.128 -r1.129 *** wxlstate.cpp 3 Aug 2007 22:17:16 -0000 1.128 --- wxlstate.cpp 6 Aug 2007 22:00:34 -0000 1.129 *************** *** 97,100 **** --- 97,101 ---- } + #if 0 // copied from the Lua 5.0.1 debug library #define LEVELS1 12 /* size of the first part of the stack */ *************** *** 114,118 **** //static int db_errorfb (lua_State *L) in ldblib.c ! int LUACALL wxlua_tracebackFunction(lua_State *L) { int level; int firstpart = 1; /* still before eventual `...' */ --- 115,119 ---- //static int db_errorfb (lua_State *L) in ldblib.c ! static int LUACALL wxlua_tracebackFunction(lua_State *L) { int level; int firstpart = 1; /* still before eventual `...' */ *************** *** 165,168 **** --- 166,170 ---- return 1; } + #endif // 0 void LUACALL wxlua_debugHookFunction(lua_State *L, lua_Debug *LDebug) *************** *** 2368,2372 **** { M_WXLSTATEDATA->m_wxlStateData->m_windowList.Append(win); - new wxLuaCallback(*this, WXLUACALLBACK_NOROUTINE, win->GetId(), wxID_ANY, wxEVT_DESTROY, win->GetEventHandler()); return true; } --- 2370,2373 ---- *************** *** 4006,4011 **** else { ! // we have to count the methods that are displayed to find the one that failed ! // since we're failing anyway, we don't need this to be fast method = wxlMethod; int i_func = 0; --- 4007,4012 ---- else { ! // We have to count the methods that are displayed to find the one that failed. ! // Since we're failing anyway, we don't need this to be fast. method = wxlMethod; int i_func = 0; Index: wxlcallb.cpp =================================================================== RCS file: /cvsroot/wxlua/wxLua/modules/wxlua/src/wxlcallb.cpp,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** wxlcallb.cpp 3 Aug 2007 22:17:16 -0000 1.38 --- wxlcallb.cpp 6 Aug 2007 22:00:34 -0000 1.39 *************** *** 27,34 **** wxLuaCallback::wxLuaCallback(const wxLuaState& wxlState, int lua_func_stack_idx, ! wxWindowID winId, wxWindowID lastId, wxEventType eventType, wxEvtHandler *evtHandler) : wxObject(), m_routine(0), m_wxlState(wxlState), ! m_evtHandler(evtHandler), m_id(winId), m_lastId(lastId), m_wxlBindEvent(NULL) --- 27,34 ---- wxLuaCallback::wxLuaCallback(const wxLuaState& wxlState, int lua_func_stack_idx, ! wxWindowID win_id, wxWindowID last_id, wxEventType eventType, wxEvtHandler *evtHandler) : wxObject(), m_routine(0), m_wxlState(wxlState), ! m_evtHandler(evtHandler), m_id(win_id), m_last_id(last_id), m_wxlBindEvent(NULL) *************** *** 36,39 **** --- 36,41 ---- wxCHECK_RET(m_wxlState.Ok(), wxT("Invalid wxLuaState")); + m_wxlState.AddTrackedCallback(this); + m_wxlBindEvent = wxlState.GetLuaEvent(eventType); *************** *** 43,47 **** // what wxEvent type class to use and someone probably made a mistake. wxString msg = wxString::Format(wxT("Invalid or unknown wxEventType : %d, winIds %d %d."), ! (int)eventType, winId, lastId); m_wxlState.terror(msg); return; --- 45,49 ---- // what wxEvent type class to use and someone probably made a mistake. wxString msg = wxString::Format(wxT("Invalid or unknown wxEventType : %d, winIds %d %d."), ! (int)eventType, win_id, last_id); m_wxlState.terror(msg); return; *************** *** 52,60 **** m_routine = m_wxlState.tinsert(lua_func_stack_idx); ! m_evtHandler->Connect(winId, lastId, eventType, (wxObjectEventFunction)&wxLuaCallback::EventHandler, this); - - m_wxlState.AddTrackedCallback(this); } --- 54,60 ---- m_routine = m_wxlState.tinsert(lua_func_stack_idx); ! m_evtHandler->Connect(win_id, last_id, eventType, (wxObjectEventFunction)&wxLuaCallback::EventHandler, this); } *************** *** 72,123 **** void wxLuaCallback::EventHandler(wxEvent& event) { ! // This is the wxLuaCallback to use, NOT "this" since "this" is a central event handler function ! wxLuaCallback *theCallback = (wxLuaCallback *) event.m_callbackUserData; wxCHECK_RET(theCallback != NULL, wxT("Invalid wxLuaCallback in wxEvent user data")); - if (!theCallback || !theCallback->GetwxLuaState().Ok()) - return; wxLuaState wxlState(theCallback->GetwxLuaState()); ! wxlState.SetInEventType(event.GetEventType()); ! ! // If this is a wxWindow being destroyed, clear out all callbacks to it for safety ! if ((theCallback->m_routine == 0) && (event.GetEventType() == wxEVT_DESTROY)) ! { ! event.Skip(); ! // delete the reference to this handler since we're clearing it ! wxlState.RemoveTrackedCallback(theCallback); ! // remove tracking or derived methods for it ! wxlState.RemoveTrackedObject(event.GetEventObject(), wxLuaState::CLEAR_TRACKED_OBJECT|wxLuaState::CLEAR_DERIVED_METHODS); ! ! // Disconnect all callbacks associated with this window's evthandler ! theCallback->ClearwxLuaState(); ! ! wxEvtHandler *evtHandler = ((wxWindow*)event.GetEventObject())->GetEventHandler(); ! ! wxList::compatibility_iterator node = wxlState.GetTrackedCallbackList()->GetFirst(); ! while (node) ! { ! wxLuaCallback *wxlCallback = (wxLuaCallback *)node->GetData(); ! if ((wxlCallback != NULL) && (wxlCallback->GetEvtHandler() == evtHandler)) ! { ! // delete the reference to all other handlers that are cleared ! wxList::compatibility_iterator pc_node = node; // remember current node ! node = node->GetNext(); ! wxlState.GetTrackedCallbackList()->Erase(pc_node); ! // remove the ref to the routine since we're clearing the wxLuaState ! wxlState.tremove(wxlCallback->m_routine); ! wxlCallback->ClearwxLuaState(); ! } ! else ! node = node->GetNext(); ! } ! } ! else ! theCallback->CallFunction(&event); ! // we want to get this too or let it pass to someone else if (event.GetEventType() == wxEVT_DESTROY) event.Skip(); --- 72,90 ---- void wxLuaCallback::EventHandler(wxEvent& event) { ! // Get the wxLuaCallback to use, NOT "this" since "this" is a central event handler function ! wxLuaCallback *theCallback = (wxLuaCallback *)event.m_callbackUserData; wxCHECK_RET(theCallback != NULL, wxT("Invalid wxLuaCallback in wxEvent user data")); + // Ok if !Ok() since the wxLuaState may been cleared during shutdown or after destroy event wxLuaState wxlState(theCallback->GetwxLuaState()); ! if (!wxlState.Ok()) ! return; ! wxlState.SetInEventType(event.GetEventType()); ! theCallback->CallFunction(&event); ! // we want the wxLuaWinDestroyCallback to get this too if (event.GetEventType() == wxEVT_DESTROY) event.Skip(); *************** *** 130,139 **** // Cannot call it if Lua is gone or the interpreter has been destroyed // This can happen when the program exists since windows may be destroyed ! // after lua has been deleted if (!m_wxlState.Ok()) return; // ref the state in case this generates a wxEVT_DESTROY which clears us - // this is why we don't get a pointer to the lua_Sstate but check it with GetLuaState() wxLuaState wxlState(m_wxlState); --- 97,105 ---- // Cannot call it if Lua is gone or the interpreter has been destroyed // This can happen when the program exists since windows may be destroyed ! // after Lua has been deleted if (!m_wxlState.Ok()) return; // ref the state in case this generates a wxEVT_DESTROY which clears us wxLuaState wxlState(m_wxlState); *************** *** 197,200 **** --- 163,167 ---- void wxLuaWinDestroyCallback::EventHandler(wxWindowDestroyEvent& event) { + // Central handler for events, forward to the specific instance wxLuaWinDestroyCallback *theCallback = (wxLuaWinDestroyCallback *)event.m_callbackUserData; if (theCallback && (((wxWindow*)event.GetEventObject()) == theCallback->m_window)) *************** *** 215,220 **** --- 182,219 ---- if (m_wxlState.Ok()) { + // clear the metatable for the copy of the we are tracking (clears it for all copies too) wxlua_tcleartrackedmetatable(m_wxlState.GetLuaState(), m_window); + // Now remove the object since it's gone + m_wxlState.RemoveTrackedObject(m_window, wxLuaState::CLEAR_TRACKED_OBJECT|wxLuaState::CLEAR_DERIVED_METHODS); + // Clear our own pointer to this window m_wxlState.RemoveTrackedWindow(m_window); + + wxEvtHandler* evtHandler = m_window->GetEventHandler(); + + // Finally, clear out the wxLuaCallbacks for the very odd cases where + // (activation) events can be sent during destruction. These can happen + // if you pop up a modal dialog (asking if they want to save perhaps) + // and when the dialog is closed the frame below sends an activation event, + // but we're right in the middle of being destroyed and we crash. + wxList::compatibility_iterator node = m_wxlState.GetTrackedCallbackList()->GetFirst(); + while (node) + { + wxLuaCallback *wxlCallback = (wxLuaCallback *)node->GetData(); + + if (wxlCallback->GetEvtHandler() == evtHandler) + { + // delete the reference to all other handlers that are cleared + wxList::compatibility_iterator pc_node = node; // remember current node + node = node->GetNext(); + m_wxlState.GetTrackedCallbackList()->Erase(pc_node); + + // remove the ref to the routine since we're clearing the wxLuaState + // See ~wxLuaCallback + m_wxlState.tremove(wxlCallback->GetLuaRoutine()); + wxlCallback->ClearwxLuaState(); + } + else + node = node->GetNext(); + } } } |