]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/toplevel.cpp
Unicode compilation fix
[wxWidgets.git] / src / gtk / toplevel.cpp
index c6ef11f6812a853a26132c763227f92a785f4d12..e3e320f77ee2eaa6d8ead0cb28ef92f9adc08ac9 100644 (file)
@@ -202,13 +202,14 @@ static gboolean gtk_frame_focus_out_callback( GtkWidget *widget,
 //-----------------------------------------------------------------------------
 
 extern "C" {
-static gboolean gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
+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
-    g_signal_stop_emission_by_name (widget, "focus");
     return TRUE;
 }
 }
@@ -238,13 +239,33 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
                                 (int)alloc->height );
 */
 
+        // 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"
 //-----------------------------------------------------------------------------
@@ -440,6 +461,7 @@ void wxTopLevelWindowGTK::Init()
     m_insertInClientArea = true;
     m_isIconized = false;
     m_fsIsShowing = false;
+    m_fsSaveFlag = 0;
     m_themeEnabled = true;
     m_gdkDecor = m_gdkFunc = 0;
     m_grabbed = false;
@@ -582,6 +604,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))
@@ -625,7 +649,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     {
         m_gdkDecor = 0;
         m_gdkFunc = 0;
-        
+
         if ((style & wxRESIZE_BORDER) != 0)
            m_gdkFunc |= GDK_FUNC_RESIZE;
     }
@@ -690,7 +714,18 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
         g_lastActiveFrame = NULL;
 }
 
+bool wxTopLevelWindowGTK::EnableCloseButton( bool enable )
+{
+    if (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;
+}
 
 bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
 {
@@ -711,9 +746,15 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
     if ( (method == wxX11_FS_WMSPEC) && !gtk_check_version(2,2,0) )
     {
         if (show)
+        {
+            m_fsSaveFlag = style;
             gtk_window_fullscreen( GTK_WINDOW( m_widget ) );
+        }
         else
+        {
+            m_fsSaveFlag = 0;
             gtk_window_unfullscreen( GTK_WINDOW( m_widget ) );
+        }
     }
     else
 #endif // GTK+ >= 2.2.0
@@ -756,6 +797,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
         }
         else // hide
         {
+            m_fsSaveFlag = 0;
             if (method != wxX11_FS_WMSPEC)
             {
                 // don't do it always, Metacity hates it
@@ -801,7 +843,7 @@ bool wxTopLevelWindowGTK::Show( bool show )
            much ugly flicker or from within the size_allocate
            handler, because GTK 1.1.X forbids that. */
 
-        GtkOnSize( m_x, m_y, m_width, m_height );
+        GtkOnSize();
     }
 
     // This seems no longer to be needed and the call
@@ -823,133 +865,212 @@ 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_widget_set_uposition( 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))
-    {
-        if (m_widget->window)
-            gdk_window_resize( m_widget->window, m_width, m_height );
-        else
-            gtk_window_set_default_size( 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") );
 
-    wxWindow::DoGetClientSize( width, height );
     if (height)
     {
-        // mini edge
-        *height -= m_miniEdge*2 + m_miniTitle;
+        *height = m_height - 2 * m_miniEdge - m_miniTitle;
+        if (*height < 0)
+            *height = 0;
     }
     if (width)
     {
-        *width -= m_miniEdge*2;
+        *width = m_width - 2 * m_miniEdge;
+        if (*width < 0)
+            *width = 0;
     }
 }
 
 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::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
-                                     int width, int height )
+void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH,
+                                          int maxW, int maxH,
+                                          int incW, int incH )
 {
-    // due to a bug in gtk, x,y are always 0
-    // m_x = x;
-    // m_y = y;
+    wxTopLevelWindowBase::DoSetSizeHints( minW, minH, maxW, maxH, incW, incH );
+
+    const wxSize minSize = GetMinSize();
+    const wxSize maxSize = GetMaxSize();
+    GdkGeometry hints;
+    int hints_mask = 0;
+    if (minSize.x > 0 || minSize.y > 0)
+    {
+        hints_mask |= GDK_HINT_MIN_SIZE;
+        hints.min_width  = minSize.x > 0 ? minSize.x : 0;
+        hints.min_height = minSize.y > 0 ? minSize.y : 0;
+    }
+    if (maxSize.x > 0 || maxSize.y > 0)
+    {
+        hints_mask |= GDK_HINT_MAX_SIZE;
+        hints.max_width  = maxSize.x > 0 ? maxSize.x : INT_MAX;
+        hints.max_height = maxSize.y > 0 ? maxSize.y : INT_MAX;
+    }
+    if (incW > 0 || incH > 0)
+    {
+        hints_mask |= GDK_HINT_RESIZE_INC;
+        hints.width_inc  = incW > 0 ? incW : 1;
+        hints.height_inc = incH > 0 ? incH : 1;
+    }
+    gtk_window_set_geometry_hints(
+        (GtkWindow*)m_widget, NULL, &hints, (GdkWindowHints)hints_mask);
+}
 
