gtk: Make GtkPointerFocus refcounted

In order to make it really sure the GtkPointerFocus is valid while being
removed from a GtkWindow.
This commit is contained in:
Carlos Garnacho 2017-05-25 16:00:40 +02:00
parent 690eb8ede6
commit b894c35008
3 changed files with 37 additions and 10 deletions

View File

@ -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;
}
void
gtk_pointer_focus_free (GtkPointerFocus *focus)
GtkPointerFocus *
gtk_pointer_focus_ref (GtkPointerFocus *focus)
{
gtk_pointer_focus_set_target (focus, NULL);
gtk_pointer_focus_set_implicit_grab (focus, NULL);
g_free (focus);
focus->ref_count++;
return focus;
}
void
gtk_pointer_focus_unref (GtkPointerFocus *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

View File

@ -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,

View File

@ -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);
}
}