Add function to check if point is inside an object
authorlucas <lucas@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 16 Sep 2010 13:59:46 +0000 (13:59 +0000)
committerlucas <lucas@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 16 Sep 2010 13:59:46 +0000 (13:59 +0000)
Add evas_object_inside_get() to check if a certain (x,y) point is inside
an evas_object. This is needed because there's no simple way to
determine it outside of evas when map transformations are used.

For instance, edje uses evas_object_geometry_get() and checks if point is
whithin the rectangle. This is wrong because the object might be
rotated, scaled. Below is a test program:

/**
 * Simple Evas test
 *
 * Compile with: gcc -O0 -g  -o evas_hello_world evas_hello_world.c $(pkg-config --cflags --libs eina evas ecore ecore-evas)
 */
 #include <Eina.h>
 #include <Evas.h>
 #include <Ecore_Evas.h>
 #include <Ecore.h>
 #include <stdio.h>

 #define WIDTH (320)
 #define HEIGHT (240)

Eina_Bool main_signal_exit(void *data, int ev_type, void *ev)
{
    ecore_main_loop_quit();
    return EINA_FALSE;
}

static void
_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    Evas_Event_Mouse_Up *ev = event_info;
    Eina_Bool b;

    b = evas_object_inside_get(obj, ev->canvas.x, ev->canvas.y);
    fprintf(stderr, "mouse_up: x=%d, y=%d inside=%d\n", ev->canvas.x,
            ev->canvas.y, b);
}

static void
_cb_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    Evas_Event_Mouse_Move *ev = event_info;
    const char *id = data;
    Eina_Bool b;

    b = evas_object_inside_get(obj, ev->cur.canvas.x, ev->cur.canvas.y);
    fprintf(stderr, "[%s] mouse_move: x=%d, y=%d inside=%d\n", id,
            ev->cur.canvas.x, ev->cur.canvas.y, b);
}

int main(void)
{
   Evas *evas;
   Ecore_Evas *window;
   Evas_Object *bg, *r1, *r2;
   Evas_Map *m;

   evas_init();
   ecore_init();
   ecore_evas_init();

   window = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
   if (!evas)
     return -1;

   evas = ecore_evas_get(window);

   bg = evas_object_rectangle_add(evas);
   evas_object_color_set(bg, 255, 255, 255, 255); // white bg
   evas_object_move(bg, 0, 0);                    // at origin
   evas_object_resize(bg, WIDTH, HEIGHT);         // covers full evas
   evas_object_show(bg);

   r1 = evas_object_rectangle_add(evas);
   evas_object_color_set(r1, 255, 0, 0, 255); // 100% opaque red
   evas_object_move(r1, 50, 50);
   evas_object_resize(r1, 100, 100);

   m = evas_map_new(4);
   evas_map_util_points_populate_from_object(m, r1);
   evas_map_util_rotate(m, 45.0, 100, 100);
   evas_map_alpha_set(m, 0);
   evas_map_smooth_set(m, 1);

   evas_object_map_set(r1, m);
   evas_object_map_enable_set(r1, 1);
   evas_map_free(m);
   evas_object_show(r1);
   evas_object_event_callback_add(r1, EVAS_CALLBACK_MOUSE_UP, _cb, NULL);
   evas_object_event_callback_add(r1, EVAS_CALLBACK_MOUSE_MOVE, _cb_move, "r1");

   r2 = evas_object_rectangle_add(evas);
   evas_object_color_set(r2, 0, 255, 0, 255);
   evas_object_move(r2, 210, 150);
   evas_object_resize(r2, 50, 50);
   evas_object_show(r2);
   evas_object_event_callback_add(r2, EVAS_CALLBACK_MOUSE_MOVE, _cb_move, "r2");

   ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, evas);

   ecore_evas_show(window);
   ecore_main_loop_begin();

   ecore_evas_free(window);

   ecore_evas_shutdown();
   ecore_shutdown();
   evas_shutdown();

   return 0;
}

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@52345 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Evas.h
src/lib/canvas/evas_object_main.c

index d133474..052cae5 100644 (file)
@@ -875,6 +875,7 @@ typedef void      (*Evas_Async_Events_Put_Cb)(void *target, Evas_Callback_Type t
    EAPI void              evas_object_move                  (Evas_Object *obj, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_resize                (Evas_Object *obj, Evas_Coord w, Evas_Coord h) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_geometry_get          (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool         evas_object_inside_get            (const Evas_Object *obj, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
 
    EAPI void              evas_object_show                  (Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_hide                  (Evas_Object *obj) EINA_ARG_NONNULL(1);
index 134c417..4c6e29f 100644 (file)
@@ -620,6 +620,46 @@ evas_object_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, E
    if (h) *h = obj->cur.geometry.h;
 }
 
+/* If an evas object does not use any transformation it's much easier to know
+ * if a point is within its bounds. This internal function is used by
+ * evas_object_inside_get() that makes the proper checks to see if the given
+ * evas object can use this version or a more elaborated one is needed.
+ */
+static inline Eina_Bool
+_evas_object_unmapped_inside_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   return ((x >= obj->cur.geometry.x) && (y >= obj->cur.geometry.y) &&
+           (x < (obj->cur.geometry.x + obj->cur.geometry.w)) &&
+           (y < (obj->cur.geometry.y + obj->cur.geometry.h)));
+}
+
+/**
+ * Check if a certain point is inside of a rectangular evas object.
+ *
+ * This function takes into account if the given evas object suffered any
+ * transformation by means of evas_map_* functions.
+ *
+ * @param obj The given evas object.
+ * @param   x   X coordinate of the point to check for.
+ * @param   y   Y coordinate of the point to check for.
+ * @ngroup Evas_Object_Group_Basic
+ */
+EAPI Eina_Bool
+evas_object_inside_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return EINA_FALSE;
+   MAGIC_CHECK_END();
+
+   if (obj->delete_me)
+      return EINA_FALSE;
+
+   if ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap))
+      return evas_map_inside_get(obj->cur.map, x, y);
+
+   return _evas_object_unmapped_inside_get(obj, x, y);
+}
+
 /**
  * @addtogroup Evas_Object_Group_Size_Hints
  * @{