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..62cc9316b1 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -56,6 +56,10 @@ #include #endif // wxUSE_LIBHILDON2 +#ifdef __WXGTK3__ +void wxGTKSizeRevalidate(wxWindow*); +#endif + // ---------------------------------------------------------------------------- // data // ---------------------------------------------------------------------------- @@ -1038,6 +1042,10 @@ bool wxTopLevelWindowGTK::Show( bool show ) wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); + +#ifdef __WXGTK3__ + wxGTKSizeRevalidate(this); +#endif } bool change = base_type::Show(show); @@ -1291,6 +1299,9 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const DecorSize& decorSize) sizeEvent.SetEventObject(this); HandleWindowEvent(sizeEvent); +#ifdef __WXGTK3__ + wxGTKSizeRevalidate(this); +#endif gtk_widget_show(m_widget); wxShowEvent showEvent(GetId(), true); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index e71ca1db8d..044c7ca587 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -219,6 +219,11 @@ static wxWindowGTK *gs_deferredFocusOut = NULL; GdkEvent *g_lastMouseEvent = NULL; int g_lastButtonNumber = 0; +#ifdef __WXGTK3__ +static GList* gs_sizeRevalidateList; +void wxGTKSizeRevalidate(wxWindow*); +#endif + //----------------------------------------------------------------------------- // debug //----------------------------------------------------------------------------- @@ -2038,6 +2043,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) +{ + wxGTKSizeRevalidate(win); +} +#endif // GTK_CHECK_VERSION(3,8,0) + } // extern "C" void wxWindowGTK::GTKHandleRealized() @@ -2083,13 +2099,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 @@ -2482,6 +2511,8 @@ wxWindowGTK::~wxWindowGTK() #ifdef __WXGTK3__ if (m_styleProvider) g_object_unref(m_styleProvider); + + gs_sizeRevalidateList = g_list_remove(gs_sizeRevalidateList, this); #endif gs_needCursorResetMap.erase(this); @@ -4531,6 +4562,32 @@ GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const return m_wxwindow ? GTKGetDrawingWindow() : gtk_widget_get_window(m_widget); } +#ifdef __WXGTK3__ +void wxGTKSizeRevalidate(wxWindow* tlw) +{ + GList* next; + for (GList* p = gs_sizeRevalidateList; p; p = next) + { + next = p->next; + wxWindow* win = static_cast(p->data); + if (wxGetTopLevelParent(win) == tlw) + { + 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)) @@ -4543,6 +4600,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; }