From 309f5fe529f3918a2b5e5b15cb7cb360ad5c6667 Mon Sep 17 00:00:00 2001 From: Paul Cornett Date: Fri, 9 Dec 2016 21:43:54 -0800 Subject: [PATCH] Fix infinite sizing loop caused by 64753769 Avoid the problems 64753769 attempted to address in a much simpler way: when a "size-allocate" is in progress, call gtk_widget_size_allocate() directly, rather than deferring a call to gtk_widget_queue_resize(). See #17585 (backport of d5681ee4a8e7140ebe3bf852f10eca56a8173b24) --- src/gtk/window.cpp | 73 ++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index bca54438b7..bc02b4ee9d 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -221,7 +221,6 @@ int g_lastButtonNumber = 0; #ifdef __WXGTK3__ static GList* gs_sizeRevalidateList; -static GSList* gs_queueResizeList; GList* wx_sizeEventList; static bool gs_inSizeAllocate; void wxGTKSizeRevalidate(wxWindow*); @@ -2099,38 +2098,6 @@ static void check_resize(GtkContainer*, wxWindow*) static void check_resize_after(GtkContainer*, wxWindow*) { gs_inSizeAllocate = false; - if (gs_queueResizeList) - { - for (GSList* p = gs_queueResizeList; p; p = p->next) - { - if (p->data == NULL) - continue; - - wxWindowGTK* w = static_cast(p->data); - g_object_remove_weak_pointer(G_OBJECT(w->m_widget), &p->data); - gtk_widget_set_size_request(w->m_widget, w->m_width, w->m_height); - - // in case only the position is changing - gtk_widget_queue_resize(w->m_widget); - - // need to force the queue-resize up to the TLW with GTK >= 3.20 - if (gtk_check_version(3,20,0) == NULL) - { - GtkWidget* widget = w->m_widget; - for (;;) - { - widget = gtk_widget_get_parent(widget); - if (widget == NULL) - break; - gtk_widget_queue_resize(widget); - if (gtk_widget_is_toplevel(widget)) - break; - } - } - } - g_slist_free(gs_queueResizeList); - gs_queueResizeList = NULL; - } } #endif // __WXGTK3__ @@ -2840,9 +2807,11 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget ) void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) { GtkWidget* parent = gtk_widget_get_parent(m_widget); + wxPizza* pizza = NULL; if (WX_IS_PIZZA(parent)) { - WX_PIZZA(parent)->move(m_widget, x, y, width, height); + pizza = WX_PIZZA(parent); + pizza->move(m_widget, x, y, width, height); if ( #ifdef __WXGTK3__ !gs_inSizeAllocate && @@ -2854,22 +2823,38 @@ void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) } } + gtk_widget_set_size_request(m_widget, width, height); + #ifdef __WXGTK3__ // With GTK3, gtk_widget_queue_resize() is ignored while a size-allocate // is in progress. This situation is common in wxWidgets, since // size-allocate can generate wxSizeEvent and size event handlers often - // call SetSize(), directly or indirectly. Work around this by deferring - // the queue-resize until after size-allocate processing is finished. - if (!gs_inSizeAllocate || !gtk_widget_get_visible(m_widget)) - gtk_widget_set_size_request(m_widget, width, height); - else + // call SetSize(), directly or indirectly. It should be fine to call + // gtk_widget_size_allocate() immediately in this case. + if (gs_inSizeAllocate && gtk_widget_get_visible(m_widget) && width > 0 && height > 0) { - gs_queueResizeList = g_slist_prepend(gs_queueResizeList, this); - g_object_add_weak_pointer(G_OBJECT(m_widget), &gs_queueResizeList->data); + // obligatory size request before size allocate to avoid GTK3 warnings + GtkRequisition req; + gtk_widget_get_preferred_size(m_widget, &req, NULL); + + GtkAllocation alloc = { x, y, width, height }; + if (pizza) + { + alloc.x -= pizza->m_scroll_x; + alloc.y -= pizza->m_scroll_y; + if (gtk_widget_get_direction(parent) == GTK_TEXT_DIR_RTL) + { + GtkBorder border; + pizza->get_border(border); + GtkAllocation parent_alloc; + gtk_widget_get_allocation(parent, &parent_alloc); + int w = parent_alloc.width - border.left - border.right; + alloc.x = w - alloc.x - alloc.width; + } + } + gtk_widget_size_allocate(m_widget, &alloc); } -#else // !__WXGTK3__ - gtk_widget_set_size_request(m_widget, width, height); -#endif // !__WXGTK3__ +#endif // __WXGTK3__ } void wxWindowGTK::ConstrainSize()