Better fix
[wxWidgets.git] / src / msw / app.cpp
index 9606840cdd95e2e1abbab3c133c0b7e8203e108d..04916f784b59ae248b3f36a6508103043b7869a8 100644 (file)
 #include "wx/filename.h"
 #include "wx/dynlib.h"
 #include "wx/evtloop.h"
+#include "wx/thread.h"
 
 #include "wx/msw/private.h"
+#include "wx/msw/dc.h"
 #include "wx/msw/ole/oleutils.h"
 #include "wx/msw/private/timer.h"
 
@@ -60,7 +62,7 @@
 
 // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some
 // compilers don't support it (missing headers, libs, ...)
-#if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__) || defined(__SALFORDC__)
+#if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__)
     #undef wxUSE_OLE
 
     #define  wxUSE_OLE 0
@@ -353,8 +355,6 @@ bool wxApp::Initialize(int& argc, wxChar **argv)
 
     RegisterWindowClasses();
 
-    wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
-
 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
     wxSetKeyboardHook(true);
 #endif
@@ -508,10 +508,10 @@ bool wxApp::UnregisterWindowClasses()
 
 void wxApp::CleanUp()
 {
-    // all objects pending for deletion must be deleted first, otherwise we
-    // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
-    // call wouldn't succeed as long as any windows still exist), so call the
-    // base class method first and only then do our clean up
+    // all objects pending for deletion must be deleted first, otherwise
+    // UnregisterWindowClasses() call wouldn't succeed (because windows
+    // using the classes being unregistered still exist), so call the base
+    // class method first and only then do our clean up
     wxAppBase::CleanUp();
 
 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
@@ -526,9 +526,6 @@ void wxApp::CleanUp()
     // unregister the classes now
     UnregisterWindowClasses();
 
-    delete wxWinHandleHash;
-    wxWinHandleHash = NULL;
-
 #ifdef __WXWINCE__
     free( wxCanvasClassName );
     free( wxCanvasClassNameNR );
@@ -569,13 +566,28 @@ void wxApp::WakeUpIdle()
     // start up again.  Doing it this way ensures that the idle handler
     // wakes up in the right thread (see also wxWakeUpMainThread() which does
     // the same for the main app thread only)
-    wxWindow *topWindow = wxTheApp->GetTopWindow();
+    wxWindow * const topWindow = wxTheApp->GetTopWindow();
     if ( topWindow )
     {
-        if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
+        HWND hwndTop = GetHwndOf(topWindow);
+
+        // Do not post WM_NULL if there's already a pending WM_NULL to avoid
+        // overflowing the message queue.
+        //
+        // Notice that due to a limitation of PeekMessage() API (which handles
+        // 0,0 range specially), we have to check the range from 0-1 instead.
+        // This still makes it possible to overflow the queue with WM_NULLs by
+        // interspersing the calles to WakeUpIdle() with windows creation but
+        // it should be rather hard to do it accidentally.
+        MSG msg;
+        if ( !::PeekMessage(&msg, hwndTop, 0, 1, PM_NOREMOVE) ||
+              ::PeekMessage(&msg, hwndTop, 1, 1, PM_NOREMOVE) )
         {
-            // should never happen
-            wxLogLastError(wxT("PostMessage(WM_NULL)"));
+            if ( !::PostMessage(hwndTop, WM_NULL, 0, 0) )
+            {
+                // should never happen
+                wxLogLastError(wxT("PostMessage(WM_NULL)"));
+            }
         }
     }
 }
@@ -605,6 +617,9 @@ void wxApp::OnQueryEndSession(wxCloseEvent& event)
 // system DLL versions
 // ----------------------------------------------------------------------------
 
+// these functions have trivial inline implementations for CE
+#ifndef __WXWINCE__
+
 #if wxUSE_DYNLIB_CLASS
 
 namespace
@@ -740,6 +755,8 @@ int wxApp::GetShell32Version()
 
 #endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
 
+#endif // !__WXWINCE__
+
 // ----------------------------------------------------------------------------
 // Yield to incoming messages
 // ----------------------------------------------------------------------------