[gtk+/wip/carlosg/event-delivery: 104/104] gtk: Make GtkPointerFocus refcounted



commit b894c350080f5686a7c8bb7107001373da097b5f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu May 25 16:00:40 2017 +0200

    gtk: Make GtkPointerFocus refcounted
    
    In order to make it really sure the GtkPointerFocus is valid while being
    removed from a GtkWindow.

 gtk/gtkpointerfocus.c        |   21 +++++++++++++++++----
 gtk/gtkpointerfocusprivate.h |    4 +++-
 gtk/gtkwindow.c              |   20 ++++++++++++++++----
 3 files changed, 36 insertions(+), 9 deletions(-)
---
diff --git a/gtk/gtkpointerfocus.c b/gtk/gtkpointerfocus.c
index 3a4026d..cb484b8 100644
--- a/gtk/gtkpointerfocus.c
+++ b/gtk/gtkpointerfocus.c
@@ -39,6 +39,7 @@ gtk_pointer_focus_new (GtkWindow        *toplevel,
   GtkPointerFocus *focus;
 
   focus = g_new0 (GtkPointerFocus, 1);
+  focus->ref_count = 1;
   focus->toplevel = toplevel;
   focus->device = device;
   focus->sequence = sequence;
@@ -48,12 +49,24 @@ gtk_pointer_focus_new (GtkWindow        *toplevel,
   return focus;
 }
 
+GtkPointerFocus *
+gtk_pointer_focus_ref (GtkPointerFocus *focus)
+{
+  focus->ref_count++;
+  return focus;
+}
+
 void
-gtk_pointer_focus_free (GtkPointerFocus *focus)
+gtk_pointer_focus_unref (GtkPointerFocus *focus)
 {
-  gtk_pointer_focus_set_target (focus, NULL);
-  gtk_pointer_focus_set_implicit_grab (focus, NULL);
-  g_free (focus);
+  focus->ref_count--;
+
+  if (focus->ref_count == 0)
+    {
+      gtk_pointer_focus_set_target (focus, NULL);
+      gtk_pointer_focus_set_implicit_grab (focus, NULL);
+      g_free (focus);
+    }
 }
 
 void
diff --git a/gtk/gtkpointerfocusprivate.h b/gtk/gtkpointerfocusprivate.h
index 5d5be95..c7ffd90 100644
--- a/gtk/gtkpointerfocusprivate.h
+++ b/gtk/gtkpointerfocusprivate.h
@@ -24,6 +24,7 @@ typedef struct _GtkPointerFocus GtkPointerFocus;
 
 struct _GtkPointerFocus
 {
+  gint ref_count;
   GdkDevice *device;
   GdkEventSequence *sequence;
   GtkWindow *toplevel;
@@ -38,7 +39,8 @@ GtkPointerFocus * gtk_pointer_focus_new  (GtkWindow        *toplevel,
                                           GdkEventSequence *sequence,
                                           gdouble           x,
                                           gdouble           y);
-void              gtk_pointer_focus_free (GtkPointerFocus *focus);
+GtkPointerFocus * gtk_pointer_focus_ref   (GtkPointerFocus *focus);
+void              gtk_pointer_focus_unref (GtkPointerFocus *focus);
 
 void              gtk_pointer_focus_set_coordinates (GtkPointerFocus *focus,
                                                      gdouble          x,
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 0304673..8e71100 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -1689,9 +1689,9 @@ device_removed_cb (GdkSeat   *seat,
 
       if (focus->device == device)
         {
-          gtk_pointer_focus_free (focus);
           window->priv->foci =
             g_list_delete_link (window->priv->foci, cur);
+          gtk_pointer_focus_unref (focus);
         }
     }
 }
@@ -11275,7 +11275,7 @@ gtk_window_add_pointer_focus (GtkWindow       *window,
 {
   GtkWindowPrivate *priv = window->priv;
 
-  priv->foci = g_list_prepend (priv->foci, focus);
+  priv->foci = g_list_prepend (priv->foci, gtk_pointer_focus_ref (focus));
 }
 
 static void
@@ -11283,8 +11283,14 @@ gtk_window_remove_pointer_focus (GtkWindow       *window,
                                  GtkPointerFocus *focus)
 {
   GtkWindowPrivate *priv = window->priv;
+  GList *pos;
+
+  pos = g_list_find (priv->foci, focus);
+  if (!pos)
+    return;
 
   priv->foci = g_list_remove (priv->foci, focus);
+  gtk_pointer_focus_unref (focus);
 }
 
 static GtkPointerFocus *
@@ -11351,6 +11357,8 @@ gtk_window_update_pointer_focus (GtkWindow        *window,
   focus = gtk_window_lookup_pointer_focus (window, device, sequence);
   if (focus)
     {
+      gtk_pointer_focus_ref (focus);
+
       if (target)
         {
           gtk_pointer_focus_set_target (focus, target);
@@ -11359,8 +11367,9 @@ gtk_window_update_pointer_focus (GtkWindow        *window,
       else
         {
           gtk_window_remove_pointer_focus (window, focus);
-          gtk_pointer_focus_free (focus);
         }
+
+      gtk_pointer_focus_unref (focus);
     }
   else if (target)
     {
@@ -11383,17 +11392,20 @@ gtk_window_update_pointer_focus_on_state_change (GtkWindow *window,
       focus = cur->data;
       l = cur->next;
 
+      gtk_pointer_focus_ref (focus);
+
       if (GTK_WIDGET (focus->toplevel) == widget)
         {
           /* Unmapping the toplevel, remove pointer focus */
           gtk_window_remove_pointer_focus (window, focus);
-          gtk_pointer_focus_free (focus);
         }
       else if (focus->target == widget ||
                gtk_widget_is_ancestor (focus->target, widget))
         {
           gtk_pointer_focus_repick_target (focus);
         }
+
+      gtk_pointer_focus_unref (focus);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]