Hey Raster,

On 7/9/07, The Rasterman Carsten Haitzler <[EMAIL PROTECTED]> wrote:
On Fri, 6 Jul 2007 18:00:08 -0300 "Andre Magalhaes" <[EMAIL PROTECTED]>
babbled:

> Hi all,
>
> As this is my first post here, let me introduce myself. I am Andre
> Moreira Magalhaes, aka andrunko, and I work for INdT in Brazil.

hey andre :)

> Now let's go to the point. I am working on a project that requires
> that an Evas_Object to have a custom click area. This object is a
> non-retangular object (a circle for eg) with a transparent backgroung.
> When i click on the background of this object, if the click was in a
> transparent area this object shouldn't receive any event. I was
> investigating the Evas code and i found 3 ways that this could be
> done.

currently evas doesn't do this. in theory it could - but it doesn't.

> 1 - Change evas_object_was_in_output_rect to always return 0 if the
> rect is in a transparent area of the object (not desired)
> 2 - Change evas_object_event_callback_call to return a boolean value
> indicating if the object handled the event and if not, keep sending
> event to the other objects in the list. If the object handled the
> event, stop there. This would require a lot of changes.
> 3 - Change evas_object_was_in_output_rect to check a for a custom
> "in_output_rect" method on the object, and if this method is set, use
> it to check if the rect is in output rect. This would require a new
> function, evas_object_is_in_output_rect_cb_set (or something similar)
> that could be implemented whenever is needed. If this method is not
> set, check the clip rectangle as it's done today.

actually i already designed for this. there is an is_inside and was_inside
method for objects. only line and polygon objects provide them and they just
return 1 - these CAN be called if a point is inside the object rect and the
code wants to determine if an event is still inside the object based on private
object data (eg polygon outline, image pixel alpha channel data etc.). right
now it basically isn't used - but its intent was to be used for this. the
problem is this is actually relatively slow/expensive to do. you probably also
want a way of enabling or disabling this level of event processing per object
to save cost. so we probably need to add an object flag to use these methods,
if they exist, or disable them (disabled by default), then provide methods for
image objects at the least - then actually use them, if they are provided, and
the flag is enabled for that object. implementing this won't be too hrd, but it
won't be trivial. you need to be able to figure otu any x,y co-ord within the
object and what pixel of the image that may map to based on paremeters of the
object, then go check that pixel's alpha channel (if the image has an alpha
channel). for polygon nd line objects you need to do some half-plane point
intersection math (easy but its order(n) where n is the number of sides of the
polygon). for lines its strange - you might want perfect inclusion, but that's a
very small space unless its a thick line (doesn't exist currently). for text...
thats hard as you need to figure out what character is in that x,y (that's easy)
and then check the character glyph pixels to see if its inside...

but anyway - i added this mechanism in at the very start but have never used it
(or really needed it enough to implement the rest of it).
hmmm, i didn't know about this is_inside method, it's similar to what
i wanted but with some improvements :D. Attached there is a patch to
implement it on evas_object_image and edje, and a callback to
enable/disable it. I didn't like the name convention but this is
something easy to change. I tested it here and it seems to be working.
This is my first patch to evas, so please let me know where i can
improve. Any comment is welcome

> In the current code, i could do repeat_events=1 to make both objects
> receive the event, and do nothing on the circle object if the clicked
> area is a transparent area. The problem is that this won't work for
> the lower widget, as it's always receive the event, even if the circle
> handled it.

see above - also add a flag to edje to enable or disable this event processing
and bingo... all done. :)

> Any other ideas on how to do it? I am willing to write a patch if you
> agree. I would vote for number 3, as it's extensible, does not require
> a lot of changes and does not impact on performance in the default
> case (no custom is_in_output_rect method).

none of the above - see my suggestion :)

> Any help is appreciate,
> BR
> Andrunko
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by DB2 Express
> Download DB2 Express C - the FREE version of DB2 express and take
> control of your XML. No limits. Just data. Click to get it now.
> http://sourceforge.net/powerbar/db2/
> _______________________________________________
> enlightenment-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
>


--
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    [EMAIL PROTECTED]
裸好多
Tokyo, Japan (東京 日本)


