Added initial test case framework
authorMinJeong Kim <minjjj.kim@samsung.com>
Fri, 23 Jan 2015 07:48:25 +0000 (16:48 +0900)
committerBoram Park <boram1288.park@samsung.com>
Wed, 18 Mar 2015 04:03:08 +0000 (13:03 +0900)
1. Visibility calculation with comp_object status.
2. Added e_test_helper for supporting external TC modules through dbus

Change-Id: Ib994d99e179579c97aa7a59ccfa63b9bb3ea7d4d
Signed-off-by: MinJeong Kim <minjjj.kim@samsung.com>
18 files changed:
data/Makefile.mk
data/dbus/Makefile.mk [new file with mode: 0644]
data/dbus/org.enlightenment.wm.conf [new file with mode: 0644]
packaging/enlightenment.spec
src/bin/Makefile.mk
src/bin/e_atoms.c
src/bin/e_atoms.h
src/bin/e_client.c
src/bin/e_client.h
src/bin/e_comp_object.c
src/bin/e_comp_object.h
src/bin/e_comp_x.c
src/bin/e_hints.c
src/bin/e_hints.h
src/bin/e_includes.h
src/bin/e_main.c
src/bin/e_test_helper.c [new file with mode: 0644]
src/bin/e_test_helper.h [new file with mode: 0644]

index 783744b298b6204718558f5eb6fac5fc7bfde235..4d85fbf4ce84a3fb5c26ddd6ac9e7d0224cf2eab 100644 (file)
@@ -9,3 +9,4 @@ include data/flags/Makefile.mk
 include data/favorites/Makefile.mk
 include data/desktop/Makefile.mk
 include data/units/Makefile.mk
+include data/dbus/Makefile.mk
diff --git a/data/dbus/Makefile.mk b/data/dbus/Makefile.mk
new file mode 100644 (file)
index 0000000..06008a8
--- /dev/null
@@ -0,0 +1,3 @@
+dbusfilesdir = /etc/dbus-1/system.d
+dbusfiles_DATA = data/dbus/org.enlightenment.wm.conf
+EXTRA_DIST += $(dbusfiles_DATA)
diff --git a/data/dbus/org.enlightenment.wm.conf b/data/dbus/org.enlightenment.wm.conf
new file mode 100644 (file)
index 0000000..868d78f
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+    <policy user="root">
+        <allow own="org.enlightenment.wm"/>
+    </policy>
+    <policy at_console="true">
+        <allow send_destination="org.enlightenment.wm"/>
+    </policy>
+    <policy context="default">
+        <allow send_destination="org.enlightenment.wm"/>
+    </policy>
+</busconfig>
index fc221fadaa334d740e6407e6549dbaa4650aad00..fb9ddc302b8640cbbcced95c7c77790266a4381c 100644 (file)
@@ -76,6 +76,7 @@ make %{?_smp_mflags}
 
 mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/
 mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/graphical.target.wants
+mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d
 install -m 0644 %{SOURCE1002} %{buildroot}%{_prefix}/lib/systemd/system/
 ln -sf ../enlightenment.service %{buildroot}%{_prefix}/lib/systemd/system/graphical.target.wants
 rm -f %{buildroot}%{_prefix}/lib/systemd/user/enlightenment.service
@@ -99,6 +100,7 @@ rm -f %{buildroot}%{_prefix}/lib/systemd/user/enlightenment.service
 %{_datadir}/applications/enlightenment_filemanager.desktop
 %{_prefix}/lib/systemd/system/enlightenment.service
 %{_prefix}/lib/systemd/system/graphical.target.wants/enlightenment.service
+%{_sysconfdir}/dbus-1/system.d/org.enlightenment.wm.conf
 %exclude /usr/share/enlightenment/data/config/profile.cfg
 
 %files devel
index 8d85ba16cdbe4cf9df15e5a5770e336a12c75555..4b0d13fe9fb93a0f290a88c2bf151e1f8c08e4e7 100644 (file)
@@ -157,6 +157,7 @@ src/bin/e_spectrum.h \
 src/bin/e_startup.h \
 src/bin/e_sys.h \
 src/bin/e_test.h \
+src/bin/e_test_helper.h \
 src/bin/e_theme_about.h \
 src/bin/e_theme.h \
 src/bin/e_thumb.h \
@@ -320,6 +321,7 @@ src/bin/e_spectrum.c \
 src/bin/e_startup.c \
 src/bin/e_sys.c \
 src/bin/e_test.c \
