2014-01-13 06:53:12 -08:00
|
|
|
#include "e.h"
|
|
|
|
|
2014-01-13 04:18:48 -08:00
|
|
|
#include "window_tree.h"
|
2014-01-14 07:07:30 -08:00
|
|
|
#include "e_mod_tiling.h"
|
2014-01-13 04:18:48 -08:00
|
|
|
|
2017-03-09 02:14:44 -08:00
|
|
|
void tiling_window_tree_dump(Window_Tree *root, int level);
|
|
|
|
|
2014-01-13 04:18:48 -08:00
|
|
|
void
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_walk(Window_Tree *root, void (*func)(void *))
|
2014-01-13 04:18:48 -08:00
|
|
|
{
|
|
|
|
Eina_Inlist *itr_safe;
|
|
|
|
Window_Tree *itr;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-01-13 09:28:46 -08:00
|
|
|
if (!root)
|
2014-02-10 01:27:57 -08:00
|
|
|
return;
|
2014-01-13 09:28:46 -08:00
|
|
|
|
2014-01-13 04:18:48 -08:00
|
|
|
EINA_INLIST_FOREACH_SAFE(root->children, itr_safe, itr)
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
tiling_window_tree_walk(itr, func);
|
|
|
|
}
|
2014-01-13 09:18:08 -08:00
|
|
|
func(root);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_free(Window_Tree *root)
|
2014-01-13 09:18:08 -08:00
|
|
|
{
|
|
|
|
tiling_window_tree_walk(root, free);
|
2014-01-13 04:18:48 -08:00
|
|
|
}
|
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
static void
|
2017-03-09 02:14:44 -08:00
|
|
|
_tiling_window_tree_split_add(Window_Tree *parent, Window_Tree *new_node, Eina_Bool append)
|
2014-01-14 04:36:08 -08:00
|
|
|
{
|
|
|
|
/* Make a new node for the parent client and split the weights in half. */
|
|
|
|
Window_Tree *new_parent_client = calloc(1, sizeof(*new_node));
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
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;
|
|
|
|
|
2017-03-09 02:14:44 -08:00
|
|
|
parent->children = eina_inlist_append(parent->children, EINA_INLIST_GET(new_parent_client));
|
|
|
|
|
|
|
|
if (append)
|
|
|
|
parent->children = eina_inlist_append(parent->children, EINA_INLIST_GET(new_node));
|
|
|
|
else
|
|
|
|
parent->children = eina_inlist_prepend(parent->children, EINA_INLIST_GET(new_node));
|
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
}
|
|
|
|
static void
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_parent_add(Window_Tree *parent, Window_Tree *new_node, Window_Tree *rel, Eina_Bool append)
|
2014-01-14 04:36:08 -08:00
|
|
|
{
|
|
|
|
/* Adjust existing children's weights */
|
|
|
|
Window_Tree *itr;
|
|
|
|
int children_count = eina_inlist_count(parent->children);
|
|
|
|
float weight = 1.0 / (children_count + 1);
|
|
|
|
|
|
|
|
new_node->parent = parent;
|
|
|
|
new_node->weight = weight;
|
|
|
|
|
|
|
|
weight *= children_count;
|
|
|
|
EINA_INLIST_FOREACH(parent->children, itr)
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
itr->weight *= weight;
|
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
if (append)
|
|
|
|
{
|
|
|
|
parent->children = eina_inlist_append_relative(parent->children,
|
|
|
|
EINA_INLIST_GET(new_node),
|
|
|
|
EINA_INLIST_GET(rel));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parent->children = eina_inlist_prepend_relative(parent->children,
|
|
|
|
EINA_INLIST_GET(new_node),
|
|
|
|
EINA_INLIST_GET(rel));
|
|
|
|
}
|
2014-01-14 04:36:08 -08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-02-10 01:27:57 -08:00
|
|
|
_tiling_window_tree_split_type_get(Window_Tree *node)
|
2014-01-14 04:36:08 -08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
while (node->parent)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
ret++;
|
|
|
|
node = node->parent;
|
2014-01-14 04:36:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret % 2;
|
|
|
|
}
|
|
|
|
|
2017-03-09 04:23:15 -08:00
|
|
|
#define VERIFY_TYPE(t) if (t > TILING_SPLIT_VERTICAL || t < 0) { ERR("Invalid insert type"); return root; }
|
|
|
|
|
2017-03-09 02:14:44 -08:00
|
|
|
Window_Tree *
|
|
|
|
tiling_window_tree_insert(Window_Tree *root, Window_Tree *buddy,
|
|
|
|
E_Client *client, Tiling_Split_Type split_type, Eina_Bool before)
|
|
|
|
{
|
2017-03-09 04:23:15 -08:00
|
|
|
Window_Tree *new_node;
|
|
|
|
Window_Tree *parent;
|
|
|
|
Tiling_Split_Type parent_split_type;
|
2017-03-09 02:14:44 -08:00
|
|
|
|
2017-03-09 04:23:15 -08:00
|
|
|
VERIFY_TYPE(split_type)
|
|
|
|
|
|
|
|
new_node = calloc(1, sizeof(*new_node));
|
2017-03-09 02:14:44 -08:00
|
|
|
new_node->client = client;
|
|
|
|
|
2017-08-12 13:26:32 -07:00
|
|
|
if (!root)
|
2017-03-09 04:23:15 -08:00
|
|
|
{
|
2017-08-12 13:26:32 -07:00
|
|
|
root = calloc(1, sizeof(*root));
|
|
|
|
root->weight = 1.0;
|
2017-03-09 04:23:15 -08:00
|
|
|
|
2017-08-12 13:26:32 -07:00
|
|
|
_tiling_window_tree_parent_add(root, new_node, NULL, !before);
|
2017-03-09 02:14:44 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-08-12 13:26:32 -07:00
|
|
|
//if there is no buddy we are going to take the last child of the root
|
2017-03-10 12:44:08 -08:00
|
|
|
if (!buddy)
|
2017-08-12 13:26:32 -07:00
|
|
|
{
|
|
|
|
buddy = root;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
buddy = EINA_INLIST_CONTAINER_GET(eina_inlist_last(buddy->children), Window_Tree);
|
|
|
|
}
|
|
|
|
while (!buddy->client);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//make sure this buddy has a client,
|
2017-08-25 11:47:05 -07:00
|
|
|
if (!buddy->client) free(new_node);
|
2017-08-12 13:26:32 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(!buddy->client, root);
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = buddy->parent;
|
|
|
|
parent_split_type = _tiling_window_tree_split_type_get(parent);
|
|
|
|
|
|
|
|
if (parent_split_type == split_type)
|
|
|
|
{
|
|
|
|
_tiling_window_tree_parent_add(parent, new_node, buddy, !before);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_tiling_window_tree_split_add(buddy, new_node, !before);
|
|
|
|
}
|
2017-03-09 02:14:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
static Window_Tree *
|
|
|
|
tiling_window_tree_unref(Window_Tree *root, Window_Tree *item)
|
2014-01-13 04:18:48 -08:00
|
|
|
{
|
2014-10-29 01:10:01 -07:00
|
|
|
if (!item->client)
|
2014-01-13 06:53:12 -08:00
|
|
|
{
|
2014-10-29 01:10:01 -07:00
|
|
|
ERR("Tried to unref node %p that doesn't have a client.", item);
|
2014-02-10 01:27:57 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-01-14 06:03:18 -08:00
|
|
|
Window_Tree *parent = item->parent;
|
2014-01-13 04:18:48 -08:00
|
|
|
int children_count = eina_inlist_count(item->parent->children);
|
|
|
|
|
2014-01-13 06:53:12 -08:00
|
|
|
if (children_count <= 2)
|
2014-01-13 04:18:48 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
Window_Tree *grand_parent = parent->parent;
|
|
|
|
Window_Tree *item_keep = NULL;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(parent->children, item_keep)
|
|
|
|
{
|
|
|
|
if (item_keep != item)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!item_keep)
|
|
|
|
{
|
2014-10-29 01:10:01 -07:00
|
|
|
parent->children =eina_inlist_remove(parent->children, EINA_INLIST_GET(item));
|
|
|
|
return parent;
|
2014-02-10 01:27:57 -08:00
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
else if (!item_keep->children && (parent != root))
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
parent->client = item_keep->client;
|
|
|
|
parent->children = NULL;
|
2014-10-29 01:10:01 -07:00
|
|
|
return grand_parent; //we must have a grand_parent here, case the parent is not root
|
2014-02-10 01:27:57 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-04 10:29:34 -07:00
|
|
|
parent->children =
|
|
|
|
eina_inlist_remove(parent->children, EINA_INLIST_GET(item));
|
2014-02-10 01:27:57 -08:00
|
|
|
if (grand_parent)
|
|
|
|
{
|
|
|
|
/* Update the children's parent. */
|
|
|
|
{
|
|
|
|
Eina_Inlist *itr_safe;
|
|
|
|
Window_Tree *itr;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH_SAFE(item_keep->children, itr_safe,
|
|
|
|
itr)
|
|
|
|
{
|
|
|
|
/* We are prepending to double-reverse the order. */
|
|
|
|
grand_parent->children =
|
|
|
|
eina_inlist_prepend_relative(grand_parent->children,
|
|
|
|
EINA_INLIST_GET(itr), EINA_INLIST_GET(parent));
|
|
|
|
itr->weight *= parent->weight;
|
|
|
|
itr->parent = grand_parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
grand_parent->children =
|
|
|
|
eina_inlist_remove(grand_parent->children,
|
|
|
|
EINA_INLIST_GET(parent));
|
|
|
|
free(parent);
|
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
return grand_parent;
|
2014-02-10 01:27:57 -08:00
|
|
|
}
|
2014-10-29 01:25:04 -07:00
|
|
|
else if (item_keep)
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
/* This is fine, as this is a child of the root so we allow
|
|
|
|
* two levels. */
|
|
|
|
item_keep->weight = 1.0;
|
2014-10-29 01:10:01 -07:00
|
|
|
return item_keep->parent;
|
2014-02-10 01:27:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Window_Tree *itr;
|
|
|
|
float weight = 1.0 - item->weight;
|
|
|
|
|
|
|
|
parent->children =
|
|
|
|
eina_inlist_remove(parent->children, EINA_INLIST_GET(item));
|
|
|
|
|
|
|
|
/* Adjust existing children's weights */
|
|
|
|
EINA_INLIST_FOREACH(parent->children, itr)
|
|
|
|
{
|
|
|
|
itr->weight /= weight;
|
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
return parent;
|
2014-02-04 08:24:44 -08:00
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
ERR("This is a state where we should never come to.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
Window_Tree *
|
|
|
|
tiling_window_tree_remove(Window_Tree *root, Window_Tree *item)
|
|
|
|
{
|
|
|
|
if (root == item)
|
|
|
|
{
|
|
|
|
free(item);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (!item->client)
|
|
|
|
{
|
|
|
|
ERR("Tried deleting node %p that doesn't have a client.", item);
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
tiling_window_tree_unref(root, item);
|
2014-02-04 08:24:44 -08:00
|
|
|
free(item);
|
2014-10-29 01:10:01 -07:00
|
|
|
if (eina_inlist_count(root->children) == 0)
|
|
|
|
{
|
|
|
|
//the last possible client was closed so we remove root
|
|
|
|
free(root);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-04 08:24:44 -08:00
|
|
|
return root;
|
2014-01-13 04:18:48 -08:00
|
|
|
}
|
|
|
|
|
2014-01-13 06:53:12 -08:00
|
|
|
Window_Tree *
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_client_find(Window_Tree *root, E_Client *client)
|
2014-01-13 06:53:12 -08:00
|
|
|
{
|
|
|
|
Window_Tree *itr;
|
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
if (!client)
|
2014-02-10 01:27:57 -08:00
|
|
|
return NULL;
|
2014-01-14 04:36:08 -08:00
|
|
|
|
2014-01-13 06:53:12 -08:00
|
|
|
if (!root || (root->client == client))
|
2014-02-10 01:27:57 -08:00
|
|
|
return root;
|
2014-01-13 06:53:12 -08:00
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(root->children, itr)
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
Window_Tree *ret;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-02-10 01:27:57 -08:00
|
|
|
ret = tiling_window_tree_client_find(itr, client);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
2014-01-13 06:53:12 -08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-02-10 01:27:57 -08:00
|
|
|
_tiling_window_tree_level_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y,
|
2014-08-28 08:30:17 -07:00
|
|
|
Evas_Coord w, Evas_Coord h, int level, Evas_Coord padding,
|
|
|
|
Eina_List **floaters)
|
2014-01-13 06:53:12 -08:00
|
|
|
{
|
|
|
|
Window_Tree *itr;
|
2014-01-14 04:36:08 -08:00
|
|
|
Tiling_Split_Type split_type = level % 2;
|
2014-01-17 06:01:48 -08:00
|
|
|
double total_weight = 0.0;
|
2014-01-13 06:53:12 -08:00
|
|
|
|
2019-08-10 02:57:09 -07:00
|
|
|
root->space.x = x;
|
|
|
|
root->space.y = y;
|
|
|
|
root->space.w = w - padding;
|
|
|
|
root->space.h = h - padding;
|
|
|
|
|
2014-01-13 06:53:12 -08:00
|
|
|
if (root->client)
|
2014-01-17 06:01:48 -08:00
|
|
|
{
|
2014-07-19 10:05:44 -07:00
|
|
|
if (!e_object_is_del(E_OBJECT(root->client)))
|
2014-08-28 08:30:17 -07:00
|
|
|
{
|
|
|
|
if ((root->client->icccm.min_w > (w - padding)) ||
|
2020-07-21 05:46:04 -07:00
|
|
|
(root->client->icccm.min_h > (h - padding))) {
|
2019-08-10 02:57:09 -07:00
|
|
|
*floaters = eina_list_append(*floaters, root->client);
|
2020-07-21 05:46:04 -07:00
|
|
|
} else {
|
|
|
|
tiling_e_client_move_resize_extra(root->client, x, y,
|
|
|
|
w - padding, h - padding);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-28 08:30:17 -07:00
|
|
|
}
|
2014-02-10 01:27:57 -08:00
|
|
|
return;
|
2014-01-17 06:01:48 -08:00
|
|
|
}
|
2014-01-13 06:53:12 -08:00
|
|
|
|
2014-01-14 04:36:08 -08:00
|
|
|
if (split_type == TILING_SPLIT_HORIZONTAL)
|
2014-01-13 06:53:12 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
EINA_INLIST_FOREACH(root->children, itr)
|
|
|
|
{
|
|
|
|
Evas_Coord itw = w * itr->weight;
|
|
|
|
|
|
|
|
total_weight += itr->weight;
|
2014-08-28 08:30:17 -07:00
|
|
|
_tiling_window_tree_level_apply(itr, x, y, itw, h, level + 1, padding, floaters);
|
2014-02-10 01:27:57 -08:00
|
|
|
x += itw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (split_type == TILING_SPLIT_VERTICAL)
|
2014-01-13 06:53:12 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
EINA_INLIST_FOREACH(root->children, itr)
|
|
|
|
{
|
|
|
|
Evas_Coord ith = h * itr->weight;
|
|
|
|
|
|
|
|
total_weight += itr->weight;
|
2014-08-28 08:30:17 -07:00
|
|
|
_tiling_window_tree_level_apply(itr, x, y, w, ith, level + 1, padding, floaters);
|
2014-02-10 01:27:57 -08:00
|
|
|
y += ith;
|
|
|
|
}
|
2014-01-13 06:53:12 -08:00
|
|
|
}
|
2014-01-17 06:01:48 -08:00
|
|
|
|
|
|
|
/* Adjust the last item's weight in case weight < 1.0 */
|
2017-02-11 23:13:00 -08:00
|
|
|
((Window_Tree *)(void *)root->children->last)->weight += 1.0 - total_weight;
|
2014-01-13 06:53:12 -08:00
|
|
|
}
|
2014-01-14 04:36:08 -08:00
|
|
|
|
2019-08-10 02:57:09 -07:00
|
|
|
Eina_Bool
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y,
|
2019-08-10 02:57:09 -07:00
|
|
|
Evas_Coord w, Evas_Coord h, Evas_Coord padding,
|
|
|
|
Eina_Bool force_float)
|
2014-01-14 04:36:08 -08:00
|
|
|
{
|
2014-08-28 08:30:17 -07:00
|
|
|
Eina_List *floaters = NULL;
|
|
|
|
E_Client *ec;
|
|
|
|
|
|
|
|
x += padding;
|
|
|
|
y += padding;
|
|
|
|
w -= padding;
|
|
|
|
h -= padding;
|
|
|
|
_tiling_window_tree_level_apply(root, x, y, w, h, 0, padding, &floaters);
|
|
|
|
|
2019-08-10 02:57:09 -07:00
|
|
|
if (floaters)
|
2014-08-28 08:30:17 -07:00
|
|
|
{
|
2019-08-10 02:57:09 -07:00
|
|
|
// some clients failed to properly fit and maybe SHOULD float
|
|
|
|
EINA_LIST_FREE(floaters, ec)
|
|
|
|
{
|
|
|
|
if (force_float) tiling_e_client_does_not_fit(ec);
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
2014-08-28 08:30:17 -07:00
|
|
|
}
|
2019-08-10 02:57:09 -07:00
|
|
|
return EINA_TRUE;
|
2014-01-14 04:36:08 -08:00
|
|
|
}
|
2014-01-14 06:17:10 -08:00
|
|
|
|
2014-01-14 09:25:32 -08:00
|
|
|
static Window_Tree *
|
2014-02-10 01:27:57 -08:00
|
|
|
_inlist_next(Window_Tree *it)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2017-02-11 23:13:00 -08:00
|
|
|
return (Window_Tree *)(void *)EINA_INLIST_GET(it)->next;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Window_Tree *
|
2014-02-10 01:27:57 -08:00
|
|
|
_inlist_prev(Window_Tree *it)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2017-02-11 23:13:00 -08:00
|
|
|
return (Window_Tree *)(void *)EINA_INLIST_GET(it)->prev;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2014-01-16 07:16:28 -08:00
|
|
|
static Eina_Bool
|
2014-02-10 01:27:57 -08:00
|
|
|
_tiling_window_tree_node_resize_direction(Window_Tree *node,
|
|
|
|
Window_Tree *parent, double dir_diff, int dir)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
|
|
|
double weight = 0.0;
|
|
|
|
double weight_diff;
|
|
|
|
Window_Tree *children_start;
|
|
|
|
Window_Tree *itr;
|
2014-02-10 01:27:57 -08:00
|
|
|
Window_Tree *(*itr_func)(Window_Tree *);
|
2014-01-14 09:25:32 -08:00
|
|
|
|
|
|
|
if (dir > 0)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
itr_func = _inlist_prev;
|
2017-02-11 23:13:00 -08:00
|
|
|
children_start = (Window_Tree *)(void *)parent->children->last;
|
2014-02-10 01:27:57 -08:00
|
|
|
}
|
|
|
|
else
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
itr_func = _inlist_next;
|
2017-02-11 23:13:00 -08:00
|
|
|
children_start = (Window_Tree *)(void *)parent->children;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2014-02-10 01:27:57 -08:00
|
|
|
itr = (Window_Tree *)children_start;
|
2014-01-14 09:25:32 -08:00
|
|
|
while (itr != node)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
weight += itr->weight;
|
2014-01-14 09:25:32 -08:00
|
|
|
|
2014-02-10 01:27:57 -08:00
|
|
|
itr = itr_func(itr);
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2014-01-16 07:16:28 -08:00
|
|
|
/* If it's at the edge, try the grandpa of the parent. */
|
2017-01-06 09:56:22 -08:00
|
|
|
if (!EINA_DBL_NONZERO(weight))
|
2014-01-16 07:16:28 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
if (parent->parent && parent->parent->parent)
|
|
|
|
{
|
|
|
|
return _tiling_window_tree_node_resize_direction(parent->parent,
|
|
|
|
parent->parent->parent, 1.0 + ((dir_diff - 1.) * node->weight),
|
|
|
|
dir);
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
2014-01-16 07:16:28 -08:00
|
|
|
}
|
2014-01-14 09:25:32 -08:00
|
|
|
|
|
|
|
weight_diff = itr->weight;
|
|
|
|
itr->weight *= dir_diff;
|
|
|
|
weight_diff -= itr->weight;
|
|
|
|
weight_diff /= weight;
|
|
|
|
|
2014-02-04 08:24:44 -08:00
|
|
|
for (itr = children_start; itr != node; itr = itr_func(itr))
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
itr->weight += itr->weight * weight_diff;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
2014-01-16 07:16:28 -08:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2014-01-16 07:16:28 -08:00
|
|
|
Eina_Bool
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff,
|
|
|
|
int h_dir, double h_diff)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
|
|
|
Window_Tree *parent = node->parent;
|
|
|
|
Window_Tree *w_parent, *h_parent;
|
2014-01-16 07:16:28 -08:00
|
|
|
Eina_Bool ret = EINA_FALSE;
|
2014-01-14 09:25:32 -08:00
|
|
|
|
|
|
|
/* If we have no parent, means we need to be full screen anyway. */
|
|
|
|
if (!parent)
|
2014-02-10 01:27:57 -08:00
|
|
|
return EINA_FALSE;
|
2014-01-14 09:25:32 -08:00
|
|
|
|
|
|
|
Window_Tree *grand_parent = parent->parent;
|
2014-02-04 08:24:44 -08:00
|
|
|
Tiling_Split_Type parent_split_type =
|
2014-02-10 01:27:57 -08:00
|
|
|
_tiling_window_tree_split_type_get(parent);
|
2014-01-14 09:25:32 -08:00
|
|
|
|
|
|
|
/* w_diff related changes. */
|
|
|
|
if (parent_split_type == TILING_SPLIT_HORIZONTAL)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
w_parent = parent;
|
|
|
|
h_parent = grand_parent;
|
|
|
|
}
|
|
|
|
else
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
w_parent = grand_parent;
|
|
|
|
h_parent = parent;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:05:17 -08:00
|
|
|
if ((!eina_dbl_exact(h_diff, 1.0)) && h_parent)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
Window_Tree *tmp_node = (h_parent == parent) ? node : parent;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-02-10 01:27:57 -08:00
|
|
|
ret = ret ||
|
|
|
|
_tiling_window_tree_node_resize_direction(tmp_node, h_parent,
|
|
|
|
h_diff, h_dir);
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:05:17 -08:00
|
|
|
if ((!eina_dbl_exact(w_diff, 1.0)) && w_parent)
|
2014-01-14 09:25:32 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
Window_Tree *tmp_node = (w_parent == parent) ? node : parent;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-02-10 01:27:57 -08:00
|
|
|
ret = ret ||
|
|
|
|
_tiling_window_tree_node_resize_direction(tmp_node, w_parent,
|
|
|
|
w_diff, w_dir);
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
2014-01-16 07:16:28 -08:00
|
|
|
|
|
|
|
return ret;
|
2014-01-14 09:25:32 -08:00
|
|
|
}
|
|
|
|
|
2014-01-16 09:18:29 -08:00
|
|
|
int
|
2014-02-10 01:27:57 -08:00
|
|
|
_tiling_window_tree_edges_get_helper(Window_Tree *node,
|
|
|
|
Tiling_Split_Type split_type, Eina_Bool gave_up_this,
|
|
|
|
Eina_Bool gave_up_parent)
|
2014-01-16 09:18:29 -08:00
|
|
|
{
|
2014-02-04 08:24:44 -08:00
|
|
|
int ret =
|
2014-02-10 01:27:57 -08:00
|
|
|
TILING_WINDOW_TREE_EDGE_LEFT | TILING_WINDOW_TREE_EDGE_RIGHT |
|
|
|
|
TILING_WINDOW_TREE_EDGE_TOP | TILING_WINDOW_TREE_EDGE_BOTTOM;
|
2014-01-16 09:18:29 -08:00
|
|
|
if (!node->parent)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else if (gave_up_this && gave_up_parent)
|
2014-01-16 09:18:29 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (gave_up_this)
|
2014-01-16 09:18:29 -08:00
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
/* Mixed the gave_up vals on purpose, we do it on every call. */
|
|
|
|
return _tiling_window_tree_edges_get_helper(node->parent, !split_type,
|
|
|
|
gave_up_parent, gave_up_this);
|
2014-01-16 09:18:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EINA_INLIST_GET(node)->prev)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
gave_up_this = EINA_TRUE;
|
|
|
|
ret ^=
|
|
|
|
(split_type ==
|
|
|
|
TILING_SPLIT_HORIZONTAL) ? TILING_WINDOW_TREE_EDGE_LEFT :
|
|
|
|
TILING_WINDOW_TREE_EDGE_TOP;
|
2014-01-16 09:18:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EINA_INLIST_GET(node)->next)
|
|
|
|
{
|
2014-02-10 01:27:57 -08:00
|
|
|
gave_up_this = EINA_TRUE;
|
|
|
|
ret ^=
|
|
|
|
(split_type ==
|
|
|
|
TILING_SPLIT_HORIZONTAL) ? TILING_WINDOW_TREE_EDGE_RIGHT :
|
|
|
|
TILING_WINDOW_TREE_EDGE_BOTTOM;
|
2014-01-16 09:18:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Mixed the gave_up vals on purpose, we do it on every call. */
|
2014-02-04 08:24:44 -08:00
|
|
|
return ret & _tiling_window_tree_edges_get_helper(node->parent, !split_type,
|
2014-02-10 01:27:57 -08:00
|
|
|
gave_up_parent, gave_up_this);
|
2014-01-16 09:18:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_edges_get(Window_Tree *node)
|
2014-01-16 09:18:29 -08:00
|
|
|
{
|
|
|
|
Tiling_Split_Type split_type = _tiling_window_tree_split_type_get(node);
|
|
|
|
|
|
|
|
return _tiling_window_tree_edges_get_helper(node, !split_type, EINA_FALSE,
|
2014-02-10 01:27:57 -08:00
|
|
|
EINA_FALSE);
|
2014-01-16 09:18:29 -08:00
|
|
|
}
|
|
|
|
|
2014-01-17 05:51:57 -08:00
|
|
|
/* Node move */
|
2014-10-29 01:10:01 -07:00
|
|
|
/**
|
|
|
|
* - break would mean that the node will be breaked out in the parent node and
|
2014-11-25 04:32:43 -08:00
|
|
|
* put into the grand parent node. If there is no grand parent node a fake node will be placed there.
|
2014-10-29 01:10:01 -07:00
|
|
|
*
|
|
|
|
* - join would mean that the node will be put together with the next/previous
|
|
|
|
* child into a new split.
|
|
|
|
*
|
|
|
|
* - The eina_bool dir is the flag in which direction the node will be added ,
|
|
|
|
* appended or prependet, or joined with the previous child or the next child
|
|
|
|
*/
|
|
|
|
void
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_node_break_out(Window_Tree *root, Window_Tree *node, Window_Tree *par, Eina_Bool dir)
|
2014-01-20 04:08:12 -08:00
|
|
|
{
|
2014-11-03 06:32:05 -08:00
|
|
|
Window_Tree *res, *ac; /* ac is the child of the root, that is a parent of a node */
|
|
|
|
|
2014-11-25 04:32:43 -08:00
|
|
|
if (!par)
|
|
|
|
{
|
|
|
|
/* we have no parent, so we add a new node between this, later we do the normal break, */
|
|
|
|
Window_Tree *rnode, *newnode, *newnode2;
|
|
|
|
Eina_Inlist *il;
|
|
|
|
|
|
|
|
newnode2 = calloc(1, sizeof(Window_Tree));
|
|
|
|
newnode2->parent = root;
|
|
|
|
newnode2->weight = 1.0;
|
|
|
|
|
|
|
|
newnode = calloc(1, sizeof(Window_Tree));
|
|
|
|
newnode->weight = 1.0;
|
|
|
|
newnode->parent = newnode2;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH_SAFE(root->children, il, rnode)
|
|
|
|
{
|
|
|
|
rnode->parent = newnode;
|
|
|
|
root->children = eina_inlist_remove(root->children, EINA_INLIST_GET(rnode));
|
|
|
|
newnode->children = eina_inlist_append(newnode->children, EINA_INLIST_GET(rnode));
|
|
|
|
}
|
|
|
|
|
|
|
|
root->children = eina_inlist_append(root->children, EINA_INLIST_GET(newnode2));
|
|
|
|
newnode2->children = eina_inlist_append(newnode2->children, EINA_INLIST_GET(newnode));
|
|
|
|
par = newnode2;
|
|
|
|
|
|
|
|
}
|
2014-11-03 06:32:05 -08:00
|
|
|
|
|
|
|
/* search a path from the node to the par */
|
|
|
|
ac = node;
|
|
|
|
while (ac->parent != par)
|
|
|
|
ac = ac->parent;
|
2014-01-20 04:08:12 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
if (dir)
|
2014-01-20 04:08:12 -08:00
|
|
|
{
|
2014-11-03 06:32:05 -08:00
|
|
|
res = _inlist_next(ac);
|
2014-10-29 01:10:01 -07:00
|
|
|
if (res)
|
2014-10-29 01:25:04 -07:00
|
|
|
{
|
|
|
|
dir = EINA_FALSE;
|
|
|
|
}
|
2014-01-20 04:08:12 -08:00
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
else
|
2014-01-17 05:51:57 -08:00
|
|
|
{
|
2014-11-03 06:32:05 -08:00
|
|
|
res = _inlist_prev(ac);
|
2014-10-29 01:10:01 -07:00
|
|
|
if (res)
|
2014-10-29 01:25:04 -07:00
|
|
|
{
|
|
|
|
dir = EINA_TRUE;
|
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
}
|
2014-02-10 01:27:57 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
tiling_window_tree_unref(root, node);
|
2014-02-10 01:27:57 -08:00
|
|
|
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_parent_add(par, node, res, dir);
|
2014-01-17 05:51:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_node_join(Window_Tree *root, Window_Tree *node, Eina_Bool dir)
|
2014-01-17 05:51:57 -08:00
|
|
|
{
|
2014-11-25 04:32:43 -08:00
|
|
|
Window_Tree *pn, *pl, *par;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
if (dir)
|
|
|
|
pn = _inlist_next(node);
|
|
|
|
else
|
|
|
|
pn = _inlist_prev(node);
|
2014-01-17 05:51:57 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
if (!pn)
|
2014-11-03 06:32:05 -08:00
|
|
|
{
|
|
|
|
if (node->parent && node->parent->parent && node->parent->parent->parent)
|
2014-11-03 06:45:03 -08:00
|
|
|
{
|
|
|
|
_tiling_window_tree_node_break_out(root, node, node->parent->parent->parent, dir);
|
|
|
|
}
|
|
|
|
|
2014-11-03 06:32:05 -08:00
|
|
|
return;
|
|
|
|
}
|
2014-01-17 05:51:57 -08:00
|
|
|
|
2014-10-29 01:25:04 -07:00
|
|
|
par = node->parent;
|
2014-11-25 04:32:43 -08:00
|
|
|
if ((eina_inlist_count(par->children) == 2) &&
|
|
|
|
((_inlist_next(node) && _inlist_next(node)->client) ||
|
|
|
|
(_inlist_prev(node) && _inlist_prev(node)->client)))
|
|
|
|
/* swap if there are just 2 simple windows*/
|
2014-10-29 01:25:04 -07:00
|
|
|
{
|
|
|
|
par->children = eina_inlist_demote(par->children, eina_inlist_first(par->children));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pl = tiling_window_tree_unref(root, node);
|
|
|
|
if (pl == node->parent)
|
|
|
|
{
|
|
|
|
//unref has not changed the tree
|
|
|
|
if (!pn->children)
|
|
|
|
{
|
2017-03-09 02:14:44 -08:00
|
|
|
_tiling_window_tree_split_add(pn, node, EINA_TRUE);
|
2014-10-29 01:25:04 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_tiling_window_tree_parent_add(pn, node, NULL, EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//unref changed the position of pn in the tree, result of unref
|
|
|
|
//will be the new parent
|
2014-11-25 04:32:43 -08:00
|
|
|
_tiling_window_tree_parent_add(pl, node, NULL, EINA_TRUE);
|
2014-10-29 01:25:04 -07:00
|
|
|
}
|
|
|
|
}
|
2014-10-29 01:10:01 -07:00
|
|
|
}
|
2014-01-17 05:51:57 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
void
|
|
|
|
tiling_window_tree_node_change_pos(Window_Tree *node, int key)
|
|
|
|
{
|
|
|
|
if (!node->parent)
|
|
|
|
return;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
Tiling_Split_Type parent_split_type =
|
|
|
|
_tiling_window_tree_split_type_get(node->parent);
|
|
|
|
|
2014-11-03 06:32:05 -08:00
|
|
|
Window_Tree *root = node->parent,
|
2014-11-25 00:11:18 -08:00
|
|
|
*grand_parent = NULL;
|
2014-10-29 01:10:01 -07:00
|
|
|
while(root->parent)
|
|
|
|
root = root->parent;
|
2014-11-03 06:32:05 -08:00
|
|
|
|
|
|
|
if (node->parent && node->parent->parent)
|
|
|
|
grand_parent = node->parent->parent;
|
|
|
|
|
2014-10-29 01:10:01 -07:00
|
|
|
switch(key)
|
|
|
|
{
|
2014-10-29 01:25:04 -07:00
|
|
|
case TILING_WINDOW_TREE_EDGE_LEFT:
|
|
|
|
if (parent_split_type == TILING_SPLIT_HORIZONTAL)
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_node_join(root, node, EINA_FALSE);
|
2014-10-29 01:25:04 -07:00
|
|
|
else if (parent_split_type == TILING_SPLIT_VERTICAL)
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_node_break_out(root, node, grand_parent, EINA_FALSE);
|
2014-10-29 01:25:04 -07:00
|
|
|
break;
|
|
|
|
case TILING_WINDOW_TREE_EDGE_RIGHT:
|
|
|
|
if (parent_split_type == TILING_SPLIT_HORIZONTAL)
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_node_join(root, node, EINA_TRUE);
|
2014-10-29 01:25:04 -07:00
|
|
|
else if (parent_split_type == TILING_SPLIT_VERTICAL)
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_node_break_out(root, node, grand_parent,EINA_TRUE);
|
2014-10-29 01:25:04 -07:00
|
|
|
break;
|
|
|
|
case TILING_WINDOW_TREE_EDGE_TOP:
|
|
|
|
if (parent_split_type == TILING_SPLIT_HORIZONTAL)
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_node_break_out(root, node, grand_parent, EINA_FALSE);
|
2014-10-29 01:25:04 -07:00
|
|
|
else if (parent_split_type == TILING_SPLIT_VERTICAL)
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_node_join(root, node, EINA_FALSE);
|
2014-10-29 01:25:04 -07:00
|
|
|
break;
|
|
|
|
case TILING_WINDOW_TREE_EDGE_BOTTOM:
|
|
|
|
if (parent_split_type == TILING_SPLIT_HORIZONTAL)
|
2014-11-03 06:32:05 -08:00
|
|
|
_tiling_window_tree_node_break_out(root, node, grand_parent, EINA_TRUE);
|
2014-10-29 01:25:04 -07:00
|
|
|
else if (parent_split_type == TILING_SPLIT_VERTICAL)
|
2014-10-29 01:10:01 -07:00
|
|
|
_tiling_window_tree_node_join(root, node, EINA_TRUE);
|
|
|
|
break;
|
2014-01-17 05:51:57 -08:00
|
|
|
}
|
|
|
|
}
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-01-17 05:51:57 -08:00
|
|
|
/* End Node move. */
|
|
|
|
|
2014-01-14 06:17:10 -08:00
|
|
|
void
|
2014-02-10 01:27:57 -08:00
|
|
|
tiling_window_tree_dump(Window_Tree *root, int level)
|
2014-01-14 06:17:10 -08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!root)
|
2014-02-10 01:27:57 -08:00
|
|
|
return;
|
2014-01-14 06:17:10 -08:00
|
|
|
|
2014-02-04 08:24:44 -08:00
|
|
|
for (i = 0; i < level; i++)
|
2014-02-10 01:27:57 -08:00
|
|
|
printf(" ");
|
2014-01-14 06:17:10 -08:00
|
|
|
|
|
|
|
if (root->children)
|
2014-02-10 01:27:57 -08:00
|
|
|
printf("\\-");
|
2014-01-14 06:17:10 -08:00
|
|
|
else
|
2014-02-10 01:27:57 -08:00
|
|
|
printf("|-");
|
2014-01-14 06:17:10 -08:00
|
|
|
|
2014-01-20 02:38:22 -08:00
|
|
|
printf("%f (%p)\n", root->weight, root->client);
|
2014-01-14 06:17:10 -08:00
|
|
|
|
|
|
|
Window_Tree *itr;
|
2014-02-04 08:24:44 -08:00
|
|
|
|
2014-01-14 06:17:10 -08:00
|
|
|
EINA_INLIST_FOREACH(root->children, itr)
|
2014-02-10 01:27:57 -08:00
|
|
|
{
|
|
|
|
tiling_window_tree_dump(itr, level + 1);
|
|
|
|
}
|
2017-03-09 02:14:44 -08:00
|
|
|
}
|