diff --git a/include/wx/gtk/window.h b/include/wx/gtk/window.h index b27e4cdc92..01f75a5e53 100644 --- a/include/wx/gtk/window.h +++ b/include/wx/gtk/window.h @@ -463,6 +463,7 @@ public: { return m_paintContext; } + void GTKSizeRevalidate(); #endif DECLARE_DYNAMIC_CLASS(wxWindowGTK) diff --git a/src/gtk/control.cpp b/src/gtk/control.cpp index c2633772fe..3f38a406b8 100644 --- a/src/gtk/control.cpp +++ b/src/gtk/control.cpp @@ -61,11 +61,13 @@ bool wxControl::Create( wxWindow *parent, bool wxControl::SetFont(const wxFont& font) { const bool changed = base_type::SetFont(font); - if (changed && !gtk_widget_get_realized(m_widget)) + if (changed && !gtk_widget_get_realized(m_widget) && gtk_check_version(3,5,0)) { // GTK defers sending "style-updated" until widget is realized, but // GetBestSize() won't compute correct result until the signal is sent, // so we have to do it now + // But don't bother for GTK > 3.4, the change won't take effect until + // GTK updates it's style cache g_signal_emit_by_name(m_widget, "style-updated"); } return changed; diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index 4d7a6cb9ea..4535dd23c3 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -1038,6 +1038,10 @@ bool wxTopLevelWindowGTK::Show( bool show ) wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); + +#ifdef __WXGTK3__ + GTKSizeRevalidate(); +#endif } bool change = base_type::Show(show); @@ -1291,6 +1295,9 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const DecorSize& decorSize) sizeEvent.SetEventObject(this); HandleWindowEvent(sizeEvent); +#ifdef __WXGTK3__ + GTKSizeRevalidate(); +#endif gtk_widget_show(m_widget); wxShowEvent showEvent(GetId(), true); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index f9beeba98a..b29862a97a 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -219,6 +219,10 @@ static wxWindowGTK *gs_deferredFocusOut = NULL; GdkEvent *g_lastMouseEvent = NULL; int g_lastButtonNumber = 0; +#ifdef __WXGTK3__ +static GList* gs_sizeRevalidateList; +#endif + //----------------------------------------------------------------------------- // debug //----------------------------------------------------------------------------- @@ -2032,6 +2036,17 @@ static void unrealize(GtkWidget*, wxWindow* win) win->GTKHandleUnrealize(); } +#if GTK_CHECK_VERSION(3,8,0) +//----------------------------------------------------------------------------- +// "layout" from GdkFrameClock +//----------------------------------------------------------------------------- + +static void frame_clock_layout(GdkFrameClock*, wxWindow* win) +{ + win->GTKSizeRevalidate(); +} +#endif // GTK_CHECK_VERSION(3,8,0) + } // extern "C" void wxWindowGTK::GTKHandleRealized() @@ -2077,13 +2092,26 @@ void wxWindowGTK::GTKHandleRealized() } #endif + const bool isTopLevel = IsTopLevel(); +#if GTK_CHECK_VERSION(3,8,0) + if (isTopLevel && gtk_check_version(3,8,0) == NULL) + { + GdkFrameClock* clock = gtk_widget_get_frame_clock(m_widget); + if (clock && + !g_signal_handler_find(clock, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, this)) + { + g_signal_connect(clock, "layout", G_CALLBACK(frame_clock_layout), this); + } + } +#endif + wxWindowCreateEvent event(static_cast(this)); event.SetEventObject( this ); GTKProcessEvent( event ); GTKUpdateCursor(false, true); - if (m_wxwindow && IsTopLevel()) + if (m_wxwindow && isTopLevel) { // attaching to style changed signal after realization avoids initial // changes we don't care about @@ -2476,6 +2504,8 @@ wxWindowGTK::~wxWindowGTK() #ifdef __WXGTK3__ if (m_styleProvider) g_object_unref(m_styleProvider); + + gs_sizeRevalidateList = g_list_remove(gs_sizeRevalidateList, this); #endif if (m_widget) @@ -4519,6 +4549,32 @@ GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const return m_wxwindow ? GTKGetDrawingWindow() : gtk_widget_get_window(m_widget); } +#ifdef __WXGTK3__ +void wxWindowGTK::GTKSizeRevalidate() +{ + GList* next; + for (GList* p = gs_sizeRevalidateList; p; p = next) + { + next = p->next; + wxWindow* win = static_cast(p->data); + if (wxGetTopLevelParent(win) == this) + { + win->InvalidateBestSize(); + gs_sizeRevalidateList = g_list_delete_link(gs_sizeRevalidateList, p); + } + } +} + +extern "C" { +static gboolean before_resize(void* data) +{ + wxWindow* win = static_cast(data); + win->InvalidateBestSize(); + return false; +} +} +#endif // __WXGTK3__ + bool wxWindowGTK::SetFont( const wxFont &font ) { if (!wxWindowBase::SetFont(font)) @@ -4531,6 +4587,24 @@ bool wxWindowGTK::SetFont( const wxFont &font ) GTKApplyWidgetStyle(true); } +#ifdef __WXGTK3__ + // Starting with GTK 3.6, style information is cached, and the cache is only + // updated before resizing, or when showing a TLW. If a different size font + // is set, our best size calculation will be wrong. All we can do is + // invalidate the best size right before the style cache is updated, so any + // subsequent best size requests use the correct font. + if (gtk_check_version(3,8,0) == NULL) + gs_sizeRevalidateList = g_list_append(gs_sizeRevalidateList, this); + else if (gtk_check_version(3,6,0) == NULL) + { + wxWindow* tlw = wxGetTopLevelParent(static_cast(this)); + if (tlw->m_widget && gtk_widget_get_visible(tlw->m_widget)) + g_idle_add_full(GTK_PRIORITY_RESIZE - 1, before_resize, this, NULL); + else + gs_sizeRevalidateList = g_list_append(gs_sizeRevalidateList, this); + } +#endif + return true; }