+src/bin/e_test_helper.c \
 src/bin/e_theme_about.c \
 src/bin/e_theme.c \
 src/bin/e_thumb.c \
index a84c7591cd762ac20191dbd4d1b82a36866742fc..bdd917c938cd31548542d98ceeffec250daaa98c 100644 (file)
@@ -11,6 +11,7 @@ EAPI Ecore_X_Atom E_ATOM_HIDDEN = 0;
 EAPI Ecore_X_Atom E_ATOM_BORDER_SIZE = 0;
 EAPI Ecore_X_Atom E_ATOM_WINDOW_STATE = 0;
 EAPI Ecore_X_Atom E_ATOM_WINDOW_STATE_CENTERED = 0;
+EAPI Ecore_X_Atom E_ATOM_WINDOW_OPAQUE = 0;
 EAPI Ecore_X_Atom E_ATOM_DESKTOP_FILE = 0;
 EAPI Ecore_X_Atom E_ATOM_ZONE_GEOMETRY = 0;
 #endif
@@ -30,10 +31,11 @@ e_atoms_init(void)
       "__E_WINDOW_BORDER_SIZE",
       "__E_ATOM_WINDOW_STATE",
       "__E_ATOM_WINDOW_STATE_CENTERED",
+      "__E_ATOM_WINDOW_OPAQUE",
       "__E_ATOM_DESKTOP_FILE",
       "E_ZONE_GEOMETRY"
    };
-   Ecore_X_Atom atoms[11];
+   Ecore_X_Atom atoms[12];
 
    ecore_x_atoms_get(atom_names, 11, atoms);
    E_ATOM_MANAGED = atoms[0];
@@ -45,8 +47,9 @@ e_atoms_init(void)
    E_ATOM_BORDER_SIZE = atoms[6];
    E_ATOM_WINDOW_STATE = atoms[7];
    E_ATOM_WINDOW_STATE_CENTERED = atoms[8];
-   E_ATOM_DESKTOP_FILE = atoms[9];
-   E_ATOM_ZONE_GEOMETRY = atoms[10];
+   E_ATOM_WINDOW_OPAQUE = atoms[9];
+   E_ATOM_DESKTOP_FILE = atoms[10];
+   E_ATOM_ZONE_GEOMETRY = atoms[11];
 #endif
    return 1;
 }
index d01b364f4363d20ba4357ce4eb85d66275125367..2187270c9321e53505362ebf3b55795b1c9dc811 100644 (file)
@@ -23,6 +23,8 @@ extern EAPI Ecore_X_Atom E_ATOM_DESKTOP_FILE;
 extern EAPI Ecore_X_Atom E_ATOM_WINDOW_STATE;
 extern EAPI Ecore_X_Atom E_ATOM_WINDOW_STATE_CENTERED;
 
+extern EAPI Ecore_X_Atom E_ATOM_WINDOW_OPAQUE;
+
 extern EAPI Ecore_X_Atom E_ATOM_ZONE_GEOMETRY;
 
 EINTERN int    e_atoms_init(void);
index ff0a1946edd6258db5416a693d9fbdbd3f446321..1f5a54ad16914720e7818ce5b90c6e510c7eb1e0 100644 (file)
@@ -24,6 +24,7 @@ EAPI int E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN = -1;
 EAPI int E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = -1;
 EAPI int E_EVENT_CLIENT_ROTATION_CHANGE_END = -1;
 #endif
+EAPI int E_EVENT_CLIENT_VISIBILITY_CHANGE = -1;
 
 static Eina_Hash *clients_hash = NULL; // pixmap->client
 
@@ -2316,6 +2317,139 @@ _e_client_type_get(E_Client *ec)
    return ec->client_type;
 }
 
