]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/app.cpp
fixed (rare but fatal) bug in wxWindowDisabler
[wxWidgets.git] / src / gtk1 / app.cpp
index ab4547a0bf3c6484f1baf31a3d5f257f50c50f53..7b9962d1651be3a949b4264f1fbed4aa2f8ff4d0 100644 (file)
@@ -49,6 +49,10 @@ wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NUL
 
 extern bool g_isIdle;
 
 
 extern bool g_isIdle;
 
+bool g_mainThreadLocked = FALSE;
+
+GtkWidget *wxRootWindow = (GtkWidget*) NULL;
+
 //-----------------------------------------------------------------------------
 // local functions
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // local functions
 //-----------------------------------------------------------------------------
@@ -89,16 +93,24 @@ bool wxYield()
     while (gtk_events_pending())
         gtk_main_iteration();
 
     while (gtk_events_pending())
         gtk_main_iteration();
 
+    if (has_idle)
+    {
+        /* re-add idle handler (very low priority) */
+        wxTheApp->m_idleTag = gtk_idle_add_priority( 500, wxapp_idle_callback, (gpointer) NULL );
+    }
+
+    // disable log flushing from here because a call to wxYield() shouldn't
+    // normally result in message boxes popping up &c
+    wxLog::Suspend();
+
     /* it's necessary to call ProcessIdle() to update the frames sizes which
        might have been changed (it also will update other things set from
        OnUpdateUI() which is a nice (and desired) side effect) */
     /* it's necessary to call ProcessIdle() to update the frames sizes which
        might have been changed (it also will update other things set from
        OnUpdateUI() which is a nice (and desired) side effect) */
-    while (wxTheApp->ProcessIdle()) { }
+    while (wxTheApp->ProcessIdle())
+        ;
 
 
-    if (has_idle)
-    {
-        /* re-add idle handler */
-        wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
-    }
+    // let the logs be flashed again
+    wxLog::Resume();
 
     return TRUE;
 }
 
     return TRUE;
 }
@@ -109,8 +121,18 @@ bool wxYield()
 
 void wxWakeUpIdle()
 {
 
 void wxWakeUpIdle()
 {
-    if (g_isIdle) 
+#if wxUSE_THREADS
+    if (!wxThread::IsMain())
+        wxMutexGuiEnter();
+#endif
+
+    if (g_isIdle)
         wxapp_install_idle_handler();
         wxapp_install_idle_handler();
+
+#if wxUSE_THREADS
+    if (!wxThread::IsMain())
+        wxMutexGuiLeave();
+#endif
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
@@ -121,15 +143,10 @@ gint wxapp_idle_callback( gpointer WXUNUSED(data) )
 {
     if (!wxTheApp) return TRUE;
 
 {
     if (!wxTheApp) return TRUE;
 
-#if (GTK_MINOR_VERSION > 0)
-    /* when getting called from GDK's idle handler we
-       are no longer within GDK's grab on the GUI
-       thread so we must lock it here ourselves */
-    GDK_THREADS_ENTER ();
-#endif
-
-    /* sent idle event to all who request them */
-    while (wxTheApp->ProcessIdle()) { }
+    // when getting called from GDK's time-out handler
+    // we are no longer within GDK's grab on the GUI
+    // thread so we must lock it here ourselves
+    gdk_threads_enter();
 
     /* we don't want any more idle events until the next event is
        sent to wxGTK */
 
     /* we don't want any more idle events until the next event is
        sent to wxGTK */
@@ -143,10 +160,11 @@ gint wxapp_idle_callback( gpointer WXUNUSED(data) )
        emptied */
     g_isIdle = TRUE;
 
        emptied */
     g_isIdle = TRUE;
 
-#if (GTK_MINOR_VERSION > 0)
-    /* release lock again */
-    GDK_THREADS_LEAVE ();
-#endif
+    /* sent idle event to all who request them */
+    while (wxTheApp->ProcessIdle()) { }
+
+    // release lock again
+    gdk_threads_leave();
 
     return TRUE;
 }
 
     return TRUE;
 }
@@ -159,21 +177,11 @@ void wxapp_install_idle_handler()
        indicating that the idle is over. It may also
        get called from other thread for sending events
        to the main thread (and processing these in
        indicating that the idle is over. It may also
        get called from other thread for sending events
        to the main thread (and processing these in
-       idle time). */
-
-#if wxUSE_THREADS
-    if (!wxThread::IsMain())
-        GDK_THREADS_ENTER ();
-#endif
+       idle time). Very low priority. */
 
 
-    wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
+    wxTheApp->m_idleTag = gtk_idle_add_priority( 500, wxapp_idle_callback, (gpointer) NULL );
 
     g_isIdle = FALSE;
 
     g_isIdle = FALSE;
-    
-#if wxUSE_THREADS
-    if (!wxThread::IsMain())
-        GDK_THREADS_LEAVE ();
-#endif
 }
 
 #if wxUSE_THREADS
 }
 
 #if wxUSE_THREADS
