X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9e58eb5674cfac859568c9a4b1030012e1f0eb64..83cbb9e995edca4f729aab005df43f23be8f3261:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index 5030bead5f..628046c2af 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -28,6 +28,10 @@ #include #endif +#ifdef __WXMAC__ +#include +#endif + #include #include #include @@ -49,9 +53,10 @@ bool wxPyDoingCleanup = False; struct wxPyThreadState { unsigned long tid; PyThreadState* tstate; + int blocked; wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL) - : tid(_tid), tstate(_tstate) {} + : tid(_tid), tstate(_tstate), blocked(1) {} }; #include @@ -132,7 +137,7 @@ int wxPyApp::MainLoop() { bool wxPyApp::OnInitGui() { bool rval=True; wxApp::OnInitGui(); // in this case always call the base class version - wxPyBeginBlockThreads(); + wxPyBeginBlockThreads(); if (wxPyCBH_findCallback(m_myInst, "OnInitGui")) rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); wxPyEndBlockThreads(); @@ -169,8 +174,8 @@ void wxPyApp::OnAssert(const wxChar *file, } wxLogDebug(buf); return; - } - + } + // If the OnAssert is overloaded in the Python class then call it... bool found; wxPyBeginBlockThreads(); @@ -239,6 +244,44 @@ void wxPyApp::OnAssert(const wxChar *file, } #endif + // For catching Apple Events +void wxPyApp::MacOpenFile(const wxString &fileName) +{ + wxPyBeginBlockThreads(); + if (wxPyCBH_findCallback(m_myInst, "MacOpenFile")) { + PyObject* s = wx2PyString(fileName); + wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s)); + Py_DECREF(s); + } + wxPyEndBlockThreads(); +} + +void wxPyApp::MacPrintFile(const wxString &fileName) +{ + wxPyBeginBlockThreads(); + if (wxPyCBH_findCallback(m_myInst, "MacPrintFile")) { + PyObject* s = wx2PyString(fileName); + wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s)); + Py_DECREF(s); + } + wxPyEndBlockThreads(); +} + +void wxPyApp::MacNewFile() +{ + wxPyBeginBlockThreads(); + if (wxPyCBH_findCallback(m_myInst, "MacNewFile")) + wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); + wxPyEndBlockThreads(); +} + +void wxPyApp::MacReopenApp() +{ + wxPyBeginBlockThreads(); + if (wxPyCBH_findCallback(m_myInst, "MacReopenApp")) + wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); + wxPyEndBlockThreads(); +} /*static*/ @@ -329,8 +372,8 @@ void wxPyApp::_BootstrapApp() bool result; PyObject* retval = NULL; PyObject* pyint = NULL; - - + + // Get any command-line args passed to this program from the sys module int argc = 0; char** argv = NULL; @@ -350,7 +393,7 @@ void wxPyApp::_BootstrapApp() result = wxEntryStart(argc, argv); delete [] argv; - + wxPyBeginBlockThreads(); if (! result) { PyErr_SetString(PyExc_SystemError, "wxEntryStart failed!"); @@ -363,9 +406,9 @@ void wxPyApp::_BootstrapApp() // It's now ok to generate exceptions for assertion errors. wxPythonApp->SetStartupComplete(True); - + // Call the Python wxApp's OnInit function - if (wxPyCBH_findCallback(m_myInst, "OnInit")) { + if (wxPyCBH_findCallback(m_myInst, "OnInit")) { PyObject* method = m_myInst.GetLastFound(); PyObject* argTuple = PyTuple_New(0); @@ -374,8 +417,8 @@ void wxPyApp::_BootstrapApp() Py_DECREF(method); if (retval == NULL) goto error; - - pyint = PyNumber_Int(retval); + + pyint = PyNumber_Int(retval); if (! pyint) { PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value"); goto error; @@ -386,8 +429,8 @@ void wxPyApp::_BootstrapApp() // Is it okay if there is no OnInit? Probably so... result = True; } - - + + if (! result) { PyErr_SetString(PyExc_SystemExit, "OnInit returned False, exiting..."); } @@ -395,7 +438,7 @@ void wxPyApp::_BootstrapApp() error: Py_XDECREF(retval); Py_XDECREF(pyint); - + wxPyEndBlockThreads(); }; @@ -518,18 +561,23 @@ PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args) #ifdef __WXMOTIF__ #define wxPlatform "__WXMOTIF__" +#define wxPlatName "wxMotif" #endif #ifdef __WXX11__ #define wxPlatform "__WXX11__" +#define wxPlatName "wxX11" #endif #ifdef __WXGTK__ #define wxPlatform "__WXGTK__" +#define wxPlatName "wxGTK" #endif -#if defined(__WIN32__) || defined(__WXMSW__) +#ifdef __WXMSW__ #define wxPlatform "__WXMSW__" +#define wxPlatName "wxMSW" #endif #ifdef __WXMAC__ #define wxPlatform "__WXMAC__" +#define wxPlatName "wxMac" #endif #ifdef __WXDEBUG__ @@ -538,10 +586,41 @@ PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args) int wxdebug = 0; #endif + // These should be deprecated in favor of the PlatformInfo tuple built below... PyDict_SetItemString(wxPython_dict, "Platform", PyString_FromString(wxPlatform)); PyDict_SetItemString(wxPython_dict, "USE_UNICODE", PyInt_FromLong(wxUSE_UNICODE)); PyDict_SetItemString(wxPython_dict, "__WXDEBUG__", PyInt_FromLong(wxdebug)); + + PyObject* PlatInfo = PyList_New(0); + PyObject* obj; + +#define _AddInfoString(st) \ + obj = PyString_FromString(st); \ + PyList_Append(PlatInfo, obj); \ + Py_DECREF(obj) + + _AddInfoString(wxPlatform); + _AddInfoString(wxPlatName); +#if wxUSE_UNICODE + _AddInfoString("unicode"); +#else + _AddInfoString("ascii"); +#endif +#ifdef __WXGTK__ +#ifdef __WXGTK20__ + _AddInfoString("gtk2"); +#else + _AddInfoString("gtk1"); +#endif +#endif + +#undef _AddInfoString + + PyObject* PlatInfoTuple = PyList_AsTuple(PlatInfo); + Py_DECREF(PlatInfo); + PyDict_SetItemString(wxPython_dict, "PlatformInfo", PlatInfoTuple); + RETURN_NONE(); } @@ -582,7 +661,7 @@ bool wxPySwigInstance_Check(PyObject* obj) { PyObject* __wxPyFixStockObjects(PyObject* /* self */, PyObject* args) { - wxPy_ReinitStockObjects(2); + wxPy_ReinitStockObjects(2); RETURN_NONE(); } @@ -591,20 +670,20 @@ static void rsoPass2(const char* name) { static PyObject* unbornObjectClass = NULL; PyObject* obj; - + if (unbornObjectClass == NULL) { unbornObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyUnbornObject"); Py_INCREF(unbornObjectClass); } // Find the object instance - obj = PyDict_GetItemString(wxPython_dict, dropwx(name)); + obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name)); wxCHECK_RET(obj != NULL, wxT("Unable to find stock object")); wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance")); // Change its class PyObject_SetAttrString(obj, "__class__", unbornObjectClass); - + } static void rsoPass3(const char* name, const char* classname, void* ptr) @@ -614,18 +693,18 @@ static void rsoPass3(const char* name, const char* classname, void* ptr) PyObject* ptrobj; // Find the object instance - obj = PyDict_GetItemString(wxPython_dict, dropwx(name)); - wxCHECK_RET(obj != NULL, wxT("Unable to find stock object")); + obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name)); + wxCHECK_RET(obj != NULL, wxT("Unable to find stock object")); wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance")); // Find the class object and put it back in the instance - classobj = PyDict_GetItemString(wxPython_dict, dropwx(classname)); - wxCHECK_RET(classobj != NULL, wxT("Unable to find stock class object")); + classobj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(classname)); + wxCHECK_RET(classobj != NULL, wxT("Unable to find stock class object")); PyObject_SetAttrString(obj, "__class__", classobj); // Rebuild the .this swigified pointer with the new value of the C++ pointer ptrobj = wxPyMakeSwigPtr(ptr, wxString(classname, *wxConvCurrent)); - PyObject_SetAttrString(obj, "this", ptrobj); + PyObject_SetAttrString(obj, "this", ptrobj); Py_DECREF(ptrobj); } @@ -633,8 +712,6 @@ static void rsoPass3(const char* name, const char* classname, void* ptr) void wxPy_ReinitStockObjects(int pass) { - PyObject* obj; - PyObject* ptrobj; #define REINITOBJ(name, classname) \ if (pass == 1) { name = (classname*)0xC0C0C0C0; } \ @@ -771,10 +848,10 @@ void wxPyOORClientData_dtor(wxPyOORClientData* self) { if (PyErr_Occurred()) PyErr_Clear(); // just ignore it for now - + PyObject* dict = PyObject_GetAttrString(self->m_obj, "__dict__"); if (dict) { - // Clear the instance's dictionary + // Clear the instance's dictionary PyDict_Clear(dict); // put the name of the old class into the instance, and then reset the @@ -897,21 +974,21 @@ unsigned long wxPyGetCurrentThreadId() { return wxThread::GetCurrentId(); } -static PyThreadState* gs_shutdownTState; +static wxPyThreadState gs_shutdownTState; static -PyThreadState* wxPyGetThreadState() { +wxPyThreadState* wxPyGetThreadState() { if (wxPyTMutex == NULL) // Python is shutting down... - return gs_shutdownTState; + return &gs_shutdownTState; unsigned long ctid = wxPyGetCurrentThreadId(); - PyThreadState* tstate = NULL; + wxPyThreadState* tstate = NULL; wxPyTMutex->Lock(); for(size_t i=0; i < wxPyTStates->GetCount(); i++) { wxPyThreadState& info = wxPyTStates->Item(i); if (info.tid == ctid) { - tstate = info.tstate; + tstate = &info; break; } } @@ -920,10 +997,11 @@ PyThreadState* wxPyGetThreadState() { return tstate; } + static void wxPySaveThreadState(PyThreadState* tstate) { if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread... - gs_shutdownTState = tstate; + gs_shutdownTState.tstate = tstate; return; } unsigned long ctid = wxPyGetCurrentThreadId(); @@ -952,6 +1030,7 @@ void wxPySaveThreadState(PyThreadState* tstate) { #endif + // Calls from Python to wxWindows code are wrapped in calls to these // functions: @@ -959,6 +1038,7 @@ PyThreadState* wxPyBeginAllowThreads() { #ifdef WXP_WITH_THREAD PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS; wxPySaveThreadState(saved); + wxPyGetThreadState()->blocked -= 1; return saved; #else return NULL; @@ -967,6 +1047,7 @@ PyThreadState* wxPyBeginAllowThreads() { void wxPyEndAllowThreads(PyThreadState* saved) { #ifdef WXP_WITH_THREAD + wxPyGetThreadState()->blocked += 1; PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS; #endif } @@ -978,17 +1059,21 @@ void wxPyEndAllowThreads(PyThreadState* saved) { void wxPyBeginBlockThreads() { #ifdef WXP_WITH_THREAD - PyThreadState* tstate = wxPyGetThreadState(); - PyEval_RestoreThread(tstate); + wxPyThreadState* tstate = wxPyGetThreadState(); + if (tstate->blocked++ == 0) { // if nested calls then do nothing + PyEval_RestoreThread(tstate->tstate); + } #endif } void wxPyEndBlockThreads() { #ifdef WXP_WITH_THREAD - // Is there any need to save it again? - // PyThreadState* tstate = - PyEval_SaveThread(); + wxPyThreadState* tstate = wxPyGetThreadState(); + tstate->blocked -= 1; + if ( tstate->blocked == 0) { // if nested calls then do nothing + PyEval_SaveThread(); + } #endif } @@ -1281,9 +1366,8 @@ off_t wxPyCBInputStream::OnSysTell() const { if (PyLong_Check(result)) o = PyLong_AsLongLong(result); else -#else - o = PyInt_AsLong(result); #endif + o = PyInt_AsLong(result); Py_DECREF(result); }; wxPyEndBlockThreads(); @@ -1338,31 +1422,45 @@ void wxPyCallback::EventThunker(wxEvent& event) { arg = wxPyConstructObject((void*)&event, className); } - // Call the event handler, passing the event object - tuple = PyTuple_New(1); - PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg - result = PyEval_CallObject(func, tuple); - if ( result ) { - Py_DECREF(result); // result is ignored, but we still need to decref it - PyErr_Clear(); // Just in case... - } else { + if (!arg) { PyErr_Print(); - } - - if ( checkSkip ) { - // if the event object was one of our special types and - // it had been cloned, then we need to extract the Skipped - // value from the original and set it in the clone. - result = PyObject_CallMethod(arg, "GetSkipped", ""); + } else { + // Check if the event object needs some preinitialization + if (PyObject_HasAttrString(arg, "_preInit")) { + result = PyObject_CallMethod(arg, "_preInit", "O", arg); + if ( result ) { + Py_DECREF(result); // result is ignored, but we still need to decref it + PyErr_Clear(); // Just in case... + } else { + PyErr_Print(); + } + } + + // Call the event handler, passing the event object + tuple = PyTuple_New(1); + PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg + result = PyEval_CallObject(func, tuple); if ( result ) { - event.Skip(PyInt_AsLong(result)); - Py_DECREF(result); + Py_DECREF(result); // result is ignored, but we still need to decref it + PyErr_Clear(); // Just in case... } else { PyErr_Print(); } - } - Py_DECREF(tuple); + if ( checkSkip ) { + // if the event object was one of our special types and + // it had been cloned, then we need to extract the Skipped + // value from the original and set it in the clone. + result = PyObject_CallMethod(arg, "GetSkipped", ""); + if ( result ) { + event.Skip(PyInt_AsLong(result)); + Py_DECREF(result); + } else { + PyErr_Print(); + } + } + Py_DECREF(tuple); + } wxPyEndBlockThreads(); } @@ -1647,7 +1745,7 @@ PyObject* wxPy_ConvertList(wxListBase* listbase) { pyList = PyList_New(0); while (node) { wxObj = node->GetData(); - pyObj = wxPyMake_wxObject(wxObj); + pyObj = wxPyMake_wxObject(wxObj); PyList_Append(pyList, pyObj); node = node->GetNext(); } @@ -1658,6 +1756,7 @@ PyObject* wxPy_ConvertList(wxListBase* listbase) { //---------------------------------------------------------------------- long wxPyGetWinHandle(wxWindow* win) { + #ifdef __WXMSW__ return (long)win->GetHandle(); #endif @@ -1675,6 +1774,11 @@ long wxPyGetWinHandle(wxWindow* win) { #endif } #endif + +#ifdef __WXMAC__ + return (long)MAC_WXHWND(win->MacGetRootWindow()); +#endif + return 0; } @@ -2195,7 +2299,7 @@ bool wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) { bool wxPySimple_typecheck(PyObject* source, const wxChar* classname, int seqLen) { void* ptr; - + if (wxPySwigInstance_Check(source) && wxPyConvertSwigPtr(source, (void **)&ptr, classname)) return True; @@ -2203,18 +2307,26 @@ bool wxPySimple_typecheck(PyObject* source, const wxChar* classname, int seqLen) PyErr_Clear(); if (PySequence_Check(source) && PySequence_Length(source) == seqLen) return True; - + return False; -} +} bool wxSize_helper(PyObject* source, wxSize** obj) { + if (source == Py_None) { + **obj = wxSize(-1,-1); + return True; + } return wxPyTwoIntItem_helper(source, obj, wxT("wxSize")); } bool wxPoint_helper(PyObject* source, wxPoint** obj) { + if (source == Py_None) { + **obj = wxPoint(-1,-1); + return True; + } return wxPyTwoIntItem_helper(source, obj, wxT("wxPoint")); } @@ -2222,6 +2334,11 @@ bool wxPoint_helper(PyObject* source, wxPoint** obj) bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) { + if (source == Py_None) { + **obj = wxRealPoint(-1,-1); + return True; + } + // If source is an object instance then it may already be the right type if (wxPySwigInstance_Check(source)) { wxRealPoint* ptr; @@ -2254,6 +2371,11 @@ bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) { bool wxRect_helper(PyObject* source, wxRect** obj) { + if (source == Py_None) { + **obj = wxRect(-1,-1,-1,-1); + return True; + } + // If source is an object instance then it may already be the right type if (wxPySwigInstance_Check(source)) { wxRect* ptr; @@ -2294,6 +2416,11 @@ bool wxRect_helper(PyObject* source, wxRect** obj) { bool wxColour_helper(PyObject* source, wxColour** obj) { + if (source == Py_None) { + **obj = wxNullColour; + return True; + } + // If source is an object instance then it may already be the right type if (wxPySwigInstance_Check(source)) { wxColour* ptr; @@ -2352,13 +2479,19 @@ bool wxColour_typecheck(PyObject* source) { if (PyString_Check(source) || PyUnicode_Check(source)) return True; - - return False; + + return False; } bool wxPoint2D_helper(PyObject* source, wxPoint2D** obj) { + + if (source == Py_None) { + **obj = wxPoint2D(-1,-1); + return True; + } + // If source is an object instance then it may already be the right type if (wxPySwigInstance_Check(source)) { wxPoint2D* ptr;