BR
Andrunko
? src/lib/include/.evas_macros.h.swp
Index: src/lib/Evas.h
===================================================================
RCS file: /var/cvs/e/e17/libs/evas/src/lib/Evas.h,v
retrieving revision 1.99
diff -u -r1.99 Evas.h
--- src/lib/Evas.h	17 Jun 2007 02:56:57 -0000	1.99
+++ src/lib/Evas.h	9 Jul 2007 22:13:08 -0000
@@ -768,6 +768,9 @@
    EAPI void              evas_object_propagate_events_set  (Evas_Object *obj, Evas_Bool prop);
    EAPI Evas_Bool         evas_object_propagate_events_get  (Evas_Object *obj);
        
+   EAPI void              evas_object_precise_is_inside_set (Evas_Object *obj, Evas_Bool precise);
+   EAPI Evas_Bool         evas_object_precise_is_inside_get (Evas_Object *obj);
+
    EAPI void              evas_object_event_callback_add    (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info), const void *data);
    EAPI void             *evas_object_event_callback_del    (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info));
 
Index: src/lib/canvas/evas_events.c
===================================================================
RCS file: /var/cvs/e/e17/libs/evas/src/lib/canvas/evas_events.c,v
retrieving revision 1.51
diff -u -r1.51 evas_events.c
--- src/lib/canvas/evas_events.c	30 Apr 2007 04:22:42 -0000	1.51
+++ src/lib/canvas/evas_events.c	9 Jul 2007 22:13:10 -0000
@@ -57,7 +57,9 @@
 		    }
 		  else
 		    {
-		       if (evas_object_is_in_output_rect(obj, x, y, 1, 1))
+		       if (evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
+		           (!obj->precise_is_inside ||
+			    evas_object_is_inside(obj, x, y)))
 			 {
 			    in = evas_list_append(in, obj);
 			    if (!obj->repeat_events)
@@ -584,7 +586,9 @@
 		 (evas_object_clippers_is_visible(obj)) &&
 		 (evas_list_find(ins, obj)) &&
 		 (!evas_event_passes_through(obj)) &&
-		 (!obj->clip.clipees))
+		 (!obj->clip.clipees) &&
+		 (!obj->precise_is_inside ||
+		  evas_object_is_inside(obj, x, y)))
 	       {
 		  if ((px != x) || (py != y))
 		    {
@@ -989,7 +993,11 @@
    evas_object_smart_member_cache_invalidate(obj);
    if (evas_object_is_in_output_rect(obj,
 				     obj->layer->evas->pointer.x,
-				     obj->layer->evas->pointer.y, 1, 1))
+				     obj->layer->evas->pointer.y, 1, 1) &&
+       (!obj->precise_is_inside ||
+	evas_object_is_inside(obj,
+                              obj->layer->evas->pointer.x,
+                              obj->layer->evas->pointer.y)))
      evas_event_feed_mouse_move(obj->layer->evas,
 				obj->layer->evas->pointer.x,
 				obj->layer->evas->pointer.y,
@@ -1036,7 +1044,11 @@
    obj->repeat_events = repeat;
    if (evas_object_is_in_output_rect(obj,
 				     obj->layer->evas->pointer.x,
-				     obj->layer->evas->pointer.y, 1, 1))
+				     obj->layer->evas->pointer.y, 1, 1) &&
+       (!obj->precise_is_inside ||
+	evas_object_is_inside(obj,
+                              obj->layer->evas->pointer.x,
+                              obj->layer->evas->pointer.y)))
      evas_event_feed_mouse_move(obj->layer->evas,
 				obj->layer->evas->pointer.x,
 				obj->layer->evas->pointer.y,
Index: src/lib/canvas/evas_object_image.c
===================================================================
RCS file: /var/cvs/e/e17/libs/evas/src/lib/canvas/evas_object_image.c,v
retrieving revision 1.52
diff -u -r1.52 evas_object_image.c
--- src/lib/canvas/evas_object_image.c	28 Jun 2007 23:22:20 -0000	1.52
+++ src/lib/canvas/evas_object_image.c	9 Jul 2007 22:13:15 -0000
@@ -67,6 +67,7 @@
 
 static int evas_object_image_is_opaque(Evas_Object *obj);
 static int evas_object_image_was_opaque(Evas_Object *obj);
+static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
 
 static const Evas_Object_Func object_func =
 {
@@ -82,7 +83,7 @@
      NULL,
      evas_object_image_is_opaque,
      evas_object_image_was_opaque,
-     NULL,
+     evas_object_image_is_inside,
      NULL,
      NULL
 };
@@ -2249,3 +2250,32 @@
 	return 0;
    return 1;
 }
