]> git.saurik.com Git - wxWidgets.git/blame - src/x11/app.cpp
Nano-X changes: removed spurious -O for Nano-X configuration;
[wxWidgets.git] / src / x11 / app.cpp
CommitLineData
83df96d6
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "app.h"
14#endif
15
83df96d6
JS
16#include "wx/frame.h"
17#include "wx/app.h"
18#include "wx/utils.h"
19#include "wx/gdicmn.h"
83df96d6 20#include "wx/icon.h"
83df96d6 21#include "wx/dialog.h"
83df96d6
JS
22#include "wx/log.h"
23#include "wx/module.h"
24#include "wx/memory.h"
25#include "wx/log.h"
26#include "wx/intl.h"
1b0fb34b 27#include "wx/evtloop.h"
83df96d6 28
ef8c973b
VS
29#include "wx/univ/theme.h"
30#include "wx/univ/renderer.h"
31
83df96d6
JS
32#if wxUSE_THREADS
33 #include "wx/thread.h"
34#endif
35
36#if wxUSE_WX_RESOURCES
37 #include "wx/resource.h"
38#endif
39
7eaac9f5 40#include "wx/x11/private.h"
83df96d6
JS
41
42#include <string.h>
43
9d2cef1c
RR
44//------------------------------------------------------------------------
45// global data
46//------------------------------------------------------------------------
47
83df96d6
JS
48extern wxList wxPendingDelete;
49
9d2cef1c
RR
50wxHashTable *wxWidgetHashTable = NULL;
51
83df96d6
JS
52wxApp *wxTheApp = NULL;
53
9d2cef1c
RR
54// This is set within wxEntryStart -- too early on
55// to put these in wxTheApp
56static int g_newArgc = 0;
57static wxChar** g_newArgv = NULL;
58static bool g_showIconic = FALSE;
59static wxSize g_initialSize = wxDefaultSize;
83df96d6 60
9d2cef1c
RR
61// This is required for wxFocusEvent::SetWindow(). It will only
62// work for focus events which we provoke ourselves (by calling
63// SetFocus()). It will not work for those events, which X11
64// generates itself.
65static wxWindow *g_nextFocus = NULL;
66static wxWindow *g_prevFocus = NULL;
83df96d6 67
9d2cef1c
RR
68//------------------------------------------------------------------------
69// X11 error handling
70//------------------------------------------------------------------------
83df96d6
JS
71
72#ifdef __WXDEBUG__
1b0fb34b 73typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
83df96d6 74
1b0fb34b 75XErrorHandlerFunc gs_pfnXErrorHandler = 0;
83df96d6 76
1b0fb34b
JS
77static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
78{
79 // just forward to the default handler for now
c79a329d
JS
80 if (gs_pfnXErrorHandler)
81 return gs_pfnXErrorHandler(dpy, xevent);
82 else
83 return 0;
1b0fb34b 84}
83df96d6
JS
85#endif // __WXDEBUG__
86
9d2cef1c
RR
87//------------------------------------------------------------------------
88// wxApp
89//------------------------------------------------------------------------
90
83df96d6 91long wxApp::sm_lastMessageTime = 0;
a11672a4 92WXDisplay *wxApp::ms_display = NULL;
83df96d6 93
9d2cef1c
RR
94IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
95
96BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
97 EVT_IDLE(wxApp::OnIdle)
98END_EVENT_TABLE()
256d631a 99
83df96d6
JS
100bool wxApp::Initialize()
101{
83df96d6
JS
102 wxClassInfo::InitializeClasses();
103
104 // GL: I'm annoyed ... I don't know where to put this and I don't want to
105 // create a module for that as it's part of the core.
106#if wxUSE_THREADS
107 wxPendingEventsLocker = new wxCriticalSection();
108#endif
109
110 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
111 wxTheColourDatabase->Initialize();
112
113 wxInitializeStockLists();
114 wxInitializeStockObjects();
115
116#if wxUSE_WX_RESOURCES
117 wxInitializeResourceSystem();
118#endif
119
83df96d6
JS
120 wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
121
122 wxModule::RegisterModules();
123 if (!wxModule::InitializeModules()) return FALSE;
124
125 return TRUE;
126}
127
128void wxApp::CleanUp()
129{
256d631a
JS
130 if (g_newArgv)
131 delete[] g_newArgv;
132 g_newArgv = NULL;
133
83df96d6
JS
134 delete wxWidgetHashTable;
135 wxWidgetHashTable = NULL;
136
137 wxModule::CleanUpModules();
138
139#if wxUSE_WX_RESOURCES
140 wxCleanUpResourceSystem();
141#endif
142
83df96d6
JS
143 delete wxTheColourDatabase;
144 wxTheColourDatabase = NULL;
145
a11672a4
RR
146 wxDeleteStockObjects();
147
148 wxDeleteStockLists();
149
150 delete wxTheApp;
151 wxTheApp = NULL;
83df96d6 152
83df96d6
JS
153 wxClassInfo::CleanUpClasses();
154
83df96d6
JS
155#if wxUSE_THREADS
156 delete wxPendingEvents;
157 delete wxPendingEventsLocker;
158#endif
159
160#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
161 // At this point we want to check if there are any memory
162 // blocks that aren't part of the wxDebugContext itself,
163 // as a special case. Then when dumping we need to ignore
164 // wxDebugContext, too.
165 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
166 {
ba696cfa 167 wxLogDebug("There were memory leaks.");
83df96d6
JS
168 wxDebugContext::Dump();
169 wxDebugContext::PrintStatistics();
170 }
171#endif
172
173 // do it as the very last thing because everything else can log messages
174 wxLog::DontCreateOnDemand();
175 // do it as the very last thing because everything else can log messages
176 delete wxLog::SetActiveTarget(NULL);
177}
178
a11672a4
RR
179// NB: argc and argv may be changed here, pass by reference!
180int wxEntryStart( int& argc, char *argv[] )
181{
182#ifdef __WXDEBUG__
183 // install the X error handler
184 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
185#endif // __WXDEBUG__
186
256d631a
JS
187 wxString displayName;
188 bool syncDisplay = FALSE;
189
3a0b23eb 190 // Parse the arguments.
256d631a
JS
191 // We can't use wxCmdLineParser or OnInitCmdLine and friends because
192 // we have to create the Display earlier. If we can find a way to
193 // use the wxAppBase API then I'll be quite happy to change it.
194 g_newArgv = new wxChar*[argc];
195 g_newArgc = 0;
196 int i;
197 for (i = 0; i < argc; i++)
198 {
199 wxString arg(argv[i]);
200 if (arg == wxT("-display"))
201 {
202 if (i < (argc - 1))
203 {
204 i ++;
205 displayName = argv[i];
206 continue;
207 }
208 }
209 else if (arg == wxT("-geometry"))
210 {
211 if (i < (argc - 1))
212 {
213 i ++;
eb90fb3e 214 wxString windowGeometry = argv[i];
256d631a
JS
215 int w, h;
216 if (wxSscanf(windowGeometry.c_str(), _T("%dx%d"), &w, &h) != 2)
217 {
eb90fb3e 218 wxLogError(_("Invalid geometry specification '%s'"), windowGeometry.c_str());
256d631a
JS
219 }
220 else
221 {
222 g_initialSize = wxSize(w, h);
223 }
224 continue;
225 }
226 }
227 else if (arg == wxT("-sync"))
228 {
229 syncDisplay = TRUE;
230 continue;
231 }
232 else if (arg == wxT("-iconic"))
233 {
234 g_showIconic = TRUE;
45ff6421 235
256d631a
JS
236 continue;
237 }
238
239 // Not eaten by wxWindows, so pass through
240 g_newArgv[g_newArgc] = argv[i];
241 g_newArgc ++;
242 }
243
c79a329d 244 Display* xdisplay = NULL;
256d631a
JS
245 if (displayName.IsEmpty())
246 xdisplay = XOpenDisplay(NULL);
247 else
461e93f9 248 xdisplay = XOpenDisplay((char*) displayName.c_str());
a11672a4
RR
249
250 if (!xdisplay)
251 {
252 wxLogError( _("wxWindows could not open display. Exiting.") );
253 return -1;
254 }
256d631a
JS
255
256 if (syncDisplay)
257 {
258 XSynchronize(xdisplay, True);
259 }
a11672a4
RR
260
261 wxApp::ms_display = (WXDisplay*) xdisplay;
262
263 XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask);
264
7e4501ee 265 wxSetDetectableAutoRepeat( TRUE );
a11672a4
RR
266
267 if (!wxApp::Initialize())
268 return -1;
269
270 return 0;
271}
272
a11672a4
RR
273int wxEntryInitGui()
274{
275 int retValue = 0;
276
277 if ( !wxTheApp->OnInitGui() )
278 retValue = -1;
279
280 return retValue;
281}
282
283
83df96d6
JS
284int wxEntry( int argc, char *argv[] )
285{
286#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
287 // This seems to be necessary since there are 'rogue'
288 // objects present at this point (perhaps global objects?)
289 // Setting a checkpoint will ignore them as far as the
290 // memory checking facility is concerned.
291 // Of course you may argue that memory allocated in globals should be
292 // checked, but this is a reasonable compromise.
293 wxDebugContext::SetCheckpoint();
294#endif
a11672a4
RR
295 int err = wxEntryStart(argc, argv);
296 if (err)
297 return err;
83df96d6
JS
298
299 if (!wxTheApp)
300 {
301 if (!wxApp::GetInitializerFunction())
302 {
303 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
304 return 0;
305 };
306
307 wxTheApp = (wxApp*) (* wxApp::GetInitializerFunction()) ();
308 };
309
310 if (!wxTheApp)
311 {
312 printf( "wxWindows error: wxTheApp == NULL\n" );
313 return 0;
314 };
315
316 wxTheApp->SetClassName(wxFileNameFromPath(argv[0]));
317 wxTheApp->SetAppName(wxFileNameFromPath(argv[0]));
318
45ff6421
JS
319 // The command line may have been changed
320 // by stripping out -display etc.
321 if (g_newArgc > 0)
322 {
323 wxTheApp->argc = g_newArgc;
324 wxTheApp->argv = g_newArgv;
325 }
326 else
327 {
328 wxTheApp->argc = argc;
329 wxTheApp->argv = argv;
330 }
256d631a
JS
331 wxTheApp->m_showIconic = g_showIconic;
332 wxTheApp->m_initialSize = g_initialSize;
83df96d6 333
a11672a4
RR
334 int retValue;
335 retValue = wxEntryInitGui();
83df96d6
JS
336
337 // Here frames insert themselves automatically into wxTopLevelWindows by
338 // getting created in OnInit().
a11672a4
RR
339 if ( retValue == 0 )
340 {
341 if ( !wxTheApp->OnInit() )
342 retValue = -1;
343 }
83df96d6 344
a11672a4 345 if ( retValue == 0 )
83df96d6
JS
346 {
347 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
348 }
349
350 // flush the logged messages if any
351 wxLog *pLog = wxLog::GetActiveTarget();
352 if ( pLog != NULL && pLog->HasPendingMessages() )
353 pLog->Flush();
354
355 delete wxLog::SetActiveTarget(new wxLogStderr); // So dialog boxes aren't used
356 // for further messages
357
358 if (wxTheApp->GetTopWindow())
359 {
360 delete wxTheApp->GetTopWindow();
361 wxTheApp->SetTopWindow(NULL);
362 }
363
364 wxTheApp->DeletePendingObjects();
365
366 wxTheApp->OnExit();
367
368 wxApp::CleanUp();
369
370 return retValue;
371};
372
373// Static member initialization
374wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
375
376wxApp::wxApp()
377{
378 m_topWindow = NULL;
379 wxTheApp = this;
380 m_className = "";
381 m_wantDebugOutput = TRUE ;
382 m_appName = "";
383 argc = 0;
384 argv = NULL;
385 m_exitOnFrameDelete = TRUE;
83df96d6 386 m_mainColormap = (WXColormap) NULL;
7eaac9f5 387 m_topLevelWidget = (WXWindow) NULL;
83df96d6 388 m_maxRequestSize = 0;
1b0fb34b 389 m_mainLoop = NULL;
256d631a
JS
390 m_showIconic = FALSE;
391 m_initialSize = wxDefaultSize;
83df96d6
JS
392}
393
394bool wxApp::Initialized()
395{
396 if (GetTopWindow())
397 return TRUE;
398 else
399 return FALSE;
400}
401
402int wxApp::MainLoop()
403{
1b0fb34b
JS
404 int rt;
405 m_mainLoop = new wxEventLoop;
83df96d6 406
1b0fb34b 407 rt = m_mainLoop->Run();
83df96d6 408
1b0fb34b
JS
409 delete m_mainLoop;
410 m_mainLoop = NULL;
411 return rt;
412}
83df96d6 413
70b8ab77 414#if !wxUSE_NANOX
f809133f
RR
415//-----------------------------------------------------------------------
416// X11 predicate function for exposure compression
417//-----------------------------------------------------------------------
418
419struct wxExposeInfo
420{
421 Window window;
422 Bool found_non_matching;
423};
424
425static Bool expose_predicate (Display *display, XEvent *xevent, XPointer arg)
426{
427 wxExposeInfo *info = (wxExposeInfo*) arg;
428
429 if (info->found_non_matching)
430 return FALSE;
431
432 if (xevent->xany.type != Expose)
433 {
434 info->found_non_matching = TRUE;
435 return FALSE;
436 }
437
438 if (xevent->xexpose.window != info->window)
439 {
440 info->found_non_matching = TRUE;
441 return FALSE;
442 }
443
444 return TRUE;
445}
70b8ab77
JS
446#endif
447 // wxUSE_NANOX
f809133f
RR
448
449//-----------------------------------------------------------------------
1b0fb34b 450// Processes an X event.
f809133f
RR
451//-----------------------------------------------------------------------
452
1b0fb34b
JS
453void wxApp::ProcessXEvent(WXEvent* _event)
454{
455 XEvent* event = (XEvent*) _event;
83df96d6 456
1b0fb34b 457 wxWindow* win = NULL;
c79a329d 458 Window window = XEventGetWindow(event);
1b0fb34b 459 Window actualWindow = window;
0b5c0e1a 460
1b0fb34b 461 // Find the first wxWindow that corresponds to this event window
774b90fb
JS
462 // Because we're receiving events after a window
463 // has been destroyed, assume a 1:1 match between
464 // Window and wxWindow, so if it's not in the table,
465 // it must have been destroyed.
466
467 win = wxGetWindowFromTable(window);
468 if (!win)
45ff6421 469 return;
83df96d6 470
0b5c0e1a
JS
471#ifdef __WXDEBUG__
472 wxString windowClass = win->GetClassInfo()->GetClassName();
473#endif
474
1b0fb34b
JS
475 switch (event->type)
476 {
477 case KeyPress:
83df96d6 478 {
9d2cef1c 479 if (!win->IsEnabled())
b513212d
JS
480 return;
481
9d2cef1c
RR
482 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
483 wxTranslateKeyEvent(keyEvent, win, window, event);
ba696cfa 484
9d2cef1c 485 // wxLogDebug( "OnKey from %s", win->GetName().c_str() );
1b0fb34b 486
9d2cef1c
RR
487 // We didn't process wxEVT_KEY_DOWN, so send
488 // wxEVT_CHAR
489 if (!win->GetEventHandler()->ProcessEvent( keyEvent ))
490 {
491 keyEvent.SetEventType(wxEVT_CHAR);
492 win->GetEventHandler()->ProcessEvent( keyEvent );
1b0fb34b
JS
493 }
494 return;
83df96d6 495 }
1b0fb34b 496 case KeyRelease:
7eaac9f5 497 {
9d2cef1c 498 if (!win->IsEnabled())
b513212d
JS
499 return;
500
9d2cef1c
RR
501 wxKeyEvent keyEvent(wxEVT_KEY_UP);
502 wxTranslateKeyEvent(keyEvent, win, window, event);
1b0fb34b 503
9d2cef1c 504 win->GetEventHandler()->ProcessEvent( keyEvent );
83df96d6 505 return;
7eaac9f5 506 }
256d631a
JS
507 case ConfigureNotify:
508 {
c79a329d 509#if wxUSE_NANOX
9d2cef1c 510 if (event->update.utype == GR_UPDATE_SIZE)
c79a329d 511#endif
256d631a 512 {
0b5c0e1a 513 //wxLogDebug("ConfigureNotify: %s", windowClass.c_str());
c79a329d 514 wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() );
256d631a
JS
515 sizeEvent.SetEventObject( win );
516
517 win->GetEventHandler()->ProcessEvent( sizeEvent );
518 }
519 }
520#if !wxUSE_NANOX
1b0fb34b 521 case PropertyNotify:
7eaac9f5 522 {
0b5c0e1a 523 //wxLogDebug("PropertyNotify: %s", windowClass.c_str());
1b0fb34b 524 HandlePropertyChange(_event);
83df96d6 525 return;
7eaac9f5 526 }
b513212d 527 case ClientMessage:
3a0b23eb 528 {
9d2cef1c 529 if (!win->IsEnabled())
3a0b23eb
JS
530 return;
531
7e4501ee
RR
532 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);
533 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);
b513212d
JS
534
535 if (event->xclient.message_type == wm_protocols)
536 {
6a44bffd 537 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
b513212d 538 {
9d2cef1c 539 win->Close(FALSE);
b513212d
JS
540 }
541 }
542 return;
543 }
1b0fb34b 544 case ResizeRequest:
7eaac9f5 545 {
256d631a 546 /*
1b0fb34b
JS
547 * If resize event, don't resize until the last resize event for this
548 * window is recieved. Prevents flicker as windows are resized.
549 */
550
7266b672 551 Display *disp = (Display*) wxGetDisplay();
1b0fb34b
JS
552 XEvent report;
553
554 // to avoid flicker
555 report = * event;
556 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
557
1b0fb34b
JS
558 if (win)
559 {
560 wxSize sz = win->GetSize();
561 wxSizeEvent sizeEvent(sz, win->GetId());
562 sizeEvent.SetEventObject(win);
563
b513212d 564 win->GetEventHandler()->ProcessEvent( sizeEvent );
1b0fb34b
JS
565 }
566
7eaac9f5
JS
567 return;
568 }
256d631a
JS
569#endif
570#if wxUSE_NANOX
571 case GR_EVENT_TYPE_CLOSE_REQ:
572 {
573 if (win)
574 {
575 win->Close(FALSE);
576 }
577 break;
578 }
579#endif
1b0fb34b 580 case Expose:
7eaac9f5 581 {
0b5c0e1a 582 //wxLogDebug("Expose: %s", windowClass.c_str());
9d2cef1c
RR
583 win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
584 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
c79a329d 585
9d2cef1c
RR
586 win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
587 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
ba696cfa 588
f809133f 589
788519c6 590#if !wxUSE_NANOX
f809133f
RR
591 XEvent tmp_event;
592 wxExposeInfo info;
593 info.window = event->xexpose.window;
594 info.found_non_matching = FALSE;
595 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
9d2cef1c 596 {
f809133f
RR
597 win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
598 tmp_event.xexpose.width, tmp_event.xexpose.height );
599
600 win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
601 tmp_event.xexpose.width, tmp_event.xexpose.height );
1b0fb34b 602 }
f809133f
RR
603#endif
604
605 win->SendEraseEvents();
1b0fb34b 606
7eaac9f5
JS
607 return;
608 }
c79a329d 609#if !wxUSE_NANOX
4125131b
RR
610 case GraphicsExpose:
611 {
9d2cef1c
RR
612 // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(),
613 // event->xgraphicsexpose.x, event->xgraphicsexpose.y,
614 // event->xgraphicsexpose.width, event->xgraphicsexpose.height);
4125131b 615
9d2cef1c
RR
616 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
617 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
618
619 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
620 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
4125131b 621
9d2cef1c
RR
622 if (event->xgraphicsexpose.count == 0)
623 {
624 // Only erase background, paint in idle time.
625 win->SendEraseEvents();
4125131b
RR
626 }
627
628 return;
629 }
c79a329d 630#endif
1b0fb34b
JS
631 case EnterNotify:
632 case LeaveNotify:
633 case ButtonPress:
634 case ButtonRelease:
635 case MotionNotify:
7eaac9f5 636 {
7e4501ee
RR
637 if (!win->IsEnabled())
638 return;
9691c806
RR
639
640 // Here we check if the top level window is
641 // disabled, which is one aspect of modality.
642 wxWindow *tlw = win;
643 while (tlw && !tlw->IsTopLevel())
644 tlw = tlw->GetParent();
645 if (tlw && !tlw->IsEnabled())
646 return;
7e4501ee 647
7e4501ee 648 if (event->type == ButtonPress)
1b0fb34b 649 {
7e4501ee 650 if ((win != wxWindow::FindFocus()) && win->AcceptsFocus())
9d2cef1c
RR
651 {
652 // This might actually be done in wxWindow::SetFocus()
653 // and not here.
654 g_prevFocus = wxWindow::FindFocus();
655 g_nextFocus = win;
656
657 win->SetFocus();
658 }
1b0fb34b 659 }
7e4501ee
RR
660
661 wxMouseEvent wxevent;
662 wxTranslateMouseEvent(wxevent, win, window, event);
663 win->GetEventHandler()->ProcessEvent( wxevent );
7eaac9f5
JS
664 return;
665 }
1b0fb34b
JS
666 case FocusIn:
667 {
256d631a 668#if !wxUSE_NANOX
9d2cef1c
RR
669 if ((event->xfocus.detail != NotifyPointer) &&
670 (event->xfocus.mode == NotifyNormal))
256d631a 671#endif
1b0fb34b 672 {
9d2cef1c 673 // wxLogDebug( "FocusIn from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 674
1b0fb34b
JS
675 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
676 focusEvent.SetEventObject(win);
9d2cef1c
RR
677 focusEvent.SetWindow( g_prevFocus );
678 g_prevFocus = NULL;
f809133f 679
b513212d 680 win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b
JS
681 }
682 break;
683 }
684 case FocusOut:
685 {
256d631a 686#if !wxUSE_NANOX
9d2cef1c
RR
687 if ((event->xfocus.detail != NotifyPointer) &&
688 (event->xfocus.mode == NotifyNormal))
256d631a 689#endif
1b0fb34b 690 {
9d2cef1c 691 // wxLogDebug( "FocusOut from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
ba696cfa 692
1b0fb34b
JS
693 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
694 focusEvent.SetEventObject(win);
9d2cef1c
RR
695 focusEvent.SetWindow( g_nextFocus );
696 g_nextFocus = NULL;
b513212d 697 win->GetEventHandler()->ProcessEvent(focusEvent);
1b0fb34b
JS
698 }
699 break;
700 }
c79a329d
JS
701#ifndef wxUSE_NANOX
702 case DestroyNotify:
b513212d
JS
703 {
704 // Do we want to process this (for top-level windows)?
705 // But we want to be able to veto closes, anyway
706 break;
707 }
c79a329d 708#endif
1b0fb34b
JS
709 default:
710 {
45ff6421
JS
711#ifdef __WXDEBUG__
712 //wxString eventName = wxGetXEventName(XEvent& event);
713 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
714#endif
1b0fb34b
JS
715 break;
716 }
83df96d6
JS
717 }
718}
719
720// Returns TRUE if more time is needed.
1b0fb34b
JS
721// Note that this duplicates wxEventLoopImpl::SendIdleEvent
722// but ProcessIdle may be needed by apps, so is kept.
83df96d6
JS
723bool wxApp::ProcessIdle()
724{
725 wxIdleEvent event;
726 event.SetEventObject(this);
727 ProcessEvent(event);
728
729 return event.MoreRequested();
730}
731
732void wxApp::ExitMainLoop()
733{
1b0fb34b
JS
734 if (m_mainLoop)
735 m_mainLoop->Exit(0);
83df96d6
JS
736}
737
738// Is a message/event pending?
739bool wxApp::Pending()
740{
1b0fb34b 741 return wxEventLoop::GetActive()->Pending();
83df96d6
JS
742}
743
744// Dispatch a message.
745void wxApp::Dispatch()
746{
1b0fb34b 747 wxEventLoop::GetActive()->Dispatch();
83df96d6
JS
748}
749
750// This should be redefined in a derived class for
751// handling property change events for XAtom IPC.
752void wxApp::HandlePropertyChange(WXEvent *event)
753{
754 // by default do nothing special
7eaac9f5 755 // TODO: what to do for X11
256d631a 756 // XtDispatchEvent((XEvent*) event);
83df96d6
JS
757}
758
759void wxApp::OnIdle(wxIdleEvent& event)
760{
0d1dff01 761 static bool s_inOnIdle = FALSE;
83df96d6
JS
762
763 // Avoid recursion (via ProcessEvent default case)
0d1dff01 764 if (s_inOnIdle)
83df96d6
JS
765 return;
766
0d1dff01 767 s_inOnIdle = TRUE;
83df96d6 768
0d1dff01
RR
769 // Resend in the main thread events which have been prepared in other
770 // threads
83df96d6
JS
771 ProcessPendingEvents();
772
0d1dff01 773 // 'Garbage' collection of windows deleted with Close()
83df96d6
JS
774 DeletePendingObjects();
775
83df96d6
JS
776 // Send OnIdle events to all windows
777 bool needMore = SendIdleEvents();
778
779 if (needMore)
780 event.RequestMore(TRUE);
781
0d1dff01 782 s_inOnIdle = FALSE;
83df96d6
JS
783}
784
785void wxWakeUpIdle()
786{
787 // **** please implement me! ****
788 // Wake up the idle handler processor, even if it is in another thread...
789}
790
791
792// Send idle event to all top-level windows
793bool wxApp::SendIdleEvents()
794{
795 bool needMore = FALSE;
796
797 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
798 while (node)
799 {
800 wxWindow* win = node->GetData();
801 if (SendIdleEvents(win))
802 needMore = TRUE;
803 node = node->GetNext();
804 }
805
806 return needMore;
807}
808
809// Send idle event to window and all subwindows
810bool wxApp::SendIdleEvents(wxWindow* win)
811{
812 bool needMore = FALSE;
813
814 wxIdleEvent event;
815 event.SetEventObject(win);
0d1dff01
RR
816
817 win->GetEventHandler()->ProcessEvent(event);
818
819 win->OnInternalIdle();
83df96d6
JS
820
821 if (event.MoreRequested())
822 needMore = TRUE;
823
824 wxNode* node = win->GetChildren().First();
825 while (node)
826 {
827 wxWindow* win = (wxWindow*) node->Data();
828 if (SendIdleEvents(win))
829 needMore = TRUE;
830
831 node = node->Next();
832 }
0d1dff01
RR
833
834 return needMore;
83df96d6
JS
835}
836
837void wxApp::DeletePendingObjects()
838{
839 wxNode *node = wxPendingDelete.First();
840 while (node)
841 {
842 wxObject *obj = (wxObject *)node->Data();
843
844 delete obj;
845
846 if (wxPendingDelete.Member(obj))
847 delete node;
848
849 // Deleting one object may have deleted other pending
850 // objects, so start from beginning of list again.
851 node = wxPendingDelete.First();
852 }
853}
854
256d631a 855// Create display, and other initialization
83df96d6
JS
856bool wxApp::OnInitGui()
857{
ca7497c2
JS
858 // Eventually this line will be removed, but for
859 // now we don't want to try popping up a dialog
860 // for error messages.
861 delete wxLog::SetActiveTarget(new wxLogStderr);
a11672a4 862
ea596687
JS
863 if (!wxAppBase::OnInitGui())
864 return FALSE;
865
a11672a4 866 GetMainColormap( wxApp::GetDisplay() );
256d631a 867
a11672a4 868 m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() );
83df96d6
JS
869
870 return TRUE;
871}
872
873WXColormap wxApp::GetMainColormap(WXDisplay* display)
874{
875 if (!display) /* Must be called first with non-NULL display */
876 return m_mainColormap;
877
878 int defaultScreen = DefaultScreen((Display*) display);
879 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
880
881 Colormap c = DefaultColormapOfScreen(screen);
882
883 if (!m_mainColormap)
884 m_mainColormap = (WXColormap) c;
885
886 return (WXColormap) c;
887}
888
8354aa92 889Window wxGetWindowParent(Window window)
7eaac9f5 890{
86fd8bda
RR
891 wxASSERT_MSG( window, "invalid window" );
892
893 return (Window) 0;
894
7eaac9f5 895 Window parent, root = 0;
c79a329d
JS
896#if wxUSE_NANOX
897 int noChildren = 0;
898#else
7eaac9f5 899 unsigned int noChildren = 0;
c79a329d 900#endif
ea596687 901 Window* children = NULL;
c79a329d
JS
902
903 // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc)
904 int res = 1;
905#if !wxUSE_NANOX
906 res =
907#endif
908 XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
ea596687
JS
909 & children, & noChildren);
910 if (children)
911 XFree(children);
912 if (res)
7eaac9f5
JS
913 return parent;
914 else
915 return (Window) 0;
916}
917
83df96d6
JS
918void wxExit()
919{
920 int retValue = 0;
921 if (wxTheApp)
922 retValue = wxTheApp->OnExit();
923
924 wxApp::CleanUp();
925 /*
926 * Exit in some platform-specific way. Not recommended that the app calls this:
927 * only for emergencies.
928 */
929 exit(retValue);
930}
931
932// Yield to other processes
933
934bool wxApp::Yield(bool onlyIfNeeded)
935{
936 bool s_inYield = FALSE;
937
938 if ( s_inYield )
939 {
940 if ( !onlyIfNeeded )
941 {
942 wxFAIL_MSG( wxT("wxYield called recursively" ) );
943 }
944
945 return FALSE;
946 }
947
948 s_inYield = TRUE;
949
950 while (wxTheApp && wxTheApp->Pending())
951 wxTheApp->Dispatch();
952
953 s_inYield = FALSE;
954
955 return TRUE;
956}
957
ef8c973b 958wxIcon wxApp::GetStdIcon(int which) const
83df96d6 959{
ef8c973b 960 return wxTheme::Get()->GetRenderer()->GetStdIcon(which);
83df96d6
JS
961}
962
7edcafa4
JS
963void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
964{
965 // While the GUI isn't working that well, just print out the
966 // message.
967#if 0
968 wxAppBase::OnAssert(file, line, msg);
969#else
970 wxString msg2;
971 msg2.Printf("At file %s:%d: %s", file, line, msg);
972 wxLogDebug(msg2);
973#endif
974}
975