X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0d635035cc67f4d0d92b7afb79871b650406c262..2e61f6814126617f286fad69f614cccd86db6412:/src/gtk/toplevel.cpp diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index d243ce4b58..7227e4887f 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -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,95 +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_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 ); + GdkRectangle rect; + gdk_window_get_frame_extents(m_widget->window, &rect); - /* 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; - } - - 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) @@ -952,12 +1006,42 @@ void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const void wxTopLevelWindowGTK::DoSetClientSize( int width, int height ) { - wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); + GTKDoSetSize(width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle); +} - DoSetSize(-1, -1, - width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0); +void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH, + int maxW, int maxH, + int incW, int incH ) +{ + 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 @@ -995,49 +1079,8 @@ void wxTopLevelWindowGTK::GtkOnSize() 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; @@ -1375,8 +1418,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