This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository efl.

View the commit online.

commit 60b97bbe66cff8a5ab9e3975da2b4e92d80873f9
Author: Carsten Haitzler <ras...@rasterman.com>
AuthorDate: Mon Feb 10 14:08:02 2025 +0000

    evas - object - add event regions to objects
    
    @feat
---
 src/lib/evas/canvas/efl_canvas_object.eo          | 20 ++++++++
 src/lib/evas/canvas/efl_canvas_object_eo.legacy.c | 12 +++++
 src/lib/evas/canvas/efl_canvas_object_eo.legacy.h | 32 +++++++++++++
 src/lib/evas/canvas/evas_events.c                 | 58 ++++++++++++++++++++---
 src/lib/evas/canvas/evas_object_main.c            | 27 +++++++++++
 src/lib/evas/include/evas_private.h               |  2 +
 6 files changed, 144 insertions(+), 7 deletions(-)

diff --git a/src/lib/evas/canvas/efl_canvas_object.eo b/src/lib/evas/canvas/efl_canvas_object.eo
index 64aad581ea..8e90ab99f2 100644
--- a/src/lib/evas/canvas/efl_canvas_object.eo
+++ b/src/lib/evas/canvas/efl_canvas_object.eo
@@ -321,6 +321,26 @@ abstract Efl.Canvas.Object extends Efl.Loop_Consumer implements Efl.Gfx.Entity,
                          ($false).]]
          }
       }
