diff --git a/include/wx/gtk/private/win_gtk.h b/include/wx/gtk/private/win_gtk.h index 0fd421f3bc..8a382f325f 100644 --- a/include/wx/gtk/private/win_gtk.h +++ b/include/wx/gtk/private/win_gtk.h @@ -24,6 +24,8 @@ struct WXDLLIMPEXP_CORE wxPizza void put(GtkWidget* widget, int x, int y, int width, int height); void scroll(int dx, int dy); void get_border(GtkBorder& border); + void size_allocate_child( + GtkWidget* child, int x, int y, int width, int height, int parent_width = -1); GtkFixed m_fixed; GList* m_children; diff --git a/src/gtk/win_gtk.cpp b/src/gtk/win_gtk.cpp index 64570ca444..6e13eeaa05 100644 --- a/src/gtk/win_gtk.cpp +++ b/src/gtk/win_gtk.cpp @@ -105,24 +105,8 @@ static void pizza_size_allocate(GtkWidget* widget, GtkAllocation* alloc) const wxPizzaChild* child = static_cast(p->data); if (gtk_widget_get_visible(child->widget)) { - GtkAllocation child_alloc; - // note that child positions do not take border into - // account, they need to be relative to widget->window, - // which has already been adjusted - child_alloc.x = child->x - pizza->m_scroll_x; - child_alloc.y = child->y - pizza->m_scroll_y; - child_alloc.width = child->width; - child_alloc.height = child->height; - if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) - child_alloc.x = w - child_alloc.x - child_alloc.width; - - // GTK+3 doesn't like allocating 0 size, so don't do it. -#ifdef __WXGTK3__ - if (child_alloc.width && child_alloc.height) -#endif - { - gtk_widget_size_allocate(child->widget, &child_alloc); - } + pizza->size_allocate_child( + child->widget, child->x, child->y, child->width, child->height, w); } } } @@ -409,6 +393,34 @@ void wxPizza::move(GtkWidget* widget, int x, int y, int width, int height) } } +void wxPizza::size_allocate_child( + GtkWidget* child, int x, int y, int width, int height, int parent_width) +{ + if (width <= 0 || height <= 0) + return; + + GtkAllocation child_alloc; + // note that child positions do not take border into account, they need to + // be relative to widget->window, which has already been adjusted + child_alloc.x = x - m_scroll_x; + child_alloc.y = y - m_scroll_y; + child_alloc.width = width; + child_alloc.height = height; + if (gtk_widget_get_direction(GTK_WIDGET(this)) == GTK_TEXT_DIR_RTL) + { + if (parent_width < 0) + { + GtkBorder border; + get_border(border); + GtkAllocation alloc; + gtk_widget_get_allocation(GTK_WIDGET(this), &alloc); + parent_width = alloc.width - border.left - border.right; + } + child_alloc.x = parent_width - child_alloc.x - child_alloc.width; + } + gtk_widget_size_allocate(child, &child_alloc); +} + void wxPizza::put(GtkWidget* widget, int x, int y, int width, int height) { // Re-parenting a TLW under a child window is possible at wx level but diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 3d9075fb76..0f6b23e5fd 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; static bool gs_inSizeAllocate; #endif @@ -2215,38 +2214,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__ @@ -2941,9 +2908,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 && @@ -2955,22 +2924,29 @@ 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); + + if (pizza) + pizza->size_allocate_child(m_widget, x, y, width, height); + else + { + GtkAllocation a = { x, y, width, height }; + gtk_widget_size_allocate(m_widget, &a); + } } -#else // !__WXGTK3__ - gtk_widget_set_size_request(m_widget, width, height); -#endif // !__WXGTK3__ +#endif // __WXGTK3__ } void wxWindowGTK::ConstrainSize()