From 251a60ab09f7765a8ec12d1564b9589c2b7a6a7b Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 16 Sep 2010 13:59:46 +0000 Subject: [PATCH] Add function to check if point is inside an object 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 #include #include #include #include #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; } SVN revision: 52345 --- legacy/evas/src/lib/Evas.h | 1 + legacy/evas/src/lib/canvas/evas_object_main.c | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index d133474967..052cae5166 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -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); diff --git a/legacy/evas/src/lib/canvas/evas_object_main.c b/legacy/evas/src/lib/canvas/evas_object_main.c index 134c417560..4c6e29feb1 100644 --- a/legacy/evas/src/lib/canvas/evas_object_main.c +++ b/legacy/evas/src/lib/canvas/evas_object_main.c @@ -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 * @{