+
+static int
+evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Evas_Object_Image *o;
+   DATA32 *data;
+   int w, h;
+   int a;
+
+   o = (Evas_Object_Image *)(obj->object_data);
+
+   x -= obj->cur.cache.clip.x;
+   y -= obj->cur.cache.clip.y;
+   w = o->cur.image.w;
+   h = o->cur.image.h;
+
+   if (x > w || y > h) {
+     return 0;
+   }
+
+   o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
+								  o->engine_data,
+								  0,
+								  &data);
+   data += (y * w) + x;
+   a = (*data >> 24) & 0xff;
+
+   return (a != 0);
+}
Index: src/lib/canvas/evas_object_main.c
===================================================================
RCS file: /var/cvs/e/e17/libs/evas/src/lib/canvas/evas_object_main.c,v
retrieving revision 1.56
diff -u -r1.56 evas_object_main.c
--- src/lib/canvas/evas_object_main.c	21 Feb 2007 21:43:45 -0000	1.56
+++ src/lib/canvas/evas_object_main.c	9 Jul 2007 22:13:18 -0000
@@ -419,6 +419,23 @@
    return 0;
 }
 
+int
+evas_object_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   if (obj->smart.smart) return 0;
+   if (obj->func->is_inside)
+     return obj->func->is_inside(obj, x, y);
+   return 0;
+}
+
+int
+evas_object_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   if (obj->smart.smart) return 0;
+   if (obj->func->was_inside)
+     return obj->func->was_inside(obj, x, y);
+   return 0;
+}
 /* routines apps will call */
 
 /**
@@ -1221,3 +1238,33 @@
    if (obj->delete_me) return "";
    return obj->type;
 }
+
+/**
+ * Set whether to use a precise (usually expensive) point collision detection.
+ * @param obj The given object.
+ * @param precise wheter to use a precise point collision detection or not
+ * The default value is false.
+ * @ingroup Evas_Object_Group
+ */
+EAPI void
+evas_object_precise_is_inside_set(Evas_Object *obj, Evas_Bool precise)
+{
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   obj->precise_is_inside = precise;
+}
+
+/**
+ * Determine whether an object is set to use a precise point collision detection.
+ * @param obj The given object.
+ * @ingroup Evas_Object_Group
+ */
+EAPI Evas_Bool
+evas_object_precise_is_inside_get(Evas_Object *obj)
+{
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return 0;
+   MAGIC_CHECK_END();
+   return obj->precise_is_inside;
+}
Index: src/lib/include/evas_private.h
===================================================================
RCS file: /var/cvs/e/e17/libs/evas/src/lib/include/evas_private.h,v
retrieving revision 1.85
diff -u -r1.85 evas_private.h
--- src/lib/include/evas_private.h	28 Jun 2007 23:22:20 -0000	1.85
+++ src/lib/include/evas_private.h	9 Jul 2007 22:13:21 -0000
@@ -448,6 +448,8 @@
    unsigned short              in_layer : 1;
    unsigned short              no_propagate : 1;
 
+   unsigned short              precise_is_inside : 1;
+
    unsigned char               delete_me;
 };
 
@@ -678,6 +680,8 @@
 int evas_object_was_visible(Evas_Object *obj);
 int evas_object_is_opaque(Evas_Object *obj);
 int evas_object_was_opaque(Evas_Object *obj);
+int evas_object_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+int evas_object_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
 //void evas_object_recalc_clippees(Evas_Object *obj);
 int evas_object_clippers_is_visible(Evas_Object *obj);
 int evas_object_clippers_was_visible(Evas_Object *obj);
Index: src/bin/edje_cc_handlers.c
===================================================================
RCS file: /var/cvs/e/e17/libs/edje/src/bin/edje_cc_handlers.c,v
retrieving revision 1.75
diff -u -r1.75 edje_cc_handlers.c
--- src/bin/edje_cc_handlers.c	7 Jul 2007 11:07:42 -0000	1.75
+++ src/bin/edje_cc_handlers.c	9 Jul 2007 22:15:23 -0000
@@ -43,6 +43,7 @@
 static void st_collections_group_parts_part_effect(void);
 static void st_collections_group_parts_part_mouse_events(void);
 static void st_collections_group_parts_part_repeat_events(void);
+static void st_collections_group_parts_part_precise_is_inside(void);
 static void st_collections_group_parts_part_use_alternate_font_metrics(void);
 static void st_collections_group_parts_part_clip_to_id(void);
 static void st_collections_group_parts_part_source(void);
