summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-05-25 16:00:40 +0200
committerCarlos Garnacho <carlosg@gnome.org>2017-05-25 16:25:59 +0200
commitb894c350080f5686a7c8bb7107001373da097b5f (patch)
tree7692df2162d03942e089549151cf40ff505d7d8c
parent690eb8ede6bd07715630567a3cb36155bfcef716 (diff)
downloadgtk+-wip/carlosg/event-delivery.tar.gz
gtk: Make GtkPointerFocus refcountedwip/carlosg/event-delivery
In order to make it really sure the GtkPointerFocus is valid while being removed from a GtkWindow.
-rw-r--r--gtk/gtkpointerfocus.c21
-rw-r--r--gtk/gtkpointerfocusprivate.h4
-rw-r--r--gtk/gtkwindow.c20
3 files changed, 36 insertions, 9 deletions
diff --git a/gtk/gtkpointerfocus.c b/gtk/gtkpointerfocus.c
index 3a4026d3d5..cb484b8d34 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 5d5be955e0..c7ffd90f97 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 03046731cb..8e711004bb 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);
}
}