a11y: Disconnect from buffer signals
This way, we don't get crashes when the buffer is still in use after a TextView gets finalized. https://bugzilla.gnome.org/show_bug.cgi?id=667632
This commit is contained in:
parent
cac47f45b7
commit
ff1e1e1f91
@ -31,9 +31,9 @@
|
|||||||
#include <glib/gstdio.h>
|
#include <glib/gstdio.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "gtktextviewaccessible.h"
|
#include "gtktextviewaccessible.h"
|
||||||
|
#include "gtk/gtkwidgetprivate.h"
|
||||||
|
|
||||||
|
|
||||||
static void setup_buffer (GtkTextView *view,GtkTextViewAccessible *accessible);
|
|
||||||
static void insert_text_cb (GtkTextBuffer *buffer,
|
static void insert_text_cb (GtkTextBuffer *buffer,
|
||||||
GtkTextIter *arg1,
|
GtkTextIter *arg1,
|
||||||
gchar *arg2,
|
gchar *arg2,
|
||||||
@ -65,8 +65,6 @@ gtk_text_view_accessible_initialize (AtkObject *obj,
|
|||||||
{
|
{
|
||||||
ATK_OBJECT_CLASS (_gtk_text_view_accessible_parent_class)->initialize (obj, data);
|
ATK_OBJECT_CLASS (_gtk_text_view_accessible_parent_class)->initialize (obj, data);
|
||||||
|
|
||||||
setup_buffer (GTK_TEXT_VIEW (data), GTK_TEXT_VIEW_ACCESSIBLE (obj));
|
|
||||||
|
|
||||||
obj->role = ATK_ROLE_TEXT;
|
obj->role = ATK_ROLE_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +83,6 @@ gtk_text_view_accessible_notify_gtk (GObject *obj,
|
|||||||
editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
|
editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
|
||||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, editable);
|
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, editable);
|
||||||
}
|
}
|
||||||
else if (!strcmp (pspec->name, "buffer"))
|
|
||||||
{
|
|
||||||
setup_buffer (GTK_TEXT_VIEW (obj), GTK_TEXT_VIEW_ACCESSIBLE (atk_obj));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_text_view_accessible_parent_class)->notify_gtk (obj, pspec);
|
GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_text_view_accessible_parent_class)->notify_gtk (obj, pspec);
|
||||||
}
|
}
|
||||||
@ -112,12 +106,50 @@ gtk_text_view_accessible_ref_state_set (AtkObject *accessible)
|
|||||||
return state_set;
|
return state_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_view_accessible_change_buffer (GtkTextViewAccessible *accessible,
|
||||||
|
GtkTextBuffer *old_buffer,
|
||||||
|
GtkTextBuffer *new_buffer)
|
||||||
|
{
|
||||||
|
if (old_buffer)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_matched (old_buffer, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, accessible);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_buffer)
|
||||||
|
{
|
||||||
|
g_signal_connect_after (new_buffer, "insert-text", G_CALLBACK (insert_text_cb), accessible);
|
||||||
|
g_signal_connect (new_buffer, "delete-range", G_CALLBACK (delete_range_cb), accessible);
|
||||||
|
g_signal_connect_after (new_buffer, "mark-set", G_CALLBACK (mark_set_cb), accessible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_view_accessible_widget_set (GtkAccessible *accessible)
|
||||||
|
{
|
||||||
|
gtk_text_view_accessible_change_buffer (GTK_TEXT_VIEW_ACCESSIBLE (accessible),
|
||||||
|
NULL,
|
||||||
|
gtk_text_view_get_buffer (GTK_TEXT_VIEW (gtk_accessible_get_widget (accessible))));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_view_accessible_widget_unset (GtkAccessible *accessible)
|
||||||
|
{
|
||||||
|
gtk_text_view_accessible_change_buffer (GTK_TEXT_VIEW_ACCESSIBLE (accessible),
|
||||||
|
gtk_text_view_get_buffer (GTK_TEXT_VIEW (gtk_accessible_get_widget (accessible))),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass)
|
_gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass)
|
||||||
{
|
{
|
||||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||||
|
GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
|
||||||
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
|
||||||
|
|
||||||
|
accessible_class->widget_set = gtk_text_view_accessible_widget_set;
|
||||||
|
accessible_class->widget_unset = gtk_text_view_accessible_widget_unset;
|
||||||
|
|
||||||
class->ref_state_set = gtk_text_view_accessible_ref_state_set;
|
class->ref_state_set = gtk_text_view_accessible_ref_state_set;
|
||||||
class->initialize = gtk_text_view_accessible_initialize;
|
class->initialize = gtk_text_view_accessible_initialize;
|
||||||
|
|
||||||
@ -129,20 +161,6 @@ _gtk_text_view_accessible_init (GtkTextViewAccessible *accessible)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
setup_buffer (GtkTextView *view,
|
|
||||||
GtkTextViewAccessible *accessible)
|
|
||||||
{
|
|
||||||
GtkTextBuffer *buffer;
|
|
||||||
|
|
||||||
buffer = gtk_text_view_get_buffer (view);
|
|
||||||
|
|
||||||
/* Set up signal callbacks */
|
|
||||||
g_signal_connect_after (buffer, "insert-text", G_CALLBACK (insert_text_cb), view);
|
|
||||||
g_signal_connect (buffer, "delete-range", G_CALLBACK (delete_range_cb), view);
|
|
||||||
g_signal_connect_after (buffer, "mark-set", G_CALLBACK (mark_set_cb), view);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
gtk_text_view_accessible_get_text (AtkText *text,
|
gtk_text_view_accessible_get_text (AtkText *text,
|
||||||
gint start_offset,
|
gint start_offset,
|
||||||
@ -1727,13 +1745,10 @@ insert_text_cb (GtkTextBuffer *buffer,
|
|||||||
gint len,
|
gint len,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GtkTextView *view = data;
|
GtkTextViewAccessible *accessible = data;
|
||||||
GtkTextViewAccessible *accessible;
|
|
||||||
gint position;
|
gint position;
|
||||||
gint length;
|
gint length;
|
||||||
|
|
||||||
accessible = GTK_TEXT_VIEW_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (view)));
|
|
||||||
|
|
||||||
position = gtk_text_iter_get_offset (iter);
|
position = gtk_text_iter_get_offset (iter);
|
||||||
length = g_utf8_strlen (text, len);
|
length = g_utf8_strlen (text, len);
|
||||||
|
|
||||||
@ -1748,12 +1763,9 @@ delete_range_cb (GtkTextBuffer *buffer,
|
|||||||
GtkTextIter *end,
|
GtkTextIter *end,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GtkTextView *view = data;
|
GtkTextViewAccessible *accessible = data;
|
||||||
GtkTextViewAccessible *accessible;
|
|
||||||
gint offset, length;
|
gint offset, length;
|
||||||
|
|
||||||
accessible = GTK_TEXT_VIEW_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (view)));
|
|
||||||
|
|
||||||
offset = gtk_text_iter_get_offset (start);
|
offset = gtk_text_iter_get_offset (start);
|
||||||
length = gtk_text_iter_get_offset (end) - offset;
|
length = gtk_text_iter_get_offset (end) - offset;
|
||||||
|
|
||||||
@ -1771,10 +1783,7 @@ mark_set_cb (GtkTextBuffer *buffer,
|
|||||||
GtkTextMark *mark,
|
GtkTextMark *mark,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GtkTextView *text = data;
|
GtkTextViewAccessible *accessible = data;
|
||||||
GtkTextViewAccessible *accessible;
|
|
||||||
|
|
||||||
accessible = GTK_TEXT_VIEW_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (text)));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only generate the signal for the "insert" mark, which
|
* Only generate the signal for the "insert" mark, which
|
||||||
@ -1929,3 +1938,22 @@ atk_streamable_content_interface_init (AtkStreamableContentIface *iface)
|
|||||||
iface->get_mime_type = gail_streamable_content_get_mime_type;
|
iface->get_mime_type = gail_streamable_content_get_mime_type;
|
||||||
iface->get_stream = gail_streamable_content_get_stream;
|
iface->get_stream = gail_streamable_content_get_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gtk_text_view_accessible_set_buffer (GtkTextView *textview,
|
||||||
|
GtkTextBuffer *old_buffer)
|
||||||
|
{
|
||||||
|
GtkTextViewAccessible *accessible;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_TEXT_VIEW (textview));
|
||||||
|
g_return_if_fail (old_buffer == NULL || GTK_IS_TEXT_BUFFER (old_buffer));
|
||||||
|
|
||||||
|
accessible = GTK_TEXT_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (textview)));
|
||||||
|
if (accessible == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_text_view_accessible_change_buffer (accessible,
|
||||||
|
old_buffer,
|
||||||
|
gtk_text_view_get_buffer (textview));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,10 @@ struct _GtkTextViewAccessibleClass
|
|||||||
|
|
||||||
GType _gtk_text_view_accessible_get_type (void);
|
GType _gtk_text_view_accessible_get_type (void);
|
||||||
|
|
||||||
|
void _gtk_text_view_accessible_set_buffer (GtkTextView *textview,
|
||||||
|
GtkTextBuffer *old_buffer);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GTK_TEXT_VIEW_ACCESSIBLE_H__ */
|
#endif /* __GTK_TEXT_VIEW_ACCESSIBLE_H__ */
|
||||||
|
@ -1479,6 +1479,7 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
|
|||||||
GtkTextBuffer *buffer)
|
GtkTextBuffer *buffer)
|
||||||
{
|
{
|
||||||
GtkTextViewPrivate *priv;
|
GtkTextViewPrivate *priv;
|
||||||
|
GtkTextBuffer *old_buffer;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
|
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
|
||||||
g_return_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer));
|
g_return_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer));
|
||||||
@ -1488,6 +1489,7 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
|
|||||||
if (priv->buffer == buffer)
|
if (priv->buffer == buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
old_buffer = priv->buffer;
|
||||||
if (priv->buffer != NULL)
|
if (priv->buffer != NULL)
|
||||||
{
|
{
|
||||||
/* Destroy all anchored children */
|
/* Destroy all anchored children */
|
||||||
@ -1531,7 +1533,6 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
|
|||||||
if (priv->layout)
|
if (priv->layout)
|
||||||
gtk_text_layout_set_buffer (priv->layout, NULL);
|
gtk_text_layout_set_buffer (priv->layout, NULL);
|
||||||
|
|
||||||
g_object_unref (priv->buffer);
|
|
||||||
priv->dnd_mark = NULL;
|
priv->dnd_mark = NULL;
|
||||||
priv->first_para_mark = NULL;
|
priv->first_para_mark = NULL;
|
||||||
cancel_pending_scroll (text_view);
|
cancel_pending_scroll (text_view);
|
||||||
@ -1581,6 +1582,10 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_gtk_text_view_accessible_set_buffer (text_view, old_buffer);
|
||||||
|
if (old_buffer)
|
||||||
|
g_object_unref (old_buffer);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (text_view), "buffer");
|
g_object_notify (G_OBJECT (text_view), "buffer");
|
||||||
|
|
||||||
if (gtk_widget_get_visible (GTK_WIDGET (text_view)))
|
if (gtk_widget_get_visible (GTK_WIDGET (text_view)))
|
||||||
|
Loading…
Reference in New Issue
Block a user