From de21e6ddb82bb0e6a9c7b5c7b9e997f48d3c3df8 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Sat, 12 Aug 2017 22:26:32 +0200 Subject: [PATCH] tiling: fix insertion in the tree the problem here was that in the initial case the function got the previous state of the tree wrong, so the insertion of a second client ended up in a unpossible state of the tree, this should not happen anymore now. The insertion is now also way more stable, since in a errorcase the client is not just not placed in the tree but associated with a window tree, its just not placing the client in the window tree at all. --- src/modules/tiling/e_mod_tiling.c | 2 +- src/modules/tiling/window_tree.c | 53 +++++++++++++++++-------------- src/modules/tiling/window_tree.h | 10 ++++++ 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/modules/tiling/e_mod_tiling.c b/src/modules/tiling/e_mod_tiling.c index 775e38a5c..3b86d33f1 100644 --- a/src/modules/tiling/e_mod_tiling.c +++ b/src/modules/tiling/e_mod_tiling.c @@ -703,7 +703,7 @@ _insert_client_prefered(E_Client *ec) } else { - _G.tinfo->tree = tiling_window_tree_insert(_G.tinfo->tree, _G.tinfo->tree, ec, _current_tiled_state(EINA_FALSE), EINA_FALSE); + _G.tinfo->tree = tiling_window_tree_insert(_G.tinfo->tree, NULL, ec, _current_tiled_state(EINA_FALSE), EINA_FALSE); } } diff --git a/src/modules/tiling/window_tree.c b/src/modules/tiling/window_tree.c index d0e61d5b6..b64a18889 100644 --- a/src/modules/tiling/window_tree.c +++ b/src/modules/tiling/window_tree.c @@ -95,13 +95,6 @@ _tiling_window_tree_split_type_get(Window_Tree *node) #define VERIFY_TYPE(t) if (t > TILING_SPLIT_VERTICAL || t < 0) { ERR("Invalid insert type"); return root; } -#define ROOT_CHECK() \ - if (!root) \ - { \ - new_node->weight = 1.0; \ - return new_node; \ - } - Window_Tree * tiling_window_tree_insert(Window_Tree *root, Window_Tree *buddy, E_Client *client, Tiling_Split_Type split_type, Eina_Bool before) @@ -115,28 +108,42 @@ tiling_window_tree_insert(Window_Tree *root, Window_Tree *buddy, new_node = calloc(1, sizeof(*new_node)); new_node->client = client; - ROOT_CHECK() - - parent = buddy->parent; - - if (!parent) + if (!root) { - //this means buddy is the root so just set buddy to NULL and parent to buddy - parent = buddy; - buddy = NULL; - } + root = calloc(1, sizeof(*root)); + root->weight = 1.0; - 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); + _tiling_window_tree_parent_add(root, new_node, NULL, !before); } else { + //if there is no buddy we are going to take the last child of the root if (!buddy) - buddy = root; - _tiling_window_tree_split_add(buddy, new_node, !before); + { + 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, + 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); + } } return root; diff --git a/src/modules/tiling/window_tree.h b/src/modules/tiling/window_tree.h index 93baba858..364305c3d 100644 --- a/src/modules/tiling/window_tree.h +++ b/src/modules/tiling/window_tree.h @@ -34,6 +34,16 @@ int tiling_window_tree_edges_get(Window_Tree *node); void tiling_window_tree_free(Window_Tree *root); void tiling_window_tree_walk(Window_Tree *root, void (*func)(void *)); +/** + * Insert a new client into the tree + * + * @param root the root node where to insert in some subtree + * @param buddy the buddy where you want to place client to, buddy MUST be a node with a associated client OR NULL + * @param split_type the split type you want to insert the client + * @param before true to insert the client before the buddy false to insert it after the buddy + * + * @return the new root node + */ Window_Tree *tiling_window_tree_insert(Window_Tree *root, Window_Tree *buddy, E_Client *client, Tiling_Split_Type split_type, Eina_Bool before);