// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
-
-#ifdef __WXGTK__
-#include <gtk/gtk.h>
-#endif
+#include <stdio.h> // get the correct definition of NULL
#undef DEBUG
#include <Python.h>
#include "helpers.h"
+
#ifdef __WXMSW__
#include <wx/msw/private.h>
#undef FindWindow
#undef GetClassInfo
#undef GetClassName
#endif
-#include <wx/module.h>
+
+#ifdef __WXGTK__
+#include <gtk/gtk.h>
+#endif
//---------------------------------------------------------------------------
// This one isn't acutally called... See __wxStart()
bool wxPyApp::OnInit(void) {
- return false;
+ return FALSE;
}
int wxPyApp::MainLoop(void) {
}
bResult = PyInt_AS_LONG(result);
if (! bResult) {
- PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
+ PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
return NULL;
}
//---------------------------------------------------------------------------
-PyObject* wxPyConstructObject(void* ptr, char* className) {
+PyObject* wxPyConstructObject(void* ptr, const char* className) {
char buff[64]; // should always be big enough...
char swigptr[64];
//---------------------------------------------------------------------------
-//static bool _wxPyInEvent = false;
-//static unsigned int _wxPyNestCount = 0;
+static unsigned int _wxPyNestCount = 0;
+
+static PyThreadState* myPyThreadState_Get() {
+ PyThreadState* current;
+ current = PyThreadState_Swap(NULL);
+ PyThreadState_Swap(current);
+ return current;
+}
-HELPEREXPORT bool wxPyRestoreThread() {
-// #ifdef WXP_WITH_THREAD
-// //if (wxPyEventThreadState != PyThreadState_Get()) {
-// if (! _wxPyInEvent) {
-// PyEval_RestoreThread(wxPyEventThreadState);
-// _wxPyInEvent = true;
-// return TRUE;
-// } else
-// #endif
-// return FALSE;
+HELPEREXPORT bool wxPyRestoreThread() {
// NOTE: The Python API docs state that if a thread already has the
// interpreter lock and calls PyEval_RestoreThread again a deadlock
- // occurs, so I put in the above code as a guard condition since there are
- // many possibilites for nested events and callbacks in wxPython.
+ // occurs, so I put in this code as a guard condition since there are
+ // many possibilites for nested events and callbacks in wxPython. If
+ // The current thread is our thread, then we can assume that we
+ // already have the lock. (I hope!)
//
- // Unfortunately, it seems like somebody was lying (or I'm not
- // understanding...) because each of the nested calls to this function
- // MUST call PyEval_RestoreThread or Python pukes with a thread error (at
- // least on Win32.)
- //
- // until I know better, this is how I am doing it instead:
#ifdef WXP_WITH_THREAD
- PyEval_RestoreThread(wxPyEventThreadState);
-// _wxPyNestCount += 1;
-// if (_wxPyNestCount == 1)
-// return TRUE;
-// else
+ _wxPyNestCount += 1;
+ if (wxPyEventThreadState != myPyThreadState_Get()) {
+ PyEval_RestoreThread(wxPyEventThreadState);
+ return TRUE;
+ }
+ else
#endif
return FALSE;
}
HELPEREXPORT void wxPySaveThread(bool doSave) {
#ifdef WXP_WITH_THREAD
-// if (doSave) {
+ if (doSave) {
wxPyEventThreadState = PyEval_SaveThread();
-// _wxPyInEvent = false;
-// }
-// _wxPyNestCount -= 1;
+ }
+ _wxPyNestCount -= 1;
#endif
}
-
// This function is used for all events destined for Python event handlers.
void wxPyCallback::EventThunker(wxEvent& event) {
wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
bool doSave = wxPyRestoreThread();
- arg = wxPyConstructObject((void*)&event, event.GetClassInfo()->GetClassName());
+ wxString className = event.GetClassInfo()->GetClassName();
+
+ if (className == "wxPyEvent")
+ arg = ((wxPyEvent*)&event)->GetSelf();
+ else if (className == "wxPyCommandEvent")
+ arg = ((wxPyCommandEvent*)&event)->GetSelf();
+ else
+ arg = wxPyConstructObject((void*)&event, className);
tuple = PyTuple_New(1);
PyTuple_SET_ITEM(tuple, 0, arg);
wxPyCallbackHelper::wxPyCallbackHelper() {
m_self = NULL;
m_lastFound = NULL;
+ m_incRef = FALSE;
}
wxPyCallbackHelper::~wxPyCallbackHelper() {
bool doSave = wxPyRestoreThread();
- Py_XDECREF(m_self);
+ if (m_incRef)
+ Py_XDECREF(m_self);
wxPySaveThread(doSave);
}
void wxPyCallbackHelper::setSelf(PyObject* self, int incref) {
m_self = self;
+ m_incRef = incref;
if (incref)
Py_INCREF(m_self);
}
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+// These classes can be derived from in Python and passed through the event
+// system without loosing anything. They do this by keeping a reference to
+// themselves and some special case handling in wxPyCallback::EventThunker.
+
+
+wxPyEvtSelfRef::wxPyEvtSelfRef() {
+ //m_self = Py_None; // **** We don't do normal ref counting to prevent
+ //Py_INCREF(m_self); // circular loops...
+ m_cloned = FALSE;
+}
+
+wxPyEvtSelfRef::~wxPyEvtSelfRef() {
+ bool doSave = wxPyRestoreThread();
+ if (m_cloned)
+ Py_DECREF(m_self);
+ wxPySaveThread(doSave);
+}
+
+void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
+ bool doSave = wxPyRestoreThread();
+ if (m_cloned)
+ Py_DECREF(m_self);
+ m_self = self;
+ if (clone) {
+ Py_INCREF(m_self);
+ m_cloned = TRUE;
+ }
+ wxPySaveThread(doSave);
+}
+
+PyObject* wxPyEvtSelfRef::GetSelf() const {
+ Py_INCREF(m_self);
+ return m_self;
+}
+
+
+wxPyEvent::wxPyEvent(int id)
+ : wxEvent(id) {
+}
+
+wxPyEvent::~wxPyEvent() {
+}
+
+// This one is so the event object can be Cloned...
+void wxPyEvent::CopyObject(wxObject& dest) const {
+ wxEvent::CopyObject(dest);
+ ((wxPyEvent*)&dest)->SetSelf(m_self, TRUE);
+}
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);
+
+
+wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
+ : wxCommandEvent(commandType, id) {
+}
+
+wxPyCommandEvent::~wxPyCommandEvent() {
+}
+
+void wxPyCommandEvent::CopyObject(wxObject& dest) const {
+ wxCommandEvent::CopyObject(dest);
+ ((wxPyCommandEvent*)&dest)->SetSelf(m_self, TRUE);
+}
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);
+
+
+
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Convert a wxList to a Python List
-PyObject* wxPy_ConvertList(wxListBase* list, char* className) {
+PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
PyObject* pyList;
PyObject* pyObj;
wxObject* wxObj;