Avoid using gdk_window_freeze_updates() to implement Freeze()
Implement Freeze() by blocking the GtkWindow "expose-event"/"draw" signal instead. Since the introduction of client-side windows in GTK+ 2.18, gdk_window_freeze_updates() is unuseable because the impl_window (and thus the update_freeze_count) for a given GdkWindow can change unpredictably. See #16795
This commit is contained in:
parent
c15ae5e4a3
commit
b7cf54d24a
@ -383,6 +383,7 @@ protected:
|
||||
virtual void DoFreeze() wxOVERRIDE;
|
||||
virtual void DoThaw() wxOVERRIDE;
|
||||
|
||||
void GTKConnectFreezeWidget(GtkWidget* widget);
|
||||
void GTKFreezeWidget(GtkWidget *w);
|
||||
void GTKThawWidget(GtkWidget *w);
|
||||
void GTKDisconnect(void* instance);
|
||||
|
@ -695,6 +695,7 @@ bool wxTextCtrl::Create( wxWindow *parent,
|
||||
gulong sig_id = g_signal_connect(m_buffer, "mark_set", G_CALLBACK(mark_set), &m_anonymousMarkList);
|
||||
// Create view
|
||||
m_text = gtk_text_view_new_with_buffer(m_buffer);
|
||||
GTKConnectFreezeWidget(m_text);
|
||||
// gtk_text_view_set_buffer adds its own reference
|
||||
g_object_unref(m_buffer);
|
||||
g_signal_handler_disconnect(m_buffer, sig_id);
|
||||
@ -1975,6 +1976,8 @@ void wxTextCtrl::DoFreeze()
|
||||
wxCHECK_RET(m_text != NULL, wxT("invalid text ctrl"));
|
||||
|
||||
GTKFreezeWidget(m_text);
|
||||
if (m_widget != m_text)
|
||||
GTKFreezeWidget(m_widget);
|
||||
|
||||
if ( HasFlag(wxTE_MULTILINE) )
|
||||
{
|
||||
@ -2021,6 +2024,8 @@ void wxTextCtrl::DoThaw()
|
||||
}
|
||||
|
||||
GTKThawWidget(m_text);
|
||||
if (m_widget != m_text)
|
||||
GTKThawWidget(m_widget);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -2138,9 +2138,6 @@ static void frame_clock_layout(GdkFrameClock*, wxWindow* win)
|
||||
|
||||
void wxWindowGTK::GTKHandleRealized()
|
||||
{
|
||||
if (IsFrozen())
|
||||
DoFreeze();
|
||||
|
||||
GdkWindow* const window = GTKGetDrawingWindow();
|
||||
|
||||
if (m_wxwindow)
|
||||
@ -2224,11 +2221,6 @@ void wxWindowGTK::GTKHandleUnrealize()
|
||||
{
|
||||
m_isGtkPositionValid = false;
|
||||
|
||||
// unrealizing a frozen window seems to have some lingering effect
|
||||
// preventing updates to the affected area
|
||||
if (IsFrozen())
|
||||
DoThaw();
|
||||
|
||||
if (m_wxwindow)
|
||||
{
|
||||
if (m_imContext)
|
||||
@ -2578,12 +2570,6 @@ wxWindowGTK::~wxWindowGTK()
|
||||
m_imContext = NULL;
|
||||
}
|
||||
|
||||
// avoid problem with GTK+ 2.18 where a frozen window causes the whole
|
||||
// TLW to be frozen, and if the window is then destroyed, nothing ever
|
||||
// gets painted again
|
||||
while (IsFrozen())
|
||||
Thaw();
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
if (m_styleProvider)
|
||||
g_object_unref(m_styleProvider);
|
||||
@ -2629,6 +2615,10 @@ void wxWindowGTK::PostCreation()
|
||||
{
|
||||
wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
|
||||
|
||||
GTKConnectFreezeWidget(m_widget);
|
||||
if (m_wxwindow && m_wxwindow != m_widget)
|
||||
GTKConnectFreezeWidget(m_wxwindow);
|
||||
|
||||
#if wxGTK_HAS_COMPOSITING_SUPPORT
|
||||
// Set RGBA visual as soon as possible to minimize the possibility that
|
||||
// somebody uses the wrong one.
|
||||
@ -5120,53 +5110,49 @@ GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const
|
||||
// freeze/thaw
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
static gboolean draw_freeze(GtkWidget*, void*, wxWindow*)
|
||||
{
|
||||
// stop other handlers from being invoked
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void wxWindowGTK::GTKConnectFreezeWidget(GtkWidget* widget)
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
gulong id = g_signal_connect(widget, "draw", G_CALLBACK(draw_freeze), this);
|
||||
#else
|
||||
gulong id = g_signal_connect(widget, "expose-event", G_CALLBACK(draw_freeze), this);
|
||||
#endif
|
||||
g_signal_handler_block(widget, id);
|
||||
}
|
||||
|
||||
void wxWindowGTK::GTKFreezeWidget(GtkWidget* widget)
|
||||
{
|
||||
if (widget && gtk_widget_get_has_window(widget))
|
||||
{
|
||||
GdkWindow* window = gtk_widget_get_window(widget);
|
||||
if (window)
|
||||
{
|
||||
#if GTK_CHECK_VERSION(2,18,0)
|
||||
#ifndef __WXGTK3__
|
||||
if (gtk_check_version(2,18,0) == NULL)
|
||||
#endif
|
||||
{
|
||||
// impl_window for a non-native GdkWindow can change if
|
||||
// gdk_window_ensure_native() is called on it or some other
|
||||
// GdkWindow in the same TLW. Since the freeze count is on the
|
||||
// impl_window, we have to make sure impl_window does not change
|
||||
// after we call gdk_window_freeze_updates().
|
||||
gdk_window_ensure_native(window);
|
||||
}
|
||||
#endif
|
||||
gdk_window_freeze_updates(window);
|
||||
}
|
||||
}
|
||||
g_signal_handlers_unblock_by_func(widget, (void*)draw_freeze, this);
|
||||
}
|
||||
|
||||
void wxWindowGTK::GTKThawWidget(GtkWidget* widget)
|
||||
{
|
||||
if (widget && gtk_widget_get_has_window(widget))
|
||||
{
|
||||
GdkWindow* window = gtk_widget_get_window(widget);
|
||||
if (window)
|
||||
gdk_window_thaw_updates(window);
|
||||
}
|
||||
g_signal_handlers_block_by_func(widget, (void*)draw_freeze, this);
|
||||
gtk_widget_queue_draw(widget);
|
||||
}
|
||||
|
||||
void wxWindowGTK::DoFreeze()
|
||||
{
|
||||
GtkWidget* widget = m_wxwindow;
|
||||
if (widget == NULL)
|
||||
widget = m_widget;
|
||||
GTKFreezeWidget(widget);
|
||||
wxCHECK_RET(m_widget, "invalid window");
|
||||
|
||||
GTKFreezeWidget(m_widget);
|
||||
if (m_wxwindow && m_wxwindow != m_widget)
|
||||
GTKFreezeWidget(m_wxwindow);
|
||||
}
|
||||
|
||||
void wxWindowGTK::DoThaw()
|
||||
{
|
||||
GtkWidget* widget = m_wxwindow;
|
||||
if (widget == NULL)
|
||||
widget = m_widget;
|
||||
GTKThawWidget(widget);
|
||||
wxCHECK_RET(m_widget, "invalid window");
|
||||
|
||||
GTKThawWidget(m_widget);
|
||||
if (m_wxwindow && m_wxwindow != m_widget)
|
||||
GTKThawWidget(m_wxwindow);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user