[gtk] widget: Fix gtk_widget_pick() on 3d-transformed widgets



commit bed4c68041fb77a683c29ec5a5e6ddddb441058c
Author: Benjamin Otte <otte redhat com>
Date:   Sun Mar 3 19:40:32 2019 +0100

    widget: Fix gtk_widget_pick() on 3d-transformed widgets
    
    Picking is done by drawing a line along the parent's z axis and picking
    at the intersection with the child's z=0 plane.
    
    However, the previous code was casting a ray along the child's z axis.
    
    This patch actually transforms the line to pick into the target's
    coordinate system and then computes the corrrect intersection with the
    z=0 plane.
    
    Using graphene_point3d_interpolate() to compute the final intersection
    point is a bit of abuse of that function, but I found no better way in
    Graphene to achieve the same thing.

 gtk/gtkwidget.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 80f8dcc099..56f26387a9 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -822,13 +822,20 @@ gtk_widget_real_pick (GtkWidget *widget,
       GtkWidgetPrivate *priv = gtk_widget_get_instance_private (child);
       graphene_matrix_t inv;
       GtkWidget *picked;
-      graphene_point_t p;
+      graphene_point3d_t p0, p1, res;
 
-      graphene_matrix_inverse (&priv->transform, &inv);
-      graphene_point_init (&p, x, y);
-      graphene_matrix_transform_point (&inv, &p, &p);
+      if (!graphene_matrix_inverse (&priv->transform, &inv))
+        continue;
+      graphene_point3d_init (&p0, x, y, 0);
+      graphene_point3d_init (&p1, x, y, 1);
+      graphene_matrix_transform_point3d (&inv, &p0, &p0);
+      graphene_matrix_transform_point3d (&inv, &p1, &p1);
+      if (fabs (p0.z - p1.z) < 1.f / 4096)
+        continue;
+
+      graphene_point3d_interpolate (&p0, &p1, p0.z / (p0.z - p1.z), &res);
 
-      picked = gtk_widget_pick (child, p.x, p.y);
+      picked = gtk_widget_pick (child, res.x, res.y);
       if (picked)
         return picked;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]