]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/toplevel.cpp
fix PangoFontMetrics leak in GetCharHeight() (bug 1691180)
[wxWidgets.git] / src / gtk / toplevel.cpp
index cb8a7b56ac6b22627cff1063fc55cb7fbeb7326e..7227e4887fff368f4829b65e0132d5043e946b46 100644 (file)
@@ -197,23 +197,6 @@ static gboolean gtk_frame_focus_out_callback( GtkWidget *widget,
 }
 }
 
-//-----------------------------------------------------------------------------
-// "focus" from m_window
-//-----------------------------------------------------------------------------
-
-extern "C" {
-static gboolean gtk_frame_focus_callback( GtkWidget *WXUNUSED(widget),
-                                          GtkDirectionType WXUNUSED(d),
-                                          wxWindow *WXUNUSED(win) )
-{
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    // This disables GTK's tab traversal
-    return TRUE;
-}
-}
-
 //-----------------------------------------------------------------------------
 // "size_allocate"
 //-----------------------------------------------------------------------------
@@ -242,12 +225,30 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
         // Tell the wxWindow class about the new size
         win->m_width = alloc->width;
         win->m_height = alloc->height;
-        
+
         win->GtkUpdateSize();
     }
 }
 }
 
+// ----------------------------------------------------------------------------
+// "size_request"
+// ----------------------------------------------------------------------------
+
+extern "C" {
+void wxgtk_tlw_size_request_callback(GtkWidget * WXUNUSED(widget),
+                                     GtkRequisition *requisition,
+                                     wxTopLevelWindowGTK *win)
+{
+    // we must return the size of the window without WM decorations, otherwise
+    // GTK+ gets confused, so don't call just GetSize() here
+    int w, h;
+    win->GTKDoGetSize(&w, &h);
+
+    requisition->height = h;
+    requisition->width = w;
+}
+}
 //-----------------------------------------------------------------------------
 // "delete_event"
 //-----------------------------------------------------------------------------
@@ -586,6 +587,8 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     g_signal_connect (m_widget, "size_allocate",
                       G_CALLBACK (gtk_frame_size_callback), this);
 
+    g_signal_connect (m_widget, "size_request",
+                      G_CALLBACK (wxgtk_tlw_size_request_callback), this);
     PostCreation();
 
     if ((m_x != -1) || (m_y != -1))
@@ -608,10 +611,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     g_signal_connect (m_widget, "configure_event",
                       G_CALLBACK (gtk_frame_configure_callback), this);
 
-    // disable native tab traversal
-    g_signal_connect (m_widget, "focus",
-                      G_CALLBACK (gtk_frame_focus_callback), this);
-
     // activation
     g_signal_connect_after (m_widget, "focus_in_event",
                       G_CALLBACK (gtk_frame_focus_in_callback), this);
@@ -629,7 +628,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     {
         m_gdkDecor = 0;
         m_gdkFunc = 0;
-        
+
         if ((style & wxRESIZE_BORDER) != 0)
            m_gdkFunc |= GDK_FUNC_RESIZE;
     }
@@ -700,10 +699,10 @@ bool wxTopLevelWindowGTK::EnableCloseButton( bool enable )
         m_gdkFunc |= GDK_FUNC_CLOSE;
     else
         m_gdkFunc &= ~GDK_FUNC_CLOSE;
-    
+
     if (GTK_WIDGET_REALIZED(m_widget) && (m_widget->window))
         gdk_window_set_functions( m_widget->window, (GdkWMFunction)m_gdkFunc );
-        
+
     return true;
 }
 
@@ -845,92 +844,150 @@ void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXU
     wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
 }
 
