e_slot,e_splitlayout: added to support tiling window 15/85815/6
authorJuyeon Lee <juyeonne.lee@samsung.com>
Mon, 29 Aug 2016 07:31:21 +0000 (16:31 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Mon, 29 Aug 2016 12:37:08 +0000 (05:37 -0700)
e_slot and e_splitlayout are smart object

e_slot : represents split region
         clients added on each slot will have the same geometry
         and they are raised/lowered in group.
         focus can be set on top most client in the slot.

e_splitlayout : represents a layout on canvas
         slots are added as a child object.

Change-Id: Ibfac748023a54ce85bd34bec8675229a65447c92

src/bin/Makefile.mk
src/bin/e_client.h
src/bin/e_desk.h
src/bin/e_includes.h
src/bin/e_main.c
src/bin/e_policy.c
src/bin/e_policy.h
src/bin/e_slot.c [new file with mode: 0644]
src/bin/e_slot.h [new file with mode: 0644]
src/bin/e_splitlayout.c [new file with mode: 0644]
src/bin/e_splitlayout.h [new file with mode: 0644]

index 875c648..9b92aa9 100644 (file)
@@ -71,6 +71,8 @@ src/bin/e_resist.h \
 src/bin/e_scale.h \
 src/bin/e_screensaver.h \
 src/bin/e_signals.h \
+src/bin/e_slot.h \
+src/bin/e_splitlayout.h \
 src/bin/e_test_helper.h \
 src/bin/e_theme.h \
 src/bin/e_user.h \
@@ -152,6 +154,8 @@ src/bin/e_resist.c \
 src/bin/e_scale.c \
 src/bin/e_screensaver.c \
 src/bin/e_signals.c \
+src/bin/e_slot.c \
+src/bin/e_splitlayout.c \
 src/bin/e_test_helper.c \
 src/bin/e_theme.c \
 src/bin/e_user.c \
index ea9d03e..19a9e19 100644 (file)
@@ -851,6 +851,13 @@ struct E_Client
        } parent;
    } transform_core;
 
+   struct
+   {
+      unsigned char            resizable : 1;  // or scalable
+      unsigned char            splited : 1;
+      int                      s_id;           // split(slot) id
+   } layout;
+
    Ecore_Timer *map_timer;
    Eina_Bool pointer_enter_sent;
 
index b683097..59fa66f 100644 (file)
@@ -32,7 +32,8 @@ struct _E_Desk
    int                  x, y;
    unsigned char        visible : 1;
    unsigned int         deskshow_toggle : 1;
-   Eina_List            *fullscreen_clients;
+   Eina_List           *fullscreen_clients;
+   Evas_Object         *layout;      /* Desk's splitlayout*/
 
    Evas_Object         *bg_object;
 
index e98fe15..e183f01 100644 (file)
@@ -61,3 +61,5 @@
 #endif
 #include "e_policy.h"
 #include "e_process.h"
+#include "e_splitlayout.h"
+#include "e_slot.h"
index d926de5..645c5ca 100644 (file)
@@ -586,6 +586,7 @@ main(int argc, char **argv)
    e_screensaver_preinit();
    e_zone_init();
    e_desk_init();
+   e_slot_init();
 
    TRACE_DS_BEGIN(MAIN:WAIT /dev/dri/card0);
    if (e_config->sleep_for_dri)
@@ -1109,6 +1110,7 @@ _e_main_screens_shutdown(void)
    e_comp_shutdown();
    e_client_shutdown();
 
+   e_slot_shutdown();
    e_desk_shutdown();
    e_zone_shutdown();
    return 1;
index 073e222..3f5d1d4 100644 (file)
@@ -34,6 +34,8 @@ static Eina_Bool   _e_policy_client_maximize_policy_apply(E_Policy_Client *pc);
 static void        _e_policy_client_maximize_policy_cancel(E_Policy_Client *pc);
 static void        _e_policy_client_floating_policy_apply(E_Policy_Client *pc);
 static void        _e_policy_client_floating_policy_cancel(E_Policy_Client *pc);
+static void        _e_policy_client_split_policy_apply(E_Policy_Client *pc);
+static void        _e_policy_client_split_policy_cancel(E_Policy_Client *pc);
 static void        _e_policy_client_launcher_set(E_Policy_Client *pc);
 
 static void        _e_policy_cb_hook_client_eval_pre_new_client(void *d EINA_UNUSED, E_Client *ec);
@@ -155,6 +157,14 @@ _e_policy_client_normal_check(E_Client *ec)
      }
    else if (e_policy_client_is_subsurface(ec))
      goto cancel_max;
+   else if (e_policy_client_is_splited(ec))
+     {
+        E_Policy_Client *pc;
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+        _e_policy_client_split_policy_apply(pc);
+        return EINA_FALSE;
+     }
 
    if ((ec->netwm.type == E_WINDOW_TYPE_NORMAL) ||
        (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) ||
@@ -419,6 +429,124 @@ _e_policy_client_floating_policy_cancel(E_Policy_Client *pc)
      EC_CHANGED(pc->ec);
 }
 
+static void
+_e_policy_client_split_policy_apply(E_Policy_Client *pc)
+{
+   E_Client *ec;
+
+   if (!pc) return;
+   if (pc->split_policy_state) return;
+
+   pc->split_policy_state = EINA_TRUE;
+   ec = pc->ec;
+
+#undef _SET
+# define _SET(a) pc->orig.a = pc->ec->a
+   _SET(borderless);
+   _SET(fullscreen);
+   _SET(maximized);
+   _SET(lock_user_location);
+   _SET(lock_client_location);
+   _SET(lock_user_size);
+   _SET(lock_client_size);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   if (ec->remember)
+     {
+        e_remember_del(ec->remember);
+        ec->remember = NULL;
+     }
+
+   /* skip hooks of e_remeber for eval_pre_post_fetch and eval_post_new_client */
+   ec->internal_no_remember = 1;
+
+   if (!ec->borderless)
+     {
+        ec->borderless = 1;
+        ec->border.changed = 1;
+        EC_CHANGED(pc->ec);
+     }
+
+   /* do not allow client to change these properties */
+   ec->lock_user_location = 1;
+   ec->lock_client_location = 1;
+   ec->lock_user_size = 1;
+   ec->lock_client_size = 1;
+   ec->lock_user_shade = 1;
+   ec->lock_client_shade = 1;
+   ec->lock_user_maximize = 1;
+   ec->lock_client_maximize = 1;
+   ec->lock_user_fullscreen = 1;
+   ec->lock_client_fullscreen = 1;
+   ec->skip_fullscreen = 1;
+}
+
+static void
+_e_policy_client_split_policy_cancel(E_Policy_Client *pc)
+{
+   E_Client *ec;
+   Eina_Bool changed = EINA_FALSE;
+
+   if (!pc) return;
+   if (!pc->split_policy_state) return;
+
+   pc->split_policy_state = EINA_FALSE;
+   ec = pc->ec;
+
+   if (pc->orig.borderless != ec->borderless)
+     {
+        ec->border.changed = 1;
+        changed = EINA_TRUE;
+     }
+
+   if ((pc->orig.fullscreen != ec->fullscreen) &&
+       (pc->orig.fullscreen))
+     {
+        ec->need_fullscreen = 1;
+        changed = EINA_TRUE;
+     }
+
+   if (pc->orig.maximized != ec->maximized)
+     {
+        if (pc->orig.maximized)
+          ec->changes.need_maximize = 1;
+        else
+          e_client_unmaximize(ec, ec->maximized);
+
+        changed = EINA_TRUE;
+     }
+#undef _SET
+# define _SET(a) ec->a = pc->orig.a
+   _SET(borderless);
+   _SET(fullscreen);
+   _SET(maximized);
+   _SET(lock_user_location);
+   _SET(lock_client_location);
+   _SET(lock_user_size);
+   _SET(lock_client_size);
+   _SET(lock_client_stacking);
+   _SET(lock_user_shade);
+   _SET(lock_client_shade);
+   _SET(lock_user_maximize);
+   _SET(lock_client_maximize);
+   _SET(lock_user_fullscreen);
+   _SET(lock_client_fullscreen);
+#undef _SET
+
+   ec->skip_fullscreen = 0;
+
+   /* only set it if the border is changed or fullscreen/maximize has changed */
+   if (changed)
+     EC_CHANGED(pc->ec);
+}
+
 E_Config_Policy_Desk *
 _e_policy_desk_get_by_num(unsigned int zone_num, int x, int y)
 {
@@ -567,6 +695,15 @@ _e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
         return;
      }
 
