From b5434d1de570a7898819e0addd40a8060793fde3 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 16 Jan 2014 17:18:29 +0000 Subject: [PATCH] Tiling2: Restrict allowed resizes of windows. --- src/modules/tiling/e_mod_tiling.c | 103 ++++++++++++++++++++++++++++++ src/modules/tiling/window_tree.c | 49 ++++++++++++++ src/modules/tiling/window_tree.h | 7 ++ 3 files changed, 159 insertions(+) diff --git a/src/modules/tiling/e_mod_tiling.c b/src/modules/tiling/e_mod_tiling.c index 6965dadd3..c014ea8ff 100644 --- a/src/modules/tiling/e_mod_tiling.c +++ b/src/modules/tiling/e_mod_tiling.c @@ -732,6 +732,108 @@ static void _move_or_resize(E_Client *ec) _reapply_tree(); } +static void +_resize_begin_hook(void *data EINA_UNUSED, E_Client *ec) +{ + Client_Extra *extra; + + if (!ec) { + return; + } + if (!is_tilable(ec)) { + return; + } + + if (!desk_should_tile_check(ec->desk)) + return; + + extra = eina_hash_find(_G.client_extras, &ec); + if (!extra) { + ERR("No extra for %p", ec); + return; + } + + if (is_ignored_window(extra)) + 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 edges = tiling_window_tree_edges_get(item); + if (edges & TILING_WINDOW_TREE_EDGE_LEFT) + { + switch (ec->resize_mode) + { + case E_POINTER_RESIZE_L: + ec->resize_mode = E_POINTER_RESIZE_NONE; + break; + case E_POINTER_RESIZE_TL: + ec->resize_mode = E_POINTER_RESIZE_T; + break; + case E_POINTER_RESIZE_BL: + ec->resize_mode = E_POINTER_RESIZE_B; + break; + default: + break; + } + } + if (edges & TILING_WINDOW_TREE_EDGE_RIGHT) + { + switch (ec->resize_mode) + { + case E_POINTER_RESIZE_R: + ec->resize_mode = E_POINTER_RESIZE_NONE; + break; + case E_POINTER_RESIZE_TR: + ec->resize_mode = E_POINTER_RESIZE_T; + break; + case E_POINTER_RESIZE_BR: + ec->resize_mode = E_POINTER_RESIZE_B; + break; + default: + break; + } + } + if (edges & TILING_WINDOW_TREE_EDGE_TOP) + { + switch (ec->resize_mode) + { + case E_POINTER_RESIZE_T: + ec->resize_mode = E_POINTER_RESIZE_NONE; + break; + case E_POINTER_RESIZE_TL: + ec->resize_mode = E_POINTER_RESIZE_L; + break; + case E_POINTER_RESIZE_TR: + ec->resize_mode = E_POINTER_RESIZE_R; + break; + default: + break; + } + } + if (edges & TILING_WINDOW_TREE_EDGE_BOTTOM) + { + switch (ec->resize_mode) + { + case E_POINTER_RESIZE_B: + ec->resize_mode = E_POINTER_RESIZE_NONE; + break; + case E_POINTER_RESIZE_BL: + ec->resize_mode = E_POINTER_RESIZE_L; + break; + case E_POINTER_RESIZE_BR: + ec->resize_mode = E_POINTER_RESIZE_R; + break; + default: + break; + } + } +} + static Eina_Bool _resize_hook(void *data __UNUSED__, int type __UNUSED__, E_Event_Client *event) { @@ -1014,6 +1116,7 @@ e_modapi_init(E_Module *m) (Ecore_Event_Handler_Cb) _f, \ NULL); + e_client_hook_add(E_CLIENT_HOOK_RESIZE_BEGIN, _resize_begin_hook, NULL); HANDLER(_G.handler_client_resize, CLIENT_RESIZE, _resize_hook); HANDLER(_G.handler_client_move, CLIENT_MOVE, _move_hook); HANDLER(_G.handler_client_add, CLIENT_ADD, _add_hook); diff --git a/src/modules/tiling/window_tree.c b/src/modules/tiling/window_tree.c index 0ecc77a15..64a71c0cf 100644 --- a/src/modules/tiling/window_tree.c +++ b/src/modules/tiling/window_tree.c @@ -396,6 +396,55 @@ tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int return ret; } +int +_tiling_window_tree_edges_get_helper(Window_Tree *node, Tiling_Split_Type split_type, Eina_Bool gave_up_this, + Eina_Bool gave_up_parent) +{ + int ret = TILING_WINDOW_TREE_EDGE_LEFT | TILING_WINDOW_TREE_EDGE_RIGHT | + TILING_WINDOW_TREE_EDGE_TOP | TILING_WINDOW_TREE_EDGE_BOTTOM; + if (!node->parent) + { + return ret; + } + else if (gave_up_this && gave_up_parent) + { + return 0; + } + else if (gave_up_this) + { + /* 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); + } + + if (EINA_INLIST_GET(node)->prev) + { + gave_up_this = EINA_TRUE; + ret ^= (split_type == TILING_SPLIT_HORIZONTAL) ? + TILING_WINDOW_TREE_EDGE_LEFT : TILING_WINDOW_TREE_EDGE_TOP; + } + + if (EINA_INLIST_GET(node)->next) + { + gave_up_this = EINA_TRUE; + ret ^= (split_type == TILING_SPLIT_HORIZONTAL) ? + TILING_WINDOW_TREE_EDGE_RIGHT : TILING_WINDOW_TREE_EDGE_BOTTOM; + } + + /* Mixed the gave_up vals on purpose, we do it on every call. */ + return ret & _tiling_window_tree_edges_get_helper(node->parent, !split_type ,gave_up_parent, + gave_up_this); +} + +int +tiling_window_tree_edges_get(Window_Tree *node) +{ + Tiling_Split_Type split_type = _tiling_window_tree_split_type_get(node); + + return _tiling_window_tree_edges_get_helper(node, !split_type, EINA_FALSE, + EINA_FALSE); +} + 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 6cca18c1b..424a92943 100644 --- a/src/modules/tiling/window_tree.h +++ b/src/modules/tiling/window_tree.h @@ -21,6 +21,13 @@ struct _Window_Tree double weight; }; +#define TILING_WINDOW_TREE_EDGE_LEFT (1 << 0) +#define TILING_WINDOW_TREE_EDGE_RIGHT (1 << 1) +#define TILING_WINDOW_TREE_EDGE_TOP (1 << 2) +#define TILING_WINDOW_TREE_EDGE_BOTTOM (1 << 3) + +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 *));