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