]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/frame.cpp
Fox around a bug in GTK's GtkNotebook
[wxWidgets.git] / src / gtk / frame.cpp
index 961aae908a966a8b148006ddf5190255c35be6ff..0e181020ffa081d93985e6d9baa5f9548b886c5d 100644 (file)
@@ -33,18 +33,37 @@ const int wxMENU_HEIGHT    = 27;
 const int wxSTATUS_HEIGHT  = 25;
 const int wxPLACE_HOLDER   = 0;
 
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
 //-----------------------------------------------------------------------------
 // data
 //-----------------------------------------------------------------------------
 
 extern wxList wxPendingDelete;
 
+//-----------------------------------------------------------------------------
+// debug
+//-----------------------------------------------------------------------------
+
+#ifdef __WXDEBUG__
+
+extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
+
+#endif
+
 //-----------------------------------------------------------------------------
 // "size_allocate"
 //-----------------------------------------------------------------------------
 
 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return;
 
 /*
@@ -68,6 +87,8 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
 
 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
 /*
     printf( "OnDelete from " );
     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
@@ -86,6 +107,8 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX
 
 static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return;
     
     win->m_menuBarDetached = FALSE;
@@ -98,6 +121,8 @@ static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *
 
 static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return;
     
     win->m_menuBarDetached = TRUE;
@@ -110,6 +135,8 @@ static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *
 
 static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return;
     
     win->m_toolBarDetached = FALSE;
@@ -122,6 +149,8 @@ static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidge
 
 static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSED(child), wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return;
     
     win->m_toolBarDetached = TRUE;
@@ -134,6 +163,8 @@ static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSE
 
 static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     if (!win->HasVMT()) return FALSE;
 
     win->m_x = event->x;
@@ -156,6 +187,8 @@ static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventC
 static gint 
 gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
 {
+    if (g_isIdle) wxapp_install_idle_handler();
+
     /* all this is for Motif Window Manager "hints" and is supposed to be
        recognized by other WM as well. not tested. */
     long decor = (long) GDK_DECOR_ALL;
@@ -163,16 +196,18 @@ gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
     
     if ((win->m_windowStyle & wxCAPTION) == 0)
        decor |= GDK_DECOR_TITLE;
-/*  if ((win->m_windowStyle & wxMINIMIZE) == 0)
-       func |= GDK_FUNC_MINIMIZE;
-    if ((win->m_windowStyle & wxMAXIMIZE) == 0)
-       func |= GDK_FUNC_MAXIMIZE;            */
     if ((win->m_windowStyle & wxSYSTEM_MENU) == 0)
        decor |= GDK_DECOR_MENU;
     if ((win->m_windowStyle & wxMINIMIZE_BOX) == 0)
+    {
+       func |= GDK_FUNC_MINIMIZE;
        decor |= GDK_DECOR_MINIMIZE;
+    }
     if ((win->m_windowStyle & wxMAXIMIZE_BOX) == 0)
+    {
+       func |= GDK_FUNC_MAXIMIZE;
        decor |= GDK_DECOR_MAXIMIZE;
+    }
     if ((win->m_windowStyle & wxRESIZE_BORDER) == 0)
        func |= GDK_FUNC_RESIZE;
        
@@ -193,14 +228,19 @@ gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
        win->SetIcon( icon );
     }
     
-    if (!win->m_sizeSet)
+    /* we set the focus to the child that accepts the focus. this
+       doesn't really have to be done in "realize" but why not? */
+    wxNode *node = win->m_children.First();
+    while (node)
     {
-        /* by calling GtkOnSize here, we don't have to call
-           either after showing the frame, which would entail
-           much ugly flicker or from within the size_allocate
-           handler, because GTK 1.1.X forbids that. */
-
-        win->GtkOnSize( win->m_x, win->m_y, win->m_width, win->m_height );
+        wxWindow *child = (wxWindow*) node->Data();
+       if (child->AcceptsFocus())
+       {
+           child->SetFocus();
+           break;
+       }
+       
+        node = node->Next();
     }
     
     return FALSE;
@@ -323,6 +363,10 @@ bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
 
     m_widget = gtk_window_new( win_type );
 
+#ifdef __WXDEBUG__
+    debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
+#endif
+
     gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
 
@@ -335,17 +379,22 @@ bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
     GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
     gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
     
+#ifdef __WXDEBUG__
+    debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
+#endif
+
     /* m_wxwindow only represents the client area without toolbar and menubar */
     m_wxwindow = gtk_myfixed_new();
     gtk_widget_show( m_wxwindow );
     gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
     
