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