discomfitor pushed a commit to branch master.

commit fa7744b4de1a694630b703e32295598c963a1572
Author: Mike Blumenkrantz <[email protected]>
Date:   Fri Jul 26 14:42:48 2013 +0100

    fix ibar client menu to track multiple windows per exe
---
 src/bin/e_border.c            |  51 +++++++------
 src/bin/e_exec.c              |  21 ++++--
 src/bin/e_exec.h              |   4 +-
 src/modules/ibar/e_mod_main.c | 170 ++++++++++++++++++++++++++++++------------
 4 files changed, 169 insertions(+), 77 deletions(-)

diff --git a/src/bin/e_border.c b/src/bin/e_border.c
index a22962a..ae0802d 100644
--- a/src/bin/e_border.c
+++ b/src/bin/e_border.c
@@ -4899,10 +4899,10 @@ _e_border_del(E_Border *bd)
 
    if (bd->exe_inst)
      {
-        if (bd->exe_inst->phony)
+        if (bd->exe_inst->phony && (eina_list_count(bd->exe_inst->borders) == 
1))
           e_exec_phony_del(bd->exe_inst);
         else
-          bd->exe_inst->bd = NULL;
+          bd->exe_inst->borders = eina_list_remove(bd->exe_inst->borders, bd);
         bd->exe_inst = NULL;
      }
 
@@ -7999,30 +7999,35 @@ _e_border_eval0(E_Border *bd)
           {
              inst = 
e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
                                                         bd->client.netwm.pid);
-             if ((inst) && (inst->used == 0))
+             if (inst)
                {
-                  E_Zone *zone;
-                  E_Desk *desk;
-
-                  inst->used++;
-                  zone = e_container_zone_number_get(bd->zone->container,
-                                                     inst->screen);
-                  if (zone) e_border_zone_set(bd, zone);
-                  desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
-                                          inst->desk_y);
-                  if (desk) e_border_desk_set(bd, desk);
-                  if (bd->client.netwm.pid != ecore_exe_pid_get(inst->exe))
+                  Eina_Bool found;
+                  if (inst->used == 0)
                     {
-                       /* most likely what has happened here is that the 
.desktop launcher
-                        * has spawned a process which then created this 
border, meaning the
-                        * E_Exec instance will be deleted in a moment, and we 
will be unable to track it.
-                        * to prevent this, we convert our instance to a phony
-                        */
-                        inst->phony = 1;
+                       E_Zone *zone;
+                       E_Desk *desk;
+
+                       inst->used++;
+                       zone = e_container_zone_number_get(bd->zone->container,
+                                                          inst->screen);
+                       if (zone) e_border_zone_set(bd, zone);
+                       desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
+                                               inst->desk_y);
+                       if (desk) e_border_desk_set(bd, desk);
+                       if (bd->client.netwm.pid != 
ecore_exe_pid_get(inst->exe))
+                         {
+                            /* most likely what has happened here is that the 
.desktop launcher
+                             * has spawned a process which then created this 
border, meaning the
+                             * E_Exec instance will be deleted in a moment, 
and we will be unable to track it.
+                             * to prevent this, we convert our instance to a 
phony
+                             */
+                             inst->phony = 1;
+                         }
                     }
-                  inst->bd = bd;
-                  bd->exe_inst = inst;
-                  e_exec_instance_found(inst);
+                  found = !!inst->borders;
+                  e_exec_instance_client_add(inst, bd);
+                  if (!found)
+                    e_exec_instance_found(inst);
                }
              else if (!inst)
                e_exec_phony(bd);
diff --git a/src/bin/e_exec.c b/src/bin/e_exec.c
index 25f9eab..5ea76f1 100644
--- a/src/bin/e_exec.c
+++ b/src/bin/e_exec.c
@@ -77,6 +77,7 @@ static E_Exec_Instance *(*_e_exec_executor_func)(void *data, 
E_Zone * zone, Efre
 static void *_e_exec_executor_data = NULL;
 
 EAPI int E_EVENT_EXEC_NEW = -1;
+EAPI int E_EVENT_EXEC_NEW_CLIENT = -1;
 EAPI int E_EVENT_EXEC_DEL = -1;
 
 /* externally accessible functions */
@@ -93,6 +94,7 @@ e_exec_init(void)
 #endif
 
    E_EVENT_EXEC_NEW = ecore_event_type_new();
+   E_EVENT_EXEC_NEW_CLIENT = ecore_event_type_new();
    E_EVENT_EXEC_DEL = ecore_event_type_new();
    return 1;
 }