+      @property event_rects @beta {
+         [[ A series of rectangles relative to object top-left that define
+            the input seriface area of the object instead of the normal
+            full object geometry itself. The object geometry itself acts
+            implicitly as a master clip to this set of rects if they are
+            outside the bounds of the object geometry. If set to a NULL
+            array, the rectangle region set is cleared and normal behavior
+            resumes.
+
+            The array of rectangles is terminated by a rectangle of geometry
+            0,0 0x0.
+         ]]
+         set {
+         }
+         get {
+         }
+         values {
+            region: ptr(const(Eina.Rect)); [[ The rects in the region ]]
+         }
+      }
       @property anti_alias {
          [[Whether or not the given Evas object is to be drawn
            anti-aliased.
diff --git a/src/lib/evas/canvas/efl_canvas_object_eo.legacy.c b/src/lib/evas/canvas/efl_canvas_object_eo.legacy.c
index 2d9a5a0682..e4a272a329 100644
--- a/src/lib/evas/canvas/efl_canvas_object_eo.legacy.c
+++ b/src/lib/evas/canvas/efl_canvas_object_eo.legacy.c
@@ -84,6 +84,18 @@ evas_object_pass_events_get(const Efl_Canvas_Object *obj)
    return efl_canvas_object_pass_events_get(obj);
 }
 
+EVAS_API void
+evas_object_event_rects_set(Efl_Canvas_Object *obj, const Eina_Rect *region)
+{
+  efl_canvas_object_event_rects_set(obj, region);
+}
+
+EVAS_API const Eina_Rect *
+evas_object_event_rects_get(const Efl_Canvas_Object *obj)
+{
+  return efl_canvas_object_event_rects_get(obj);
+}
+
 EVAS_API void
 evas_object_anti_alias_set(Efl_Canvas_Object *obj, Eina_Bool anti_alias)
 {
diff --git a/src/lib/evas/canvas/efl_canvas_object_eo.legacy.h b/src/lib/evas/canvas/efl_canvas_object_eo.legacy.h
index c78d89d48c..524b64208f 100644
--- a/src/lib/evas/canvas/efl_canvas_object_eo.legacy.h
+++ b/src/lib/evas/canvas/efl_canvas_object_eo.legacy.h
@@ -320,6 +320,38 @@ EVAS_API void evas_object_pass_events_set(Efl_Canvas_Object *obj, Eina_Bool pass
  */
 EVAS_API Eina_Bool evas_object_pass_events_get(const Efl_Canvas_Object *obj);
 
+/**
+ * @brief Set the event region in rects of an object
+ *
+ * @param[in] obj The object.
+ * @param[in] region The rectangles (Eina_Rect) or NULL to reset.
+ * 
+ * The region is an array of rectangles which is "null" terminated by a
+ * rectangkle at the end being 0, 0 0x0 (all 0's).
+ * 
+ * @since 1.29
+ * 
+ * @see evas_object_event_rects_get()
+ *
+ * @ingroup Evas_Object_Group
+ */
+EVAS_API void evas_object_event_rects_set(Efl_Canvas_Object *obj, const Eina_Rect *region);
+
+/**
+ * @brief Get the event region in rects of an object
+ *
+ * @param[in] obj The object.
+ *
+ * @return The rectangles (Eina_Rect) or NULL when default object area used
+ *
+ * @since 1.29
+ * 
+ * @see evas_object_event_rects_set()
+ * 
+ * @ingroup Evas_Object_Group
+ */
+EVAS_API const Eina_Rect *evas_object_event_rects_get(const Efl_Canvas_Object *obj);
+
 /**
  * @brief Sets whether or not the given Evas object is to be drawn
  * anti-aliased.
diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c
index c76fb52de1..29a6c9f02a 100644
--- a/src/lib/evas/canvas/evas_events.c
+++ b/src/lib/evas/canvas/evas_events.c
@@ -49,7 +49,8 @@ static inline Eina_Bool
 _evas_event_object_pointer_allow_precise(Eo *eo_obj, Evas_Object_Protected_Data *obj, int x, int y, const Eina_List *ins)
 {
    return eina_list_data_find(ins, eo_obj) &&
-     ((!obj->precise_is_inside) || evas_object_is_inside(eo_obj, obj, x, y));
+     (((!obj->precise_is_inside) && (!obj->event_rects)) ||
+         evas_object_is_inside(eo_obj, obj, x, y));
 }
 
 #define EVAS_EVENT_FEED_SAFETY_CHECK(evas) _evas_event_feed_check(evas)
@@ -260,7 +261,8 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data
              Evas_Object_Protected_Data *clip = obj->cur->clipper;
              int norep = 0;
 
-             if (clip && clip->mask->is_mask && clip->precise_is_inside)
+             if (clip && clip->mask->is_mask && clip->precise_is_inside &&
+                 (!clip->event_rects))
                if (!evas_object_is_inside(clip->object, clip, x, y))
                  return in;
 
@@ -339,7 +341,8 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data
         else
           {
              Evas_Object_Protected_Data *clip = obj->cur->clipper;
-             if (clip && clip->mask->is_mask && clip->precise_is_inside)
+             if (clip && clip->mask->is_mask && clip->precise_is_inside &&
+                 (!clip->event_rects))
                inside = evas_object_is_inside(clip->object, clip, x, y);
              else
                inside = evas_object_is_in_output_rect(eo_obj, obj, x, y, 1, 1);
@@ -356,7 +359,7 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data
                          }
                     }
                }
-             if (inside && ((!obj->precise_is_inside) ||
+             if (inside && (((!obj->precise_is_inside) && (!obj->event_rects)) ||
                             (evas_object_is_inside(eo_obj, obj, x, y))))
                {
                   if (!evas_event_freezes_through(eo_obj, obj))
@@ -3970,9 +3973,10 @@ _feed_mouse_move_eval_internal(Eo *eo_obj, Evas_Object_Protected_Data *obj)
    in_output_rect = evas_object_is_in_output_rect(eo_obj, obj, pdata->seat->x,
                                                   pdata->seat->y, 1, 1);
    if ((in_output_rect) &&
-       ((!obj->precise_is_inside) || (evas_object_is_inside(eo_obj, obj,
-                                                            pdata->seat->x,
-                                                            pdata->seat->y))))
+       (((!obj->precise_is_inside) && (!obj->event_rects)) ||
+           (evas_object_is_inside(eo_obj, obj,
+                                  pdata->seat->x,
+                                  pdata->seat->y))))
      {
         _canvas_event_feed_mouse_move_legacy(evas->evas, evas,
                                              pdata->seat->x, pdata->seat->y,
@@ -4044,6 +4048,46 @@ _efl_canvas_object_pass_events_get(const Eo *eo_obj EINA_UNUSED, Evas_Object_Pro
    return obj->pass_events;
 }
 
+EOLIAN void
+_efl_canvas_object_event_rects_set(Eo *obj, Evas_Object_Protected_Data *pd, const Eina_Rect *region)
+{
+   Eina_Rect *new_rects;
+   const Eina_Rect *r;
+   int n = 0;
+
+   if ((!region) && (!pd->event_rects)) return;
+   if (pd->event_rects)
+     {
+       free(pd->event_rects);
+       pd->event_rects = NULL;
+     }
+   if (region)
+     {
+       // count rects
+       for (r = region; ; r++, n++)
+         {
+           if ((r->x | r->y | r->w | r->h) == 0) break;
+         }
+       n++; // need 1 more slot for 0 0 0x0 rect
+       // alloc new rects
+       new_rects = malloc(n * sizeof(Eina_Rect));
+       if (!new_rects) return; // EEK
+       // fll it in
+       memcpy(new_rects, region, n * sizeof(Eina_Rect));
+       // nuke old ones
+       // store new rects
+       pd->event_rects = new_rects;
+     }
+   // reprocess in/out mouse and events
+   _feed_mouse_move_eval_internal(obj, pd);
+}
+
+EOLIAN const Eina_Rect *
+_efl_canvas_object_event_rects_get(const Eo *obj EINA_UNUSED, Evas_Object_Protected_Data *pd)
+{
+   return pd->event_rects;
+}
+
 EOLIAN void
 _efl_canvas_object_repeat_events_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Eina_Bool repeat)
 {
diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c
index e1b5839957..4f16a9540a 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -510,6 +510,11 @@ evas_object_free(Evas_Object_Protected_Data *obj, Eina_Bool clean_layer)
      {
        EVAS_MEMPOOL_FREE(_mp_sh, obj->size_hints);
      }
+   if (obj->event_rects)
+     {
+       free(obj->event_rects);
+       obj->event_rects = NULL;
+     }
    eina_cow_free(evas_object_proxy_cow, (const Eina_Cow_Data**) &obj->proxy);
    eina_cow_free(evas_object_map_cow, (const Eina_Cow_Data**) &obj->map);
    eina_cow_free(evas_object_state_cow, (const Eina_Cow_Data**) &obj->cur);
@@ -862,10 +867,29 @@ evas_object_was_opaque(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
    return 0;
 }
 
+static int
+evas_object_is_inside_event_rects(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, Evas_Coord x, Evas_Coord y)
+{
+  Evas_Coord rx, ry;
+  const Eina_Rect *r;
+
+  rx = x - obj->cur->geometry.x;
+  ry = y - obj->cur->geometry.y;
+  for (r = obj->event_rects;; r++)
+    {
+      if ((r->x | r->y | r->w | r->h) == 0) break;
+      if (eina_rectangle_coords_inside(&(r->rect), rx, ry)) return 1;
+    }
+  return 0;
+}
+
 int
 evas_object_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Coord x, Evas_Coord y)
 {
    if (obj->is_smart) return 0;
+   if ((obj->event_rects) &&
+       (!evas_object_is_inside_event_rects(eo_obj, obj, x, y)))
+     return 0;
    if (obj->func->is_inside)
      return obj->func->is_inside(eo_obj, obj, obj->private_data, x, y);
    return 0;
@@ -875,6 +899,9 @@ int
 evas_object_was_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Coord x, Evas_Coord y)
 {
    if (obj->is_smart) return 0;
+   if ((obj->event_rects) &&
+       (!evas_object_is_inside_event_rects(eo_obj, obj, x, y)))
+     return 0;
    if (obj->func->was_inside)
      return obj->func->was_inside(eo_obj, obj, obj->private_data, x, y);
    return 0;
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 3af4addc57..5a4b447ee9 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -724,6 +724,8 @@ struct _Evas_Object_Protected_Data
 
    Evas_Size_Hints            *size_hints;
 
+   Eina_Rect                  *event_rects;
+
    int                         last_mouse_down_counter;
    int                         last_mouse_up_counter;
    int                         last_event_id;

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to