-void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
-{
-    wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
+// ----------------------------------------------------------------------------
+// window geometry
+// ----------------------------------------------------------------------------
 
-    // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
-    wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
+void wxTopLevelWindowGTK::GTKDoGetSize(int *width, int *height) const
+{
+    return wxTopLevelWindowBase::DoGetSize(width, height);
+}
 
+void wxTopLevelWindowGTK::GTKDoSetSize(int width, int height)
+{
     // avoid recursions
     if (m_resizing)
         return;
     m_resizing = true;
 
-    int old_x = m_x;
-    int old_y = m_y;
-
     int old_width = m_width;
     int old_height = m_height;
 
-    if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
+    if ( width != -1 )
+        m_width = width;
+    if ( height != -1 )
+        m_height = height;
+
+    // GPE's window manager doesn't like size hints at all, esp. when the user
+    // has to use the virtual keyboard, so don't constrain size there
+#ifndef __WXGPE__
+    int minWidth = GetMinWidth(),
+        minHeight = GetMinHeight(),
+        maxWidth = GetMaxWidth(),
+        maxHeight = GetMaxHeight();
+
+    if ( minWidth != -1 && m_width < minWidth )
+        m_width = minWidth;
+    if ( minHeight != -1 && m_height < minHeight )
+        m_height = minHeight;
+    if ( maxWidth != -1 && m_width > maxWidth )
+        m_width = maxWidth;
+    if ( maxHeight != -1 && m_height > maxHeight )
+        m_height = maxHeight;
+#endif // __WXGPE__
+
+    if ( m_width != old_width || m_height != old_height )
     {
-        if (x != -1) m_x = x;
-        if (y != -1) m_y = y;
+        gtk_window_resize( GTK_WINDOW(m_widget), m_width, m_height );
+
+        /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
+           done either directly before the frame is shown or in idle time
+           so that different calls to SetSize() don't lead to flicker. */
+        m_sizeSet = false;
     }
-    else
+
+    m_resizing = false;
+}
+
+void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
+{
+    wxCHECK_RET( m_widget, wxT("invalid frame") );
+
+    // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
+    wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
+
+
+    // deal with the position first
+    int old_x = m_x;
+    int old_y = m_y;
+
+    if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+    {
+        // -1 means "use existing" unless the flag above is specified
+        if ( x != -1 )
+            m_x = x;
+        if ( y != -1 )
+            m_y = y;
+    }
+    else // wxSIZE_ALLOW_MINUS_ONE
     {
         m_x = x;
         m_y = y;
     }
-    if (width != -1) m_width = width;
-    if (height != -1) m_height = height;
-    
-/*
-    if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
+
+    if ( m_x != old_x || m_y != old_y )
     {
-        if (width == -1) m_width = 80;
+        gtk_window_move( GTK_WINDOW(m_widget), m_x, m_y );
     }
 
-    if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
+
+    // and now change the size: as we want to set the size of the entire
+    // window, including decorations, we must adjust the size passed to
+    // GTKDoSetSize() which takes with the size of undecorated frame only
+    if ( width != -1 || height != -1 )
     {
-       if (height == -1) m_height = 26;
+        int wTotal,
+            hTotal;
+        DoGetSize(&wTotal, &hTotal);
+
+        int wUndec,
+            hUndec;
+        GTKDoGetSize(&wUndec, &hUndec);
+
+        if ( width != -1 )
+            width -= wTotal - wUndec;
+        if ( height != -1 )
+            height -= hTotal - hUndec;
     }
-*/
 
-    int minWidth = GetMinWidth(),
-        minHeight = GetMinHeight(),
-        maxWidth = GetMaxWidth(),
-        maxHeight = GetMaxHeight();
-
-#ifdef __WXGPE__
-    // GPE's window manager doesn't like size hints
-    // at all, esp. when the user has to use the
-    // virtual keyboard.
-    minWidth = -1;
-    minHeight = -1;
-    maxWidth = -1;
-    maxHeight = -1;
-#endif
+    GTKDoSetSize(width, height);
+}
 
-    if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
-    if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
-    if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
-    if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
+void wxTopLevelWindowGTK::DoGetSize(int *width, int *height) const
+{
+    wxCHECK_RET( m_widget, wxT("invalid frame") );
 
-    if ((m_x != -1) || (m_y != -1))
+    if ( !m_widget->window )
     {
-        if ((m_x != old_x) || (m_y != old_y))
-        {
-            gtk_window_move( GTK_WINDOW(m_widget), m_x, m_y );
-        }
+        // this can happen if we're called before the window is realized, so
+        // don't assert but just return the stored values
+        GTKDoGetSize(width, height);
+        return;
     }
 
-    if ((m_width != old_width) || (m_height != old_height))
-    {
-        gtk_window_resize( GTK_WINDOW(m_widget), m_width, m_height );
-
-        /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
-           done either directly before the frame is shown or in idle time
-           so that different calls to SetSize() don't lead to flicker. */
-        m_sizeSet = false;
-    }
+    GdkRectangle rect;
+    gdk_window_get_frame_extents(m_widget->window, &rect);
 
-    m_resizing = false;
+    if ( width )
+        *width = rect.width;
+    if ( height )
+        *height = rect.height;
 }
 
 void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
 {
+    if ( IsIconized() )
+    {
+        // for consistency with wxMSW, client area is supposed to be empty for
+        // the iconized windows
+        if ( width )
+            *width = 0;
+        if ( height )
+            *height = 0;
+
+        return;
+    }
+
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
 
     if (height)
@@ -949,10 +1006,7 @@ void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
 
 void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
 {
-    wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
-
-    DoSetSize(-1, -1,
-              width + m_miniEdge*2, height  + m_miniEdge*2 + m_miniTitle, 0);
+    GTKDoSetSize(width + m_miniEdge*2, height  + m_miniEdge*2 + m_miniTitle);
 }
 
 void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,