[gtksourceview/wip/various-stuff: 3/7] Completion: weak reference to the view
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/various-stuff: 3/7] Completion: weak reference to the view
- Date: Mon, 27 Jan 2014 17:43:52 +0000 (UTC)
commit 6877b934fa58a4098b30374f0ee5263331dab24f
Author: Sébastien Wilmet <swilmet gnome org>
Date: Sun Jan 26 20:30:26 2014 +0100
Completion: weak reference to the view
There was a reference cycle between the view and completion. Now only
the view has a strong reference to the completion. It is more logical
that the view owns the completion, not vice-versa.
This wasn't really a problem as far as the view was added to a
container. Because when the container is destroyed, it calls
gtk_widget_destroy() on its children, which calls g_object_run_dispose()
which breaks the reference cycle.
Anyway, it's better to not rely on gtk_widget_destroy(), and thus avoid
reference cycles in C code.
The drawback is that there are now checks to see if view == NULL, before
using view.
gtksourceview/gtksourcecompletion.c | 76 +++++++++++++++++++++++++++++++---
1 files changed, 69 insertions(+), 7 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 4acdf5b..a151209 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -172,6 +172,9 @@ struct _GtkSourceCompletionPrivate
/* Properties */
+ /* Weak reference to the view. You must check if view != NULL before
+ * using it.
+ */
GtkSourceView *view;
guint num_accelerators;
guint auto_complete_delay;
@@ -293,6 +296,8 @@ get_iter_at_insert (GtkSourceCompletion *completion,
{
GtkTextBuffer *buffer;
+ g_return_if_fail (GTK_IS_TEXT_VIEW (completion->priv->view));
+
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
gtk_text_buffer_get_iter_at_mark (buffer,
iter,
@@ -436,6 +441,11 @@ update_window_position (GtkSourceCompletion *completion)
GtkTextIter iter;
gboolean iter_set = FALSE;
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
/* The model can be modified while there is no completion context, for
* example when the headers are shown or hidden. This triggers a signal
* to update the window position, but if there is no completion context,
@@ -564,6 +574,11 @@ update_proposal_info (GtkSourceCompletion *completion)
static void
gtk_source_completion_show_default (GtkSourceCompletion *completion)
{
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
gtk_widget_show (GTK_WIDGET (completion->priv->main_window));
if (!completion->priv->remember_info_visibility)
@@ -637,6 +652,11 @@ gtk_source_completion_activate_proposal (GtkSourceCompletion *completion)
GtkTextIter insert_iter;
gboolean activated;
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
if (!get_selected_proposal (completion, &provider, &proposal))
{
return;
@@ -1560,7 +1580,14 @@ gtk_source_completion_dispose (GObject *object)
reset_completion (completion);
- g_clear_object (&completion->priv->view);
+ if (completion->priv->view != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (completion->priv->view),
+ (gpointer *)&completion->priv->view);
+
+ completion->priv->view = NULL;
+ }
+
g_clear_object (&completion->priv->default_info);
g_clear_object (&completion->priv->model_proposals);
@@ -1583,10 +1610,17 @@ gtk_source_completion_dispose (GObject *object)
}
static void
-connect_view (GtkSourceCompletion *completion)
+connect_view (GtkSourceCompletion *completion,
+ GtkSourceView *view)
{
- GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
- GtkStyleContext *style_context = gtk_widget_get_style_context (GTK_WIDGET (completion->priv->view));
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ GtkStyleContext *style_context = gtk_widget_get_style_context (GTK_WIDGET (view));
+
+ g_assert (completion->priv->view == NULL);
+ completion->priv->view = view;
+
+ g_object_add_weak_pointer (G_OBJECT (view),
+ (gpointer *)&completion->priv->view);
g_signal_connect_object (completion->priv->view,
"focus-out-event",
@@ -1733,9 +1767,7 @@ gtk_source_completion_set_property (GObject *object,
switch (prop_id)
{
case PROP_VIEW:
- /* On construction only */
- completion->priv->view = g_value_dup_object (value);
- connect_view (completion);
+ connect_view (completion, g_value_get_object (value));
break;
case PROP_REMEMBER_INFO_VISIBILITY:
completion->priv->remember_info_visibility = g_value_get_boolean (value);
@@ -2337,6 +2369,11 @@ static void
init_main_window (GtkSourceCompletion *completion,
GtkBuilder *builder)
{
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
completion->priv->main_window = GTK_SOURCE_COMPLETION_INFO (gtk_builder_get_object (builder,
"main_window"));
completion->priv->info_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "info_button"));
completion->priv->selection_image = GTK_IMAGE (gtk_builder_get_object (builder, "selection_image"));
@@ -2491,6 +2528,11 @@ gtk_source_completion_show (GtkSourceCompletion *completion,
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), FALSE);
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_CONTEXT (context), FALSE);
+ if (completion->priv->view == NULL)
+ {
+ return FALSE;
+ }
+
/* Make sure to clear any active completion */
reset_completion (completion);
@@ -2742,6 +2784,11 @@ gtk_source_completion_create_context (GtkSourceCompletion *completion,
g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION (completion), NULL);
+ if (completion->priv->view == NULL)
+ {
+ return NULL;
+ }
+
if (position == NULL)
{
get_iter_at_insert (completion, &iter);
@@ -2770,6 +2817,11 @@ gtk_source_completion_move_window (GtkSourceCompletion *completion,
g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
g_return_if_fail (iter != NULL);
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
if (!gtk_widget_get_visible (GTK_WIDGET (completion->priv->main_window)))
{
return;
@@ -2800,6 +2852,11 @@ gtk_source_completion_block_interactive (GtkSourceCompletion *completion)
g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
g_signal_handler_block (buffer, completion->priv->signals_ids[TEXT_BUFFER_INSERT_TEXT]);
@@ -2821,6 +2878,11 @@ gtk_source_completion_unblock_interactive (GtkSourceCompletion *completion)
g_return_if_fail (GTK_SOURCE_IS_COMPLETION (completion));
+ if (completion->priv->view == NULL)
+ {
+ return;
+ }
+
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (completion->priv->view));
g_signal_handler_unblock (buffer, completion->priv->signals_ids[TEXT_BUFFER_INSERT_TEXT]);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]