diff --git a/src/modules/tiling/window_tree.c b/src/modules/tiling/window_tree.c index e6272c5cd..67a0041c4 100644 --- a/src/modules/tiling/window_tree.c +++ b/src/modules/tiling/window_tree.c @@ -1,3 +1,5 @@ +#include "e.h" + #include "window_tree.h" void @@ -13,43 +15,47 @@ tiling_window_tree_free(Window_Tree *root) } Window_Tree * -tiling_window_tree_add(Window_Tree *parent, E_Client *client) +tiling_window_tree_add(Window_Tree *parent, E_Client *client, Tiling_Split_Type split_type) { Window_Tree *new_node = calloc(1, sizeof(*new_node)); - new_node->parent = parent; new_node->client = client; + if (!parent) { new_node->weight = 1.0; return new_node; } - else if (parent->children) + else if (parent->parent && parent->parent->children && (parent->parent->split_type == split_type)) { /* Adjust existing children's weights */ + Window_Tree *grand_parent = parent->parent; Window_Tree *itr; - int children_count = eina_inlist_count(parent->children); + int children_count = eina_inlist_count(grand_parent->children); float weight = 1.0 / (children_count + 1); + new_node->parent = grand_parent; new_node->weight = weight; weight *= children_count; - EINA_INLIST_FOREACH(parent->children, itr) + EINA_INLIST_FOREACH(grand_parent->children, itr) { itr->weight *= weight; } - parent->children = eina_inlist_append(parent->children, + grand_parent->children = eina_inlist_append(grand_parent->children, EINA_INLIST_GET(new_node)); } else { /* Make a new node for the parent client and split the weights in half. */ Window_Tree *new_parent_client = calloc(1, sizeof(*new_node)); + new_node->parent = parent; new_parent_client->parent = parent; new_parent_client->client = parent->client; parent->client = NULL; new_parent_client->weight = 0.5; new_node->weight = 0.5; + parent->split_type = split_type; parent->children = eina_inlist_append(parent->children, EINA_INLIST_GET(new_parent_client)); @@ -60,22 +66,36 @@ tiling_window_tree_add(Window_Tree *parent, E_Client *client) return new_node; } -void -tiling_window_tree_remove(Window_Tree *item) +Window_Tree * +tiling_window_tree_remove(Window_Tree *root, Window_Tree *item) { - /* FIXME: Ignoring ilegal deletion of the rood node or items with children atm. */ + if (root == item) + { + free(item); + return NULL; + } int children_count = eina_inlist_count(item->parent->children); - float weight = (((float) children_count) - 1.0) / children_count; - if (children_count == 1) + if (children_count <= 2) { - item->parent->client = item->client; + Window_Tree *item_keep = NULL; + /* Adjust existing children's weights */ + EINA_INLIST_FOREACH(item->parent->children, item_keep) + { + if (item_keep != item) + break; + } + + item->parent->client = item_keep->client; item->parent->children = NULL; + + free(item_keep); } else { Window_Tree *itr; + float weight = (((float) children_count) - 1.0) / children_count; item->parent->children = eina_inlist_remove(item->parent->children, EINA_INLIST_GET(item)); @@ -88,5 +108,65 @@ tiling_window_tree_remove(Window_Tree *item) } free(item); + return root; } +Window_Tree * +tiling_window_tree_client_find(Window_Tree *root, E_Client *client) +{ + Window_Tree *itr; + + if (!root || (root->client == client)) + return root; + + EINA_INLIST_FOREACH(root->children, itr) + { + Window_Tree *ret; + ret = tiling_window_tree_client_find(itr, client); + if (ret) + return ret; + } + + return NULL; +} + +/* FIXME: Deduplicate this func. */ +static void +_e_client_move_resize(E_Client *ec, + int x, + int y, + int w, + int h) +{ + DBG("%p -> %dx%d+%d+%d", ec, w, h, x, y); + evas_object_geometry_set(ec->frame, x, y, w, h); +} + +void +tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y, + Evas_Coord w, Evas_Coord h) +{ + Window_Tree *itr; + + if (root->client) + _e_client_move_resize(root->client, x, y, w, h); + + if (root->split_type == TILING_SPLIT_HORIZONTAL) + { + EINA_INLIST_FOREACH(root->children, itr) + { + Evas_Coord itw = w * itr->weight; + tiling_window_tree_apply(itr, x, y, itw, h); + x += itw; + } + } + else if (root->split_type == TILING_SPLIT_VERTICAL) + { + EINA_INLIST_FOREACH(root->children, itr) + { + Evas_Coord ith = h * itr->weight; + tiling_window_tree_apply(itr, x, y, w, ith); + y += ith; + } + } +} diff --git a/src/modules/tiling/window_tree.h b/src/modules/tiling/window_tree.h index db9e15379..dfea0bba9 100644 --- a/src/modules/tiling/window_tree.h +++ b/src/modules/tiling/window_tree.h @@ -2,6 +2,11 @@ #define WINDOW_TREE_HO #include +typedef enum { + TILING_SPLIT_HORIZONTAL, + TILING_SPLIT_VERTICAL +} Tiling_Split_Type; + typedef struct _Window_Tree Window_Tree; struct _Window_Tree @@ -12,6 +17,17 @@ struct _Window_Tree Eina_Inlist *children; /* Window_Tree * type */ E_Client *client; float weight; + Tiling_Split_Type split_type; }; +void tiling_window_tree_free(Window_Tree *root); + +Window_Tree *tiling_window_tree_add(Window_Tree *parent, E_Client *client, Tiling_Split_Type split_type); + +Window_Tree *tiling_window_tree_remove(Window_Tree *root, Window_Tree *item); + +Window_Tree *tiling_window_tree_client_find(Window_Tree *root, E_Client *client); + +void tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); + #endif