[gtk] widget: Add gtk_widget_compute_transform
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk] widget: Add gtk_widget_compute_transform
- Date: Tue, 19 Feb 2019 18:24:23 +0000 (UTC)
commit dbf0654e5b52e1cfd983cd8382185adb5feff095
Author: Timm Bäder <mail baedert org>
Date: Sun Feb 17 08:47:09 2019 +0100
widget: Add gtk_widget_compute_transform
docs/reference/gtk/gtk4-sections.txt | 1 +
gtk/gtkwidget.c | 128 +++++++++++++++++++++++------------
gtk/gtkwidget.h | 4 ++
3 files changed, 90 insertions(+), 43 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 9ddc0c6c96..b6785ed0c5 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -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
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0ba379e23a..42e43a28f6 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -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);
+ return FALSE;
}
- 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;
}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index e912b6e612..f62049a894 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]