+static void
+_e_client_visibility_zone_calculate(E_Zone *zone)
+{
+   E_Client *ec;
+   Evas_Object *o;
+   Eina_Tiler *t;
+   Eina_Rectangle r, *_r;
+   Eina_Iterator *itr;
+   Eina_Bool is_intersected = EINA_FALSE;
+   const int edge = 1;
+
+   if (!zone) return;
+
+   t = eina_tiler_new(zone->w + edge, zone->h + edge);
+   eina_tiler_tile_size_set(t, 1, 1);
+
+   EINA_RECTANGLE_SET(&r, zone->x, zone->y, zone->w, zone->h);
+   eina_tiler_rect_add(t, &r);
+
+   for (o = evas_object_top_get(zone->comp->evas); o; o = evas_object_below_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+
+        /* check e_client and skip e_clients not intersects with zone */
+        if (!ec) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+        if (ec->zone != zone) continue;
+        if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
+                          zone->x, zone->y, zone->w, zone->h))
+          continue;
+
+        /* check if internal animation is running */
+        if (e_comp_object_is_animating(ec->frame)) continue;
+
+        /* check if external animation is running */
+        if (evas_object_data_get(ec->frame, "effect_running")) continue;
+
+        /* check intersects */
+        if (eina_tiler_empty(t)) is_intersected = EINA_FALSE;
+
+        itr = eina_tiler_iterator_new(t);
+        EINA_ITERATOR_FOREACH(itr, _r)
+          {
+             if (E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
+                              _r->x, _r->y, _r->w, _r->h))
+               {
+                  is_intersected = EINA_TRUE;
+                  break;
+               }
+          }
+        eina_iterator_free(itr);
+
+        /* check some visible state */
+        if ((!ec->visible) || (ec->iconic) ||
+            (!evas_object_visible_get(ec->frame)) ||
+            (e_object_is_del(E_OBJECT(ec))))
+          is_intersected = EINA_FALSE;
+
+#ifndef HAVE_WAYLAND_ONLY
+        /* check if it entered to hide process
+         * TODO: support wayland
+         */
+        if (ec->icccm.state ==  ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
+          is_intersected = EINA_FALSE;
+#endif
+        if (is_intersected)
+          {
+             Eina_Bool opaque = EINA_FALSE;
+             /* unobscured case */
+             if (ec->visibility.obscured == 0)
+               {
+                  /* previous state is unobscured */
+                  /* do nothing */
+               }
+             else
+               {
+                  /* previous state is obscured */
+                  ec->visibility.obscured = 0;
+                  _e_client_event_simple(ec, E_EVENT_CLIENT_VISIBILITY_CHANGE);
+               }
+
+             /* check alpha window is opaque or not. */
+             if ((ec->visibility.opaque > 0) && (ec->argb)) opaque = EINA_TRUE;
+
+             /* if e_client is not alpha or opaque then delete intersect rect */
+             if ((!ec->argb) || (opaque))
+               {
+                  EINA_RECTANGLE_SET(&r,
+                                     ec->x, ec->y,
+                                     ec->w + edge, ec->h + edge);
+                  eina_tiler_rect_del(t, &r);
+               }
+          }
+        else
+          {
+             /* obscured case */
+             if (ec->visibility.obscured != 1)
+               {
+                  /* previous state is unobscured */
+                  ec->visibility.obscured = 1;
+                  _e_client_event_simple(ec, E_EVENT_CLIENT_VISIBILITY_CHANGE);
+               }
+             else
+               {
+                  /* previous state is obscured */
+                  /* do nothing */
+               }
+          }
+     }
+
+   eina_tiler_free(t);
+}
+
+EAPI void
+e_client_visibility_calculate(E_Client *ec)
+{
+   const Eina_List *cl;
+   E_Comp *c;
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   EINA_LIST_FOREACH(e_comp_list(), cl, c)
+     {
+        E_Zone *zone;
+        Eina_List *zl;
+
+        EINA_LIST_FOREACH(c->zones, zl, zone)
+          {
+             _e_client_visibility_zone_calculate(zone);
+          }
+     }
+}
+
 ////////////////////////////////////////////////
 EINTERN void
 e_client_idler_before(void)
@@ -2347,6 +2481,9 @@ e_client_idler_before(void)
         if (client_type != _e_client_type_get(ec))
            _e_client_event_property(ec, E_CLIENT_PROPERTY_CLIENT_TYPE);
 
+        /* calculate visibility of the client" */
+        e_client_visibility_calculate(ec);
+
         /* PRE_POST_FETCH calls e_remember apply for new client */
         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, ec)) continue;
         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_FETCH, ec)) continue;
@@ -2446,6 +2583,7 @@ e_client_init(void)
    E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
    E_EVENT_CLIENT_ROTATION_CHANGE_END = ecore_event_type_new();
 #endif
+   E_EVENT_CLIENT_VISIBILITY_CHANGE = ecore_event_type_new();
 
    return (!!clients_hash);
 }
@@ -2560,6 +2698,9 @@ e_client_new(E_Comp *c EINA_UNUSED, E_Pixmap *cp, int first_map, int internal)
    ec->netwm.action.close = 0;
    ec->netwm.opacity = 255;
 