@@ -182,7 +190,7 @@ void wxapp_install_thread_wakeup()
 {
     if (wxTheApp->m_wakeUpTimerTag) return;
 
 {
     if (wxTheApp->m_wakeUpTimerTag) return;
 
-    wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 100, wxapp_wakeup_timerout_callback, (gpointer) NULL );
+    wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 50, wxapp_wakeup_timerout_callback, (gpointer) NULL );
 }
 
 void wxapp_uninstall_thread_wakeup()
 }
 
 void wxapp_uninstall_thread_wakeup()
@@ -195,31 +203,31 @@ void wxapp_uninstall_thread_wakeup()
 
 gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
 {
 
 gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
 {
-    wxapp_uninstall_thread_wakeup();
-
-#if (GTK_MINOR_VERSION > 0)
     // when getting called from GDK's time-out handler
     // we are no longer within GDK's grab on the GUI
     // thread so we must lock it here ourselves
     // when getting called from GDK's time-out handler
     // we are no longer within GDK's grab on the GUI
     // thread so we must lock it here ourselves
-    GDK_THREADS_ENTER ();
-#endif
+    gdk_threads_enter();
+
+    wxapp_uninstall_thread_wakeup();
 
     // unblock other threads wishing to do some GUI things
     wxMutexGuiLeave();
 
 
     // unblock other threads wishing to do some GUI things
     wxMutexGuiLeave();
 
+    g_mainThreadLocked = TRUE;
+
     // wake up other threads
     wxUsleep( 1 );
 
     // block other thread again
     wxMutexGuiEnter();
 
     // wake up other threads
     wxUsleep( 1 );
 
     // block other thread again
     wxMutexGuiEnter();
 
-#if (GTK_MINOR_VERSION > 0)
-    // release lock again
-    GDK_THREADS_LEAVE ();
-#endif
+    g_mainThreadLocked = FALSE;
 
     wxapp_install_thread_wakeup();
 
 
     wxapp_install_thread_wakeup();
 
+    // release lock again
+    gdk_threads_leave();
+
     return TRUE;
 }
 
     return TRUE;
 }
 
@@ -250,6 +258,8 @@ wxApp::wxApp()
 #endif
 
     m_colorCube = (unsigned char*) NULL;
 #endif
 
     m_colorCube = (unsigned char*) NULL;
+
+    m_useBestVisual = FALSE;
 }
 
 wxApp::~wxApp()
 }
 
 wxApp::~wxApp()
@@ -270,8 +280,9 @@ bool wxApp::OnInitGui()
     /* on some machines, the default visual is just 256 colours, so
        we make sure we get the best. this can sometimes be wasteful,
        of course, but what do these guys pay $30.000 for? */
     /* on some machines, the default visual is just 256 colours, so
        we make sure we get the best. this can sometimes be wasteful,
        of course, but what do these guys pay $30.000 for? */
-/*
-    if (gdk_visual_get_best() != gdk_visual_get_system())
+
+    if ((gdk_visual_get_best() != gdk_visual_get_system()) &&
+        (m_useBestVisual))
     {
         GdkVisual* vis = gdk_visual_get_best();
         gtk_widget_set_default_visual( vis );
     {
         GdkVisual* vis = gdk_visual_get_best();
         gtk_widget_set_default_visual( vis );
@@ -281,7 +292,6 @@ bool wxApp::OnInitGui()
 
         visual = vis;
     }
 
         visual = vis;
     }
-*/
 
     /* Nothing to do for 15, 16, 24, 32 bit displays */
     if (visual->depth > 8) return TRUE;
 
     /* Nothing to do for 15, 16, 24, 32 bit displays */
     if (visual->depth > 8) return TRUE;
