Tiling2: Fixed bugs and improve the window tree implementation.

This commit is contained in:
Tom Hacohen 2014-01-13 14:53:12 +00:00
parent cfd4ea4f9f
commit 9060fa64b9
2 changed files with 108 additions and 12 deletions

View File

@ -1,3 +1,5 @@
#include "e.h"
#include "window_tree.h" #include "window_tree.h"
void void
@ -13,43 +15,47 @@ tiling_window_tree_free(Window_Tree *root)
} }
Window_Tree * 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)); Window_Tree *new_node = calloc(1, sizeof(*new_node));
new_node->parent = parent;
new_node->client = client; new_node->client = client;
if (!parent) if (!parent)
{ {
new_node->weight = 1.0; new_node->weight = 1.0;
return new_node; 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 */ /* Adjust existing children's weights */
Window_Tree *grand_parent = parent->parent;
Window_Tree *itr; 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); float weight = 1.0 / (children_count + 1);
new_node->parent = grand_parent;
new_node->weight = weight; new_node->weight = weight;
weight *= children_count; weight *= children_count;
EINA_INLIST_FOREACH(parent->children, itr) EINA_INLIST_FOREACH(grand_parent->children, itr)
{ {
itr->weight *= weight; itr->weight *= weight;
} }
parent->children = eina_inlist_append(parent->children, grand_parent->children = eina_inlist_append(grand_parent->children,
EINA_INLIST_GET(new_node)); EINA_INLIST_GET(new_node));
} }
else else
{ {
/* Make a new node for the parent client and split the weights in half. */ /* Make a new node for the parent client and split the weights in half. */
Window_Tree *new_parent_client = calloc(1, sizeof(*new_node)); Window_Tree *new_parent_client = calloc(1, sizeof(*new_node));
new_node->parent = parent;
new_parent_client->parent = parent; new_parent_client->parent = parent;
new_parent_client->client = parent->client; new_parent_client->client = parent->client;
parent->client = NULL; parent->client = NULL;
new_parent_client->weight = 0.5; new_parent_client->weight = 0.5;
new_node->weight = 0.5; new_node->weight = 0.5;
parent->split_type = split_type;
parent->children = eina_inlist_append(parent->children, parent->children = eina_inlist_append(parent->children,
EINA_INLIST_GET(new_parent_client)); EINA_INLIST_GET(new_parent_client));
@ -60,22 +66,36 @@ tiling_window_tree_add(Window_Tree *parent, E_Client *client)
return new_node; return new_node;
} }
void Window_Tree *
tiling_window_tree_remove(Window_Tree *item) 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); 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; item->parent->children = NULL;
free(item_keep);
} }
else else
{ {
Window_Tree *itr; Window_Tree *itr;
float weight = (((float) children_count) - 1.0) / children_count;
item->parent->children = eina_inlist_remove(item->parent->children, item->parent->children = eina_inlist_remove(item->parent->children,
EINA_INLIST_GET(item)); EINA_INLIST_GET(item));
@ -88,5 +108,65 @@ tiling_window_tree_remove(Window_Tree *item)
} }
free(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;
}
}
}

View File

@ -2,6 +2,11 @@
#define WINDOW_TREE_HO #define WINDOW_TREE_HO
#include <e.h> #include <e.h>
typedef enum {
TILING_SPLIT_HORIZONTAL,
TILING_SPLIT_VERTICAL
} Tiling_Split_Type;
typedef struct _Window_Tree Window_Tree; typedef struct _Window_Tree Window_Tree;
struct _Window_Tree struct _Window_Tree
@ -12,6 +17,17 @@ struct _Window_Tree
Eina_Inlist *children; /* Window_Tree * type */ Eina_Inlist *children; /* Window_Tree * type */
E_Client *client; E_Client *client;
float weight; 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 #endif