+   ec->visibility.obscured = -1;
+   ec->visibility.opaque = -1;
+
    EC_CHANGED(ec);
 
    e_comp->clients = eina_list_append(e_comp->clients, ec);
index 527b3707d0e96e8a6fe2cac666212dce5365b945..7126d77b23d8c417bb7dfa6321255dcaabd14f1a 100644 (file)
@@ -583,6 +583,7 @@ struct E_Client
          } rot;
 #endif
          unsigned char state : 1;
+         unsigned char opaque : 1;
          unsigned char video_parent : 1;
          unsigned char video_position : 1;
          unsigned char profile : 1;
@@ -640,6 +641,12 @@ struct E_Client
 #endif
    } changes;
 
+   struct
+  {
+     int opaque;
+     int obscured;
+  } visibility;
+
    unsigned int       visible : 1; // client is set to be visible by display server (never use this)
    unsigned int       hidden : 1; // set when window has been hidden by api and should not be shown
    unsigned int       moving : 1;
@@ -813,6 +820,7 @@ EAPI extern int E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN;
 EAPI extern int E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL;
 EAPI extern int E_EVENT_CLIENT_ROTATION_CHANGE_END;
 #endif
+EAPI extern int E_EVENT_CLIENT_VISIBILITY_CHANGE;
 
 EINTERN void e_client_idler_before(void);
 EINTERN Eina_Bool e_client_init(void);
@@ -895,6 +903,7 @@ EAPI Eina_Bool e_client_is_stacking(const E_Client *ec);
 EAPI Eina_Bool e_client_desk_window_profile_available_check(E_Client *ec, const char *profile);
 EAPI void      e_client_desk_window_profile_wait_desk_set(E_Client *ec, E_Desk *desk);
 EAPI void      e_client_layout_cb_set(E_Client_Layout_Cb cb);
+EAPI void      e_client_visibility_calculate(E_Client *ec);
 
 YOLO EAPI void e_client_focus_stack_set(Eina_List *l);
 
index 6e30bb03e47fd4b1a2e4453f89a69439f33e6276..0bd7f2ca4bc124a886477c288534fc357c97b13d 100644 (file)
@@ -3623,11 +3623,16 @@ _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission,
           e_comp_shape_queue(cw->comp);
      }
 
+   if (evas_object_data_get(cw->smart_obj, "effect_running"))
+     {
+        evas_object_data_del(cw->smart_obj, "effect_running");
+        e_client_visibility_calculate(cw->ec);
+     }
+
    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
    if (!end_cb) return;
    end_data = evas_object_data_get(obj, "_e_comp.end_data");
    end_cb(end_data, cw->smart_obj, emission, source);
-
 }
 
 /* clip effect to client's zone */
@@ -3664,6 +3669,7 @@ e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *
    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
+   evas_object_data_set(cw->smart_obj, "effect_running", (void*)1);
 
    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
    if (cw->animating) return;
@@ -3692,6 +3698,12 @@ e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
         cw->comp->animating--;
         e_object_unref(E_OBJECT(cw->ec));
      }
+
+   if (evas_object_data_get(cw->smart_obj, "effect_running"))
+     {
+        evas_object_data_del(cw->smart_obj, "effect_running");
+        e_client_visibility_calculate(cw->ec);
+     }
 }
 
 static int
@@ -3837,3 +3849,11 @@ e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb
      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
 }
+
+EAPI unsigned int
+e_comp_object_is_animating(Evas_Object *obj)
+{
+   SOFT_ENTRY(0);
+
+   return cw->animating;
+}
index 5368102eb17a0dd4e9df85e3644cb6cef4cb3335..1b37f2d101e468dcd8bc1d951691e14ced4ea0e8 100644 (file)
@@ -107,6 +107,7 @@ EAPI void e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov);
 EAPI E_Comp_Object_Intercept_Hook *e_comp_object_intercept_hook_add(E_Comp_Object_Intercept_Hook_Point hookpoint, E_Comp_Object_Intercept_Hook_Cb func, const void *data);
 EAPI void e_comp_object_intercept_hook_del(E_Comp_Object_Intercept_Hook *ch);
 #endif
+EAPI unsigned int e_comp_object_is_animating(Evas_Object *obj);
 
 #endif
 #endif
index 27523fd7d521c803a983ad6445e3ba2860ca3533..bf04fed8708452ec8bc0a1d95a27e050fa2a0261 100644 (file)
@@ -310,6 +310,10 @@ _e_comp_x_client_new_helper(E_Client *ec)
                {
                   ec->e.fetch.state = 1;
                }