@@ -368,13 +378,6 @@ void wxApp::OnIdle( wxIdleEvent &event )
     /* 'Garbage' collection of windows deleted with Close(). */
     DeletePendingObjects();
 
     /* 'Garbage' collection of windows deleted with Close(). */
     DeletePendingObjects();
 
-    /* flush the logged messages if any */
-#if wxUSE_LOG
-    wxLog *log = wxLog::GetActiveTarget();
-    if (log != NULL && log->HasPendingMessages())
-        log->Flush();
-#endif // wxUSE_LOG
-
     /* Send OnIdle events to all windows */
     bool needMore = SendIdleEvents();
 
     /* Send OnIdle events to all windows */
     bool needMore = SendIdleEvents();
 
@@ -382,6 +385,11 @@ void wxApp::OnIdle( wxIdleEvent &event )
         event.RequestMore(TRUE);
 
     s_inOnIdle = FALSE;
         event.RequestMore(TRUE);
 
     s_inOnIdle = FALSE;
+
+    /* flush the logged messages if any */
+#if wxUSE_LOG
+    wxLog::FlushActive();
+#endif // wxUSE_LOG
 }
 
 bool wxApp::SendIdleEvents()
 }
 
 bool wxApp::SendIdleEvents()
@@ -484,17 +492,16 @@ bool wxApp::Initialize()
     wxPendingEventsLocker = new wxCriticalSection();
 #endif
 
     wxPendingEventsLocker = new wxCriticalSection();
 #endif
 
-/*
-    wxTheFontNameDirectory =  new wxFontNameDirectory;
-    wxTheFontNameDirectory->Initialize();
-*/
-
     wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
     wxTheColourDatabase->Initialize();
 
     wxInitializeStockLists();
     wxInitializeStockObjects();
 
     wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
     wxTheColourDatabase->Initialize();
 
     wxInitializeStockLists();
     wxInitializeStockObjects();
 
+#if wxUSE_WX_RESOURCES
+    wxInitializeResourceSystem();
+#endif
+
     wxModule::RegisterModules();
     if (!wxModule::InitializeModules()) return FALSE;
 
     wxModule::RegisterModules();
     if (!wxModule::InitializeModules()) return FALSE;
 