+   if (e_policy_client_is_splited(ec))
+     {
+        E_Policy_Client *pc;
+        pc = eina_hash_find(hash_policy_clients, &ec);
+        _e_policy_client_maximize_policy_cancel(pc);
+        _e_policy_client_split_policy_apply(pc);
+        return;
+     }
+
    if (!_e_policy_client_normal_check(ec)) return;
 
    pd = eina_hash_find(hash_policy_desks, &ec->desk);
@@ -578,6 +715,9 @@ _e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
    if (pc->flt_policy_state)
      _e_policy_client_floating_policy_cancel(pc);
 
+   if (pc->split_policy_state)
+     _e_policy_client_split_policy_cancel(pc);
+
    _e_policy_client_maximize_policy_apply(pc);
 }
 
@@ -1135,6 +1275,9 @@ e_policy_client_maximize(E_Client *ec)
 
    if (e_policy_client_is_subsurface(ec)) return EINA_FALSE;
 
+   if (e_policy_client_is_splited(ec))
+      return EINA_FALSE;
+
    if ((ec->netwm.type != E_WINDOW_TYPE_NORMAL) &&
        (ec->netwm.type != E_WINDOW_TYPE_UNKNOWN) &&
        (ec->netwm.type != E_WINDOW_TYPE_NOTIFICATION))
@@ -1303,6 +1446,18 @@ e_policy_client_is_cbhm(E_Client *ec)
    return EINA_FALSE;
 }
 
