widget: Add gtk_widget_compute_transform

This commit is contained in:
Timm Bäder
2019-02-17 08:47:09 +01:00
committed by Benjamin Otte
parent 4529f52c02
commit dbf0654e5b
3 changed files with 90 additions and 43 deletions

View File

@@ -4541,6 +4541,7 @@ gtk_widget_get_allocated_size
gtk_widget_get_width
gtk_widget_get_height
gtk_widget_compute_bounds
gtk_widget_compute_transform
gtk_widget_contains
gtk_widget_pick
gtk_widget_get_can_default

View File

@@ -820,11 +820,11 @@ gtk_widget_real_pick (GtkWidget *widget,
child = _gtk_widget_get_prev_sibling (child))
{
GtkWidget *picked;
int dx, dy;
double dx, dy;
gtk_widget_get_origin_relative_to_parent (child, &dx, &dy);
gtk_widget_translate_coordinatesf (widget, child, x, y, &dx, &dy);
picked = gtk_widget_pick (child, x - dx, y - dy);
picked = gtk_widget_pick (child, dx, dy);
if (picked)
return picked;
}
@@ -4507,54 +4507,31 @@ gtk_widget_translate_coordinatesf (GtkWidget *src_widget,
double *dest_x,
double *dest_y)
{
GtkWidget *ancestor;
GtkWidget *parent;
graphene_matrix_t transform;
graphene_point_t p;
g_return_val_if_fail (GTK_IS_WIDGET (src_widget), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (dest_widget), FALSE);
ancestor = gtk_widget_common_ancestor (src_widget, dest_widget);
if (!ancestor)
if (!gtk_widget_compute_transform (src_widget, dest_widget, &transform))
{
if (dest_x)
*dest_x = 0;
if (dest_y)
*dest_y = 0;
return FALSE;
}
parent = src_widget;
while (parent != ancestor)
{
int origin_x, origin_y;
gtk_widget_get_origin_relative_to_parent (parent, &origin_x, &origin_y);
src_x += origin_x;
src_y += origin_y;
parent = _gtk_widget_get_parent (parent);
}
parent = dest_widget;
while (parent != ancestor)
{
int origin_x, origin_y;
gtk_widget_get_origin_relative_to_parent (parent, &origin_x, &origin_y);
src_x -= origin_x;
src_y -= origin_y;
parent = _gtk_widget_get_parent (parent);
}
graphene_point_init (&p, src_x, src_y);
graphene_matrix_transform_point (&transform, &p, &p);
if (dest_x)
*dest_x = src_x;
*dest_x = p.x;
if (dest_y)
*dest_y = src_y;
*dest_y = p.y;
return TRUE;
}
@@ -11300,6 +11277,74 @@ gtk_widget_pick (GtkWidget *widget,
return GTK_WIDGET_GET_CLASS (widget)->pick (widget, x, y);
}
/**
* gtk_widget_compute_transform:
* @widget: a #GtkWidget
* @target: the target widget that the matrix will transform to
* @out_transform: (out caller-allocates): location to
* store the final transformation
*
* Computes a matrix suitable to describe a transformation from
* @widget's coordinate system into @target's coordinate system.
*
* Returns: %TRUE if the transform could be computed, %FALSE otherwise.
* The transform can not be computed in certain cases, for example when
* @widget and @target do not share a common ancestor.
*/
gboolean
gtk_widget_compute_transform (GtkWidget *widget,
GtkWidget *target,
graphene_matrix_t *out_transform)
{
GtkWidget *parent;
GtkWidget *ancestor;
graphene_matrix_t transform;
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE);
g_return_val_if_fail (out_transform != NULL, FALSE);
ancestor = gtk_widget_common_ancestor (widget, target);
if (!ancestor)
return FALSE;
graphene_matrix_init_identity (&transform);
parent = widget;
while (parent != ancestor)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (parent);
graphene_matrix_multiply (&transform, &priv->transform, &transform);
parent = priv->parent;
}
g_assert (parent == ancestor);
{
graphene_matrix_t down_transform;
graphene_matrix_t inv;
graphene_matrix_init_identity (&down_transform);
while (parent != ancestor)
{
graphene_matrix_multiply (&down_transform, &parent->priv->transform, &down_transform);
parent = parent->priv->parent;
}
graphene_matrix_inverse (&down_transform, &inv);
graphene_matrix_multiply (&transform, &inv, &transform);
}
*out_transform = transform;
return TRUE;
}
/**
* gtk_widget_compute_bounds:
* @widget: the #GtkWidget to query
@@ -11323,26 +11368,23 @@ gtk_widget_compute_bounds (GtkWidget *widget,
GtkWidget *target,
graphene_rect_t *out_bounds)
{
graphene_matrix_t transform;
GtkCssBoxes boxes;
int x, y;
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE);
g_return_val_if_fail (out_bounds != NULL, FALSE);
if (!gtk_widget_translate_coordinates (widget,
target,
0, 0,
&x, &y))
if (!gtk_widget_compute_transform (widget, target, &transform))
{
graphene_rect_init_from_rect (out_bounds, graphene_rect_zero ());
return FALSE;
}
gtk_css_boxes_init (&boxes, widget);
graphene_rect_offset_r (gtk_css_boxes_get_border_rect (&boxes),
x, y,
out_bounds);
graphene_matrix_transform_bounds (&transform,
gtk_css_boxes_get_border_rect (&boxes),
out_bounds);
return TRUE;
}

View File

@@ -614,6 +614,10 @@ GDK_AVAILABLE_IN_ALL
void gtk_widget_get_allocation (GtkWidget *widget,
GtkAllocation *allocation);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_compute_transform (GtkWidget *widget,
GtkWidget *target,
graphene_matrix_t *out_transform);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_compute_bounds (GtkWidget *widget,
GtkWidget *target,
graphene_rect_t *out_bounds);