Merge branch 'wip/surface-transform-data' into 'master'

Surface transform listener fixes

See merge request GNOME/gtk!776
This commit is contained in:
Matthias Clasen 2019-04-25 16:42:42 +00:00
commit 2bd9b42479
2 changed files with 90 additions and 58 deletions

View File

@ -2906,7 +2906,7 @@ gtk_widget_root (GtkWidget *widget)
if (priv->context)
gtk_style_context_set_display (priv->context, gtk_root_get_display (priv->root));
if (priv->surface_transform_changed_callbacks)
if (priv->surface_transform_data)
add_parent_surface_transform_changed_listener (widget);
GTK_WIDGET_GET_CLASS (widget)->root (widget);
@ -2918,6 +2918,7 @@ static void
gtk_widget_unroot (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data;
/* roots are rooted by default and cannot be unrooted */
if (GTK_IS_ROOT (widget))
@ -2926,7 +2927,9 @@ gtk_widget_unroot (GtkWidget *widget)
g_assert (priv->root);
g_assert (!priv->realized);
if (priv->parent_surface_transform_changed_parent)
surface_transform_data = priv->surface_transform_data;
if (surface_transform_data &&
surface_transform_data->tracked_parent)
remove_parent_surface_transform_changed_listener (widget);
GTK_WIDGET_GET_CLASS (widget)->unroot (widget);
@ -3609,15 +3612,17 @@ static void
notify_surface_transform_changed (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data =
priv->surface_transform_data;
graphene_matrix_t *surface_transform;
GList *l;
if (priv->cached_surface_transform_valid)
surface_transform = &priv->cached_surface_transform;
if (surface_transform_data->cached_surface_transform_valid)
surface_transform = &surface_transform_data->cached_surface_transform;
else
surface_transform = NULL;
for (l = priv->surface_transform_changed_callbacks; l;)
for (l = surface_transform_data->callbacks; l;)
{
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
GList *l_next = l->next;
@ -3626,8 +3631,8 @@ notify_surface_transform_changed (GtkWidget *widget)
surface_transform,
info->user_data) == G_SOURCE_REMOVE)
{
priv->surface_transform_changed_callbacks =
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
surface_transform_data->callbacks =
g_list_delete_link (surface_transform_data->callbacks, l);
surface_transform_changed_callback_info_destroy (info);
}
@ -3636,58 +3641,57 @@ notify_surface_transform_changed (GtkWidget *widget)
}
static void
destroy_surface_transform_changed_callbacks (GtkWidget *widget)
destroy_surface_transform_data (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l;
GtkWidgetSurfaceTransformData *surface_transform_data;
for (l = priv->surface_transform_changed_callbacks; l;)
{
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
GList *l_next = l->next;
surface_transform_data = priv->surface_transform_data;
if (!surface_transform_data)
return;
priv->surface_transform_changed_callbacks =
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
surface_transform_changed_callback_info_destroy (info);
l = l_next;
}
g_list_free_full (surface_transform_data->callbacks,
(GDestroyNotify) surface_transform_changed_callback_info_destroy);
g_slice_free (GtkWidgetSurfaceTransformData, surface_transform_data);
priv->surface_transform_data = NULL;
}
static void
sync_widget_surface_transform (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data =
priv->surface_transform_data;
gboolean was_valid;
graphene_matrix_t prev_transform;
was_valid = priv->cached_surface_transform_valid;
prev_transform = priv->cached_surface_transform;
was_valid = surface_transform_data->cached_surface_transform_valid;
prev_transform = surface_transform_data->cached_surface_transform;
if (GTK_IS_ROOT (widget))
{
gsk_transform_to_matrix (priv->transform,
&priv->cached_surface_transform);
priv->cached_surface_transform_valid = TRUE;
&surface_transform_data->cached_surface_transform);
surface_transform_data->cached_surface_transform_valid = TRUE;
}
else if (!priv->root)
{
priv->cached_surface_transform_valid = FALSE;
surface_transform_data->cached_surface_transform_valid = FALSE;
}
else if (gtk_widget_compute_transform (widget, GTK_WIDGET (priv->root),
&priv->cached_surface_transform))
&surface_transform_data->cached_surface_transform))
{
priv->cached_surface_transform_valid = TRUE;
surface_transform_data->cached_surface_transform_valid = TRUE;
}
else
{
g_warning ("Could not compute surface transform");
priv->cached_surface_transform_valid = FALSE;
surface_transform_data->cached_surface_transform_valid = FALSE;
}
if (was_valid != priv->cached_surface_transform_valid ||
(was_valid && priv->cached_surface_transform_valid &&
!graphene_matrix_equal (&priv->cached_surface_transform,
if (was_valid != surface_transform_data->cached_surface_transform_valid ||
(was_valid && surface_transform_data->cached_surface_transform_valid &&
!graphene_matrix_equal (&surface_transform_data->cached_surface_transform,
&prev_transform)))
notify_surface_transform_changed (widget);
}
@ -3710,32 +3714,48 @@ static void
remove_parent_surface_transform_changed_listener (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data =
priv->surface_transform_data;
g_assert (priv->parent_surface_transform_changed_parent);
g_assert (surface_transform_data->tracked_parent);
gtk_widget_remove_surface_transform_changed_callback (
priv->parent_surface_transform_changed_parent,
priv->parent_surface_transform_changed_id);
priv->parent_surface_transform_changed_id = 0;
g_clear_object (&priv->parent_surface_transform_changed_parent);
surface_transform_data->tracked_parent,
surface_transform_data->parent_surface_transform_changed_id);
surface_transform_data->parent_surface_transform_changed_id = 0;
g_clear_object (&surface_transform_data->tracked_parent);
}
static void
add_parent_surface_transform_changed_listener (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkWidgetSurfaceTransformData *surface_transform_data =
priv->surface_transform_data;
GtkWidget *parent;
g_assert (!priv->parent_surface_transform_changed_parent);
g_assert (!surface_transform_data->tracked_parent);
parent = priv->parent;
priv->parent_surface_transform_changed_id =
surface_transform_data->parent_surface_transform_changed_id =
gtk_widget_add_surface_transform_changed_callback (
parent,
parent_surface_transform_changed_cb,
widget,
NULL);
priv->parent_surface_transform_changed_parent = g_object_ref (parent);
surface_transform_data->tracked_parent = g_object_ref (parent);
}
static GtkWidgetSurfaceTransformData *
ensure_surface_transform_data (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
if (!priv->surface_transform_data)
priv->surface_transform_data = g_slice_new0 (GtkWidgetSurfaceTransformData);
return priv->surface_transform_data;
}
/**
@ -3759,17 +3779,20 @@ gtk_widget_add_surface_transform_changed_callback (GtkWidget
GDestroyNotify notify)
{
GtkWidgetPrivate *priv;
GtkWidgetSurfaceTransformData *surface_transform_data;
GtkSurfaceTransformChangedCallbackInfo *info;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
g_return_val_if_fail (callback, 0);
priv = gtk_widget_get_instance_private (widget);
surface_transform_data = ensure_surface_transform_data (widget);
if (priv->parent && !priv->parent_surface_transform_changed_id)
if (priv->parent &&
!surface_transform_data->parent_surface_transform_changed_id)
add_parent_surface_transform_changed_listener (widget);
if (!priv->surface_transform_changed_callbacks)
if (!surface_transform_data->callbacks)
sync_widget_surface_transform (widget);
info = g_slice_new0 (GtkSurfaceTransformChangedCallbackInfo);
@ -3779,8 +3802,8 @@ gtk_widget_add_surface_transform_changed_callback (GtkWidget
info->user_data = user_data;
info->notify = notify;
priv->surface_transform_changed_callbacks =
g_list_prepend (priv->surface_transform_changed_callbacks, info);
surface_transform_data->callbacks =
g_list_prepend (surface_transform_data->callbacks, info);
return info->id;
}
@ -3798,34 +3821,37 @@ gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget,
guint id)
{
GtkWidgetPrivate *priv;
GtkWidgetSurfaceTransformData *surface_transform_data;
GList *l;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (id);
priv = gtk_widget_get_instance_private (widget);
surface_transform_data = priv->surface_transform_data;
for (l = priv->surface_transform_changed_callbacks; l; l = l->next)
g_return_if_fail (surface_transform_data);
for (l = surface_transform_data->callbacks; l; l = l->next)
{
GtkSurfaceTransformChangedCallbackInfo *info = l->data;
if (info->id == id)
{
priv->surface_transform_changed_callbacks =
g_list_delete_link (priv->surface_transform_changed_callbacks, l);
surface_transform_data->callbacks =
g_list_delete_link (surface_transform_data->callbacks, l);
surface_transform_changed_callback_info_destroy (info);
break;
}
}
if (!priv->surface_transform_changed_callbacks)
if (!surface_transform_data->callbacks)
{
if (priv->parent_surface_transform_changed_parent)
if (surface_transform_data->tracked_parent)
remove_parent_surface_transform_changed_listener (widget);
g_signal_handler_disconnect (widget, priv->parent_changed_handler_id);
priv->parent_changed_handler_id = 0;
g_slice_free (GtkWidgetSurfaceTransformData, surface_transform_data);
priv->surface_transform_data = NULL;
}
}
@ -4443,7 +4469,7 @@ gtk_widget_allocate (GtkWidget *widget,
priv->transform = transform;
if (priv->surface_transform_changed_callbacks)
if (priv->surface_transform_data)
sync_widget_surface_transform (widget);
if (!alloc_needed && !size_changed && !baseline_changed)
@ -8310,7 +8336,7 @@ gtk_widget_real_destroy (GtkWidget *object)
gtk_grab_remove (widget);
destroy_tick_callbacks (widget);
destroy_surface_transform_changed_callbacks (widget);
destroy_surface_transform_data (widget);
}
static void

View File

@ -47,6 +47,17 @@ typedef gboolean (*GtkSurfaceTransformChangedCallback) (GtkWidget
#define GTK_STATE_FLAGS_BITS 14
typedef struct _GtkWidgetSurfaceTransformData
{
GtkWidget *tracked_parent;
guint parent_surface_transform_changed_id;
GList *callbacks;
gboolean cached_surface_transform_valid;
graphene_matrix_t cached_surface_transform;
} GtkWidgetSurfaceTransformData;
struct _GtkWidgetPrivate
{
/* The state of the widget. Needs to be able to hold all GtkStateFlags bits
@ -121,12 +132,7 @@ struct _GtkWidgetPrivate
GList *tick_callbacks;
/* Surface relative transform updates callbacks */
guint parent_surface_transform_changed_id;
GtkWidget *parent_surface_transform_changed_parent;
gulong parent_changed_handler_id;
GList *surface_transform_changed_callbacks;
gboolean cached_surface_transform_valid;
graphene_matrix_t cached_surface_transform;
GtkWidgetSurfaceTransformData *surface_transform_data;
/* The widget's name. If the widget does not have a name
* (the name is NULL), then its name (as returned by