+Eina_Bool
+e_policy_client_is_splited(E_Client *ec)
+{
+   E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
+   E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
+
+   if (ec->layout.splited)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
 void
 e_policy_interceptors_clean(void)
 {
index ec21521..aae1d83 100644 (file)
@@ -56,6 +56,7 @@ struct _E_Policy_Client
    Eina_Bool max_policy_state;
    Eina_Bool flt_policy_state;
    Eina_Bool allow_user_geom;
+   Eina_Bool split_policy_state;
    int       user_geom_ref;
 };
 
@@ -119,6 +120,7 @@ EINTERN Eina_Bool        e_policy_client_is_floating(E_Client *ec);
 EINTERN Eina_Bool        e_policy_client_is_cursor(E_Client *ec);
 EINTERN Eina_Bool        e_policy_client_is_subsurface(E_Client *ec);
 EINTERN Eina_Bool        e_policy_client_is_cbhm(E_Client *ec);
+EINTERN Eina_Bool        e_policy_client_is_splited(E_Client *ec);
 
 EINTERN E_Policy_Softkey *e_policy_softkey_add(E_Zone *zone);
 EINTERN void              e_policy_softkey_del(E_Policy_Softkey *softkey);
diff --git a/src/bin/e_slot.c b/src/bin/e_slot.c
new file mode 100644 (file)
index 0000000..9e13106
--- /dev/null
@@ -0,0 +1,860 @@
+#include "e.h"
+
+/* global variables */
+#define SLOT_SMART_ENTRY Slot_Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
+#define SPLIT_DEBUG 0
+
+typedef enum _Slot_Client_Type
+{
+   E_SLOT_CLIENT_TYPE_NORMAL = 0,
+   E_SLOT_CLIENT_TYPE_TRANSFORM = 1
+}E_Slot_Client_Type;
+
+typedef struct _Slot_Smart_Data
+{
+   Evas_Object               *parent_obj;       // smart_obj belong to
+
+   Evas_Object               *clip;
+   Evas_Object               *slot_layout;
+   Evas_Object               *bg_object;       // for test
+
+   Eina_List                 *clist;           // E_Client list added on slot
+
+   int                        x, y, w, h;
+   int                        id;
+   Eina_Bool                  changed;
+}Slot_Smart_Data;
+
+typedef struct _E_Slot_Client
+{
+   E_Client                  *ec;
+   Evas_Object               *slot;
+
+   struct
+     {
+        int                   x, y, w, h;
+     } orig;
+   int                        type;
+   E_Util_Transform          *transform;
+}E_Slot_Client;
+
+typedef struct _E_Slot_G
+{
+   Eina_List           *slot_objs;
+   Eina_Hash           *hash_slot_objs;        // data : smart object , key: slot id
+   Eina_Hash           *hash_slot_clients;     // data : E_Slot_Client, key: ec
+}E_Slot_G;
+
+static E_Slot_G    *_e_slot_g = NULL;
+
+static int          id = 0;
+
+static Evas_Smart  *_e_slot_smart = NULL;
+
+
+/* static functions */
+static int _e_slot_generate_id(void);
+static E_Slot_Client* _e_slot_client_new(Evas_Object *obj, E_Client* ec, E_Slot_Client_Type type);
+static void _e_slot_client_del(E_Slot_Client* slot_client);
+static void _e_slot_client_restore_all(Evas_Object *obj);
+static Eina_Bool _e_slot_client_type_reset(E_Slot_Client* slot_client, E_Slot_Client_Type type);
+static Eina_Bool _e_slot_client_obj_reset(E_Slot_Client* slot_client, Evas_Object *obj);
+static Eina_Bool _e_slot_client_type_restore(E_Slot_Client* slot_client);
+
+static void
+_slot_smart_add(Evas_Object *obj)
+{
+   Slot_Smart_Data *sd;
+   Evas *e = evas_object_evas_get(obj);
+
+   sd = E_NEW(Slot_Smart_Data, 1);
+   if (EINA_UNLIKELY(!sd)) return;
+
+   sd->clip = evas_object_rectangle_add(e);
+   evas_object_move(sd->clip, 0, 0);
+   evas_object_resize(sd->clip, 200002, 200002);
+   evas_object_smart_member_add(sd->clip, obj);
+
+   sd->slot_layout = e_layout_add(e);
+   evas_object_clip_set(sd->slot_layout, sd->clip);
+   e_layout_virtual_size_set(sd->slot_layout, e_comp->w, e_comp->h); // FIXME:
+   evas_object_smart_member_add(sd->slot_layout, obj);
+   evas_object_name_set(sd->slot_layout, "e_slot->slot_layout");
+   evas_object_show(sd->slot_layout);
+
+   sd->bg_object = evas_object_rectangle_add(e);
+   evas_object_name_set(sd->bg_object, "e_slot->bg_object");
+   evas_object_color_set(sd->bg_object, 0, 0, 0, 255);
+
+   e_layout_pack(sd->slot_layout, sd->bg_object);
+   e_layout_child_move(sd->bg_object, 0, 0);
+
+   evas_object_show(sd->bg_object);
+   evas_object_smart_data_set(obj, sd);
+}
+
+static void
+_slot_smart_del(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+
+   _e_slot_g->slot_objs = eina_list_remove(_e_slot_g->slot_objs, obj);
+
+   _e_slot_client_restore_all(obj);
+
+   eina_list_free(sd->clist);
+   sd->clist = NULL;
+
+   evas_object_del(sd->bg_object);
+   evas_object_del(sd->slot_layout);
+   if (sd->clip)
+     {
+        evas_object_clip_unset(sd->clip);
+        evas_object_del(sd->clip);
+     }
+
+   free(sd);
+}
+
+static void
+_slot_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   SLOT_SMART_ENTRY
+
+   if ((sd->x == x) && (sd->y == y)) return;
+
+   sd->x = x;
+   sd->y = y;
+
+   evas_object_move(sd->clip, x, y);
+   evas_object_move(sd->slot_layout,  x, y);
+   evas_object_move(sd->bg_object, x, y);
+}
+
+static void
+_slot_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   SLOT_SMART_ENTRY
+
+   sd->w = w;
+   sd->h = h;
+
+   evas_object_resize(sd->clip, w, h);
+   evas_object_resize(sd->slot_layout, w, h);
+   evas_object_resize(sd->bg_object, w, h);
+}
+
+static void
+_slot_smart_show(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+
+   evas_object_show(sd->bg_object);
+   evas_object_show(sd->slot_layout);
+   evas_object_show(sd->clip);
+}
+
+static void
+_slot_smart_hide(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+
+   evas_object_hide(sd->bg_object);
+   evas_object_hide(sd->slot_layout);
+   evas_object_hide(sd->clip);
+}
+
+static void
+_slot_smart_init(void)
+{
+   if (_e_slot_smart) return;
+     {
+        static const Evas_Smart_Class sc =
+          {
+             "slot_smart",
+             EVAS_SMART_CLASS_VERSION,
+             _slot_smart_add,
+             _slot_smart_del,
+             _slot_smart_move,
+             _slot_smart_resize,
+             _slot_smart_show,
+             _slot_smart_hide,
+             NULL, /* color_set */
+             NULL, /* clip_set */
+             NULL, /* clip_unset */
+             NULL, /* calculate */
+             NULL, /* member_add */
+             NULL, /* member_del */
+
+             NULL, /* parent */
+             NULL, /* callbacks */
+             NULL, /* interfaces */
+             NULL  /* data */
+          };
+        _e_slot_smart = evas_smart_class_new(&sc);
+     }
+}
+
+static void
+e_slot_layout_cb(void)
+{
+   Eina_List *l;
+   Evas_Object *obj = NULL;
+   Slot_Smart_Data *sd = NULL;
+
+   EINA_LIST_FOREACH(_e_slot_g->slot_objs, l, obj)
+     {
+        sd = evas_object_smart_data_get(obj);
+        if (sd && sd->changed) e_slot_update(obj);
+     }
+}
+
+EINTERN void
+e_slot_init(void)
+{
+   ELOGF("SLOT", "e_slot_init", 0, 0);
+   E_Slot_G *g = NULL;
+   g = E_NEW(E_Slot_G, 1);
+
+   EINA_SAFETY_ON_NULL_RETURN(g);
+
+   g->hash_slot_objs = eina_hash_pointer_new(NULL);
+   g->hash_slot_clients = eina_hash_pointer_new(NULL);
+   e_client_layout_cb_set(e_slot_layout_cb);
+
+   _e_slot_g = g;
+}
+
+EINTERN int
+e_slot_shutdown(void)
+{
+   ELOGF("SLOT", "e_slot_shutdown", 0, 0);
+
+   E_FREE_FUNC(_e_slot_g->slot_objs, eina_list_free);
+
+   E_FREE_FUNC(_e_slot_g->hash_slot_objs, eina_hash_free);
+   E_FREE_FUNC(_e_slot_g->hash_slot_clients, eina_hash_free);
+   E_FREE(_e_slot_g);
+
+   return 1;
+}
+
+E_API Evas_Object *
+e_slot_new(Evas_Object *parent)
+{
+   Evas_Object *o;
+   Slot_Smart_Data *sd;
+
+   _slot_smart_init();
+   o = evas_object_smart_add(e_comp->evas, _e_slot_smart);
+   sd = evas_object_smart_data_get(o);
+   sd->id = _e_slot_generate_id();
+   sd->parent_obj = parent;
+
+#if SPLIT_DEBUG
+   int r =100, b = 100, g = 100;
+   if (sd->id % 2) {
+        r = 255;
+        evas_object_name_set(o, "red_slot->smart_obj");
+        INF("------------------------------- RED RED RED %s (%d)", __FUNCTION__, __LINE__);
+   }
+   else {
+        b = 255;
+        INF("------------------------------- BLUE BLUE BLUE %s (%d)", __FUNCTION__, __LINE__);
+        evas_object_name_set(o, "blue_slot->smart_obj");
+   }
+   evas_object_color_set(sd->bg_object, r, g, b, 255);
+   evas_object_show(sd->bg_object);
+   e_layout_child_move(sd->bg_object, 0, 0);
+#endif
+
+   _e_slot_g->slot_objs = eina_list_append(_e_slot_g->slot_objs, o);
+
+   eina_hash_add(_e_slot_g->hash_slot_objs, &sd->id, o);
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_add", o);
+
+   evas_object_show(o);
+
+   ELOGF("SLOT", "|Create new slot - id:%d ", 0, 0, sd->id);
+   evas_object_data_set(o, "e_slot_object", (void*)1);
+
+   return o;
+}
+
+E_API void
+e_slot_del(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+   ELOGF("SLOT", "|Remove slot - id:%d ", 0, 0, sd->id);
+
+   eina_hash_del_by_key(_e_slot_g->hash_slot_objs, &sd->id);
+   evas_object_del(obj);
+}
+
+E_API void
+e_slot_move(Evas_Object *obj, int x, int y)
+{
+   SLOT_SMART_ENTRY
+
+   if (sd->x == x && sd->y == y) return;
+
+   ELOGF("SLOT", "|Move slot - id:%d  (%d, %d) -> (%d, %d)", 0, 0,
+         sd->id, sd->x, sd->y, x, y);
+
+   evas_object_move(obj, x, y);
+   sd->changed = 1;
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_move", obj);
+}
+
+E_API void
+e_slot_resize(Evas_Object *obj, int w, int h)
+{
+   SLOT_SMART_ENTRY
+
+   if (sd->w == w && sd->h == h) return;
+
+   ELOGF("SLOT", "|Resize slot - id:%d  (%dx%d) -> (%dx%d)", 0, 0,
+         sd->id, sd->w, sd->h, w, h);
+
+   evas_object_resize(obj, w, h);
+   sd->changed = 1;
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_resize", obj);
+}
+
+E_API void
+e_slot_raise(Evas_Object *obj)
+//e_slot_client_raise
+{
+   SLOT_SMART_ENTRY
+
+   Eina_List *l = NULL;
+   Evas_Object *o = NULL;
+   E_Client *ec = NULL;
+   E_Client *ec2 = NULL;
+   int cnt = 0;
+
+   for (o = evas_object_bottom_get(e_comp->evas); o; o = evas_object_above_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+        if (!ec) continue;
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+        if (ec->layout.s_id != sd->id) continue;
+        ELOGF("SLOT", "|raise ec[list add] - id:%d [cnt:%d]", ec->pixmap, ec, sd->id, cnt++);
+        l = eina_list_append(l, ec);
+     }
+
+   cnt = 0;
+   EINA_LIST_FREE(l, ec2)
+     {
+        ELOGF("SLOT", "e_slot_raise |raise ec - id:%d [cnt:%d]", ec2->pixmap, ec2, sd->id, cnt++);
+        evas_object_raise(ec2->frame);
+     }
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_raise", obj);
+}
+
+E_API void
+e_slot_lower(Evas_Object *obj)
+//e_slot_client_lower
+{
+   SLOT_SMART_ENTRY
+
+   Eina_List *l = NULL;
+   Evas_Object *o = NULL;
+   E_Client *ec = NULL;
+   E_Client *ec2 = NULL;
+   int cnt = 0;
+
+   for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+        if (!ec) continue;
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+        if (ec->layout.s_id != sd->id) continue;
+        ELOGF("SLOT", "e_slot_lower |lower ec[list add] - id:%d [cnt:%d]", ec->pixmap, ec, sd->id, cnt++);
+        l = eina_list_append(l, ec);
+     }
+
+   cnt = 0;
+   EINA_LIST_FREE(l, ec2)
+     {
+        ELOGF("SLOT", "e_slot_lower |lower ec - id:%d [cnt:%d]", ec2->pixmap, ec2, sd->id, cnt++);
+        evas_object_lower(ec2->frame);
+     }
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_lower", obj);
+}
+
+E_API void
+e_slot_focus_set(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+
+   Evas_Object *o = NULL;
+   E_Client *ec = NULL;
+   int cnt = 0;
+
+   if (sd->parent_obj)
+     evas_object_smart_callback_call(sd->parent_obj, "slot_focus", obj);
+
+   for(o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+        if (!ec) continue;
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+        if (ec->layout.s_id != sd->id) continue;
+        ELOGF("SLOT", "e_slot_focus_set |ec foucsed set - id:%d [cnt:%d]", ec->pixmap, ec, sd->id, cnt++);
+        if (ec->frame) evas_object_raise(ec->frame);
+        break;
+     }
+}
+
+E_API void
+e_slot_update(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+
+   Eina_List *l = NULL;
+   E_Slot_Client *slot_client = NULL;
+   E_Client *ec;
+   int x, y, w, h;
+   int cnt = 0;
+
+   if (sd->clist)
+     {
+        EINA_LIST_FOREACH(sd->clist, l, ec)
+          {
+             if (e_object_is_del(E_OBJECT(ec))) continue;
+             if (e_client_util_ignored_get(ec)) continue;
+             if (!ec->comp_data) continue;
+
+             slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+             e_client_geometry_get(slot_client->ec, &x, &y, &w, &h);
+
+             if (slot_client->type == E_SLOT_CLIENT_TYPE_TRANSFORM)
+               {
+                  if (slot_client->transform)
+                    {
+                       e_util_transform_move(slot_client->transform, (double)sd->x, (double)sd->y, 0);
+                       e_util_transform_scale(slot_client->transform,  (double)sd->w /(double)slot_client->ec->w, (double)sd->h /(double)slot_client->ec->h, 1.0);
+                       e_client_transform_core_update(slot_client->ec);
+
+                       ELOGF("SLOT", "e_slot_update |transform update - id:%d (%d,%d) (%lf x %lf) [cnt:%d]", slot_client->ec->pixmap, slot_client->ec,
+                             sd->id, sd->x, sd->y, (double)sd->w/(double)slot_client->ec->w, (double)sd->h /(double)slot_client->ec->h, cnt++);
+                    }
+               }
+             else
+               {
+                  if (slot_client->ec->frame)
+                    {
+                       evas_object_move(slot_client->ec->frame, sd->x, sd->y);
+                       evas_object_resize(slot_client->ec->frame, sd->w, sd->h);
+                       ELOGF("SLOT", "e_slot_update |resize update - id:%d (%d,%d,%dx%d) [cnt:%d]", slot_client->ec->pixmap, slot_client->ec,
+                             sd->id, sd->x, sd->y, sd->w, sd->h, cnt++);
+                    }
+               }
+          }
+     }
+
+   sd->changed = 0;
+   e_client_visibility_calculate();
+}
+
+E_API Eina_List*
+e_slot_list_get(void)
+{
+   return _e_slot_g->slot_objs;
+}
+
+E_API Evas_Object *
+e_slot_find_by_id(int slot_id)
+{
+   Evas_Object *obj = NULL;
+
+   obj = eina_hash_find(_e_slot_g->hash_slot_objs, &slot_id);
+
+   return obj;
+}
+
+E_API Eina_Bool
+e_slot_client_add(Evas_Object *obj, E_Client *ec, Eina_Bool resizable)
+{
+   Slot_Smart_Data *sd;
+   E_Slot_Client* slot_client = NULL;
+   int ret = EINA_FALSE;
+   int type = resizable ? E_SLOT_CLIENT_TYPE_NORMAL : E_SLOT_CLIENT_TYPE_TRANSFORM;
+
+   if (!obj) return EINA_FALSE;
+   if (!ec) return EINA_FALSE;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+
+   slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+   if (slot_client)
+     {
+        if ((slot_client->slot == obj) &&
+            (slot_client->type == type))
+          return EINA_FALSE;
+        else
+          {
+             /* if already allocated, replace ec from prev. slot */
+             if (slot_client->slot != obj)
+               ret |= _e_slot_client_obj_reset(slot_client, obj);
+
+             if (slot_client->type != type)
+               ret |= _e_slot_client_type_reset(slot_client, type);
+
+             if (ret) goto client_changed;
+             else
+               return EINA_FALSE;
+          }
+     }
+
+   slot_client = _e_slot_client_new(obj, ec, type);
+   if (!slot_client) return EINA_FALSE;
+
+   sd->clist = eina_list_append(sd->clist, ec);
+   eina_hash_add(_e_slot_g->hash_slot_clients, &ec, slot_client);
+
+   ELOGF("SLOT", "%s | Add - id:%d type:%d", ec->pixmap, ec, __FUNCTION__, sd->id, type);
+   ret = EINA_TRUE;
+
+client_changed:
+   ec->layout.s_id = sd->id;
+   ec->layout.splited = EINA_TRUE;
+   sd->changed = EINA_TRUE;
+   return ret;
+}
+
+E_API Eina_Bool
+e_slot_client_remove(Evas_Object *obj, E_Client *ec)
+{
+   Slot_Smart_Data *sd;
+   E_Slot_Client* slot_client = NULL;
+
+   if (!obj) return EINA_FALSE;
+   if (!ec) return EINA_FALSE;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return EINA_FALSE;
+
+   slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+   if (!slot_client) return EINA_FALSE;
+
+   _e_slot_client_type_restore(slot_client);
+
+   eina_hash_del_by_key(_e_slot_g->hash_slot_clients, &ec);
+
+   _e_slot_client_del(slot_client);
+
+   sd->clist = eina_list_remove(sd->clist, ec);
+
+   ec->layout.s_id = 0;
+   ec->layout.splited = EINA_FALSE;
+   sd->changed = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+
+E_API int
+e_slot_client_type_get(E_Client *ec)
+{
+   E_Slot_Client *slot_client = NULL;
+   int type = -1;
+
+   if (!ec) return type;
+
+   slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+   if (slot_client) type = slot_client->type;
+
+   return type;
+}
+
+E_API void
+e_slot_client_update(E_Client *ec)
+{
+   Slot_Smart_Data *sd;
+   E_Slot_Client *slot_client = NULL;
+   int x, y, w, h;
+
+   if (!ec) return;
+
+   slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+   if (!slot_client) return;
+
+   sd = evas_object_smart_data_get(slot_client->slot);
+   if (!sd) return;
+
+   if (slot_client)
+     {
+        if (e_object_is_del(E_OBJECT(slot_client->ec))) return;
+        if (e_client_util_ignored_get(slot_client->ec)) return;
+        if (!slot_client->ec->comp_data) return;
+
+        e_client_geometry_get(slot_client->ec, &x, &y, &w, &h);
+
+        if (slot_client->type == E_SLOT_CLIENT_TYPE_TRANSFORM)
+          {
+             if (slot_client->transform)
+               {
+                  e_util_transform_move(slot_client->transform, (double)sd->x, (double)sd->y, 0);
+                  e_util_transform_scale(slot_client->transform,  (double)sd->w/(double)slot_client->ec->w, (double)sd->h /(double)slot_client->ec->h, 1.0);
+                  e_client_transform_core_update(slot_client->ec);
+
+                  ELOGF("SLOT", "e_slot_client_update |transform update - id:%d (%d,%d) (%lf x %lf) ", slot_client->ec->pixmap, slot_client->ec,
+                        ec->layout.s_id, sd->x, sd->y, (double)sd->w/(double)slot_client->ec->w, (double)sd->h /(double)slot_client->ec->h);
+               }
+          }
+        else
+          {
+             if (slot_client->ec->frame)
+               {
+                  evas_object_move(slot_client->ec->frame, sd->x, sd->y);
+                  evas_object_resize(slot_client->ec->frame, sd->w, sd->h);
+                  ELOGF("SLOT", "e_slot_client_update |resize update - id:%d (%d,%d,%dx%d)", slot_client->ec->pixmap, slot_client->ec,
+                        ec->layout.s_id, sd->x, sd->y, sd->w, sd->h);
+               }
+          }
+     }
+}
+
+E_API int
+e_slot_find_id(Evas_Object *obj)
+{
+   Slot_Smart_Data *sd;
+
+   if (!obj) return -1;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return -1;
+
+   return sd->id;
+}
+
+/* static functions */
+static int
+_e_slot_generate_id(void)
+{
+   /* FIXME: */
+   return ++id;
+}
+
+static E_Slot_Client*
+_e_slot_client_new(Evas_Object *obj, E_Client* ec, E_Slot_Client_Type type)
+{
+   E_Slot_Client *slot_client = NULL;
+
+   slot_client = E_NEW(E_Slot_Client, 1);
+   if (!slot_client) return NULL;
+
+   slot_client->ec = ec;
+   slot_client->slot = obj;
+   slot_client->orig.x = ec->x;
+   slot_client->orig.y = ec->y;
+   slot_client->orig.w = ec->w;
+   slot_client->orig.h = ec->h;
+
+   if (slot_client->orig.x == 0 &&
+       slot_client->orig.y == 0 &&
+       slot_client->orig.w == 1 &&
+       slot_client->orig.h == 1)
+     {
+        slot_client->orig.x = ec->zone->x;
+        slot_client->orig.y = ec->zone->y;
+        slot_client->orig.w = ec->zone->w;
+        slot_client->orig.h = ec->zone->h;
+     }
+
+   slot_client->transform = NULL;
+   slot_client->type = type;
+   if (type == E_SLOT_CLIENT_TYPE_TRANSFORM)
+     {
+        slot_client->transform = e_util_transform_new();
+        e_client_transform_core_add(slot_client->ec, slot_client->transform);
+     }
+
+   ELOGF("SLOT", "|Create slot client - type:%d orig: %d,%d,%dx%d", ec->pixmap, ec,
+         type, ec->x, ec->y, ec->w, ec->h);
+
+   return slot_client;
+}
+
+static void
+_e_slot_client_del(E_Slot_Client* slot_client)
+{
+   if (!slot_client) return;
+   E_FREE(slot_client);
+}
+
+static Eina_Bool
+_e_slot_client_obj_reset(E_Slot_Client* slot_client, Evas_Object *obj)
+{
+   Slot_Smart_Data *sd_old;
+   Slot_Smart_Data *sd_new;
+
+   if (!slot_client) return EINA_FALSE;
+   if (slot_client->slot == obj) return EINA_FALSE;
+
+   sd_old = evas_object_smart_data_get(slot_client->slot);
+   sd_new = evas_object_smart_data_get(obj);
+
+   if (!sd_old || !sd_old) return EINA_FALSE;
+
+   sd_old->clist = eina_list_remove(sd_old->clist, slot_client->ec);
+   sd_new->clist = eina_list_append(sd_new->clist, slot_client->ec);
+
+   ELOGF("SLOT", "%s | Modify - id:from %d   to %d", slot_client->ec->pixmap, slot_client->ec,
+         __FUNCTION__, sd_old->id, sd_new->id);
+
+   return EINA_TRUE;
+}
+
+
+static Eina_Bool
+_e_slot_client_type_reset(E_Slot_Client* slot_client, E_Slot_Client_Type type)
+{
+   Eina_Bool ret = EINA_FALSE;
+
+   if (!slot_client) return EINA_FALSE;
+   if (slot_client->type == type) return EINA_FALSE;
+
+   switch (type)
+     {
+      case E_SLOT_CLIENT_TYPE_TRANSFORM:
+         if (!slot_client->transform)
+           {
+              slot_client->transform = e_util_transform_new();
+              e_client_transform_core_add(slot_client->ec, slot_client->transform);
+              ELOGF("SLOT", "Reset client |type %d ", slot_client->ec->pixmap, slot_client->ec, type);
+              ret = EINA_TRUE;
+           }
+         break;
+
+      default:
+      case E_SLOT_CLIENT_TYPE_NORMAL:
+         if (slot_client->transform)
+           {
+              e_client_transform_core_remove(slot_client->ec, slot_client->transform);
+              e_util_transform_del(slot_client->transform);
+              slot_client->transform = NULL;
+              ELOGF("SLOT", "Reset client |type %d ", slot_client->ec->pixmap, slot_client->ec, type);
+              ret = EINA_TRUE;
+           }
+         break;
+     }
+
+   return ret;
+}
+
+static Eina_Bool
+_e_slot_client_type_restore(E_Slot_Client* slot_client)
+{
+   Eina_Bool ret = EINA_FALSE;
+
+   if (!slot_client) return EINA_FALSE;
+   if (e_object_is_del(E_OBJECT(slot_client->ec))) return EINA_FALSE;
+
+   switch (slot_client->type)
+     {
+      case E_SLOT_CLIENT_TYPE_TRANSFORM:
+         if (slot_client->transform)
+           {
+              e_client_transform_core_remove(slot_client->ec, slot_client->transform);
+              e_util_transform_del(slot_client->transform);
+              slot_client->transform = NULL;
+
+              ELOGF("SLOT", "Restore client |unset transform ", slot_client->ec->pixmap, slot_client->ec);
+
+              ret = EINA_TRUE;
+           }
+         break;
+
+      default:
+      case E_SLOT_CLIENT_TYPE_NORMAL:
+         if (slot_client->ec->frame)
+           {
+              /* restore to its origin size when remove from slot */
+              evas_object_move(slot_client->ec->frame, slot_client->orig.x, slot_client->orig.y);
+              evas_object_resize(slot_client->ec->frame, slot_client->orig.w, slot_client->orig.h);
+
+              ELOGF("SLOT", "Restore client |restore its origin size: %d,%d,%dx%d", slot_client->ec->pixmap, slot_client->ec,
+                    slot_client->orig.x, slot_client->orig.y, slot_client->orig.w, slot_client->orig.h);
+              ret = EINA_TRUE;
+           }
+         break;
+     }
+
+   if (!ret) ELOGF("SLOT", "Restore client |failed", slot_client->ec->pixmap, slot_client->ec);
+   return ret;
+}
+
+static void
+_e_slot_client_restore_all(Evas_Object *obj)
+{
+   SLOT_SMART_ENTRY
+   E_Slot_Client* slot_client = NULL;
+   E_Client *ec;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(sd->clist, l, ec)
+     {
+        slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+        if (slot_client)
+          {
+             _e_slot_client_type_restore(slot_client);
+             eina_hash_del_by_key(_e_slot_g->hash_slot_clients, &ec);
+             _e_slot_client_del(slot_client);
+          }
+     }
+}
+
+E_API Eina_List*
+e_slot_client_list_get(Evas_Object *obj)
+{
+   Slot_Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return NULL;
+
+   return sd->clist;
+}
+
+E_API int
+e_slot_client_count_get(Evas_Object *obj)
+{
+   Slot_Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   if (!sd) return 0;
+
+   return eina_list_count(sd->clist);
+}
+
+E_API int
+e_slot_client_slot_id_get(E_Client *ec)
+{
+   E_Slot_Client *slot_client = NULL;
+   Slot_Smart_Data *sd;
+
+   if (!ec) return -1;
+
+   slot_client = eina_hash_find(_e_slot_g->hash_slot_clients, &ec);
+   if (!slot_client) return -1;
+
+   sd = evas_object_smart_data_get(slot_client->slot);
+   if (!sd) return -1;
+
+   return sd->id;
+}
diff --git a/src/bin/e_slot.h b/src/bin/e_slot.h
new file mode 100644 (file)
index 0000000..b2efeb2
--- /dev/null
@@ -0,0 +1,39 @@
+#ifdef E_TYPEDEFS
+
+
+#else
+
+#ifndef E_SLOT_H_
+#define E_SLOT_H_
+
+
+EINTERN void                  e_slot_init(void);
+EINTERN int                   e_slot_shutdown(void);
+
+E_API Evas_Object            *e_slot_new(Evas_Object *parent);
+E_API void                    e_slot_del(Evas_Object *obj);
+E_API void                    e_slot_move(Evas_Object *obj, int x, int y);
+E_API void                    e_slot_resize(Evas_Object *obj, int w, int h);
+
+E_API Evas_Object            *e_slot_find_by_id(int slot_id);
+E_API int                     e_slot_find_id(Evas_Object *obj);
+E_API void                    e_slot_update(Evas_Object *obj);
+
+E_API Eina_Bool               e_slot_client_add(Evas_Object *obj, E_Client *ec, Eina_Bool resizable);
+E_API Eina_Bool               e_slot_client_remove(Evas_Object *obj, E_Client *ec);
+E_API Eina_List              *e_slot_client_list_get(Evas_Object *obj);
+E_API int                     e_slot_client_count_get(Evas_Object *obj);
+E_API int                     e_slot_client_slot_id_get(E_Client* ec);
+E_API int                     e_slot_client_type_get(E_Client* ec);
+E_API void                    e_slot_client_update(E_Client *ec);
+
+
+E_API void                    e_slot_raise(Evas_Object *obj);
+E_API void                    e_slot_lower(Evas_Object *obj);
+E_API void                    e_slot_focus_set(Evas_Object *obj);
+
+
+E_API Eina_List              *e_slot_list_get(void); // list of e_slot smart obj
+
+#endif
+#endif
diff --git a/src/bin/e_splitlayout.c b/src/bin/e_splitlayout.c
new file mode 100644 (file)
index 0000000..1b1a747
--- /dev/null
@@ -0,0 +1,587 @@
+#include "e.h"
+
+/* global variables */
+#define SMART_NAME            "splitlayout"
+#define SLAYOUT_ENTRY                    \
+   Splitlayout_Data *sd;                        \
+sd = evas_object_smart_data_get(obj)
+
+typedef struct _Splitlayout_Data  Splitlayout_Data;
+typedef struct _Splitlayout_Item  Splitlayout_Item;
+
+struct _Splitlayout_Data
+{
+   E_Desk              *desk;
+
+   Evas_Object         *obj;
+   Evas_Object         *clip;
+   Evas_Object         *bg;         // background color
+   Evas_Object         *fg;         // splitter
+
+   int                  x, y, w, h;
+   int                  layer;
+
+   int                  frozen;
+   unsigned char        changed : 1;
+   Eina_Inlist          *items;
+};
+
+struct _Splitlayout_Item
+{
+   EINA_INLIST;
+   Splitlayout_Data    *sd;
+   Evas_Coord           x, y, w, h;
+   Evas_Object         *obj;         // e_slot smart objs
+};
+
+static Evas_Smart     *_splitlayout_smart = NULL;
+
+/* static functions */
+static void
+_layout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   e_splitlayout_unpack(obj);
+}
+
+static Splitlayout_Item *
+_layout_smart_adopt(Splitlayout_Data *sd, Evas_Object *obj)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (li) e_splitlayout_unpack(obj);
+   li = calloc(1, sizeof(Splitlayout_Item));
+   if (!li) return NULL;
+   li->sd = sd;
+   li->obj = obj;
+   /* defaults */
+   li->x = 0;
+   li->y = 0;
+   li->w = 0;
+   li->h = 0;
+   evas_object_clip_set(obj, sd->clip);
+   evas_object_smart_member_add(obj, li->sd->obj);
+   evas_object_data_set(obj, "e_slot_data", li);
+   evas_object_layer_set(obj, evas_object_layer_get(sd->obj));
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
+                                  _layout_smart_item_del_hook, NULL);
+   if ((!evas_object_visible_get(sd->clip)) &&
+       (evas_object_visible_get(sd->obj)))
+     evas_object_show(sd->clip);
+   return li;
+}
+
+static void
+_layout_smart_disown(Evas_Object *obj)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+   if (!li->sd->items)
+     {
+        if (evas_object_visible_get(li->sd->clip))
+          evas_object_hide(li->sd->clip);
+     }
+   evas_object_event_callback_del(obj,
+                                  EVAS_CALLBACK_FREE,
+                                  _layout_smart_item_del_hook);
+   evas_object_smart_member_del(obj);
+   evas_object_data_del(obj, "e_slot_data");
+   free(li);
+}
+
+static void
+_layout_smart_move_resize_item(Splitlayout_Item *li)
+{
+#ifdef SPLIT_DEBUG
+   int eo_x, eo_y, eo_w, eo_h;
+#endif
+
+   evas_object_move(li->obj, li->sd->x + li->x, li->sd->y + li->y);
+   evas_object_resize(li->obj, li->w, li->h);
+
+#ifdef SPLIT_DEBUG
+   evas_object_geometry_get(li->obj,&eo_x,&eo_y,&eo_w,&eo_h);
+   INF(" %s obj- x(%d) y(%d) w(%d) h(%d)", __FUNCTION__, eo_x, eo_y, eo_w, eo_h);
+#endif
+
+}
+
+static void
+_layout_smart_reconfigure(Splitlayout_Data *sd)
+{
+   Splitlayout_Item *li;
+
+   if (!sd->changed) return;
+
+   EINA_INLIST_FOREACH(sd->items, li)
+      _layout_smart_move_resize_item(li);
+   sd->changed = 0;
+}
+
+static void
+_layout_intercept_layer_set(void *data, Evas_Object *obj, int layer)
+{
+   Splitlayout_Data *sd = data;
+   Splitlayout_Item *li;
+
+   EINA_INLIST_FOREACH(sd->items, li)
+     {
+        evas_object_layer_set(li->obj, layer);
+     }
+
+   evas_object_layer_set(obj, layer);
+}
+
+static void
+_layout_smart_add(Evas_Object *obj)
+{
+   Splitlayout_Data *sd;
+
+   sd = E_NEW(Splitlayout_Data, 1);
+   if (EINA_UNLIKELY(!sd)) return;
+
+   sd->obj = obj;
+   sd->x = sd->y = sd->w = sd->h = 0;
+   sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
+   evas_object_smart_member_add(sd->clip, obj);
+   evas_object_move(sd->clip, 0, 0);
+   evas_object_resize(sd->clip, 200002, 200002);
+   evas_object_smart_data_set(obj, sd);
+
+   sd->bg = evas_object_rectangle_add(evas_object_evas_get(obj));
+   evas_object_clip_set(sd->bg, sd->clip);
+#ifdef SPLIT_DEBUG
+   evas_object_color_set(sd->bg, 255, 255, 0, 255);  // (yellow) background color can be configed
+#else
+   evas_object_color_set(sd->bg, 255, 255, 255, 255);
+#endif
+   evas_object_name_set(sd->bg, "e_splitlayout->bg");
+   evas_object_smart_member_add(sd->bg, sd->obj);
+   evas_object_show(sd->bg);
+
+   evas_object_intercept_layer_set_callback_add(obj, _layout_intercept_layer_set, sd);
+}
+
+static void
+_layout_smart_del(Evas_Object *obj)
+{
+   SLAYOUT_ENTRY;
+
+   while (sd->items)
+     {
+        Splitlayout_Item *li = (Splitlayout_Item*)sd->items;
+        sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(li));
+        _layout_smart_disown(li->obj);
+     }
+   if (sd->bg) evas_object_del(sd->bg);
+   if (sd->clip) evas_object_del(sd->clip);
+   free(sd);
+}
+
+static void
+_layout_smart_show(Evas_Object *obj)
+{
+   SLAYOUT_ENTRY;
+#ifdef SPLIT_DEBUG
+   int eo_x, eo_y, eo_w, eo_h;
+#endif
+
+   evas_object_show(sd->bg);
+   evas_object_show(sd->clip);
+
+#ifdef SPLIT_DEBUG
+   EINA_INLIST_FOREACH(sd->items, li)
+   {
+   INF("%s child %s", __FUNCTION__, evas_object_name_get(li->obj));
+   evas_object_geometry_get(li->obj, &eo_x, &eo_y, &eo_w, &eo_h);
+   INF("%s child - x(%d) y(%d) w(%d) h(%d)", __FUNCTION__, eo_x,eo_y,eo_w,eo_h);
+   }
+
+   evas_object_geometry_get(sd->clip, &eo_x, &eo_y, &eo_w, &eo_h);
+   INF("%s clip- x(%d) y(%d) w(%d) h(%d)", __FUNCTION__, eo_x,eo_y,eo_w,eo_h);
+   evas_object_geometry_get(sd->bg,&eo_x,&eo_y,&eo_w,&eo_h);
+   INF("%s bg - x(%d) y(%d) w(%d) h(%d)", __FUNCTION__, eo_x,eo_y,eo_w,eo_h);
+#endif
+}
+
+static void
+_layout_smart_hide(Evas_Object *obj)
+{
+   SLAYOUT_ENTRY;
+
+   evas_object_hide(sd->bg);
+   evas_object_hide(sd->clip);
+}
+
+static void
+_layout_smart_move(Evas_Object *obj, int x, int y)
+{
+   SLAYOUT_ENTRY;
+   Splitlayout_Item *li;
+   Evas_Coord dx, dy;
+
+   if ((x == sd->x) && (y == sd->y)) return;
+   dx = x - sd->x;
+   dy = y - sd->y;
+
+   evas_object_move(sd->clip, x, y);
+   evas_object_move(sd->bg, x, y);
+   EINA_INLIST_FOREACH(sd->items, li)
+     {
+        Evas_Coord ox, oy;
+
+        evas_object_geometry_get(li->obj, &ox, &oy, NULL, NULL);
+        evas_object_move(li->obj, ox + dx, oy + dy);
+     }
+   sd->x = x;
+   sd->y = y;
+}
+
+static void
+_layout_smart_resize(Evas_Object *obj, int w, int h)
+{
+   SLAYOUT_ENTRY;
+
+   if ((w == sd->w) && (h == sd->h)) return;
+   sd->w = w;
+   sd->h = h;
+   sd->changed = 1;
+
+   evas_object_resize(sd->clip, w, h);
+   evas_object_resize(sd->bg, w, h);
+   if (sd->frozen <= 0) _layout_smart_reconfigure(sd);
+}
+
+static void
+_layout_smart_init(void)
+{
+   if (_splitlayout_smart) return;
+     {
+        static const Evas_Smart_Class sc =
+          {
+             SMART_NAME,
+             EVAS_SMART_CLASS_VERSION,
+             _layout_smart_add,
+             _layout_smart_del,
+             _layout_smart_move,
+             _layout_smart_resize,
+             _layout_smart_show,
+             _layout_smart_hide,
+             NULL, /* color_set */
+             NULL, /* clip_set */
+             NULL, /* clip_unset */
+             NULL, /* calculate */
+             NULL, /* member_add */
+             NULL, /* member_del */
+
+             NULL, /* parent */
+             NULL, /* callbacks */
+             NULL, /* interfaces */
+             NULL  /* data */
+          };
+        _splitlayout_smart = evas_smart_class_new(&sc);
+     }
+}
+
+#ifdef SPLIT_DEBUG
+static void
+_e_splitlayout_cb_slot_add(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+static void
+_e_splitlayout_cb_slot_del(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+static void
+_e_splitlayout_cb_slot_move(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+
+static void
+_e_splitlayout_cb_slot_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+
+static void
+_e_splitlayout_cb_slot_lower(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+
+static void
+_e_splitlayout_cb_slot_raise(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+
+
+static void
+_e_splitlayout_cb_slot_update(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   sd = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(event_info);
+   obj = event_info;
+}
+#endif
+
+E_API Evas_Object *
+e_splitlayout_add(E_Desk *desk)
+{
+   Splitlayout_Data *sd;
+   Evas_Object *o;
+   Evas *e;
+#ifdef SPLIT_DEBUG
+   int eo_x, eo_y, eo_w, eo_h;
+#endif
+   e = e_comp->evas;
+
+   _layout_smart_init();
+   o = evas_object_smart_add(e, _splitlayout_smart);
+   sd = evas_object_smart_data_get(o);
+   sd->desk = desk;
+   e_object_ref(E_OBJECT(desk));
+
+   evas_object_name_set(sd->obj, "e_splitlayout:obj");
+
+#ifdef SPLIT_DEBUG
+   evas_object_smart_callback_add(sd->obj, "slot_add",    (Evas_Smart_Cb)_e_splitlayout_cb_slot_add,    sd);
+   evas_object_smart_callback_add(sd->obj, "slot_del",    (Evas_Smart_Cb)_e_splitlayout_cb_slot_del,    sd);
+   evas_object_smart_callback_add(sd->obj, "slot_move",   (Evas_Smart_Cb)_e_splitlayout_cb_slot_move,   sd);
+   evas_object_smart_callback_add(sd->obj, "slot_resize", (Evas_Smart_Cb)_e_splitlayout_cb_slot_resize, sd);
+   evas_object_smart_callback_add(sd->obj, "slot_lower",  (Evas_Smart_Cb)_e_splitlayout_cb_slot_lower,  sd);
+   evas_object_smart_callback_add(sd->obj, "slot_raise",  (Evas_Smart_Cb)_e_splitlayout_cb_slot_raise,  sd);
+   evas_object_smart_callback_add(sd->obj, "slot_update", (Evas_Smart_Cb)_e_splitlayout_cb_slot_update, sd);
+
+   evas_object_geometry_get(sd->clip, &eo_x, &eo_y, &eo_w, &eo_h);
+   INF("%s clip- x(%d) y(%d) w(%d) h(%d)", __FUNCTION__,  eo_x, eo_y, eo_w, eo_h);
+   evas_object_geometry_get(sd->bg, &eo_x, &eo_y, &eo_w, &eo_h);
+   INF("%s bg - x(%d) y(%d) w(%d) h(%d)", __FUNCTION__ , eo_x, eo_y, eo_w, eo_h);
+#endif
+
+   ELOGF("SPLIT", "Added Split layout", NULL, NULL);
+
+   return sd->obj;
+}
+
+E_API int
+e_splitlayout_freeze(Evas_Object *obj)
+{
+   Splitlayout_Data *sd;
+
+   if (evas_object_smart_smart_get(obj) != _splitlayout_smart) SMARTERR(0);
+   sd = evas_object_smart_data_get(obj);
+   sd->frozen++;
+   return sd->frozen;
+}
+
+E_API int
+e_splitlayout_thaw(Evas_Object *obj)
+{
+   Splitlayout_Data *sd;
+
+   if (evas_object_smart_smart_get(obj) != _splitlayout_smart) SMARTERR(0);
+   sd = evas_object_smart_data_get(obj);
+   sd->frozen--;
+   if (sd->frozen <= 0) _layout_smart_reconfigure(sd);
+   return sd->frozen;
+}
+
+E_API void
+e_splitlayout_pack(Evas_Object *obj, Evas_Object *child)
+{
+   Splitlayout_Data *sd;
+   Splitlayout_Item *li;
+
+   if (evas_object_smart_smart_get(obj) != _splitlayout_smart) SMARTERRNR();
+   sd = evas_object_smart_data_get(obj);
+   li = _layout_smart_adopt(sd, child);
+   sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(li));
+   evas_object_lower(child);
+   if (sd->frozen <= 0) _layout_smart_move_resize_item(li);
+}
+
+E_API void
+e_splitlayout_child_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+
+   if ((li->x == x) && (li->y == y)) return;
+   li->x = x;
+   li->y = y;
+   if (li->sd->frozen <= 0) _layout_smart_move_resize_item(li);
+}
+
+E_API void
+e_splitlayout_child_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((li->w == w) && (li->h == h)) return;
+   li->w = w;
+   li->h = h;
+   if (li->sd->frozen <= 0) _layout_smart_move_resize_item(li);
+}
+
+E_API void
+e_splitlayout_child_raise(Evas_Object *obj)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+   if (!li->sd->items) return;
+   li->sd->items = eina_inlist_demote(li->sd->items, EINA_INLIST_GET(li));
+   evas_object_raise(obj);
+}
+
+E_API void
+e_splitlayout_child_lower(Evas_Object *obj)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+   if (!li->sd->items) return;
+   li->sd->items = eina_inlist_promote(li->sd->items, EINA_INLIST_GET(li));
+   evas_object_lower(obj);
+}
+
+E_API void
+e_splitlayout_child_raise_above(Evas_Object *obj, Evas_Object *above)
+{
+   Splitlayout_Item *li, *li2;
+
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(above);
+   if (obj == above) return;
+   li = evas_object_data_get(obj, "e_slot_data");
+   li2 = evas_object_data_get(above, "e_slot_data");
+   if ((!li) || (!li2) || (li->sd != li2->sd)) return;
+   li->sd->items = eina_inlist_remove(li->sd->items, EINA_INLIST_GET(li));
+   evas_object_stack_above(obj, above);
+   li->sd->items = eina_inlist_append_relative(li->sd->items, EINA_INLIST_GET(li), EINA_INLIST_GET(li2));
+}
+
+E_API void
+e_splitlayout_child_lower_below(Evas_Object *obj, Evas_Object *below)
+{
+   Splitlayout_Item *li, *li2;
+
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(below);
+   if (obj == below) return;
+   li = evas_object_data_get(obj, "e_slot_data");
+   li2 = evas_object_data_get(below, "e_slot_data");
+   if ((!li) || (!li2) || (li->sd != li2->sd)) return;
+   li->sd->items = eina_inlist_remove(li->sd->items, EINA_INLIST_GET(li));
+   evas_object_stack_below(obj, below);
+   li->sd->items = eina_inlist_prepend_relative(li->sd->items, EINA_INLIST_GET(li), EINA_INLIST_GET(li2));
+}
+
+E_API void
+e_splitlayout_child_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+
+   if (x) *x = li->x;
+   if (y) *y = li->y;
+   if (w) *w = li->w;
+   if (h) *h = li->h;
+}
+
+E_API void
+e_splitlayout_unpack(Evas_Object *obj)
+{
+   Splitlayout_Data *sd;
+   Splitlayout_Item *li;
+
+   li = evas_object_data_get(obj, "e_slot_data");
+   if (!li) return;
+   sd = li->sd;
+   sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(li));
+   _layout_smart_disown(obj);
+}
+
+E_API Eina_List *
+e_splitlayout_children_get(Evas_Object *obj)
+{
+   Splitlayout_Data *sd;
+   Eina_List *l = NULL;
+   Splitlayout_Item *li;
+
+   if (evas_object_smart_smart_get(obj) != _splitlayout_smart) SMARTERRNR() NULL;
+   sd = evas_object_smart_data_get(obj);
+   EINA_INLIST_FOREACH(sd->items, li)
+      l = eina_list_append(l, li->obj);
+   return l;
+}
+
diff --git a/src/bin/e_splitlayout.h b/src/bin/e_splitlayout.h
new file mode 100644 (file)
index 0000000..ad1228b
--- /dev/null
@@ -0,0 +1,24 @@
+#ifdef E_TYPEDEFS
+
+
+#else
+#ifndef E_SPLITLAYOUT_H
+#define E_SPLITLAYOUT_H
+
+
+E_API Evas_Object                *e_splitlayout_add               (E_Desk *desk);
+E_API int                         e_splitlayout_freeze            (Evas_Object *obj);
+E_API int                         e_splitlayout_thaw              (Evas_Object *obj);
+E_API void                        e_splitlayout_unpack            (Evas_Object *obj);
+E_API void                        e_splitlayout_pack              (Evas_Object *obj, Evas_Object *child);
+E_API void                        e_splitlayout_child_move        (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+E_API void                        e_splitlayout_child_resize      (Evas_Object *obj, Evas_Coord w, Evas_Coord h);
+E_API void                        e_splitlayout_child_raise       (Evas_Object *obj);
+E_API void                        e_splitlayout_child_lower       (Evas_Object *obj);
+E_API void                        e_splitlayout_child_raise_above (Evas_Object *obj, Evas_Object *above);
+E_API void                        e_splitlayout_child_lower_below (Evas_Object *obj, Evas_Object *below);
+E_API void                        e_splitlayout_child_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+E_API Eina_List                  *e_splitlayout_children_get      (Evas_Object *obj);
+
+#endif
+#endif