From 6b606cde418f4215b6d4d6da2f45cd1e094e511c Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 14 Jan 2014 17:25:32 +0000 Subject: [PATCH] Tiling2: Added resizing support. There are still some bugs. --- src/modules/tiling/e_mod_tiling.c | 61 +++++++++++++++++++- src/modules/tiling/window_tree.c | 94 +++++++++++++++++++++++++++++++ src/modules/tiling/window_tree.h | 4 +- 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/src/modules/tiling/e_mod_tiling.c b/src/modules/tiling/e_mod_tiling.c index 13cbb0f10..b317e2645 100644 --- a/src/modules/tiling/e_mod_tiling.c +++ b/src/modules/tiling/e_mod_tiling.c @@ -333,10 +333,18 @@ tiling_e_client_move_resize_extra(E_Client *ec, int w, int h) { - Client_Extra *extra = _get_or_create_client_extra(ec); - if (!extra) { + Client_Extra *extra = eina_hash_find(_G.client_extras, &ec); + if (!extra) { ERR("No extra for %p", ec); - } + return; + } + + extra->expected = (geom_t) { + .x = x, + .y = y, + .w = w, + .h = h, + }; _e_client_move_resize(ec, x, y, w, h); } @@ -597,6 +605,12 @@ static void _move_or_resize(E_Client *ec) if (!ec) { return; } + if (is_floating_window(ec)) { + return; + } + if (!is_tilable(ec)) { + return; + } if (!desk_should_tile_check(ec->desk)) return; @@ -618,6 +632,47 @@ static void _move_or_resize(E_Client *ec) return; } + if ((ec->x == extra->expected.x) && (ec->y == extra->expected.y) && + (ec->w == extra->expected.w) && (ec->h == extra->expected.h)) + { + + return; + } + + Window_Tree *item = tiling_window_tree_client_find(_G.tinfo->tree, ec); + if (!item) + { + ERR("Couldn't find tree item for resized client %p!", ec); + return; + } + + { + int w_dir = 1, h_dir = 1; + double w_diff = 1.0, h_diff = 1.0; + if (abs(extra->expected.w - ec->w) >= MAX(ec->icccm.step_w, 1)) + { + w_diff = ((double) ec->w) / extra->expected.w; + printf("w %d %d %f\n", extra->expected.w, ec->w, w_diff); + } + if (abs(extra->expected.h - ec->h) >= MAX(ec->icccm.step_h, 1)) + { + h_diff = ((double) ec->h) / extra->expected.h; + printf("h %d %d %f\n", extra->expected.h, ec->h, h_diff); + } + if (extra->expected.x != ec->x) + { + w_dir = -1; + } + if (extra->expected.y != ec->y) + { + h_dir = -1; + } + if ((w_diff != 1.0) || (h_diff != 1.0)) + { + tiling_window_tree_node_resize(item, w_dir, w_diff, h_dir, h_diff); + } + } + _reapply_tree(); } diff --git a/src/modules/tiling/window_tree.c b/src/modules/tiling/window_tree.c index 350966e22..41ee12ec7 100644 --- a/src/modules/tiling/window_tree.c +++ b/src/modules/tiling/window_tree.c @@ -281,6 +281,100 @@ tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y, _tiling_window_tree_level_apply(root, x, y, w, h, 0); } +static Window_Tree * +_inlist_next(Window_Tree *it) +{ + return (Window_Tree *) EINA_INLIST_GET(it)->next; +} + +static Window_Tree * +_inlist_prev(Window_Tree *it) +{ + return (Window_Tree *) EINA_INLIST_GET(it)->prev; +} + +static void +_tiling_window_tree_node_resize_direction(Window_Tree *node, Window_Tree *parent, + double dir_diff, int dir) +{ + double weight = 0.0; + double weight_diff; + Window_Tree *children_start; + Window_Tree *itr; + Window_Tree *(*itr_func)(Window_Tree *); + + if (dir > 0) + { + itr_func = _inlist_prev; + children_start = (Window_Tree *) parent->children->last; + } + else + { + itr_func = _inlist_next; + children_start = (Window_Tree *) parent->children; + } + + + itr = (Window_Tree *) children_start; + while (itr != node) + { + weight += itr->weight; + + itr = itr_func(itr); + } + + if (weight == 0.0) + return; + + weight_diff = itr->weight; + itr->weight *= dir_diff; + weight_diff -= itr->weight; + weight_diff /= weight; + + for (itr = children_start ; itr != node ; itr = itr_func(itr)) + { + itr->weight += itr->weight * weight_diff; + } +} + +void +tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int h_dir, double h_diff) +{ + Window_Tree *parent = node->parent; + Window_Tree *w_parent, *h_parent; + + /* If we have no parent, means we need to be full screen anyway. */ + if (!parent) + return; + + Window_Tree *grand_parent = parent->parent; + Tiling_Split_Type parent_split_type = _tiling_window_tree_split_type_get(parent); + + /* w_diff related changes. */ + if (parent_split_type == TILING_SPLIT_HORIZONTAL) + { + w_parent = parent; + h_parent = grand_parent; + } + else + { + w_parent = grand_parent; + h_parent = parent; + } + + if ((h_diff != 1.0) && h_parent) + { + Window_Tree *tmp_node = (h_parent == parent) ? node : parent; + _tiling_window_tree_node_resize_direction(tmp_node, h_parent, h_diff, h_dir); + } + + if ((w_diff != 1.0) && w_parent) + { + Window_Tree *tmp_node = (w_parent == parent) ? node : parent; + _tiling_window_tree_node_resize_direction(tmp_node, w_parent, w_diff, w_dir); + } +} + void tiling_window_tree_dump(Window_Tree *root, int level) { diff --git a/src/modules/tiling/window_tree.h b/src/modules/tiling/window_tree.h index 520899ca3..5241e2718 100644 --- a/src/modules/tiling/window_tree.h +++ b/src/modules/tiling/window_tree.h @@ -18,7 +18,7 @@ struct _Window_Tree /* FIXME: client is falid iff children is null. Sholud enforce it. */ Eina_Inlist *children; /* Window_Tree * type */ E_Client *client; - float weight; + double weight; }; void tiling_window_tree_free(Window_Tree *root); @@ -32,4 +32,6 @@ 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); +void tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int h_dir, double h_diff); + #endif