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 d5681ee4a8)
This commit is contained in:
Paul Cornett
2016-12-09 21:43:54 -08:00
parent 28aea07674
commit 309f5fe529

View File

@@ -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<wxWindowGTK*>(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()