@@ -505,14 +512,14 @@ void wxApp::CleanUp()
 {
     wxModule::CleanUpModules();
 
 {
     wxModule::CleanUpModules();
 
+#if wxUSE_WX_RESOURCES
+    wxCleanUpResourceSystem();
+#endif
+
     if (wxTheColourDatabase)
         delete wxTheColourDatabase;
     if (wxTheColourDatabase)
         delete wxTheColourDatabase;
-    wxTheColourDatabase = (wxColourDatabase*) NULL;
 
 
-/*
-    if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
-    wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
-*/
+    wxTheColourDatabase = (wxColourDatabase*) NULL;
 
     wxDeleteStockObjects();
 
 
     wxDeleteStockObjects();
 
@@ -558,8 +565,23 @@ void wxApp::CleanUp()
 // wxEntry
 //-----------------------------------------------------------------------------
 
 // wxEntry
 //-----------------------------------------------------------------------------
 
-int wxEntry( int argc, char *argv[] )
+
+int wxEntryStart( int argc, char *argv[] )
 {
 {
+#if wxUSE_THREADS
+    /* GTK 1.2 up to version 1.2.3 has broken threads */
+    if ((gtk_major_version == 1) &&
+        (gtk_minor_version == 2) &&
+        (gtk_micro_version < 4))
+    {
+        printf( "wxWindows warning: GUI threading disabled due to outdated GTK version\n" );
+    }
+    else
+    {
+        g_thread_init(NULL);
+    }
+#endif
+
     gtk_set_locale();
 
 #if wxUSE_WCHAR_T
     gtk_set_locale();
 
 #if wxUSE_WCHAR_T
@@ -568,12 +590,66 @@ int wxEntry( int argc, char *argv[] )
     if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
 #endif
 
     if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
 #endif
 
+    gdk_threads_enter();
+
     gtk_init( &argc, &argv );
 
     wxSetDetectableAutoRepeat( TRUE );
 
     if (!wxApp::Initialize())
     gtk_init( &argc, &argv );
 
     wxSetDetectableAutoRepeat( TRUE );
 
     if (!wxApp::Initialize())
+    {
+        gdk_threads_leave();
         return -1;
         return -1;
+    }
+
+    return 0;
+}
+
+
+int wxEntryInitGui()
+{
+    int retValue = 0;
+
+    if ( !wxTheApp->OnInitGui() )
+        retValue = -1;
+
+    wxRootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+    gtk_widget_realize( wxRootWindow );
+
+    return retValue;
+}
+
+
+void wxEntryCleanup()
+{
+#if wxUSE_LOG
+    // flush the logged messages if any
+    wxLog *log = wxLog::GetActiveTarget();
+    if (log != NULL && log->HasPendingMessages())
+        log->Flush();
+
+    // continuing to use user defined log target is unsafe from now on because
+    // some resources may be already unavailable, so replace it by something
+    // more safe
+    wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
+    if ( oldlog )
+        delete oldlog;
+#endif // wxUSE_LOG
+
+    wxApp::CleanUp();
+
+    gdk_threads_leave();
+}
+
+
+
+int wxEntry( int argc, char *argv[] )
+{
+    int err;
+
+    err = wxEntryStart(argc, argv);
+    if (err)
+        return err;
 
     if (!wxTheApp)
     {
 
     if (!wxTheApp)
     {
@@ -593,9 +669,10 @@ int wxEntry( int argc, char *argv[] )
 #if wxUSE_UNICODE
     wxTheApp->argv = new wxChar*[argc+1];
     int mb_argc = 0;
 #if wxUSE_UNICODE
     wxTheApp->argv = new wxChar*[argc+1];
     int mb_argc = 0;
-    while (mb_argc < argc) {
-      wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
-      mb_argc++;
+    while (mb_argc < argc)
+    {
+        wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
+        mb_argc++;
     }
     wxTheApp->argv[mb_argc] = (wxChar *)NULL;
 #else
     }
     wxTheApp->argv[mb_argc] = (wxChar *)NULL;
 #else
@@ -606,10 +683,8 @@ int wxEntry( int argc, char *argv[] )
     wxStripExtension( name );
     wxTheApp->SetAppName( name );
 
     wxStripExtension( name );
     wxTheApp->SetAppName( name );
 
-    int retValue = 0;
-
-    if ( !wxTheApp->OnInitGui() )
-        retValue = -1;
+    int retValue;
+    retValue = wxEntryInitGui();
 
     // Here frames insert themselves automatically into wxTopLevelWindows by
     // getting created in OnInit().
 
     // Here frames insert themselves automatically into wxTopLevelWindows by
     // getting created in OnInit().
@@ -630,7 +705,7 @@ int wxEntry( int argc, char *argv[] )
 
         if (wxTheApp->Initialized())
         {
 
         if (wxTheApp->Initialized())
         {
-            retValue = wxTheApp->OnRun();
+            wxTheApp->OnRun();
 
             wxWindow *topWindow = wxTheApp->GetTopWindow();
             if (topWindow)
 
             wxWindow *topWindow = wxTheApp->GetTopWindow();
             if (topWindow)
@@ -648,25 +723,12 @@ int wxEntry( int argc, char *argv[] )
                     wxTheApp->SetTopWindow( (wxWindow*) NULL );
                 }
             }
                     wxTheApp->SetTopWindow( (wxWindow*) NULL );
                 }
             }
-            wxTheApp->OnExit();
+
+            retValue = wxTheApp->OnExit();
         }
     }
 
         }
     }
 
-#if wxUSE_LOG
-    // flush the logged messages if any
-    wxLog *log = wxLog::GetActiveTarget();
-    if (log != NULL && log->HasPendingMessages())
-        log->Flush();
-
-    // continuing to use user defined log target is unsafe from now on because
-    // some resources may be already unavailable, so replace it by something
-    // more safe
-    wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
-    if ( oldlog )
-        delete oldlog;
-#endif // wxUSE_LOG
-
-    wxApp::CleanUp();
+    wxEntryCleanup();
 
     return retValue;
 }
 
     return retValue;
 }