@@ -179,6 +180,7 @@
      {"collections.group.parts.part.effect", st_collections_group_parts_part_effect},
      {"collections.group.parts.part.mouse_events", st_collections_group_parts_part_mouse_events},
      {"collections.group.parts.part.repeat_events", st_collections_group_parts_part_repeat_events},
+     {"collections.group.parts.part.precise_is_inside", st_collections_group_parts_part_precise_is_inside},
      {"collections.group.parts.part.use_alternate_font_metrics", st_collections_group_parts_part_use_alternate_font_metrics},
      {"collections.group.parts.part.clip_to", st_collections_group_parts_part_clip_to_id},
      {"collections.group.parts.part.source", st_collections_group_parts_part_source},
@@ -899,6 +901,7 @@
    ep->type = EDJE_PART_TYPE_IMAGE;
    ep->mouse_events = 1;
    ep->repeat_events = 0;
+   ep->precise_is_inside = 0;
    ep->use_alternate_font_metrics = 0;
    ep->clip_to_id = -1;
    ep->dragable.confine_id = -1;
@@ -984,6 +987,19 @@
 }
 
 static void
+st_collections_group_parts_part_precise_is_inside(void)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+
+   check_arg_count(1);
+   
+   pc = evas_list_data(evas_list_last(edje_collections));
+   ep = evas_list_data(evas_list_last(pc->parts));
+   ep->precise_is_inside = parse_bool(0);
+}
+
+static void
 st_collections_group_parts_part_use_alternate_font_metrics(void)
 {
    Edje_Part_Collection *pc;
Index: src/lib/edje_data.c
===================================================================
RCS file: /var/cvs/e/e17/libs/edje/src/lib/edje_data.c,v
retrieving revision 1.37
diff -u -r1.37 edje_data.c
--- src/lib/edje_data.c	6 Jul 2007 22:36:40 -0000	1.37
+++ src/lib/edje_data.c	9 Jul 2007 22:15:26 -0000
@@ -345,6 +345,7 @@
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "effect", effect, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "mouse_events", mouse_events, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "repeat_events", repeat_events, EET_T_CHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "precise_is_inside", precise_is_inside, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "clip_to_id", clip_to_id, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part, Edje_Part, "use_alternate_font_metrics", use_alternate_font_metrics, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_part, Edje_Part, "default_desc", default_desc, _edje_edd_edje_part_description);
Index: src/lib/edje_load.c
===================================================================
RCS file: /var/cvs/e/e17/libs/edje/src/lib/edje_load.c,v
retrieving revision 1.105
diff -u -r1.105 edje_load.c
--- src/lib/edje_load.c	27 May 2007 05:28:07 -0000	1.105
+++ src/lib/edje_load.c	9 Jul 2007 22:15:28 -0000
@@ -326,6 +326,8 @@
 			 }
 		       else
 			 evas_object_pass_events_set(rp->object, 1);
+		       if (ep->precise_is_inside)
+		         evas_object_precise_is_inside_set(rp->object, 1);
 		    }
 		  if (rp->part->clip_to_id < 0)
 		    evas_object_clip_set(rp->object, ed->clipper);
Index: src/lib/edje_private.h
===================================================================
RCS file: /var/cvs/e/e17/libs/edje/src/lib/edje_private.h,v
retrieving revision 1.128
diff -u -r1.128 edje_private.h
--- src/lib/edje_private.h	6 Jul 2007 23:33:42 -0000	1.128
+++ src/lib/edje_private.h	9 Jul 2007 22:15:31 -0000
@@ -427,6 +427,7 @@
    unsigned char          effect; /* 0 = plain... */
    unsigned char          mouse_events; /* it will affect/respond to mouse events */
    unsigned char          repeat_events; /* it will repeat events to objects below */
+   unsigned char          precise_is_inside;
    unsigned char          use_alternate_font_metrics;
 };
 
Index: src/lib/edje_util.c
===================================================================
RCS file: /var/cvs/e/e17/libs/edje/src/lib/edje_util.c,v
retrieving revision 1.96
diff -u -r1.96 edje_util.c
--- src/lib/edje_util.c	17 Jun 2007 07:09:02 -0000	1.96
+++ src/lib/edje_util.c	9 Jul 2007 22:15:35 -0000
@@ -2121,6 +2121,8 @@
    else
      evas_object_pass_events_set(obj_swallow, 1);
 
+   if (rp->part->precise_is_inside)
+     evas_object_precise_is_inside_set(obj_swallow, 1);
 
    rp->edje->dirty = 1;
    _edje_recalc(rp->edje);
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to