+             if (atoms[i] == E_ATOM_WINDOW_OPAQUE)
+               {
+                  ec->e.fetch.opaque = 1;
+               }
              /* loop to check for qtopia atoms */
              if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
                ec->qtopia.fetch.soft_menu = 1;
@@ -1800,6 +1804,11 @@ _e_comp_x_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_W
      {
         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
      }
+  else if (ev->atom == E_ATOM_WINDOW_OPAQUE)
+     {
+        ec->e.fetch.opaque = 1;
+        EC_CHANGED(ec);
+     }
    else if (ev->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
      {
         ec->e.fetch.video_position = 1;
@@ -2930,6 +2939,12 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
         ec->e.fetch.state = 0;
         rem_change = 1;
      }
+   if (ec->changes.prop || ec->e.fetch.opaque)
+     {
+        e_hints_window_e_opaque_get(ec);
+        ec->e.fetch.opaque = 0;
+        rem_change = 1;
+     }
    if (ec->e.fetch.profile)
      {
         const char **list = NULL;
index 8481f8beac9277c6b64b77307c106bd5b35e4fe4..5fd73cb8ff8733522f2842a629bf146c7704ae9f 100644 (file)
@@ -1601,6 +1601,27 @@ e_hints_window_e_state_set(E_Client *ec __UNUSED__)
    /* TODO */
 }
 
+EAPI void
+e_hints_window_e_opaque_get(E_Client *ec)
+{
+#ifdef HAVE_WAYLAND_ONLY
+#else
+   unsigned int opaque;
+   int ret = -1;
+
+   if (!e_pixmap_is_x(ec->pixmap)) return;
+
+   ret =
+     ecore_x_window_prop_card32_get(e_client_util_win_get(ec), E_ATOM_WINDOW_OPAQUE,
+                                    &opaque, 1);
+   if (ret == -1)
+     ec->visibility.opaque = -1;
+   else
+     ec->visibility.opaque = (int)opaque;
+
+#endif
+}
+
 EAPI void
 e_hints_window_qtopia_soft_menu_get(E_Client *ec)
 {
index a0c5f9a1ec17369a7a4c629b4f5f2543720058b2..8e3c9c72ae42eac04c3dbaa9bdc73fdcf8fdacb2 100644 (file)
@@ -37,6 +37,8 @@ EAPI void e_hints_window_desktop_set(E_Client *ec);
 EAPI void e_hints_window_e_state_set(E_Client *ec);
 EAPI void e_hints_window_e_state_get(E_Client *ec);
 
+EAPI void e_hints_window_e_opaque_get(E_Client *ec);
+
 EAPI void e_hints_window_qtopia_soft_menu_get(E_Client *ec);
 EAPI void e_hints_window_qtopia_soft_menus_get(E_Client *ec);
 
index 832a7d2a025a765282a7c2b2b94cd8eb0019e4ac..61d5f6429e7856178dab9581ff19877576706e75 100644 (file)
@@ -42,6 +42,7 @@
 #include "e_gadcon_popup.h"
 #include "e_ipc_codec.h"
 #include "e_test.h"
+#include "e_test_helper.h"
 #include "e_prefix.h"
 #include "e_datastore.h"
 #include "e_msg.h"
index d7bb2c1baa6919f87f642f2706004649ef5e3432..e789c8131b8431b472062a693d412c9d537744b9 100644 (file)
@@ -1023,6 +1023,11 @@ main(int argc, char **argv)
    e_test();
    TS("E_Test Done");
 
+   TS("E_Test_Helper Init");
+   e_test_helper_init();
+   _e_main_shutdown_push(e_test_helper_shutdown);
+   TS("E_Test_Helper Done");
+
    if (e_config->show_splash)
      e_init_status_set(_("Setup Shelves"));
    TS("E_Shelf Init");
diff --git a/src/bin/e_test_helper.c b/src/bin/e_test_helper.c
new file mode 100644 (file)
index 0000000..f029136
--- /dev/null
@@ -0,0 +1,427 @@
+#include "e.h"
+
+#define BUS "org.enlightenment.wm"
+#define PATH "/org/enlightenment/wm"
+#define IFACE "org.enlightenment.wm.Test"
+
+typedef struct _Test_Helper_Data
+{
+   Eldbus_Connection *conn;
+   Eldbus_Service_Interface *iface;
+
+   Eina_List *hdlrs;
+
+   struct
+     {
+        Ecore_Window win;
+        E_Client *ec;
+        int vis;
+        Eina_Bool disuse;
+     } registrant;
+
+} Test_Helper_Data;
+
+static Test_Helper_Data *th_data = NULL;
+
+static Eina_Bool _e_test_helper_cb_property_get(const Eldbus_Service_Interface *iface, const char *name, Eldbus_Message_Iter *iter, const Eldbus_Message *msg, Eldbus_Message **err);
+
+static Eldbus_Message* _e_test_helper_cb_register_window(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
+static Eldbus_Message* _e_test_helper_cb_deregister_window(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
+static Eldbus_Message* _e_test_helper_cb_change_stack(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
+static Eldbus_Message* _e_test_helper_cb_get_clients(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
+
+enum
+{
+   E_TEST_HELPER_SIGNAL_CHANGE_VISIBILITY = 0,
+   E_TEST_HELPER_SIGNAL_RESTACK,
+};
+
+static const Eldbus_Signal signals[] = {
+     [E_TEST_HELPER_SIGNAL_CHANGE_VISIBILITY] =
+       {
+          "ChangeVisibility",
+          ELDBUS_ARGS({"ub", "window id, visibility"}),
+          0
+       },
+     [E_TEST_HELPER_SIGNAL_RESTACK] =
+       {
+          "Restack",
+          ELDBUS_ARGS({"u", "window id was restacked"}),
+          0
+       },
+       { }
+};
+
+static const Eldbus_Method methods[] ={
+       {
+          "RegisterWindow",
+          ELDBUS_ARGS({"u", "window id to be registered"}),
+          ELDBUS_ARGS({"b", "accept or not"}),
+          _e_test_helper_cb_register_window, 0
+       },
+       {
+          "DeregisterWindow",
+          ELDBUS_ARGS({"u", "window id to be deregistered"}),
+          ELDBUS_ARGS({"b", "accept or not"}),
+          _e_test_helper_cb_deregister_window, 0
+       },
+       {
+          "ChangeStack",
+          ELDBUS_ARGS({"uiu", "window id to restack, stacking type, above or below"}),
+          NULL,
+          _e_test_helper_cb_change_stack, 0
+       },
+       {
+          "GetClients",
+          NULL,
+          ELDBUS_ARGS({"ua(usiiiiibb)", "array of ec"}),
+          _e_test_helper_cb_get_clients, 0
+       },
+       { }
+};
+
+static const Eldbus_Property properties[] = {
+       { "Registrant", "u", NULL, NULL, 0 },
+       { }
+};
+
+static const Eldbus_Service_Interface_Desc iface_desc = {
+     IFACE, methods, signals, properties, _e_test_helper_cb_property_get, NULL
+};
+
+static void
+_e_test_helper_registrant_clear(void)
+{
+   EINA_SAFETY_ON_NULL_RETURN(th_data);
+
+   th_data->registrant.win = 0;
+   th_data->registrant.vis = -1;
+   th_data->registrant.ec = NULL;
+   th_data->registrant.disuse = EINA_FALSE;
+}
+
+static void
+_e_test_helper_message_append_clients(Eldbus_Message_Iter *iter)
+{
+   Eldbus_Message_Iter *array_of_ec;
+   E_Client *ec;
+   Evas_Object *o;
+   E_Comp *comp;
+
+   EINA_SAFETY_ON_NULL_RETURN(th_data);
+
+   if (!(comp = e_comp_get(NULL))) return;
+
+   eldbus_message_iter_arguments_append(iter, "ua(usiiiiibb)", th_data->registrant.win, &array_of_ec);
+
+   // append clients.
+   for (o = evas_object_top_get(comp->evas); o; o = evas_object_below_get(o))
+     {
+        Eldbus_Message_Iter* struct_of_ec;
+        Ecore_Window win;
+
+        ec = evas_object_data_get(o, "E_Client");
+        if (!ec) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+
+        win = e_client_util_win_get(ec);
+        eldbus_message_iter_arguments_append(array_of_ec, "(usiiiiibb)", &struct_of_ec);
+        eldbus_message_iter_arguments_append
+           (struct_of_ec, "usiiiiibb",
+            win,
+            e_client_util_name_get(ec) ?: ec->icccm.name,
+            ec->x, ec->y, ec->w, ec->h, ec->layer,
+            ec->visible, ec->argb);
+        eldbus_message_iter_container_close(array_of_ec, struct_of_ec);
+     }
+
+   eldbus_message_iter_container_close(iter, array_of_ec);
+}
+
+static void
+_e_test_helper_restack(Ecore_Window win, int stacking, Ecore_Window target)
+{
+   E_Client *ec, *tec;
+
+   ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, win);
+   tec = e_pixmap_find_client(E_PIXMAP_TYPE_X, target);
+
+   if (!ec) return;
+
+   /* TODO: focus setting */
+   switch(stacking)
+     {
+      case 0:
+         evas_object_raise(ec->frame);
+         break;
+      case 1:
+         evas_object_lower(ec->frame);
+         break;
+      case 2:
+         if (tec)
+           evas_object_stack_above(ec->frame, tec->frame);
+         break;
+      case 3:
+         if (tec)
+           evas_object_stack_below(ec->frame, tec->frame);
+         break;
+      default:
+         break;
+     }
+}
+
+/* Signal senders */
+static void
+_e_test_helper_send_change_visibility(Ecore_Window win, Eina_Bool vis)
+{
+   Eldbus_Message *signal;
+
+   EINA_SAFETY_ON_NULL_RETURN(th_data);
+
+   signal = eldbus_service_signal_new(th_data->iface,
+                                      E_TEST_HELPER_SIGNAL_CHANGE_VISIBILITY);
+   eldbus_message_arguments_append(signal, "ub", win, vis);
+   eldbus_service_signal_send(th_data->iface, signal);
+}
+
+/* Method Handlers */
+static Eldbus_Message *
+_e_test_helper_cb_register_window(const Eldbus_Service_Interface *iface EINA_UNUSED,
+                                  const Eldbus_Message *msg)
+{
+   Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+   Ecore_Window id;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, reply);
+
+   if (!eldbus_message_arguments_get(msg, "u", &id))
+     {
+        ERR("Error on eldbus_message_arguments_get()\n");
+        return reply;
+     }
+
+   eldbus_message_arguments_append(reply, "b", !th_data->registrant.win);
+   if (!th_data->registrant.win) th_data->registrant.win = id;
+
+   return reply;
+}
+
+static Eldbus_Message *
+_e_test_helper_cb_deregister_window(const Eldbus_Service_Interface *iface EINA_UNUSED,
+                                    const Eldbus_Message *msg)
+{
+   Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+   Ecore_Window id;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, reply);
+
+   if (!eldbus_message_arguments_get(msg, "u", &id))
+     {
+        ERR("Error on eldbus_message_arguments_get()\n");
+        return reply;
+     }
+   eldbus_message_arguments_append(reply, "b", (th_data->registrant.win == id) && (th_data->registrant.vis != 1));
+
+   if (th_data->registrant.win == id)
+     {
+        th_data->registrant.disuse = EINA_TRUE;
+
+        if (th_data->registrant.ec) evas_object_hide(th_data->registrant.ec->frame);
+        if (th_data->registrant.vis != 1) _e_test_helper_registrant_clear();
+     }
+
+   return reply;
+}
+
+static Eldbus_Message*
+_e_test_helper_cb_change_stack(const Eldbus_Service_Interface *iface EINA_UNUSED,
+                               const Eldbus_Message *msg)
+{
+   Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+   Ecore_Window win, target;
+   int stacking = -1;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, reply);
+
+   if (!eldbus_message_arguments_get(msg, "uiu", &win, &stacking, &target))
+     {
+        ERR("error on eldbus_message_arguments_get()\n");
+        return reply;
+     }
+
+   if ((win) && (stacking != -1))
+     _e_test_helper_restack(win, stacking, target);
+
+   return reply;
+}
+
+static Eldbus_Message *
+_e_test_helper_cb_get_clients(const Eldbus_Service_Interface *iface EINA_UNUSED,
+                              const Eldbus_Message *msg)
+{
+   Eldbus_Message *reply;
+
+   reply = eldbus_message_method_return_new(msg);
+   _e_test_helper_message_append_clients(eldbus_message_iter_get(reply));
+
+   return reply;
+}
+
+static void
+_e_test_helper_cb_name_request(void *data EINA_UNUSED,
+                               const Eldbus_Message *msg,
+                               Eldbus_Pending *pending EINA_UNUSED)
+{
+   unsigned int flag;
+   const char *errname, *errmsg;
+
+   if (eldbus_message_error_get(msg, &errname, &errmsg))
+     {
+        ERR("error on _e_test_helper_cb_name_request %s %s\n", errname, errmsg);
+        e_test_helper_shutdown();
+        return;
+     }
+
+   if (!eldbus_message_arguments_get(msg, "u", &flag))
+     {
+        ERR("error geting arguments on _e_test_helper_cb_name_request\n");
+        e_test_helper_shutdown();
+        return;
+     }
+
+   if (flag != ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER)
+     {
+        ERR("error name already in use\n");
+        e_test_helper_shutdown();
+     }
+}
+
+static Eina_Bool
+_e_test_helper_cb_visibility_change(void *data EINA_UNUSED,
+                                    int type EINA_UNUSED,
+                                    void *event)
+{
+   E_Client *ec;
+   Ecore_Window win = 0;
+   E_Event_Client *ev = event;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+   win = e_client_util_win_get(ec);
+
+   if (!th_data->registrant.win) return ECORE_CALLBACK_PASS_ON;
+   if (win != th_data->registrant.win) return ECORE_CALLBACK_PASS_ON;
+
+   if (!th_data->registrant.ec)
+     th_data->registrant.ec = ec;
+
+   if (th_data->registrant.vis != !ec->visibility.obscured)
+     _e_test_helper_send_change_visibility(th_data->registrant.win, !ec->visibility.obscured);
+
+   th_data->registrant.vis = !ec->visibility.obscured;
+
+   if ((th_data->registrant.disuse) && (!th_data->registrant.vis))
+     _e_test_helper_registrant_clear();
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_test_helper_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Client *ec;
+   E_Event_Client *ev = event;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+
+   if (!th_data->registrant.ec) return ECORE_CALLBACK_PASS_ON;
+   if (ec != th_data->registrant.ec) return ECORE_CALLBACK_PASS_ON;
+
+   _e_test_helper_registrant_clear();
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_test_helper_cb_client_restack(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec;
+   Eldbus_Message *sig;
+   Ecore_Window win;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data->registrant.ec, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+
+   if ((win = e_client_util_win_get(ec)))
+     {
+        sig = eldbus_service_signal_new(th_data->iface, E_TEST_HELPER_SIGNAL_RESTACK);
+        eldbus_message_arguments_append(sig, "u", win);
+        eldbus_service_signal_send(th_data->iface, sig);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_test_helper_cb_property_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const char *name, Eldbus_Message_Iter *iter, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Message **err EINA_UNUSED)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(th_data, EINA_FALSE);
+
+   if (!e_util_strcmp(name, "Registrant"))
+     {
+        eldbus_message_iter_basic_append(iter, 'u', th_data->registrant.win);
+     }
+
+   return EINA_TRUE;
+}
+
+/* externally accessible functions */
+EINTERN int
+e_test_helper_init(void)
+{
+   eldbus_init();
+
+   th_data = E_NEW(Test_Helper_Data, 1);
+
+   th_data->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
+   th_data->iface = eldbus_service_interface_register(th_data->conn,
+                                                      PATH,
+                                                      &iface_desc);
+
+   eldbus_name_request(th_data->conn, BUS, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+                       _e_test_helper_cb_name_request, th_data->iface);
+
+   E_LIST_HANDLER_APPEND(th_data->hdlrs, E_EVENT_CLIENT_VISIBILITY_CHANGE,
+                         _e_test_helper_cb_visibility_change, NULL);
+   E_LIST_HANDLER_APPEND(th_data->hdlrs, E_EVENT_CLIENT_REMOVE,
+                         _e_test_helper_cb_client_remove, NULL);
+   E_LIST_HANDLER_APPEND(th_data->hdlrs, E_EVENT_CLIENT_STACK,
+                        _e_test_helper_cb_client_restack, NULL);
+
+   th_data->registrant.vis = -1;
+
+   return 1;
+}
+
+EINTERN int
+e_test_helper_shutdown(void)
+{
+   if (th_data)
+     {
+        E_FREE_LIST(th_data->hdlrs, ecore_event_handler_del);
+
+        eldbus_service_interface_unregister(th_data->iface);
+        eldbus_connection_unref(th_data->conn);
+        eldbus_shutdown();
+
+        E_FREE(th_data);
+     }
+
+   return 1;
+}
diff --git a/src/bin/e_test_helper.h b/src/bin/e_test_helper.h
new file mode 100644 (file)
index 0000000..94642b5
--- /dev/null
@@ -0,0 +1,10 @@
+#ifdef E_TYPEDEFS
+#else
+#ifndef E_TEST_HELPER_H
+#define E_TEST_HELPER_H
+
+EINTERN int e_test_helper_init(void);
+EINTERN int e_test_helper_shutdown(void);
+
+#endif
+#endif