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
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);
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
* @{