You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wxGTK3/wxGTK3-3.0.2-gtk-sizing-pro...

167 lines
5.6 KiB

From 6475376931bf316a4fd791114408f7c1fc2fe836 Mon Sep 17 00:00:00 2001
From: Paul Cornett <paulcor@users.noreply.github.com>
Date: Wed, 2 Nov 2016 10:30:44 -0700
Subject: [PATCH] Fix some sizing problems with GTK3
A change in size-allocate handling with GTK+ 3.20 exposed a flaw in our method for
deferring queue-resize requests. Using an idle callback to process the requests
did not work well with the GdkFrameClock-based system used since GTK+ 3.8. Using
the "check-resize" signal works better. Also with GTK+ >= 3.20, it seems necessary
to manually work the queue-resize up to the TLW, as otherwise the resized widgets
don't get updated without an external size-allocate event.
See #17585
(backport of 3b4ee5a031b1c2fa29772b90751a82dd7f1d3de0)
---
src/gtk/window.cpp | 102 +++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 76 insertions(+), 26 deletions(-)
diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp
index d27f889..ab56baa 100644
--- a/src/gtk/window.cpp
+++ b/src/gtk/window.cpp
@@ -221,6 +221,8 @@ int g_lastButtonNumber = 0;
#ifdef __WXGTK3__
static GList* gs_sizeRevalidateList;
+static GSList* gs_queueResizeList;
+static bool gs_inSizeAllocate;
void wxGTKSizeRevalidate(wxWindow*);
#endif
@@ -2083,6 +2085,54 @@ static void frame_clock_layout(GdkFrameClock*, wxWindow* win)
}
#endif // GTK_CHECK_VERSION(3,8,0)
+#ifdef __WXGTK3__
+//-----------------------------------------------------------------------------
+// "check-resize"
+//-----------------------------------------------------------------------------
+
+static void check_resize(GtkContainer*, wxWindow*)
+{
+ gs_inSizeAllocate = true;
+}
+
+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__
+
} // extern "C"
void wxWindowGTK::GTKHandleRealized()
@@ -2670,6 +2720,13 @@ void wxWindowGTK::PostCreation()
g_signal_connect(m_wxwindow ? m_wxwindow : m_widget, "size_allocate",
G_CALLBACK(size_allocate), this);
}
+#ifdef __WXGTK3__
+ else
+ {
+ g_signal_connect(m_widget, "check-resize", G_CALLBACK(check_resize), this);
+ g_signal_connect_after(m_widget, "check-resize", G_CALLBACK(check_resize_after), this);
+ }
+#endif
#if GTK_CHECK_VERSION(2, 8, 0)
#ifndef __WXGTK3__
@@ -2778,46 +2835,39 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
G_CALLBACK (gtk_window_leave_callback), this);
}
-static GSList* gs_queueResizeList;
-
-extern "C" {
-static gboolean queue_resize(void*)
-{
- gdk_threads_enter();
- for (GSList* p = gs_queueResizeList; p; p = p->next)
- {
- if (p->data)
- {
- gtk_widget_queue_resize(GTK_WIDGET(p->data));
- g_object_remove_weak_pointer(G_OBJECT(p->data), &p->data);
- }
- }
- g_slist_free(gs_queueResizeList);
- gs_queueResizeList = NULL;
- gdk_threads_leave();
- return false;
-}
-}
-
void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)
{
- gtk_widget_set_size_request(m_widget, width, height);
GtkWidget* parent = gtk_widget_get_parent(m_widget);
if (WX_IS_PIZZA(parent))
+ {
WX_PIZZA(parent)->move(m_widget, x, y, width, height);
+ if (
+#ifdef __WXGTK3__
+ !gs_inSizeAllocate &&
+#endif
+ gtk_widget_get_visible(m_widget))
+ {
+ // in case only the position is changing
+ gtk_widget_queue_resize(m_widget);
+ }
+ }
+#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 (g_slist_find(gs_queueResizeList, m_widget) == NULL)
+ if (!gs_inSizeAllocate || !gtk_widget_get_visible(m_widget))
+ gtk_widget_set_size_request(m_widget, width, height);
+ else
{
- if (gs_queueResizeList == NULL)
- g_idle_add_full(GTK_PRIORITY_RESIZE, queue_resize, NULL, NULL);
- gs_queueResizeList = g_slist_prepend(gs_queueResizeList, m_widget);
+ gs_queueResizeList = g_slist_prepend(gs_queueResizeList, this);
g_object_add_weak_pointer(G_OBJECT(m_widget), &gs_queueResizeList->data);
}
+#else // !__WXGTK3__
+ gtk_widget_set_size_request(m_widget, width, height);
+#endif // !__WXGTK3__
}
void wxWindowGTK::ConstrainSize()