]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/x11/app.cpp
don't send duplicate set/kill focus events when the text control part of the control...
[wxWidgets.git] / src / x11 / app.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/x11/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// for compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#include "wx/app.h"
16
17#ifndef WX_PRECOMP
18 #include "wx/hash.h"
19 #include "wx/intl.h"
20 #include "wx/log.h"
21 #include "wx/utils.h"
22 #include "wx/frame.h"
23 #include "wx/icon.h"
24 #include "wx/dialog.h"
25 #include "wx/timer.h"
26 #include "wx/memory.h"
27 #include "wx/gdicmn.h"
28 #include "wx/module.h"
29#endif
30
31#include "wx/evtloop.h"
32#include "wx/filename.h"
33
34#include "wx/univ/theme.h"
35#include "wx/univ/renderer.h"
36
37#if wxUSE_THREADS
38 #include "wx/thread.h"
39#endif
40
41#include "wx/x11/private.h"
42
43#include <string.h>
44
45//------------------------------------------------------------------------
46// global data
47//------------------------------------------------------------------------
48
49wxWindowHash *wxWidgetHashTable = NULL;
50wxWindowHash *wxClientWidgetHashTable = NULL;
51
52static bool g_showIconic = false;
53static wxSize g_initialSize = wxDefaultSize;
54
55// This is required for wxFocusEvent::SetWindow(). It will only
56// work for focus events which we provoke ourselves (by calling
57// SetFocus()). It will not work for those events, which X11
58// generates itself.
59static wxWindow *g_nextFocus = NULL;
60static wxWindow *g_prevFocus = NULL;
61
62//------------------------------------------------------------------------
63// X11 error handling
64//------------------------------------------------------------------------
65
66#ifdef __WXDEBUG__
67typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
68
69XErrorHandlerFunc gs_pfnXErrorHandler = 0;
70
71static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
72{
73 // just forward to the default handler for now
74 if (gs_pfnXErrorHandler)
75 return gs_pfnXErrorHandler(dpy, xevent);
76 else
77 return 0;
78}
79#endif // __WXDEBUG__
80
81//------------------------------------------------------------------------
82// wxApp
83//------------------------------------------------------------------------
84
85long wxApp::sm_lastMessageTime = 0;
86
87IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
88
89BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
90 EVT_IDLE(wxAppBase::OnIdle)
91END_EVENT_TABLE()
92
93bool wxApp::Initialize(int& argC, wxChar **argV)
94{
95#if defined(__WXDEBUG__) && !wxUSE_NANOX
96 // install the X error handler
97 gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler );
98#endif // __WXDEBUG__
99
100 wxString displayName;
101 bool syncDisplay = false;
102
103 int argCOrig = argC;
104 for ( int i = 0; i < argCOrig; i++ )
105 {
106 if (wxStrcmp( argV[i], _T("-display") ) == 0)
107 {
108 if (i < (argC - 1))
109 {
110 argV[i++] = NULL;
111
112 displayName = argV[i];
113
114 argV[i] = NULL;
115 argC -= 2;
116 }
117 }
118 else if (wxStrcmp( argV[i], _T("-geometry") ) == 0)
119 {
120 if (i < (argC - 1))
121 {
122 argV[i++] = NULL;
123
124 int w, h;
125 if (wxSscanf(argV[i], _T("%dx%d"), &w, &h) != 2)
126 {
127 wxLogError( _("Invalid geometry specification '%s'"),
128 wxString(argV[i]).c_str() );
129 }
130 else
131 {
132 g_initialSize = wxSize(w, h);
133 }
134
135 argV[i] = NULL;
136 argC -= 2;
137 }
138 }
139 else if (wxStrcmp( argV[i], _T("-sync") ) == 0)
140 {
141 syncDisplay = true;
142
143 argV[i] = NULL;
144 argC--;
145 }
146 else if (wxStrcmp( argV[i], _T("-iconic") ) == 0)
147 {
148 g_showIconic = true;
149
150 argV[i] = NULL;
151 argC--;
152 }
153 }
154
155 if ( argC != argCOrig )
156 {
157 // remove the argumens we consumed
158 for ( int i = 0; i < argC; i++ )
159 {
160 while ( !argV[i] )
161 {
162 memmove(argV + i, argV + i + 1, argCOrig - i);
163 }
164 }
165 }
166
167 // open and set up the X11 display
168 if ( !wxSetDisplay(displayName) )
169 {
170 wxLogError(_("wxWidgets could not open display. Exiting."));
171 return false;
172 }
173
174 Display *dpy = wxGlobalDisplay();
175 if (syncDisplay)
176 XSynchronize(dpy, True);
177
178 XSelectInput(dpy, XDefaultRootWindow(dpy), PropertyChangeMask);
179
180 wxSetDetectableAutoRepeat( true );
181
182
183 if ( !wxAppBase::Initialize(argC, argV) )
184 return false;
185
186#if wxUSE_UNICODE
187 // Glib's type system required by Pango
188 g_type_init();
189#endif
190
191#if wxUSE_INTL
192 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
193#endif
194
195 wxWidgetHashTable = new wxWindowHash;
196 wxClientWidgetHashTable = new wxWindowHash;
197
198 return true;
199}
200
201void wxApp::CleanUp()
202{
203 delete wxWidgetHashTable;
204 wxWidgetHashTable = NULL;
205 delete wxClientWidgetHashTable;
206 wxClientWidgetHashTable = NULL;
207
208 wxAppBase::CleanUp();
209}
210
211wxApp::wxApp()
212{
213 m_mainColormap = NULL;
214 m_topLevelWidget = NULL;
215 m_maxRequestSize = 0;
216 m_showIconic = false;
217 m_initialSize = wxDefaultSize;
218
219#if !wxUSE_NANOX
220 m_visualInfo = NULL;
221#endif
222}
223
224wxApp::~wxApp()
225{
226#if !wxUSE_NANOX
227 delete m_visualInfo;
228#endif
229}
230
231#if !wxUSE_NANOX
232
233//-----------------------------------------------------------------------
234// X11 predicate function for exposure compression
235//-----------------------------------------------------------------------
236
237struct wxExposeInfo
238{
239 Window window;
240 Bool found_non_matching;
241};
242
243extern "C"
244Bool wxX11ExposePredicate (Display *display, XEvent *xevent, XPointer arg)
245{
246 wxExposeInfo *info = (wxExposeInfo*) arg;
247
248 if (info->found_non_matching)
249 return FALSE;
250
251 if (xevent->xany.type != Expose)
252 {
253 info->found_non_matching = true;
254 return FALSE;
255 }
256
257 if (xevent->xexpose.window != info->window)
258 {
259 info->found_non_matching = true;
260 return FALSE;
261 }
262
263 return TRUE;
264}
265
266#endif // wxUSE_NANOX
267
268//-----------------------------------------------------------------------
269// Processes an X event, returning true if the event was processed.
270//-----------------------------------------------------------------------
271
272bool wxApp::ProcessXEvent(WXEvent* _event)
273{
274 XEvent* event = (XEvent*) _event;
275
276 wxWindow* win = NULL;
277 Window window = XEventGetWindow(event);
278#if 0
279 Window actualWindow = window;
280#endif
281
282 // Find the first wxWindow that corresponds to this event window
283 // Because we're receiving events after a window
284 // has been destroyed, assume a 1:1 match between
285 // Window and wxWindow, so if it's not in the table,
286 // it must have been destroyed.
287
288 win = wxGetWindowFromTable(window);
289 if (!win)
290 {
291#if wxUSE_TWO_WINDOWS
292 win = wxGetClientWindowFromTable(window);
293 if (!win)
294#endif
295 return false;
296 }
297
298#ifdef __WXDEBUG__
299 wxString windowClass = win->GetClassInfo()->GetClassName();
300#endif
301
302 switch (event->type)
303 {
304 case Expose:
305 {
306#if wxUSE_TWO_WINDOWS && !wxUSE_NANOX
307 if (event->xexpose.window != (Window)win->GetClientAreaWindow())
308 {
309 XEvent tmp_event;
310 wxExposeInfo info;
311 info.window = event->xexpose.window;
312 info.found_non_matching = false;
313 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, wxX11ExposePredicate, (XPointer) &info ))
314 {
315 // Don't worry about optimizing redrawing the border etc.
316 }
317 win->NeedUpdateNcAreaInIdle();
318 }
319 else
320#endif
321 {
322 win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
323 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
324 win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
325 XExposeEventGetWidth(event), XExposeEventGetHeight(event));
326
327#if !wxUSE_NANOX
328 XEvent tmp_event;
329 wxExposeInfo info;
330 info.window = event->xexpose.window;
331 info.found_non_matching = false;
332 while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, wxX11ExposePredicate, (XPointer) &info ))
333 {
334 win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
335 tmp_event.xexpose.width, tmp_event.xexpose.height );
336
337 win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
338 tmp_event.xexpose.width, tmp_event.xexpose.height );
339 }
340#endif
341
342 // This simplifies the expose and clear areas to simple
343 // rectangles.
344 win->GetUpdateRegion() = win->GetUpdateRegion().GetBox();
345 win->GetClearRegion() = win->GetClearRegion().GetBox();
346
347 // If we only have one X11 window, always indicate
348 // that borders might have to be redrawn.
349 if (win->GetMainWindow() == win->GetClientAreaWindow())
350 win->NeedUpdateNcAreaInIdle();
351
352 // Only erase background, paint in idle time.
353 win->SendEraseEvents();
354
355 // EXPERIMENT
356 //win->Update();
357 }
358
359 return true;
360 }
361
362#if !wxUSE_NANOX
363 case GraphicsExpose:
364 {
365 wxLogTrace( _T("expose"), _T("GraphicsExpose from %s"), win->GetName().c_str());
366
367 win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
368 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
369
370 win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y,
371 event->xgraphicsexpose.width, event->xgraphicsexpose.height);
372
373 if (event->xgraphicsexpose.count == 0)
374 {
375 // Only erase background, paint in idle time.
376 win->SendEraseEvents();
377 // win->Update();
378 }
379
380 return true;
381 }
382#endif
383
384 case KeyPress:
385 {
386 if (!win->IsEnabled())
387 return false;
388
389 wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
390 wxTranslateKeyEvent(keyEvent, win, window, event);
391
392 // wxLogDebug( "OnKey from %s", win->GetName().c_str() );
393
394 // We didn't process wxEVT_KEY_DOWN, so send wxEVT_CHAR
395 if (win->GetEventHandler()->ProcessEvent( keyEvent ))
396 return true;
397
398 keyEvent.SetEventType(wxEVT_CHAR);
399 // Do the translation again, retaining the ASCII
400 // code.
401 if (wxTranslateKeyEvent(keyEvent, win, window, event, true) &&
402 win->GetEventHandler()->ProcessEvent( keyEvent ))
403 return true;
404
405 if ( (keyEvent.m_keyCode == WXK_TAB) &&
406 win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
407 {
408 wxNavigationKeyEvent new_event;
409 new_event.SetEventObject( win->GetParent() );
410 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
411 new_event.SetDirection( (keyEvent.m_keyCode == WXK_TAB) );
412 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
413 new_event.SetWindowChange( keyEvent.ControlDown() );
414 new_event.SetCurrentFocus( win );
415 return win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
416 }
417
418 return false;
419 }
420 case KeyRelease:
421 {
422 if (!win->IsEnabled())
423 return false;
424
425 wxKeyEvent keyEvent(wxEVT_KEY_UP);
426 wxTranslateKeyEvent(keyEvent, win, window, event);
427
428 return win->GetEventHandler()->ProcessEvent( keyEvent );
429 }
430 case ConfigureNotify:
431 {
432#if wxUSE_NANOX
433 if (event->update.utype == GR_UPDATE_SIZE)
434#endif
435 {
436 wxTopLevelWindow *tlw = wxDynamicCast(win, wxTopLevelWindow);
437 if ( tlw )
438 {
439 tlw->SetConfigureGeometry( XConfigureEventGetX(event), XConfigureEventGetY(event),
440 XConfigureEventGetWidth(event), XConfigureEventGetHeight(event) );
441 }
442
443 if ( tlw && tlw->IsShown() )
444 {
445 tlw->SetNeedResizeInIdle();
446 }
447 else
448 {
449 wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() );
450 sizeEvent.SetEventObject( win );
451
452 return win->GetEventHandler()->ProcessEvent( sizeEvent );
453 }
454 }
455 return false;
456 }
457#if !wxUSE_NANOX
458 case PropertyNotify:
459 {
460 //wxLogDebug("PropertyNotify: %s", windowClass.c_str());
461 return HandlePropertyChange(_event);
462 }
463 case ClientMessage:
464 {
465 if (!win->IsEnabled())
466 return false;
467
468 Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);
469 Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);
470
471 if (event->xclient.message_type == wm_protocols)
472 {
473 if ((Atom) (event->xclient.data.l[0]) == wm_delete_window)
474 {
475 win->Close(false);
476 return true;
477 }
478 }
479 return false;
480 }
481#if 0
482 case DestroyNotify:
483 {
484 printf( "destroy from %s\n", win->GetName().c_str() );
485 break;
486 }
487 case CreateNotify:
488 {
489 printf( "create from %s\n", win->GetName().c_str() );
490 break;
491 }
492 case MapRequest:
493 {
494 printf( "map request from %s\n", win->GetName().c_str() );
495 break;
496 }
497 case ResizeRequest:
498 {
499 printf( "resize request from %s\n", win->GetName().c_str() );
500
501 Display *disp = (Display*) wxGetDisplay();
502 XEvent report;
503
504 // to avoid flicker
505 report = * event;
506 while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
507
508 wxSize sz = win->GetSize();
509 wxSizeEvent sizeEvent(sz, win->GetId());
510 sizeEvent.SetEventObject(win);
511
512 return win->GetEventHandler()->ProcessEvent( sizeEvent );
513 }
514#endif
515#endif
516#if wxUSE_NANOX
517 case GR_EVENT_TYPE_CLOSE_REQ:
518 {
519 if (win)
520 {
521 win->Close(false);
522 return true;
523 }
524 return false;
525 break;
526 }
527#endif
528 case EnterNotify:
529 case LeaveNotify:
530 case ButtonPress:
531 case ButtonRelease:
532 case MotionNotify:
533 {
534 if (!win->IsEnabled())
535 return false;
536
537 // Here we check if the top level window is
538 // disabled, which is one aspect of modality.
539 wxWindow *tlw = win;
540 while (tlw && !tlw->IsTopLevel())
541 tlw = tlw->GetParent();
542 if (tlw && !tlw->IsEnabled())
543 return false;
544
545 if (event->type == ButtonPress)
546 {
547 if ((win != wxWindow::FindFocus()) && win->AcceptsFocus())
548 {
549 // This might actually be done in wxWindow::SetFocus()
550 // and not here. TODO.
551 g_prevFocus = wxWindow::FindFocus();
552 g_nextFocus = win;
553
554 wxLogTrace( _T("focus"), _T("About to call SetFocus on %s of type %s due to button press"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
555
556 // Record the fact that this window is
557 // getting the focus, because we'll need to
558 // check if its parent is getting a bogus
559 // focus and duly ignore it.
560 // TODO: may need to have this code in SetFocus, too.
561 extern wxWindow* g_GettingFocus;
562 g_GettingFocus = win;
563 win->SetFocus();
564 }
565 }
566
567#if !wxUSE_NANOX
568 if (event->type == LeaveNotify || event->type == EnterNotify)
569 {
570 // Throw out NotifyGrab and NotifyUngrab
571 if (event->xcrossing.mode != NotifyNormal)
572 return false;
573 }
574#endif
575 wxMouseEvent wxevent;
576 wxTranslateMouseEvent(wxevent, win, window, event);
577 return win->GetEventHandler()->ProcessEvent( wxevent );
578 }
579 case FocusIn:
580#if !wxUSE_NANOX
581 if ((event->xfocus.detail != NotifyPointer) &&
582 (event->xfocus.mode == NotifyNormal))
583#endif
584 {
585 wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
586
587 extern wxWindow* g_GettingFocus;
588 if (g_GettingFocus && g_GettingFocus->GetParent() == win)
589 {
590 // Ignore this, this can be a spurious FocusIn
591 // caused by a child having its focus set.
592 g_GettingFocus = NULL;
593 wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s being deliberately ignored"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
594 return true;
595 }
596 else
597 {
598 wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
599 focusEvent.SetEventObject(win);
600 focusEvent.SetWindow( g_prevFocus );
601 g_prevFocus = NULL;
602
603 return win->GetEventHandler()->ProcessEvent(focusEvent);
604 }
605 }
606 return false;
607
608 case FocusOut:
609#if !wxUSE_NANOX
610 if ((event->xfocus.detail != NotifyPointer) &&
611 (event->xfocus.mode == NotifyNormal))
612#endif
613 {
614 wxLogTrace( _T("focus"), _T("FocusOut from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() );
615
616 wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
617 focusEvent.SetEventObject(win);
618 focusEvent.SetWindow( g_nextFocus );
619 g_nextFocus = NULL;
620 return win->GetEventHandler()->ProcessEvent(focusEvent);
621 }
622 return false;
623
624#ifdef __WXDEBUG__
625 default:
626 //wxString eventName = wxGetXEventName(XEvent& event);
627 //wxLogDebug(wxT("Event %s not handled"), eventName.c_str());
628 break;
629#endif // __WXDEBUG__
630 }
631
632 return false;
633}
634
635// This should be redefined in a derived class for
636// handling property change events for XAtom IPC.
637bool wxApp::HandlePropertyChange(WXEvent *event)
638{
639 // by default do nothing special
640 // TODO: what to do for X11
641 // XtDispatchEvent((XEvent*) event);
642 return false;
643}
644
645void wxApp::WakeUpIdle()
646{
647 // TODO: use wxMotif implementation?
648
649 // Wake up the idle handler processor, even if it is in another thread...
650}
651
652
653// Create display, and other initialization
654bool wxApp::OnInitGui()
655{
656#if wxUSE_LOG
657 // Eventually this line will be removed, but for
658 // now we don't want to try popping up a dialog
659 // for error messages.
660 delete wxLog::SetActiveTarget(new wxLogStderr);
661#endif
662
663 if (!wxAppBase::OnInitGui())
664 return false;
665
666 Display *dpy = wxGlobalDisplay();
667 GetMainColormap(dpy);
668
669 m_maxRequestSize = XMaxRequestSize(dpy);
670
671#if !wxUSE_NANOX
672 m_visualInfo = new wxXVisualInfo;
673 wxFillXVisualInfo(m_visualInfo, dpy);
674#endif
675
676 return true;
677}
678
679#if wxUSE_UNICODE
680
681#include <pango/pango.h>
682#include <pango/pangox.h>
683#ifdef HAVE_PANGO_XFT
684 #include <pango/pangoxft.h>
685#endif
686
687PangoContext* wxApp::GetPangoContext()
688{
689 static PangoContext *s_pangoContext = NULL;
690 if ( !s_pangoContext )
691 {
692 Display *dpy = wxGlobalDisplay();
693
694#ifdef HAVE_PANGO_XFT
695 int xscreen = DefaultScreen(dpy);
696 static int use_xft = -1;
697 if (use_xft == -1)
698 {
699 wxString val = wxGetenv( L"GDK_USE_XFT" );
700 use_xft = val == L"1";
701 }
702
703 if (use_xft)
704 s_pangoContext = pango_xft_get_context(dpy, xscreen);
705 else
706#endif // HAVE_PANGO_XFT
707 s_pangoContext = pango_x_get_context(dpy);
708
709 if (!PANGO_IS_CONTEXT(s_pangoContext))
710 wxLogError( wxT("No pango context.") );
711 }
712
713 return s_pangoContext;
714}
715
716#endif // wxUSE_UNICODE
717
718WXColormap wxApp::GetMainColormap(WXDisplay* display)
719{
720 if (!display) /* Must be called first with non-NULL display */
721 return m_mainColormap;
722
723 int defaultScreen = DefaultScreen((Display*) display);
724 Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);
725
726 Colormap c = DefaultColormapOfScreen(screen);
727
728 if (!m_mainColormap)
729 m_mainColormap = (WXColormap) c;
730
731 return (WXColormap) c;
732}
733
734Window wxGetWindowParent(Window window)
735{
736 wxASSERT_MSG( window, _T("invalid window") );
737
738 return (Window) 0;
739
740#ifndef __VMS
741 // VMS chokes on unreacheable code
742 Window parent, root = 0;
743#if wxUSE_NANOX
744 int noChildren = 0;
745#else
746 unsigned int noChildren = 0;
747#endif
748 Window* children = NULL;
749
750 // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc)
751 int res = 1;
752#if !wxUSE_NANOX
753 res =
754#endif
755 XQueryTree((Display*) wxGetDisplay(), window, & root, & parent,
756 & children, & noChildren);
757 if (children)
758 XFree(children);
759 if (res)
760 return parent;
761 else
762 return (Window) 0;
763#endif
764}
765
766void wxApp::Exit()
767{
768 wxApp::CleanUp();
769
770 wxAppConsole::Exit();
771}
772
773// Yield to other processes
774
775bool wxApp::Yield(bool onlyIfNeeded)
776{
777 // Sometimes only 2 yields seem
778 // to do the trick, e.g. in the
779 // progress dialog
780 int i;
781 for (i = 0; i < 2; i++)
782 {
783 static bool s_inYield = false;
784
785 if ( s_inYield )
786 {
787 if ( !onlyIfNeeded )
788 {
789 wxFAIL_MSG( wxT("wxYield called recursively" ) );
790 }
791
792 return false;
793 }
794
795 s_inYield = true;
796
797 // Make sure we have an event loop object,
798 // or Pending/Dispatch will fail
799 wxEventLoop* eventLoop = wxEventLoop::GetActive();
800 wxEventLoop* newEventLoop = NULL;
801 if (!eventLoop)
802 {
803 newEventLoop = new wxEventLoop;
804 wxEventLoop::SetActive(newEventLoop);
805 }
806
807 // Call dispatch at least once so that sockets
808 // can be tested
809 wxTheApp->Dispatch();
810
811 while (wxTheApp && wxTheApp->Pending())
812 wxTheApp->Dispatch();
813
814#if wxUSE_TIMER
815 wxTimer::NotifyTimers();
816#endif
817 ProcessIdle();
818
819 if (newEventLoop)
820 {
821 wxEventLoop::SetActive(NULL);
822 delete newEventLoop;
823 }
824
825 s_inYield = false;
826 }
827
828 return true;
829}
830
831#ifdef __WXDEBUG__
832
833void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
834{
835 // While the GUI isn't working that well, just print out the
836 // message.
837#if 1
838 wxAppBase::OnAssert(file, line, cond, msg);
839#else
840 wxString msg2;
841 msg2.Printf("At file %s:%d: %s", file, line, msg);
842 wxLogDebug(msg2);
843#endif
844}
845
846#endif // __WXDEBUG__