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

git pushed a commit to reference refs/pull/176/head
in repository enlightenment.

View the commit online.

commit b44d839382861b9119b17e409b2e5a87188758c2
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Sep 15 21:51:41 2026 -0600

    perf: ibar - don't relayout or re-emit signals on a pure move
    
    Profiling a shelf autohide animation on a Pinebook Pro (RK3399) showed
    _ibar_cb_icon_move, _ibar_cb_resize_job and _ibar_resize_handle together
    accounting for ~11% of the busy CPU cluster, entirely from work that a
    translation does not need.
    
    Two separate problems:
    
    1. _ibar_cb_obj_moveresize was registered for both EVAS_CALLBACK_MOVE and
       EVAS_CALLBACK_RESIZE and unconditionally scheduled a full
       _ibar_resize_handle(): 4x elm_box_recalculate(), min/max size hints on
       every icon, plus gadcon min size and aspect. None of that changes when
       the box only moves - only the drop zone follows the new position. Split
       into _ibar_cb_obj_move (drop zone only) and _ibar_cb_obj_resize, with a
       resize_pending flag so a coalesced move+resize still relays out.
    
    2. _ibar_cb_icon_move ran, per icon per frame: evas_output_size_get(), an
       edje_object_part_geometry_get() on "e.text.label" which forces an edje
       recalc plus a part-name hash lookup, and a zone lookup - then emitted
       the origin signal via _ibar_icon_signal_emit(), which fans out to four
       edje objects. Only the E_GADCON_ORIENT_FLOAT branch actually used
       cw/len/zone, so that work moved inside it, and the emit is now gated on
       the signal having changed.
    
    The gating matters more than skipping a no-op signal: the theme's origin
    descriptions carry link.transition SINUSOIDAL 0.1 on three clip parts, so
    the old code restarted a 0.1s transition per icon on every animation frame.
    
    The e,origin,* signals live in a program namespace disjoint from every
    other _ibar_icon_signal_emit() call site (e,state,* and e,action,*), so
    nothing else disturbs the cached state. The cache is invalidated in
    _ibar_icon_fill(), which recreates o_icon and o_icon2 - those have not
    seen the origin signal yet.
    
    Measured on the same workload, A72 cluster, before -> after (samples):
    
      _ibar_resize_handle        99 ->    0
      _ibar_cb_resize_job       101 ->    0
      _ibar_cb_icon_move        122 ->   86
      ibar total                325 ->   87   (-73%)
      enlightenment total      2048 -> 1375   (-33%)
    
    Edje recalc fell with it - _edje_part_recalc -71%,
    _edje_color_class_recursive_find -77% - because the ibar relayout was
    generating most of that traffic.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/modules/ibar/e_mod_main.c | 92 +++++++++++++++++++++++++++++++------------
 1 file changed, 66 insertions(+), 26 deletions(-)

diff --git a/src/modules/ibar/e_mod_main.c b/src/modules/ibar/e_mod_main.c
index d870fac4f..e02ef2fd9 100644
--- a/src/modules/ibar/e_mod_main.c
+++ b/src/modules/ibar/e_mod_main.c
@@ -61,6 +61,7 @@ struct _IBar
    Evas_Coord   dnd_x, dnd_y;
    IBar_Icon   *menu_icon;
    Eina_Bool    focused E_BITFIELD;
+   Eina_Bool    resize_pending E_BITFIELD;
 };
 
 struct _IBar_Icon
@@ -80,6 +81,7 @@ struct _IBar_Icon
    Eina_List       *menu_pending; //clients with menu items pending
    E_Gadcon_Popup  *menu;
    const char      *hashname;
+   const char      *origin_sig;
    int              mouse_down;
    struct
    {
@@ -93,6 +95,12 @@ struct _IBar_Icon
    Eina_Bool       starting E_BITFIELD;
 };
 
+/* the label origin signals. single definitions so IBar_Icon->origin_sig can be
+ * compared by pointer to find out whether anything actually changed. */
+static const char _sig_origin_center[] = "e,origin,center";
+static const char _sig_origin_left[] = "e,origin,left";
+static const char _sig_origin_right[] = "e,origin,right";
+
 static IBar        *_ibar_new(Evas_Object *parent, Instance *inst);
 static void         _ibar_free(IBar *b);
 static void         _ibar_cb_empty_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
@@ -113,7 +121,8 @@ static void         _ibar_icon_empty(IBar_Icon *ic);
 static void         _ibar_sep_create(IBar *b);
 static void         _ibar_icon_signal_emit(IBar_Icon *ic, const char *sig, const char *src);
 static void         _ibar_cb_app_change(void *data, E_Order *eo);
-static void         _ibar_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void         _ibar_cb_obj_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void         _ibar_cb_obj_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
 static void         _ibar_cb_menu_icon_action_exec(void *data, E_Menu *m, E_Menu_Item *mi);
 static void         _ibar_cb_menu_icon_new(void *data, E_Menu *m, E_Menu_Item *mi);
 static void         _ibar_cb_menu_icon_add(void *data, E_Menu *m, E_Menu_Item *mi);
@@ -292,9 +301,9 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
                         _ibar_inst_cb_leave, _ibar_inst_cb_drop,
                         drop, 3, x, y, w, h);
    evas_object_event_callback_add(b->o_outerbox, EVAS_CALLBACK_MOVE,
-                                  _ibar_cb_obj_moveresize, inst);
+                                  _ibar_cb_obj_move, inst);
    evas_object_event_callback_add(b->o_outerbox, EVAS_CALLBACK_RESIZE,
-                                  _ibar_cb_obj_moveresize, inst);
+                                  _ibar_cb_obj_resize, inst);
    ibar_config->instances = eina_list_append(ibar_config->instances, inst);
    _ibar_resize_handle(b);
    inst->iconify_provider = e_comp_object_effect_mover_add(80, "e,action,*iconify", _ibar_cb_iconify_provider, inst);