@@ -257,7 +259,7 @@ e_exec_phony(E_Border *bd)
      }
    inst->used = 1;
    bd->exe_inst = inst;
-   inst->bd = bd;
+   inst->borders = eina_list_append(inst->borders, bd);
    if (bd->zone) inst->screen = bd->zone->num;
    if (bd->desk)
      {
@@ -342,6 +344,15 @@ e_exec_instance_found(E_Exec_Instance *inst)
 }
 
 EAPI void
+e_exec_instance_client_add(E_Exec_Instance *inst, E_Border *bd)
+{
+   inst->borders = eina_list_append(inst->borders, bd);
+   bd->exe_inst = inst;
+   inst->ref++;
+   ecore_event_add(E_EVENT_EXEC_NEW_CLIENT, inst, _e_exec_cb_exec_new_free, 
inst);
+}
+
+EAPI void
 e_exec_instance_watcher_add(E_Exec_Instance *inst, void (*func)(void *data, 
E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data)
 {
    E_Exec_Watch *iw;
@@ -618,6 +629,7 @@ static void
 _e_exec_instance_free(E_Exec_Instance *inst)
 {
    Eina_List *instances;
+   E_Border *bd;
 
    if (inst->ref) return;
    E_FREE_LIST(inst->watchers, free);
@@ -644,11 +656,8 @@ _e_exec_instance_free(E_Exec_Instance *inst)
      e_exec_start_pending = eina_list_remove(e_exec_start_pending,
                                              inst->desktop);
    if (inst->expire_timer) ecore_timer_del(inst->expire_timer);
-   if (inst->bd)
-     {
-        inst->bd->exe_inst = NULL;
-        inst->bd = NULL;
-     }
+   EINA_LIST_FREE(inst->borders, bd)
+     bd->exe_inst = NULL;
    if (inst->desktop) efreet_desktop_free(inst->desktop);
    free(inst);
 }
diff --git a/src/bin/e_exec.h b/src/bin/e_exec.h
index 9cc3966..86090b8 100644
--- a/src/bin/e_exec.h
+++ b/src/bin/e_exec.h
@@ -9,7 +9,7 @@ typedef struct _E_Exec_Instance E_Exec_Instance;
 struct _E_Exec_Instance
 {
    Efreet_Desktop *desktop;
-   E_Border       *bd;
+   Eina_List      *borders;
    const char     *key;
    Ecore_Exe      *exe;
    int             startup_id;
@@ -46,9 +46,11 @@ EAPI void e_exec_instance_watcher_del(E_Exec_Instance *inst, 
void (*func) (void
 EAPI const Eina_List *e_exec_desktop_instances_find(const Efreet_Desktop 
*desktop);
 
 EAPI const Eina_Hash *e_exec_instances_get(void);
+EAPI void e_exec_instance_client_add(E_Exec_Instance *inst, E_Border *bd);
 
 /* sends E_Exec_Instance */
 EAPI extern int E_EVENT_EXEC_NEW;
+EAPI extern int E_EVENT_EXEC_NEW_CLIENT;
 EAPI extern int E_EVENT_EXEC_DEL;
 
 #endif
diff --git a/src/modules/ibar/e_mod_main.c b/src/modules/ibar/e_mod_main.c
index 7c70d7c..5cf91c5 100644
--- a/src/modules/ibar/e_mod_main.c
+++ b/src/modules/ibar/e_mod_main.c
@@ -524,8 +524,18 @@ _ibar_fill(IBar *b)
           {
              EINA_LIST_FOREACH(l, ll, exe)
                {
+                  E_Border *bd;
+                  Eina_List *lll;
+                  Eina_Bool skip = EINA_TRUE;
+
                   if (!exe->desktop) continue;
-                  if (exe->bd && exe->bd->client.netwm.state.skip_taskbar) 
continue;
+                  EINA_LIST_FOREACH(exe->borders, lll, bd)
+                    if (!bd->client.netwm.state.skip_taskbar)
+                      {
+                         skip = EINA_FALSE;
+                         break;
+                      }
+                  if (skip) continue;
                   ic = eina_hash_find(b->icon_hash, 
_desktop_name_get(exe->desktop));
                   if (ic)
                     {
@@ -1025,6 +1035,7 @@ _ibar_cb_icon_menu_img_del(void *data, Evas *e 
EINA_UNUSED, Evas_Object *obj EIN
    IBar_Icon *ic = evas_object_data_del(data, "ibar_icon");
 
    if (!ic) return; //menu is closing
+   if (!ic->menu) return; //who knows
    edje_object_part_box_remove(ic->menu->o_bg, "e.box", data);
    evas_object_del(data);
    if (eina_list_count(ic->exes) < 2)
@@ -1071,33 +1082,37 @@ _ibar_icon_menu(IBar_Icon *ic)
      {
         Evas_Object *img;
         const char *txt;
+        Eina_List *ll;
+        E_Border *bd;
 
-        if (!exe->bd) continue; //WTF
-        it = edje_object_add(e);
-        e_popup_object_add(ic->menu->win, it);
-        e_theme_edje_object_set(it, "base/theme/modules/ibar",
-                                "e/modules/ibar/menu/item");
-        img = e_comp_win_image_mirror_add(exe->bd->cw);
-        evas_object_event_callback_add(img, EVAS_CALLBACK_DEL,
-                                       _ibar_cb_icon_menu_img_del, it);
-        txt = exe->bd->client.netwm.name ?:
-          (exe->bd->client.icccm.title ?: exe->bd->client.icccm.name);
-        w = exe->bd->cw->pw;
-        h = exe->bd->cw->ph;
-        e_popup_object_add(ic->menu->win, img);
-        evas_object_show(img);
-        edje_extern_object_aspect_set(img, EDJE_ASPECT_CONTROL_BOTH, w, h);
-        edje_object_part_swallow(it, "e.swallow.icon", img);
-        edje_object_part_text_set(it, "e.text.title", txt);
-        edje_object_calc_force(it);
-        edje_object_size_min_calc(it, &w, &h);
-        edje_extern_object_min_size_set(it, w, h);
-        evas_object_size_hint_min_set(it, w, h);
-        evas_object_show(it);
-        evas_object_event_callback_add(it, EVAS_CALLBACK_MOUSE_UP,
-          _ibar_cb_icon_menu_mouse_up, exe->bd);
-        evas_object_data_set(it, "ibar_icon", ic);
-        edje_object_part_box_append(o, "e.box", it);
+        EINA_LIST_FOREACH(exe->borders, ll, bd)
+          {
+             if (bd->client.netwm.state.skip_taskbar) continue;
+             it = edje_object_add(e);
+             e_popup_object_add(ic->menu->win, it);
+             e_theme_edje_object_set(it, "base/theme/modules/ibar",
+                                     "e/modules/ibar/menu/item");
+             img = e_comp_win_image_mirror_add(bd->cw);
+             evas_object_event_callback_add(img, EVAS_CALLBACK_DEL,
+                                            _ibar_cb_icon_menu_img_del, it);
+             txt = e_border_name_get(bd);
+             w = bd->cw->pw;
+             h = bd->cw->ph;
+             e_popup_object_add(ic->menu->win, img);
+             evas_object_show(img);
+             edje_extern_object_aspect_set(img, EDJE_ASPECT_CONTROL_BOTH, w, 
h);
+             edje_object_part_swallow(it, "e.swallow.icon", img);
+             edje_object_part_text_set(it, "e.text.title", txt);
+             edje_object_calc_force(it);
+             edje_object_size_min_calc(it, &w, &h);
+             edje_extern_object_min_size_set(it, w, h);
+             evas_object_size_hint_min_set(it, w, h);
+             evas_object_show(it);
+             evas_object_event_callback_add(it, EVAS_CALLBACK_MOUSE_UP,
+               _ibar_cb_icon_menu_mouse_up, bd);
+             evas_object_data_set(it, "ibar_icon", ic);
+             edje_object_part_box_append(o, "e.box", it);
+          }
      }
    if (!ic->menu->win->objects)
      {
@@ -1293,35 +1308,56 @@ _ibar_cb_icon_reset(void *data)
 static void
 _ibar_cb_icon_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj 
__UNUSED__, void *event_info)
 {
-   Evas_Event_Mouse_Wheel *ev;
+   Evas_Event_Mouse_Wheel *ev = event_info;
    E_Exec_Instance *exe;
-   IBar_Icon *ic;
+   IBar_Icon *ic = data;
+   E_Border *cur, *sel = NULL;
+   Eina_List *l;
 
-   ev = event_info;
-   ic = data;
-
    if (!ic->exes) return;
 
+   cur = e_border_focused_get();
    if (!ic->exe_current)
-     ic->exe_current = eina_list_nth_list(ic->exes, 0);
-
+     ic->exe_current = ic->exes;
+
+   exe = eina_list_data_get(ic->exe_current);
    if (ev->z < 0)
-     {
-        ic->exe_current = eina_list_next(ic->exe_current);
-        if (!ic->exe_current)
-          ic->exe_current = eina_list_nth_list(ic->exes, 0);
+     {
+        if (cur->exe_inst == exe)
+          {
+             l = eina_list_data_find_list(exe->borders, cur);
+             if (l) sel = eina_list_data_get(eina_list_next(l));
+          }
+        if (!sel)
+          {
+             ic->exe_current = eina_list_next(ic->exe_current);
+             if (!ic->exe_current)
+               ic->exe_current = ic->exes;
+          }
      }
    else if (ev->z > 0)
      {
-        ic->exe_current = eina_list_prev(ic->exe_current);
-        if (!ic->exe_current)
-          ic->exe_current = eina_list_last(ic->exes);
+        if (cur->exe_inst == exe)
+          {
+             l = eina_list_data_find_list(exe->borders, cur);
+             if (l) sel = eina_list_data_get(eina_list_prev(l));
+          }
+        if (!sel)
+          {
+             ic->exe_current = eina_list_prev(ic->exe_current);
+             if (!ic->exe_current)
+               ic->exe_current = eina_list_last(ic->exes);
+          }
+     }
+
+   if (!sel)
+     {
+        exe = eina_list_data_get(ic->exe_current);
+        sel = eina_list_data_get(exe->borders);
      }
 
-   exe = eina_list_data_get(ic->exe_current);
-
-   if (!exe->bd) return;
-   e_border_activate(exe->bd, 1);
+   if (sel)
+     e_border_activate(sel, 1);
 }
 
 static void
@@ -2237,14 +2273,52 @@ _ibar_cb_exec_del(void *d EINA_UNUSED, int t 
EINA_UNUSED, E_Exec_Instance *exe)
 }
 
 static Eina_Bool
-_ibar_cb_exec_new(void *d EINA_UNUSED, int t EINA_UNUSED, E_Exec_Instance *exe)
+_ibar_cb_exec_new_client(void *d EINA_UNUSED, int t EINA_UNUSED, 
E_Exec_Instance *exe)
 {
    IBar *b;
+   E_Border *bd;
    Eina_List *l;
    Eina_Bool skip;
 
    if (!exe->desktop) return ECORE_CALLBACK_RENEW; //can't do anything here :(
-   skip = exe->bd && exe->bd->client.netwm.state.skip_taskbar;
+   bd = eina_list_last_data_get(exe->borders); //only care about last (new) one
+   skip = bd->client.netwm.state.skip_taskbar;
+   EINA_LIST_FOREACH(ibars, l, b)
+     {
+        IBar_Icon *ic;
+
+        ic = eina_hash_find(b->icon_hash, _desktop_name_get(exe->desktop));
+        if (ic)
+          {
+             _ibar_icon_signal_emit(ic, "e,state,started", "e");
+             if (!ic->exes) _ibar_icon_signal_emit(ic, "e,state,on", "e");
+             if (skip) continue;
+             if (!eina_list_data_find(ic->exes, exe))
+               ic->exes = eina_list_append(ic->exes, exe);
+          }
+        else if (!b->inst->ci->dont_add_nonorder)
+          {
+             if (skip) continue;
+             _ibar_sep_create(b);
+             ic = _ibar_icon_notinorder_new(b, exe);
+             _ibar_resize_handle(b);
+          }
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_ibar_cb_exec_new(void *d EINA_UNUSED, int t EINA_UNUSED, E_Exec_Instance *exe)
+{
+   IBar *b;
+   E_Border *bd;
+   Eina_List *l;
+   Eina_Bool skip = EINA_TRUE;
+
+   if (!exe->desktop) return ECORE_CALLBACK_RENEW; //can't do anything here :(
+   EINA_LIST_FOREACH(exe->borders, l, bd)
+     if (!bd->client.netwm.state.skip_taskbar)
+       skip = EINA_FALSE;
    EINA_LIST_FOREACH(ibars, l, b)
      {
         IBar_Icon *ic;
@@ -2325,6 +2399,8 @@ e_modapi_init(E_Module *m)
                          _ibar_cb_config_icons, NULL);
    E_LIST_HANDLER_APPEND(ibar_config->handlers, E_EVENT_EXEC_NEW,
                          _ibar_cb_exec_new, NULL);
+   E_LIST_HANDLER_APPEND(ibar_config->handlers, E_EVENT_EXEC_NEW_CLIENT,
+                         _ibar_cb_exec_new_client, NULL);
    E_LIST_HANDLER_APPEND(ibar_config->handlers, E_EVENT_EXEC_DEL,
                          _ibar_cb_exec_del, NULL);
    E_LIST_HANDLER_APPEND(ibar_config->handlers, E_EVENT_BORDER_PROPERTY,

-- 

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk

Reply via email to