From 6795380282bf4abea57b7ba34ffb7c4f986f3073 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 17 Jan 2014 13:51:57 +0000 Subject: [PATCH] Tiling2: Added support for swapping windows. --- src/modules/tiling/e_mod_tiling.c | 65 +++++++++++++++++++++++++--- src/modules/tiling/window_tree.c | 72 +++++++++++++++++++++++++++++++ src/modules/tiling/window_tree.h | 2 + 3 files changed, 132 insertions(+), 7 deletions(-) diff --git a/src/modules/tiling/e_mod_tiling.c b/src/modules/tiling/e_mod_tiling.c index f7b5870d7..f65947b48 100644 --- a/src/modules/tiling/e_mod_tiling.c +++ b/src/modules/tiling/e_mod_tiling.c @@ -65,7 +65,10 @@ static struct tiling_mod_main_g Eina_Hash *overlays; E_Action *act_togglefloat, - *act_swap, + *act_move_up, + *act_move_down, + *act_move_left, + *act_move_right, *act_toggle_split_mode; int warp_x, @@ -530,11 +533,10 @@ _e_mod_menu_border_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED } /* }}} */ -/* {{{ Swap */ +/* {{{ Move windows */ static void -_e_mod_action_swap_cb(E_Object *obj __UNUSED__, - const char *params __UNUSED__) +_action_swap(int cross_edge) { E_Desk *desk; E_Client *focused_ec; @@ -550,6 +552,42 @@ _e_mod_action_swap_cb(E_Object *obj __UNUSED__, if (!desk_should_tile_check(desk)) return; + Window_Tree *item = tiling_window_tree_client_find(_G.tinfo->tree, focused_ec); + + if (item) + { + tiling_window_tree_node_move(item, cross_edge); + + _reapply_tree(); + } +} + +static void +_e_mod_action_move_left_cb(E_Object *obj __UNUSED__, + const char *params __UNUSED__) +{ + _action_swap(TILING_WINDOW_TREE_EDGE_LEFT); +} + +static void +_e_mod_action_move_right_cb(E_Object *obj __UNUSED__, + const char *params __UNUSED__) +{ + _action_swap(TILING_WINDOW_TREE_EDGE_RIGHT); +} + +static void +_e_mod_action_move_up_cb(E_Object *obj __UNUSED__, + const char *params __UNUSED__) +{ + _action_swap(TILING_WINDOW_TREE_EDGE_TOP); +} + +static void +_e_mod_action_move_down_cb(E_Object *obj __UNUSED__, + const char *params __UNUSED__) +{ + _action_swap(TILING_WINDOW_TREE_EDGE_BOTTOM); } /* }}} */ @@ -1137,8 +1175,18 @@ e_modapi_init(E_Module *m) ACTION_ADD(_G.act_togglefloat, _e_mod_action_toggle_floating_cb, N_("Toggle floating"), "toggle_floating", NULL, NULL, 0); - ACTION_ADD(_G.act_swap, _e_mod_action_swap_cb, - N_("Swap a window with an other"), "swap", + + ACTION_ADD(_G.act_move_up, _e_mod_action_move_up_cb, + N_("Move the focused window up"), "move_up", + NULL, NULL, 0); + ACTION_ADD(_G.act_move_down, _e_mod_action_move_down_cb, + N_("Move the focused window down"), "move_down", + NULL, NULL, 0); + ACTION_ADD(_G.act_move_left, _e_mod_action_move_left_cb, + N_("Move the focused window left"), "move_left", + NULL, NULL, 0); + ACTION_ADD(_G.act_move_right, _e_mod_action_move_right_cb, + N_("Move the focused window right"), "move_right", NULL, NULL, 0); ACTION_ADD(_G.act_toggle_split_mode, _e_mod_action_toggle_split_mode, @@ -1275,7 +1323,10 @@ e_modapi_shutdown(E_Module *m __UNUSED__) act = NULL; \ } ACTION_DEL(_G.act_togglefloat, "Toggle floating", "toggle_floating"); - ACTION_DEL(_G.act_swap, "Swap a window with an other", "swap"); + ACTION_DEL(_G.act_move_up, "Move the focused window up", "move_up"); + ACTION_DEL(_G.act_move_down, "Move the focused window down", "move_down"); + ACTION_DEL(_G.act_move_left, "Move the focused window left", "move_left"); + ACTION_DEL(_G.act_move_right, "Move the focused window right", "move_right"); ACTION_DEL(_G.act_toggle_split_mode, "Toggle split mode", "toggle_split_mode"); diff --git a/src/modules/tiling/window_tree.c b/src/modules/tiling/window_tree.c index c76d12cc9..b20dea629 100644 --- a/src/modules/tiling/window_tree.c +++ b/src/modules/tiling/window_tree.c @@ -445,6 +445,78 @@ tiling_window_tree_edges_get(Window_Tree *node) EINA_FALSE); } +/* Node move */ +static struct _Node_Move_Context { + Window_Tree *node; + Window_Tree *ret; + int cross_edge; +} _node_move_ctx; + +static void +_tiling_window_tree_node_move_walker(void *_node) +{ + Window_Tree *node = _node; + + /* We are only interested in nodes with clients. */ + if (!node->client) + return; + + /* Quit if we've already found something. */ + if (_node_move_ctx.ret) + return; + + switch (_node_move_ctx.cross_edge) + { + case TILING_WINDOW_TREE_EDGE_LEFT: + if ((node->client->x + node->client->w) == + _node_move_ctx.node->client->x) + _node_move_ctx.ret = node; + break; + case TILING_WINDOW_TREE_EDGE_RIGHT: + if (node->client->x == + (_node_move_ctx.node->client->x + _node_move_ctx.node->client->w)) + _node_move_ctx.ret = node; + break; + case TILING_WINDOW_TREE_EDGE_TOP: + if ((node->client->y + node->client->h) == + _node_move_ctx.node->client->y) + _node_move_ctx.ret = node; + break; + case TILING_WINDOW_TREE_EDGE_BOTTOM: + if (node->client->y == + (_node_move_ctx.node->client->y + _node_move_ctx.node->client->h)) + _node_move_ctx.ret = node; + break; + default: + break; + } +} + +void +tiling_window_tree_node_move(Window_Tree *node, int cross_edge) +{ + Window_Tree *root = node; + /* FIXME: This is very slow and possibly buggy. Can be done much better, + * but is very easy to implement. */ + + while (root->parent) + root = root->parent; + + _node_move_ctx.node = node; + _node_move_ctx.cross_edge = cross_edge; + _node_move_ctx.ret = NULL; + + tiling_window_tree_walk(root, _tiling_window_tree_node_move_walker); + + if (_node_move_ctx.ret) + { + E_Client *ec = node->client; + node->client = _node_move_ctx.ret->client; + _node_move_ctx.ret->client = ec; + } +} +/* End Node move. */ + 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 424a92943..0078ee5f0 100644 --- a/src/modules/tiling/window_tree.h +++ b/src/modules/tiling/window_tree.h @@ -41,4 +41,6 @@ void tiling_window_tree_apply(Window_Tree *root, Evas_Coord x, Evas_Coord y, Eva Eina_Bool tiling_window_tree_node_resize(Window_Tree *node, int w_dir, double w_diff, int h_dir, double h_diff); +void tiling_window_tree_node_move(Window_Tree *node, int cross_edge); + #endif