-    /* we allow the frame to get the focus as otherwise no
-       key events will get sent to it. the point with this is
-       that the menu's key accelerators work by interceting
-       key events here */
-    GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
-    gtk_widget_grab_focus( m_wxwindow );
+#ifdef __WXDEBUG__
+    debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
+#endif
+
+    /* we donm't allow the frame to get the focus as otherwise
+       the frame will grabit at arbitrary fcous changes. */
+    GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
 
     if (m_parent) m_parent->AddChild( this );
 
@@ -391,7 +440,6 @@ bool wxFrame::Show( bool show )
 {
     wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
 
-#if 0
     if (show && !m_sizeSet)
     {
         /* by calling GtkOnSize here, we don't have to call
@@ -401,7 +449,6 @@ bool wxFrame::Show( bool show )
 
         GtkOnSize( m_x, m_y, m_width, m_height );
     }
-#endif
 
     return wxWindow::Show( show );
 }
@@ -465,8 +512,8 @@ void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
     {
         if ((m_x != old_x) || (m_y != old_y))
         {
-            /* m_sizeSet = FALSE; */
-            gtk_widget_set_uposition( m_widget, m_x, m_y );
+            /* we set the size here and in gtk_frame_map_callback */
+           gtk_widget_set_uposition( m_widget, m_x, m_y );
         }
     }
 
@@ -620,6 +667,9 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height
             m_frameMenuBar->m_height = hh;
 
             gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameMenuBar->m_widget, xx, yy );
+           
+//         m_frameMenuBar->m_widget->requisition.width = ww;
+//         m_frameMenuBar->m_widget->requisition.height = hh;
             gtk_widget_set_usize( m_frameMenuBar->m_widget, ww, hh );
        
            client_area_y_offset += hh;
@@ -645,6 +695,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height
             m_frameToolBar->m_width = ww;
 
             gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameToolBar->m_widget, xx, yy );
+           
             gtk_widget_set_usize( m_frameToolBar->m_widget, ww, hh );
        
            client_area_y_offset += hh;
@@ -677,12 +728,15 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height
         m_frameStatusBar->m_height = hh;
 
         gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameStatusBar->m_widget, xx, yy );
+       
+//     m_frameStatusBar->m_widget->requisition.width = ww;
+//     m_frameStatusBar->m_widget->requisition.height = hh;
         gtk_widget_set_usize( m_frameStatusBar->m_widget, ww, hh );
     }
 
     /* we actually set the size of a frame here and no-where else */
     gtk_widget_set_usize( m_widget, m_width, m_height );
-
+    
     m_sizeSet = TRUE;
 
     /* send size event to frame */
@@ -703,7 +757,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height
 
 void wxFrame::OnInternalIdle()
 {
-    if (!m_sizeSet)
+    if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
         GtkOnSize( m_x, m_y, m_width, m_height );
 
     DoMenuUpdates();
@@ -724,16 +778,16 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
     }
     else
     {
-        // do we have exactly one child?
+        /* do we have exactly one child? */
         wxWindow *child = (wxWindow *)NULL;
         for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
         {
             wxWindow *win = (wxWindow *)node->Data();
             if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
             {
-                if ( child )
+                if (child)
                 {
-                    // it's the second one: do nothing
+                    /* it's the second one: do nothing */
                     return;
                 }
 
@@ -741,10 +795,10 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
             }
         }
 
-        // no children at all?
-        if ( child )
+        /* no children at all? */
+        if (child)
         {
-            // yes: set it's size to fill all the frame
+            /* yes: set it's size to fill all the frame */
             int client_x, client_y;
             GetClientSize( &client_x, &client_y );
             child->SetSize( 1, 1, client_x-2, client_y-2 );
@@ -755,6 +809,12 @@ void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
 {
     menu->SetInvokingWindow( win );
+    
+#if (GTK_MINOR_VERSION > 0)
+    /* support for native hot keys  */
+    gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(win->m_widget));
+#endif
+
     wxNode *node = menu->GetItems().First();
     while (node)
     {
@@ -774,8 +834,8 @@ void wxFrame::SetMenuBar( wxMenuBar *menuBar )
 
     if (m_frameMenuBar)
     {
-        /* support for native key accelerators indicated by underscroes */
 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
+        /* support for native key accelerators indicated by underscroes */
          gtk_accel_group_attach( m_frameMenuBar->m_accel, GTK_OBJECT(m_widget));
 #endif