1 
2 #ifdef __WXGTK__
3 #include <gdk/gdkx.h>
4 #include <gtk/gtk.h>
5 #endif
6 
7 #ifdef __WXMAC__
8 #include <wx/osx/private.h>
9 #endif
10 
11 #ifdef __WXMSW__
12 #include <wx/msw/private.h>
13 #include <wx/msw/winundef.h>
14 #include <wx/msw/msvcrt.h>
15 #endif
16 
17 
18 #ifdef __WXMSW__             // If building for Windows...
19 
20 //----------------------------------------------------------------------
21 // This gets run when the DLL is loaded.  We just need to save the
22 // instance handle.
23 //----------------------------------------------------------------------
24 
25 extern "C"
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)26 BOOL WINAPI DllMain(
27     HINSTANCE   hinstDLL,    // handle to DLL module
28     DWORD       fdwReason,   // reason for calling function
29     LPVOID      lpvReserved  // reserved
30    )
31 {
32     // If wxPython is embedded in another wxWidgets app then
33     // the instance has already been set.
34     if (! wxGetInstance())
35         wxSetInstance(hinstDLL);
36 
37     return TRUE;
38 }
39 #endif  // __WXMSW__
40 
41 //----------------------------------------------------------------------
42 // Classes for implementing the wxp main application shell.
43 //----------------------------------------------------------------------
44 
45 
46 class wxPyApp : public wxApp
47 {
48     DECLARE_ABSTRACT_CLASS(wxPyApp)
49 
50 public:
wxPyApp()51     wxPyApp() : wxApp() {
52         m_assertMode = wxAPP_ASSERT_EXCEPTION;
53         m_startupComplete = false;
54         //m_callFilterEvent = false;
55         wxApp::SetInstance(this);
56     }
57 
~wxPyApp()58     ~wxPyApp() {
59         wxApp::SetInstance(NULL);
60     }
61 
62 
63 #ifndef __WXMAC__
MacNewFile()64     virtual void MacNewFile() {}
MacOpenFile(const wxString &)65     virtual void MacOpenFile(const wxString &) {}
MacOpenFiles(const wxArrayString & fileNames)66     virtual void MacOpenFiles(const wxArrayString& fileNames) {}
MacOpenURL(const wxString &)67     virtual void MacOpenURL(const wxString &) {}
MacPrintFile(const wxString &)68     virtual void MacPrintFile(const wxString &) {}
MacReopenApp()69     virtual void MacReopenApp() {}
OSXIsGUIApplication()70     virtual bool OSXIsGUIApplication() { return true; }
71 #endif
72 
73 #ifdef __WXMAC__
GetMacAboutMenuItemId()74     static long GetMacAboutMenuItemId()               { return s_macAboutMenuItemId; }
GetMacPreferencesMenuItemId()75     static long GetMacPreferencesMenuItemId()         { return s_macPreferencesMenuItemId; }
GetMacExitMenuItemId()76     static long GetMacExitMenuItemId()                { return s_macExitMenuItemId; }
GetMacHelpMenuTitleName()77     static wxString GetMacHelpMenuTitleName()         { return s_macHelpMenuTitleName; }
SetMacAboutMenuItemId(long val)78     static void SetMacAboutMenuItemId(long val)       { s_macAboutMenuItemId = val; }
SetMacPreferencesMenuItemId(long val)79     static void SetMacPreferencesMenuItemId(long val) { s_macPreferencesMenuItemId = val; }
SetMacExitMenuItemId(long val)80     static void SetMacExitMenuItemId(long val)        { s_macExitMenuItemId = val; }
SetMacHelpMenuTitleName(const wxString & val)81     static void SetMacHelpMenuTitleName(const wxString& val) { s_macHelpMenuTitleName = val; }
82 #else
GetMacAboutMenuItemId()83     static long GetMacAboutMenuItemId()               { return 0; }
GetMacPreferencesMenuItemId()84     static long GetMacPreferencesMenuItemId()         { return 0; }
GetMacExitMenuItemId()85     static long GetMacExitMenuItemId()                { return 0; }
GetMacHelpMenuTitleName()86     static wxString GetMacHelpMenuTitleName()         { return wxEmptyString; }
SetMacAboutMenuItemId(long)87     static void SetMacAboutMenuItemId(long)           { }
SetMacPreferencesMenuItemId(long)88     static void SetMacPreferencesMenuItemId(long)     { }
SetMacExitMenuItemId(long)89     static void SetMacExitMenuItemId(long)            { }
SetMacHelpMenuTitleName(const wxString &)90     static void SetMacHelpMenuTitleName(const wxString&) { }
91 #endif
92 
GetAssertMode()93     wxAppAssertMode  GetAssertMode() { return m_assertMode; }
SetAssertMode(wxAppAssertMode mode)94     void SetAssertMode(wxAppAssertMode mode) {
95         m_assertMode = mode;
96         if (mode & wxAPP_ASSERT_SUPPRESS)
97             wxDisableAsserts();
98         else
99             wxSetDefaultAssertHandler();
100     }
101 
102     virtual void OnAssertFailure(const wxChar *file,
103                                  int line,
104                                  const wxChar *func,
105                                  const wxChar *cond,
106                                  const wxChar *msg);
107 
108 
109     // Implementing OnInit is optional for wxPython apps
OnInit()110     virtual bool OnInit()     { return true; }
OnPreInit()111     virtual void OnPreInit()  { }
112 
113     void _BootstrapApp();
114     virtual int MainLoop();
115 
116     static bool IsDisplayAvailable();
117 
118     // implementation only
SetStartupComplete(bool val)119     void SetStartupComplete(bool val) { m_startupComplete = val; }
120 
121 private:
122     wxAppAssertMode m_assertMode;
123     bool m_startupComplete;
124     //bool m_callFilterEvent;
125 };
126 
127 IMPLEMENT_ABSTRACT_CLASS(wxPyApp, wxApp);
128 
129 extern PyObject* wxAssertionError;         // Exception object raised for wxASSERT failures
130 
131 
OnAssertFailure(const wxChar * file,int line,const wxChar * func,const wxChar * cond,const wxChar * msg)132 void wxPyApp::OnAssertFailure(const wxChar *file,
133                               int line,
134                               const wxChar *func,
135                               const wxChar *cond,
136                               const wxChar *msg)
137 {
138     // ignore it?
139     if (m_assertMode & wxAPP_ASSERT_SUPPRESS)
140         return;
141 
142     // turn it into a Python exception?
143     if (m_assertMode & wxAPP_ASSERT_EXCEPTION) {
144         wxString buf;
145         buf.Alloc(4096);
146         buf.Printf(wxT("C++ assertion \"%s\" failed at %s(%d)"), cond, file, line);
147         if ( func && *func )
148             buf << wxT(" in ") << func << wxT("()");
149         if (msg != NULL)
150             buf << wxT(": ") << msg;
151 
152         // set the exception
153         wxPyThreadBlocker blocker;
154         PyObject* s = wx2PyString(buf);
155         PyErr_SetObject(wxAssertionError, s);
156         Py_DECREF(s);
157 
158         // Now when control returns to whatever API wrapper was called from
159         // Python it should detect that an exception is set and will return
160         // NULL, signalling the exception to Python.
161     }
162 
163     // Send it to the normal log destination, but only if
164     // not _DIALOG because it will call this too
165     if ( (m_assertMode & wxAPP_ASSERT_LOG) && !(m_assertMode & wxAPP_ASSERT_DIALOG)) {
166         wxString buf;
167         buf.Alloc(4096);
168         buf.Printf(wxT("%s(%d): assert \"%s\" failed"),
169                    file, line, cond);
170         if ( func && *func )
171             buf << wxT(" in ") << func << wxT("()");
172         if (msg != NULL)
173             buf << wxT(": ") << msg;
174         wxLogDebug(buf);
175     }
176 
177     // do the normal wx assert dialog?
178     if (m_assertMode & wxAPP_ASSERT_DIALOG)
179         wxApp::OnAssertFailure(file, line, func, cond, msg);
180 }
181 
182 
_BootstrapApp()183 void wxPyApp::_BootstrapApp()
184 {
185     static      bool haveInitialized = false;
186     bool        result;
187 
188     // Only initialize wxWidgets once
189     if (! haveInitialized) {
190 
191         // Copy the values in Python's sys.argv list to a C array of char* to
192         // be passed to the wxEntryStart function below.
193         #if PY_MAJOR_VERSION >= 3
194             #define argType   wchar_t
195         #else
196             #define argType   char
197         #endif
198         int       argc = 0;
199         argType** argv = NULL;
200         {
201             wxPyThreadBlocker blocker;
202             PyObject* sysargv = PySys_GetObject("argv");
203             if (sysargv != NULL) {
204                 argc = PyList_Size(sysargv);
205                 argv = new argType*[argc+1];
206                 int x;
207                 for(x=0; x<argc; x++) {
208                     PyObject *pyArg = PyList_GetItem(sysargv, x); // borrowed reference
209                     // if there isn't anything in sys.argv[0] then set it to the python executable
210                     if (x == 0 && PyObject_Length(pyArg) < 1)
211                         pyArg = PySys_GetObject("executable");
212                     #if PY_MAJOR_VERSION >= 3
213                         int len = PyObject_Length(pyArg);
214                         argv[x] = new argType[len+1];
215                         wxPyUnicode_AsWideChar(pyArg, argv[x], len+1);
216                     #else
217                         argv[x] = strdup(PyBytes_AsString(pyArg));
218                     #endif
219                 }
220                 argv[argc] = NULL;
221             }
222         }
223 
224         // Initialize wxWidgets
225 #ifdef __WXOSX__
226         wxMacAutoreleasePool autoreleasePool;
227 #endif
228         result = wxEntryStart(argc, argv);
229         // wxApp takes ownership of the argv array, don't delete it here
230 
231         if (! result)  {
232             wxPyThreadBlocker blocker;
233             PyErr_SetString(PyExc_SystemError,
234                               "wxEntryStart failed, unable to initialize wxWidgets!"
235 #ifdef __WXGTK__
236                               "  (Is DISPLAY set properly?)"
237 #endif
238                 );
239             goto error;
240         }
241     }
242     else {
243         this->argc = 0;
244     }
245 
246     // It's now ok to generate exceptions for assertion errors.
247     SetStartupComplete(true);
248 
249     // Call the Python wxApp's OnPreInit and OnInit functions if they exist
250     OnPreInit();
251 
252     // Only use CallOnInit the first time, otherwise it will block on [NSApp run] in wxOSX_Cocoa;
253     if (! haveInitialized)
254         result = CallOnInit();
255     else
256         result = OnInit();
257 
258 //#ifdef __WXOSX_COCOA__
259 //    OSXSetInitWasCalled(true);  TODO: consider adding this method to wxApp
260 //#endif
261 
262     if (! result) {
263         wxPyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
264     }
265 
266     haveInitialized = true;
267 
268 error:
269     return;
270 }
271 
272 
MainLoop()273 int wxPyApp::MainLoop()
274 {
275     int retval = 0;
276 
277     {
278 #ifdef __WXOSX__
279         wxMacAutoreleasePool autoreleasePool;
280 #endif
281         DeletePendingObjects();
282     }
283     bool initialized = wxTopLevelWindows.GetCount() != 0;
284     if (initialized) {
285         if ( m_exitOnFrameDelete == Later ) {
286             m_exitOnFrameDelete = Yes;
287         }
288 
289         retval = wxApp::MainLoop();
290         OnExit();
291     }
292     return retval;
293 }
294 
295 
296 // Function to test if the Display (or whatever is the platform equivallent)
297 // can be connected to.
IsDisplayAvailable()298 bool wxPyApp::IsDisplayAvailable()
299 {
300 #ifdef __WXGTK__
301     Display* display;
302     display = XOpenDisplay(NULL);
303     if (display == NULL)
304         return false;
305     XCloseDisplay(display);
306     return true;
307 #endif
308 
309 #ifdef __WXMAC__
310     // This is adapted from Python's Mac/Modules/MacOS.c in the
311     // MacOS_WMAvailable function.
312     bool rv;
313     ProcessSerialNumber psn;
314 
315     /*
316     ** This is a fairly innocuous call to make if we don't have a window
317     ** manager, or if we have no permission to talk to it. It will print
318     ** a message on stderr, but at least it won't abort the process.
319     ** It appears the function caches the result itself, and it's cheap, so
320     ** no need for us to cache.
321     */
322 #ifdef kCGNullDirectDisplay
323     /* On 10.1 CGMainDisplayID() isn't available, and
324     ** kCGNullDirectDisplay isn't defined.
325     */
326     if (CGMainDisplayID() == 0) {
327         rv = false;
328     } else
329 #endif
330     {
331         // Also foreground the application on the first call as a side-effect.
332         if (GetCurrentProcess(&psn) < 0 || SetFrontProcess(&psn) < 0) {
333             rv = false;
334         } else {
335             rv = true;
336         }
337     }
338     return rv;
339 #endif
340 
341 #ifdef __WXMSW__
342     // TODO...
343     return true;
344 #endif
345 }
346 
347 
348 
wxGetApp()349 wxAppConsole* wxGetApp()
350 {
351     return wxApp::GetInstance();
352 }
353