@@ -948,6 +957,9 @@ _ibar_icon_free(IBar_Icon *ic)
 static void
 _ibar_icon_fill(IBar_Icon *ic)
 {
+   /* o_icon/o_icon2 are recreated below and have not seen the origin signal
+    * yet, so force the next move to emit it again. */
+   ic->origin_sig = NULL;
    if (ic->o_icon) evas_object_del(ic->o_icon);
    ic->o_icon = e_icon_add(evas_object_evas_get(ic->ibar->o_box));
    evas_object_name_set(ic->o_icon, "icon");
@@ -1019,16 +1031,35 @@ static void
 _ibar_cb_resize_job(void *data)
 {
    Instance *inst = data;
-   _ibar_resize_handle(inst->ibar);
+   IBar *b = inst->ibar;
+
+   if (b->resize_pending)
+     {
+        b->resize_pending = EINA_FALSE;
+        _ibar_resize_handle(b);
+     }
    _ibar_instance_drop_zone_recalc(inst);
-   inst->ibar->resize_job = NULL;
+   b->resize_job = NULL;
 }
 
 static void
-_ibar_cb_obj_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+_ibar_cb_obj_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Instance *inst = data;
 
+   /* a move leaves the layout alone - only the drop zone follows the box.
+    * relaying out here costs a full elm_box recalc per frame while a shelf
+    * slides in or out. */
+   if (inst->ibar->resize_job) return;
+   inst->ibar->resize_job = ecore_job_add((Ecore_Cb)_ibar_cb_resize_job, inst);
+}
+
+static void
+_ibar_cb_obj_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+
+   inst->ibar->resize_pending = EINA_TRUE;
    if (inst->ibar->resize_job) return;
    inst->ibar->resize_job = ecore_job_add((Ecore_Cb)_ibar_cb_resize_job, inst);
 }
@@ -1940,42 +1971,51 @@ static void
 _ibar_cb_icon_move(void *data, Evas *e, Evas_Object *obj, void *event_info EINA_UNUSED)
 {
    IBar_Icon *ic;
-   int x, y, w, h, cw, chx, len = 0;
-   const char *sig = "e,origin,center";
-   E_Zone *zone;
+   int x, y, w, h;
+   const char *sig = _sig_origin_center;
 
    ic = data;
    evas_object_geometry_get(ic->o_holder, &x, &y, &w, &h);
    evas_object_move(ic->o_holder2, x, y);
-   evas_output_size_get(e, &cw, NULL);
 
-   edje_object_part_geometry_get(ic->o_holder2, "e.text.label", NULL, NULL, &len, NULL);
-   chx = x + (w / 2);
-   zone = e_comp_object_util_zone_get(obj);
-   if (!zone)
-     {
-        if (x < 1)
-          zone = e_comp_zone_xy_get(0, y);
-        else
-          zone = e_comp_zone_xy_get(e_comp->w - 5, y);
-        if (!zone)
-          zone = eina_list_data_get(e_comp->zones);
-     }
    if ((ic->ibar->inst->orient == E_GADCON_ORIENT_LEFT) ||
        (ic->ibar->inst->orient == E_GADCON_ORIENT_CORNER_LT) ||
        (ic->ibar->inst->orient == E_GADCON_ORIENT_CORNER_LB))
-     sig = "e,origin,left";
+     sig = _sig_origin_left;
    else if ((ic->ibar->inst->orient == E_GADCON_ORIENT_RIGHT) ||
             (ic->ibar->inst->orient == E_GADCON_ORIENT_CORNER_RT) ||
             (ic->ibar->inst->orient == E_GADCON_ORIENT_CORNER_RB))
-     sig = "e,origin,right";
+     sig = _sig_origin_right;
    else if (ic->ibar->inst->orient == E_GADCON_ORIENT_FLOAT)
      {
+        /* only a floating bar picks its origin from where the label lands, and
+         * only here is the label geometry worth forcing an edje recalc for. */
+        int cw, chx, len = 0;
+        E_Zone *zone;
+
+        evas_output_size_get(e, &cw, NULL);
+        edje_object_part_geometry_get(ic->o_holder2, "e.text.label", NULL, NULL, &len, NULL);
+        chx = x + (w / 2);
+        zone = e_comp_object_util_zone_get(obj);
+        if (!zone)
+          {
+             if (x < 1)
+               zone = e_comp_zone_xy_get(0, y);
+             else
+               zone = e_comp_zone_xy_get(e_comp->w - 5, y);
+             if (!zone)
+               zone = eina_list_data_get(e_comp->zones);
+          }
         if (chx - (len / 2) < zone->x)
-          sig = "e,origin,left";
+          sig = _sig_origin_left;
         else if ((chx + (len / 2) > cw) || ((chx + (len / 2) > zone->x + zone->w)))
-          sig = "e,origin,right";
+          sig = _sig_origin_right;
      }
+   /* the origin only changes on reorient, or when a floating bar crosses a
+    * screen edge - re-emitting it on every move runs an edje program per icon
+    * per frame for nothing. */
+   if (ic->origin_sig == sig) return;
+   ic->origin_sig = sig;
    _ibar_icon_signal_emit(ic, sig, "e");
 }
 

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

Reply via email to