Some changes to fix event processing
[wxWidgets.git] / src / os2 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose: wxApp
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/intl.h"
29 #include "wx/dynarray.h"
30 # include "wx/wxchar.h"
31 # include "wx/icon.h"
32 #endif
33
34 #include "wx/log.h"
35 #include "wx/module.h"
36
37 #include "wx/os2/private.h"
38
39 #if wxUSE_THREADS
40 #include "wx/thread.h"
41
42 // define the array of QMSG strutures
43 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
44
45 #include "wx/arrimpl.cpp"
46
47 WX_DEFINE_OBJARRAY(wxMsgArray);
48 #endif // wxUSE_THREADS
49
50 #if wxUSE_WX_RESOURCES
51 #include "wx/resource.h"
52 #endif
53
54 #if wxUSE_TOOLTIPS
55 #include "wx/tooltip.h"
56 #endif // wxUSE_TOOLTIPS
57
58 #include <string.h>
59 #include <ctype.h>
60
61 // ---------------------------------------------------------------------------
62 // global variables
63 // ---------------------------------------------------------------------------
64
65 extern wxChar* wxBuffer;
66 extern wxChar* wxOsVersion;
67 extern wxList* wxWinHandleList;
68 extern wxList WXDLLEXPORT wxPendingDelete;
69 extern wxCursor* g_globalCursor;
70
71 HAB vHabmain = NULLHANDLE;
72 QMSG svCurrentMsg;
73 wxApp* wxTheApp = NULL;
74
75 // NB: all "NoRedraw" classes must have the same names as the "normal" classes
76 // with NR suffix - wxWindow::OS2Create() supposes this
77 wxChar wxFrameClassName[] = wxT("wxFrameClass");
78 wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
79 wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
80 wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
81 wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
82 wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
83 wxChar wxPanelClassName[] = wxT("wxPanelClass");
84 wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
85
86 HICON wxSTD_FRAME_ICON = (HICON) NULL;
87 HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
88 HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
89
90 HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
91 HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
92 HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
93
94 HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
95
96 MRESULT EXPENTRY wxWndProc( HWND
97 ,ULONG
98 ,MPARAM
99 ,MPARAM
100 );
101
102 // ===========================================================================
103 // implementation
104 // ===========================================================================
105
106 // ---------------------------------------------------------------------------
107 // wxApp
108 // ---------------------------------------------------------------------------
109
110 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
111
112 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
113 EVT_IDLE(wxApp::OnIdle)
114 EVT_END_SESSION(wxApp::OnEndSession)
115 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
116 END_EVENT_TABLE()
117
118 //
119 // Initialize
120 //
121 bool wxApp::Initialize(
122 HAB vHab
123 )
124 {
125 //
126 // OS2 has to have an anchorblock
127 //
128 vHab = WinInitialize(0);
129
130 if (!vHab)
131 return FALSE;
132 else
133 vHabmain = vHab;
134
135 // Some people may wish to use this, but
136 // probably it shouldn't be here by default.
137 #ifdef __WXDEBUG__
138 // wxRedirectIOToConsole();
139 #endif
140
141 wxBuffer = new wxChar[1500]; // FIXME; why?
142
143 wxClassInfo::InitializeClasses();
144
145 #if wxUSE_RESOURCES
146 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
147 #endif
148
149 #if wxUSE_THREADS
150 wxPendingEventsLocker = new wxCriticalSection;
151 #endif
152
153 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
154 wxTheColourDatabase->Initialize();
155
156 wxInitializeStockLists();
157 wxInitializeStockObjects();
158
159 #if wxUSE_WX_RESOURCES
160 wxInitializeResourceSystem();
161 #endif
162
163 wxBitmap::InitStandardHandlers();
164
165 RegisterWindowClasses(vHab);
166 wxWinHandleList = new wxList(wxKEY_INTEGER);
167
168 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
169 // PLEASE DO NOT ALTER THIS.
170 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
171 extern char wxDummyChar;
172 if (wxDummyChar) wxDummyChar++;
173 #endif
174
175 // wxSetKeyboardHook(TRUE);
176
177 wxModule::RegisterModules();
178 if (!wxModule::InitializeModules())
179 return FALSE;
180 return TRUE;
181 } // end of wxApp::Initialize
182
183 // ---------------------------------------------------------------------------
184 // RegisterWindowClasses
185 // ---------------------------------------------------------------------------
186
187 bool wxApp::RegisterWindowClasses(
188 HAB vHab
189 )
190 {
191 APIRET rc;
192 ERRORID vError = 0L;
193 wxString sError;
194
195 if (!::WinRegisterClass( vHab
196 ,wxFrameClassName
197 ,(PFNWP)wxWndProc
198 ,CS_SIZEREDRAW | CS_SYNCPAINT
199 ,sizeof(ULONG)
200 ))
201 {
202 vError = ::WinGetLastError(vHab);
203 sError = wxPMErrorToStr(vError);
204 wxLogLastError(sError);
205 return FALSE;
206 }
207
208 if (!::WinRegisterClass( vHab
209 ,wxFrameClassNameNoRedraw
210 ,(PFNWP)wxWndProc
211 ,0
212 ,0
213 ))
214 {
215 vError = ::WinGetLastError(vHab);
216 sError = wxPMErrorToStr(vError);
217 wxLogLastError(sError);
218 return FALSE;
219 }
220
221 if (!::WinRegisterClass( vHab
222 ,wxMDIFrameClassName
223 ,(PFNWP)wxWndProc
224 ,CS_SIZEREDRAW | CS_SYNCPAINT
225 ,0
226 ))
227 {
228 vError = ::WinGetLastError(vHab);
229 sError = wxPMErrorToStr(vError);
230 wxLogLastError(sError);
231 return FALSE;
232 }
233
234 if (!::WinRegisterClass( vHab
235 ,wxMDIFrameClassNameNoRedraw
236 ,(PFNWP)wxWndProc
237 ,0
238 ,0
239 ))
240 {
241 vError = ::WinGetLastError(vHab);
242 sError = wxPMErrorToStr(vError);
243 wxLogLastError(sError);
244 return FALSE;
245 }
246
247 if (!::WinRegisterClass( vHab
248 ,wxMDIChildFrameClassName
249 ,(PFNWP)wxWndProc
250 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
251 ,0
252 ))
253 {
254 vError = ::WinGetLastError(vHab);
255 sError = wxPMErrorToStr(vError);
256 wxLogLastError(sError);
257 return FALSE;
258 }
259
260 if (!::WinRegisterClass( vHab
261 ,wxMDIChildFrameClassNameNoRedraw
262 ,(PFNWP)wxWndProc
263 ,CS_HITTEST
264 ,0
265 ))
266 {
267 vError = ::WinGetLastError(vHab);
268 sError = wxPMErrorToStr(vError);
269 wxLogLastError(sError);
270 return FALSE;
271 }
272
273 if (!::WinRegisterClass( vHab
274 ,wxPanelClassName
275 ,(PFNWP)wxWndProc
276 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
277 ,0
278 ))
279 {
280 vError = ::WinGetLastError(vHab);
281 sError = wxPMErrorToStr(vError);
282 wxLogLastError(sError);
283 return FALSE;
284 }
285
286 if (!::WinRegisterClass( vHab
287 ,wxCanvasClassName
288 ,(PFNWP)wxWndProc
289 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
290 ,0
291 ))
292 {
293 vError = ::WinGetLastError(vHab);
294 sError = wxPMErrorToStr(vError);
295 wxLogLastError(sError);
296 return FALSE;
297 }
298 return TRUE;
299 } // end of wxApp::RegisterWindowClasses
300
301 //
302 // Cleans up any wxWindows internal structures left lying around
303 //
304 void wxApp::CleanUp()
305 {
306 //
307 // COMMON CLEANUP
308 //
309
310 #if wxUSE_LOG
311
312 //
313 // Flush the logged messages if any and install a 'safer' log target: the
314 // default one (wxLogGui) can't be used after the resources are freed just
315 // below and the user suppliedo ne might be even more unsafe (using any
316 // wxWindows GUI function is unsafe starting from now)
317 //
318 wxLog::DontCreateOnDemand();
319
320 //
321 // This will flush the old messages if any
322 //
323 delete wxLog::SetActiveTarget(new wxLogStderr);
324 #endif // wxUSE_LOG
325
326 //
327 // One last chance for pending objects to be cleaned up
328 //
329 wxTheApp->DeletePendingObjects();
330
331 wxModule::CleanUpModules();
332
333 #if wxUSE_WX_RESOURCES
334 wxCleanUpResourceSystem();
335 #endif
336
337 wxDeleteStockObjects();
338
339 //
340 // Destroy all GDI lists, etc.
341 //
342 wxDeleteStockLists();
343
344 delete wxTheColourDatabase;
345 wxTheColourDatabase = NULL;
346
347 wxBitmap::CleanUpHandlers();
348
349 delete[] wxBuffer;
350 wxBuffer = NULL;
351
352 //
353 // PM-SPECIFIC CLEANUP
354 //
355
356 // wxSetKeyboardHook(FALSE);
357
358 if (wxSTD_FRAME_ICON)
359 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
360 if (wxSTD_MDICHILDFRAME_ICON)
361 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
362 if (wxSTD_MDIPARENTFRAME_ICON)
363 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
364
365 if (wxDEFAULT_FRAME_ICON)
366 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
367 if (wxDEFAULT_MDICHILDFRAME_ICON)
368 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
369 if (wxDEFAULT_MDIPARENTFRAME_ICON)
370 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
371
372 if ( wxDisableButtonBrush )
373 {
374 // TODO: ::DeleteObject( wxDisableButtonBrush );
375 }
376
377 if (wxWinHandleList)
378 delete wxWinHandleList;
379
380 delete wxPendingEvents;
381 #if wxUSE_THREADS
382 delete wxPendingEventsLocker;
383 // If we don't do the following, we get an apparent memory leak.
384 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
385 #endif
386
387 wxClassInfo::CleanUpClasses();
388
389 delete wxTheApp;
390 wxTheApp = NULL;
391
392 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
393 // At this point we want to check if there are any memory
394 // blocks that aren't part of the wxDebugContext itself,
395 // as a special case. Then when dumping we need to ignore
396 // wxDebugContext, too.
397 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
398 {
399 wxLogDebug(wxT("There were memory leaks."));
400 wxDebugContext::Dump();
401 wxDebugContext::PrintStatistics();
402 }
403 // wxDebugContext::SetStream(NULL, NULL);
404 #endif
405
406 #if wxUSE_LOG
407 // do it as the very last thing because everything else can log messages
408 delete wxLog::SetActiveTarget(NULL);
409 #endif // wxUSE_LOG
410 } // end of wxApp::CleanUp
411
412 int wxEntry(
413 int argc
414 , char* argv[]
415 )
416 {
417 HAB vHab = 0;
418
419 if (!wxApp::Initialize(vHab))
420 return 0;
421
422 //
423 // create the application object or ensure that one already exists
424 //
425 if (!wxTheApp)
426 {
427 // The app may have declared a global application object, but we recommend
428 // the IMPLEMENT_APP macro is used instead, which sets an initializer
429 // function for delayed, dynamic app object construction.
430 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
431 wxT("No initializer - use IMPLEMENT_APP macro.") );
432 wxTheApp = (*wxApp::GetInitializerFunction()) ();
433 }
434 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
435 wxTheApp->argc = argc;
436
437 #if wxUSE_UNICODE
438 wxTheApp->argv = new wxChar*[argc+1];
439
440 int nArgc = 0;
441
442 while (nArgc < argc)
443 {
444 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
445 nArgc++;
446 }
447 wxTheApp->argv[nArgc] = (wxChar *)NULL;
448 #else
449 wxTheApp->argv = argv;
450 #endif
451
452 wxString sName(wxFileNameFromPath(argv[0]));
453
454 wxStripExtension(sName);
455 wxTheApp->SetAppName(sName);
456
457 int nRetValue = 0;
458
459 if (!wxTheApp->OnInitGui())
460 nRetValue = -1;
461
462 if (nRetValue == 0)
463 {
464 if (wxTheApp->OnInit())
465 {
466 nRetValue = wxTheApp->OnRun();
467 // nRetValue = -1;
468 }
469 }
470
471 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
472
473 if (pTopWindow)
474 {
475 // Forcibly delete the window.
476 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
477 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
478 {
479 pTopWindow->Close(TRUE);
480 wxTheApp->DeletePendingObjects();
481 }
482 else
483 {
484 delete pTopWindow;
485 wxTheApp->SetTopWindow(NULL);
486 }
487 }
488 wxTheApp->OnExit();
489 wxApp::CleanUp();
490 return(nRetValue);
491 } // end of wxEntry
492
493 bool wxApp::OnInitGui()
494 {
495 ERRORID vError;
496 wxString sError;
497
498 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
499 if (!m_hMq)
500 {
501 vError = ::WinGetLastError(vHabmain);
502 sError = wxPMErrorToStr(vError);
503 wxLogDebug(sError);
504 return FALSE;
505 }
506 return TRUE;
507 } // end of wxApp::OnInitGui
508
509 //
510 // Static member initialization
511 //
512 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
513
514 wxApp::wxApp()
515 {
516 m_topWindow = NULL;
517 wxTheApp = this;
518 m_wantDebugOutput = TRUE;
519
520 argc = 0;
521 argv = NULL;
522 m_nPrintMode = wxPRINT_WINDOWS;
523 m_exitOnFrameDelete = TRUE;
524 m_bAuto3D = TRUE;
525 } // end of wxApp::wxApp
526
527 wxApp::~wxApp()
528 {
529 //
530 // Delete command-line args
531 //
532 int i;
533
534 for (i = 0; i < argc; i++)
535 {
536 delete[] argv[i];
537 }
538 delete[] argv;
539 #endif
540 } // end of wxApp::~wxApp
541
542 bool wxApp::Initialized()
543 {
544 if (GetTopWindow())
545 return TRUE;
546 else
547 return FALSE;
548 } // end of wxApp::Initialized
549
550 //
551 // Get and process a message, returning FALSE if WM_QUIT
552 // received (and also set the flag telling the app to exit the main loop)
553 //
554 bool wxApp::DoMessage()
555 {
556 BOOL bRc = ::WinGetMsg(vHabmain, &m_vMsg, HWND(NULL), 0, 0);
557
558 if (bRc == 0)
559 {
560 // got WM_QUIT
561 m_bKeepGoing = FALSE;
562 return FALSE;
563 }
564 else if (bRc == -1)
565 {
566 // should never happen, but let's test for it nevertheless
567 wxLogLastError("GetMessage");
568 }
569 else
570 {
571 #if wxUSE_THREADS
572 wxASSERT_MSG( wxThread::IsMain()
573 ,wxT("only the main thread can process Windows messages")
574 );
575
576 static bool sbHadGuiLock = TRUE;
577 static wxMsgArray svSavedMessages;
578
579 //
580 // If a secondary thread owns is doing GUI calls, save all messages for
581 // later processing - we can't process them right now because it will
582 // lead to recursive library calls (and we're not reentrant)
583 //
584 if (!wxGuiOwnedByMainThread())
585 {
586 sbHadGuiLock = FALSE;
587
588 //
589 // Leave out WM_COMMAND messages: too dangerous, sometimes
590 // the message will be processed twice
591 //
592 if ( !wxIsWaitingForThread() ||
593 svCurrentMsg.msg != WM_COMMAND )
594 {
595 svSavedMessages.Add(svCurrentMsg);
596 }
597 return TRUE;
598 }
599 else
600 {
601 //
602 // Have we just regained the GUI lock? if so, post all of the saved
603 // messages
604 //
605 if (!sbHadGuiLock )
606 {
607 sbHadGuiLock = TRUE;
608
609 size_t nCount = svSavedMessages.Count();
610
611 for (size_t n = 0; n < nCount; n++)
612 {
613 QMSG vMsg = svSavedMessages[n];
614
615 if ( !ProcessMessage((WXMSG *)&vMsg) )
616 {
617 ::WinDispatchMsg(vHabmain, &vMsg);
618 }
619 }
620 svSavedMessages.Empty();
621 }
622 }
623 #endif // wxUSE_THREADS
624
625 // Process the message
626 if (!ProcessMessage((WXMSG *)&svCurrentMsg) )
627 {
628 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
629 }
630 }
631 return TRUE;
632 } // end of wxApp::DoMessage
633
634 //////////////////////////////////////////////////////////////////////////////
635 //
636 // Keep trying to process messages until WM_QUIT
637 // received.
638 //
639 // If there are messages to be processed, they will all be
640 // processed and OnIdle will not be called.
641 // When there are no more messages, OnIdle is called.
642 // If OnIdle requests more time,
643 // it will be repeatedly called so long as there are no pending messages.
644 // A 'feature' of this is that once OnIdle has decided that no more processing
645 // is required, then it won't get processing time until further messages
646 // are processed (it'll sit in DoMessage).
647 //
648 //////////////////////////////////////////////////////////////////////////////
649 int wxApp::MainLoop()
650 {
651 m_bKeepGoing = TRUE;
652
653 while (m_bKeepGoing)
654 {
655 #if wxUSE_THREADS
656 wxMutexGuiLeaveOrEnter();
657 #endif // wxUSE_THREADS
658 while (!Pending() && ProcessIdle())
659 {
660 }
661 DoMessage();
662 }
663 return (int)svCurrentMsg.mp1;
664 } // end of wxApp::MainLoop
665
666 //
667 // Returns TRUE if more time is needed.
668 //
669 bool wxApp::ProcessIdle()
670 {
671 wxIdleEvent vEvent;
672
673 vEvent.SetEventObject(this);
674 ProcessEvent(vEvent);
675 return vEvent.MoreRequested();
676 } // end of wxApp::ProcessIdle
677
678 void wxApp::ExitMainLoop()
679 {
680 m_bKeepGoing = FALSE;
681 }
682
683 bool wxApp::Pending()
684 {
685 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
686 }
687
688 void wxApp::Dispatch()
689 {
690 DoMessage();
691 }
692
693 //////////////////////////////////////////////////////////////////////////////
694 //
695 // Give all windows a chance to preprocess
696 // the message. Some may have accelerator tables, or have
697 // MDI complications.
698 //
699 //////////////////////////////////////////////////////////////////////////////
700 bool wxApp::ProcessMessage(
701 WXMSG* pWxmsg
702 )
703 {
704 QMSG* vMsg = (PQMSG)pWxmsg;
705 HWND hWnd = vMsg->hwnd;
706 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
707 wxWindow* pWnd;
708
709 #if wxUSE_TOOLTIPS
710 //
711 // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
712 // popup the tooltip bubbles
713 //
714 if (pWndThis && (vMsg->msg == WM_MOUSEMOVE))
715 {
716 wxToolTip* pToolTip = pWndThis->GetToolTip();
717 if (pToolTip)
718 {
719 pToolTip->RelayEvent(pWxmsg);
720 }
721 }
722 #endif // wxUSE_TOOLTIPS
723
724 //
725 // For some composite controls (like a combobox), wndThis might be NULL
726 // because the subcontrol is not a wxWindow, but only the control itself
727 // is - try to catch this case
728 //
729 while (hWnd && !pWndThis)
730 {
731 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
732 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
733 }
734
735 //
736 // Anyone for a non-translation message? Try youngest descendants first.
737 //
738 for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
739 {
740 if (pWnd->OS2ProcessMessage(pWxmsg))
741 return TRUE;
742 }
743 return FALSE;
744 } // end of wxApp::ProcessMessage
745
746 void wxApp::OnIdle(
747 wxIdleEvent& rEvent
748 )
749 {
750 static bool sbInOnIdle = FALSE;
751
752 //
753 // Avoid recursion (via ProcessEvent default case)
754 //
755 if (sbInOnIdle )
756 return;
757
758 sbInOnIdle = TRUE;
759
760 //
761 // If there are pending events, we must process them: pending events
762 // are either events to the threads other than main or events posted
763 // with wxPostEvent() functions
764 //
765 ProcessPendingEvents();
766
767 //
768 // 'Garbage' collection of windows deleted with Close().
769 //
770 DeletePendingObjects();
771
772 #if wxUSE_LOG
773 //
774 // Flush the logged messages if any
775 //
776 wxLog::FlushActive();
777 #endif // wxUSE_LOG
778
779 //
780 // Send OnIdle events to all windows
781 //
782 if (SendIdleEvents())
783 {
784 //
785 // SendIdleEvents() returns TRUE if at least one window requested more
786 // idle events
787 //
788 rEvent.RequestMore(TRUE);
789 }
790 sbInOnIdle = FALSE;
791 } // end of wxApp::OnIdle
792
793 // Send idle event to all top-level windows
794 bool wxApp::SendIdleEvents()
795 {
796 bool bNeedMore = FALSE;
797 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
798
799 while (pNode)
800 {
801 wxWindow* pWin = pNode->GetData();
802
803 if (SendIdleEvents(pWin))
804 bNeedMore = TRUE;
805 pNode = pNode->GetNext();
806 }
807 return bNeedMore;
808 } // end of wxApp::SendIdleEvents
809
810 //
811 // Send idle event to window and all subwindows
812 //
813 bool wxApp::SendIdleEvents(
814 wxWindow* pWin
815 )
816 {
817 bool bNeedMore = FALSE;
818 wxIdleEvent vEvent;
819
820 vEvent.SetEventObject(pWin);
821 pWin->GetEventHandler()->ProcessEvent(vEvent);
822
823 if (vEvent.MoreRequested())
824 bNeedMore = TRUE;
825
826 wxNode* pNode = pWin->GetChildren().First();
827
828 while (pNode)
829 {
830 wxWindow* pWin = (wxWindow*) pNode->Data();
831
832 if (SendIdleEvents(pWin))
833 bNeedMore = TRUE;
834 pNode = pNode->Next();
835 }
836 return bNeedMore;
837 } // end of wxApp::SendIdleEvents
838
839 void wxApp::DeletePendingObjects()
840 {
841 wxNode* pNode = wxPendingDelete.First();
842
843 while (pNode)
844 {
845 wxObject* pObj = (wxObject *)pNode->Data();
846
847 delete pObj;
848
849 if (wxPendingDelete.Member(pObj))
850 delete pNode;
851
852 //
853 // Deleting one object may have deleted other pending
854 // objects, so start from beginning of list again.
855 //
856 pNode = wxPendingDelete.First();
857 }
858 } // end of wxApp::DeletePendingObjects
859
860 void wxApp::OnEndSession(
861 wxCloseEvent& WXUNUSED(rEvent))
862 {
863 if (GetTopWindow())
864 GetTopWindow()->Close(TRUE);
865 } // end of wxApp::OnEndSession
866
867 //
868 // Default behaviour: close the application with prompts. The
869 // user can veto the close, and therefore the end session.
870 //
871 void wxApp::OnQueryEndSession(
872 wxCloseEvent& rEvent
873 )
874 {
875 if (GetTopWindow())
876 {
877 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
878 rEvent.Veto(TRUE);
879 }
880 } // end of wxApp::OnQueryEndSession
881
882 void wxExit()
883 {
884 wxLogError(_("Fatal error: exiting"));
885
886 wxApp::CleanUp();
887 } // end of wxExit
888
889 //
890 // Yield to incoming messages
891 //
892 bool wxYield()
893 {
894 HAB vHab = 0;
895 QMSG vMsg;
896
897 //
898 // Disable log flushing from here because a call to wxYield() shouldn't
899 // normally result in message boxes popping up &c
900 //
901 wxLog::Suspend();
902
903 //
904 // We want to go back to the main message loop
905 // if we see a WM_QUIT. (?)
906 //
907 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
908 {
909 #if wxUSE_THREADS
910 wxMutexGuiLeaveOrEnter();
911 #endif // wxUSE_THREADS
912 if (!wxTheApp->DoMessage())
913 break;
914 }
915 //
916 // If they are pending events, we must process them.
917 //
918 if (wxTheApp)
919 wxTheApp->ProcessPendingEvents();
920
921 //
922 // Let the logs be flashed again
923 //
924 wxLog::Resume();
925 return TRUE;
926 } // end of wxYield
927
928 wxIcon wxApp::GetStdIcon(
929 int nWhich
930 ) const
931 {
932 switch(nWhich)
933 {
934 case wxICON_INFORMATION:
935 return wxIcon("wxICON_INFO");
936
937 case wxICON_QUESTION:
938 return wxIcon("wxICON_QUESTION");
939
940 case wxICON_EXCLAMATION:
941 return wxIcon("wxICON_WARNING");
942
943 default:
944 wxFAIL_MSG(wxT("requested non existent standard icon"));
945 // still fall through
946
947 case wxICON_HAND:
948 return wxIcon("wxICON_ERROR");
949 }
950 return wxIcon("wxICON_ERROR");
951 } // end of wxApp::GetStdIcon
952
953 //-----------------------------------------------------------------------------
954 // wxWakeUpIdle
955 //-----------------------------------------------------------------------------
956
957 void wxWakeUpIdle()
958 {
959 //
960 // Send the top window a dummy message so idle handler processing will
961 // start up again. Doing it this way ensures that the idle handler
962 // wakes up in the right thread (see also wxWakeUpMainThread() which does
963 // the same for the main app thread only)
964 //
965 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
966
967 if (pTopWindow)
968 {
969 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
970 {
971 //
972 // Should never happen
973 //
974 wxLogLastError("PostMessage(WM_NULL)");
975 }
976 }
977 } // end of wxWakeUpIdle
978
979 HINSTANCE wxGetInstance()
980 {
981 return wxhInstance;
982 }
983
984 void wxSetInstance(HINSTANCE hInst)
985 {
986 wxhInstance = hInst;
987 }
988