]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/toplevel.cpp
Crash fix under VC++
[wxWidgets.git] / src / gtk1 / toplevel.cpp
index d5fff696dd247c683f636880743875e9c1bfd666..eff0e4f34e9be918718d4f09fbaead2cc6e1a980 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "wx/defs.h"
 
+#include "wx/toplevel.h"
 #include "wx/log.h"
 #include "wx/dialog.h"
 #include "wx/control.h"
@@ -61,10 +62,92 @@ extern bool g_isIdle;
 // data
 // ----------------------------------------------------------------------------
 
-extern wxList         wxPendingDelete;
+extern wxList           wxPendingDelete;
 
-extern int            g_openDialogs;
-extern wxWindowGTK   *g_delayedFocus;
+extern int              g_openDialogs;
+extern wxWindowGTK     *g_delayedFocus;
+
+// the frame that is currently active (i.e. its child has focus). It is
+// used to generate wxActivateEvents
+static wxTopLevelWindowGTK *g_activeFrame = (wxTopLevelWindowGTK*) NULL;
+static wxTopLevelWindowGTK *g_lastActiveFrame = (wxTopLevelWindowGTK*) NULL;
+
+// if we detect that the app has got/lost the focus, we set this variable to
+// either TRUE or FALSE and an activate event will be sent during the next
+// OnIdle() call and it is reset to -1: this value means that we shouldn't
+// send any activate events at all
+static int              g_sendActivateEvent = -1;
+
+//-----------------------------------------------------------------------------
+// "focus_in_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_frame_focus_in_callback( GtkWidget *widget,
+                                         GdkEvent *WXUNUSED(event),
+                                         wxTopLevelWindowGTK *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+        
+    switch ( g_sendActivateEvent )
+    {
+        case -1:
+            // we've got focus from outside, synthetize wxActivateEvent
+            g_sendActivateEvent = 1;
+            break;
+
+        case 0:
+            // another our window just lost focus, it was already ours before
+            // - don't send any wxActivateEvent
+            g_sendActivateEvent = -1;
+            break;
+    }
+
+    g_activeFrame = win;
+    g_lastActiveFrame = g_activeFrame;
+        
+    // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
+        
+    wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
+    wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId());
+    event.SetEventObject(g_activeFrame);
+    g_activeFrame->GetEventHandler()->ProcessEvent(event);
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// "focus_out_event"
+//-----------------------------------------------------------------------------
+
+static gint gtk_frame_focus_out_callback( GtkWidget *widget, 
+                                          GdkEventFocus *WXUNUSED(gdk_event), 
+                                          wxTopLevelWindowGTK *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    // if the focus goes out of our app alltogether, OnIdle() will send
+    // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
+    // g_sendActivateEvent to -1
+    g_sendActivateEvent = 0;
+        
+    // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") );
+        
+    // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() );
+
+    if (g_activeFrame)
+    {
+        wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
+        wxActivateEvent event(wxEVT_ACTIVATE, FALSE, g_activeFrame->GetId());
+        event.SetEventObject(g_activeFrame);
+        g_activeFrame->GetEventHandler()->ProcessEvent(event);
+
+        g_activeFrame = NULL;
+    }
+        
+    return FALSE;
+}
 
 //-----------------------------------------------------------------------------
 // "focus" from m_window
@@ -141,6 +224,7 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX
     if (!win->m_hasVMT || !win->IsShown())
         return FALSE;
 
+
     int x = 0;
     int y = 0;
     gdk_window_get_root_origin( win->m_widget->window, &x, &y );
@@ -348,10 +432,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     //     e.g. in wxTaskBarIconAreaGTK
     if (m_widget == NULL)
     {
-        GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
-        if (style & wxFRAME_TOOL_WINDOW)
-            win_type = GTK_WINDOW_POPUP;
-
         if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
         {
 #ifdef __WXGTK20__
@@ -368,15 +448,23 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
         }
         else
         {
-            m_widget = gtk_window_new(win_type);
+            m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+#if GTK_CHECK_VERSION(2,1,0)
+            if (style & wxFRAME_TOOL_WINDOW)
+                gtk_window_set_type_hint(GTK_WINDOW(m_widget),
+                                         GDK_WINDOW_TYPE_HINT_UTILITY);
+#endif
+
         }
     }
 
-    if (m_parent && (((GTK_IS_WINDOW(m_parent->m_widget)) &&
+    wxWindow *topParent = wxGetTopLevelParent(m_parent);
+    if (topParent && (((GTK_IS_WINDOW(topParent->m_widget)) &&
                      (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
                     (style & wxFRAME_FLOAT_ON_PARENT)))
     {
-        gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
+        gtk_window_set_transient_for( GTK_WINDOW(m_widget),
+                                      GTK_WINDOW(topParent->m_widget) );
     }
 
 #if GTK_CHECK_VERSION(2,2,0)
@@ -457,6 +545,12 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
         GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
 
+    // activation
+    gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
+        GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback), (gpointer)this );
+    gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
+        GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback), (gpointer)this );
+            
     // decorations
     if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
     {
@@ -517,6 +611,11 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
     {
         gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
     }
+    
+    if (g_activeFrame == this)
+        g_activeFrame = NULL;
+    if (g_lastActiveFrame == this)
+        g_lastActiveFrame = NULL;
 }
 
 
@@ -527,6 +626,15 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
 
     m_fsIsShowing = show;
 
+#if GTK_CHECK_VERSION(2,2,0)
+
+    if (show)
+        gtk_window_fullscreen( GTK_WINDOW( m_widget ) );
+    else
+        gtk_window_unfullscreen( GTK_WINDOW( m_widget ) );
+
+#else
+
     GdkWindow *window = m_widget->window;
     wxX11FullScreenMethod method =
         wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
@@ -585,7 +693,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
         SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
                 m_fsSaveFrame.width, m_fsSaveFrame.height);
     }
-
+#endif
 
     return TRUE;
 }
@@ -607,7 +715,10 @@ bool wxTopLevelWindowGTK::Show( bool show )
 
         GtkOnSize( m_x, m_y, m_width, m_height );
     }
-
+    
+    if (show)
+        gtk_widget_set_uposition( m_widget, m_x, m_y );
+    
     return wxWindow::Show( show );
 }
 
@@ -869,6 +980,20 @@ void wxTopLevelWindowGTK::OnInternalIdle()
     }
 
     wxWindow::OnInternalIdle();
+    
+    // Synthetize activate events.
+    if ( g_sendActivateEvent != -1 )
+    {
+        bool activate = g_sendActivateEvent != 0;
+        
+        // if (!activate) wxPrintf( wxT("de") );
+        // wxPrintf( wxT("activate\n") );
+        
+        // do it only once
+        g_sendActivateEvent = -1;
+
+        wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame);
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -1067,13 +1192,8 @@ bool wxTopLevelWindowGTK::SetShape(const wxRegion& region)
     return do_shape_combine_region(window, region);
 }
 
-bool wxTopLevelWindowGTK::HasFocus()
+bool wxTopLevelWindowGTK::IsActive()
 {
-#ifdef __WXGTK20__
-    return GTK_WINDOW( m_widget )->has_toplevel_focus;
-#else
-    return ( wxGetTopLevelParent(FindFocus()) = this );
-#endif
+    return (this == (wxTopLevelWindowGTK*)g_activeFrame);
 }
 
-// vi:sts=4:sw=4:et