+
+void wxTopLevelWindowGTK::GtkOnSize()
+{
     // avoid recursions
     if (m_resizing) return;
     m_resizing = true;
 
     if ( m_wxwindow == NULL ) return;
 
-    m_width = width;
-    m_height = height;
-
     /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
        wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
        set in wxFrame::Create so it is used to check what kind of frame we
@@ -979,54 +1100,18 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
 
     if (m_mainWidget)
     {
-        // set size hints
-        gint            flag = 0; // GDK_HINT_POS;
-        GdkGeometry     geom;
-
-        if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
-        if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
-
-        geom.min_width = minWidth;
-        geom.min_height = minHeight;
-
-            // Because of the way we set GDK_HINT_MAX_SIZE above, if either of
-            // maxHeight or maxWidth is set, we must set them both, else the
-            // remaining -1 will be taken literally.
-
-            // I'm certain this also happens elsewhere, and is the probable
-            // cause of other such things as:
-            // Gtk-WARNING **: gtk_widget_size_allocate():
-            //       attempt to allocate widget with width 65535 and height 600
-            // but I don't have time to track them all now..
-            //
-            // Really we need to encapulate all this height/width business and
-            // stop any old method from ripping at the members directly and
-            // scattering -1's without regard for who might resolve them later.
-
-        geom.max_width = ( maxHeight == -1 ) ? maxWidth
-                         : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth()
-                           : maxWidth ;
-
-        geom.max_height = ( maxWidth == -1 ) ? maxHeight    // ( == -1 here )
-                          : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight()
-                            : maxHeight ;
-
-        gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
-                                       (GtkWidget*) NULL,
-                                       &geom,
-                                       (GdkWindowHints) flag );
-
-        /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
-         * menubar, the toolbar and the client area, which is represented by
-         * m_wxwindow.
-         * this hurts in the eye, but I don't want to call SetSize()
-         * because I don't want to call any non-native functions here. */
-
+        // m_mainWidget holds the menubar, the toolbar and the client area,
+        // which is represented by m_wxwindow.
         int client_x = m_miniEdge;
         int client_y = m_miniEdge + m_miniTitle;
         int client_w = m_width - 2*m_miniEdge;
         int client_h = m_height - 2*m_miniEdge - m_miniTitle;
+        if (client_w < 0)
+            client_w = 0;
+        if (client_h < 0)
+            client_h = 0;
 
+        // Let the parent perform the resize
         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
                               m_wxwindow,
                               client_x, client_y, client_w, client_h );
@@ -1051,7 +1136,7 @@ void wxTopLevelWindowGTK::OnInternalIdle()
 {
     if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
     {
-        GtkOnSize( m_x, m_y, m_width, m_height );
+        GtkOnSize();
 
         // we'll come back later
         if (g_isIdle)
@@ -1354,8 +1439,7 @@ bool wxTopLevelWindowGTK::CanSetTransparent()
 #if GTK_CHECK_VERSION(2,10,0)
     if (!gtk_check_version(2,10,0))
     {
-        if (gtk_widget_is_composited (m_widget))
-            return true;
+        return (gtk_widget_is_composited (m_widget));
     }
     else
 #endif // In case of lower versions than gtk+-2.10.0 we could look for _NET_WM_CM_Sn ourselves