00001
00002
00003
00004
00005 #include "all.h"
00006 #include "cmdparse.tab.h"
00007
00008 typedef enum { BEFORE, AFTER } position_t;
00009
00010
00011
00012
00013
00014
00015 static void insert_con_into(Con *con, Con *target, position_t position) {
00016 Con *parent = target->parent;
00017
00018
00019
00020 Con *old_parent = con->parent;
00021
00022 con_detach(con);
00023 con_fix_percent(con->parent);
00024
00025
00026
00027 if (parent->type == CT_WORKSPACE) {
00028 Con *split = workspace_attach_to(parent);
00029 if (split != parent) {
00030 DLOG("Got a new split con, using that one instead\n");
00031 con->parent = split;
00032 con_attach(con, split, false);
00033 DLOG("attached\n");
00034 con->percent = 0.0;
00035 con_fix_percent(split);
00036 con = split;
00037 DLOG("ok, continuing with con %p instead\n", con);
00038 con_detach(con);
00039 }
00040 }
00041
00042 con->parent = parent;
00043
00044 if (position == BEFORE) {
00045 TAILQ_INSERT_BEFORE(target, con, nodes);
00046 TAILQ_INSERT_HEAD(&(parent->focus_head), con, focused);
00047 } else if (position == AFTER) {
00048 TAILQ_INSERT_AFTER(&(parent->nodes_head), target, con, nodes);
00049 TAILQ_INSERT_HEAD(&(parent->focus_head), con, focused);
00050 }
00051
00052
00053
00054
00055 con->percent = 0.0;
00056 con_fix_percent(parent);
00057
00058 CALL(old_parent, on_remove_child);
00059 }
00060
00061
00062
00063
00064
00065
00066 static void attach_to_workspace(Con *con, Con *ws) {
00067 con_detach(con);
00068 con_fix_percent(con->parent);
00069
00070 CALL(con->parent, on_remove_child);
00071
00072 con->parent = ws;
00073
00074 TAILQ_INSERT_TAIL(&(ws->nodes_head), con, nodes);
00075 TAILQ_INSERT_TAIL(&(ws->focus_head), con, focused);
00076
00077
00078
00079
00080 con->percent = 0.0;
00081 con_fix_percent(ws);
00082 }
00083
00084
00085
00086
00087
00088
00089 void tree_move(int direction) {
00090 DLOG("Moving in direction %d\n", direction);
00091
00092 Con *con = focused;
00093
00094 if (con->type == CT_WORKSPACE) {
00095 DLOG("Not moving workspace\n");
00096 return;
00097 }
00098
00099 if (con->parent->type == CT_WORKSPACE && con_num_children(con->parent) == 1) {
00100 DLOG("This is the only con on this workspace, not doing anything\n");
00101 return;
00102 }
00103
00104 orientation_t o = (direction == TOK_LEFT || direction == TOK_RIGHT ? HORIZ : VERT);
00105
00106 Con *same_orientation = con_parent_with_orientation(con, o);
00107
00108
00109
00110 do {
00111
00112 if (!same_orientation) {
00113 if (con_is_floating(con)) {
00114
00115 floating_disable(con, true);
00116 return;
00117 }
00118 if (con_inside_floating(con)) {
00119
00120 DLOG("Inside floating, moving to workspace\n");
00121 attach_to_workspace(con, con_get_workspace(con));
00122 goto end;
00123 }
00124 DLOG("Force-changing orientation\n");
00125 ws_force_orientation(con_get_workspace(con), o);
00126 same_orientation = con_parent_with_orientation(con, o);
00127 }
00128
00129
00130 if (same_orientation == con->parent) {
00131 DLOG("We are in the same container\n");
00132 Con *swap;
00133 if ((swap = (direction == TOK_LEFT || direction == TOK_UP ?
00134 TAILQ_PREV(con, nodes_head, nodes) :
00135 TAILQ_NEXT(con, nodes)))) {
00136 if (!con_is_leaf(swap)) {
00137 insert_con_into(con, con_descend_focused(swap), AFTER);
00138 goto end;
00139 }
00140 if (direction == TOK_LEFT || direction == TOK_UP)
00141 TAILQ_SWAP(swap, con, &(swap->parent->nodes_head), nodes);
00142 else TAILQ_SWAP(con, swap, &(swap->parent->nodes_head), nodes);
00143
00144 TAILQ_REMOVE(&(con->parent->focus_head), con, focused);
00145 TAILQ_INSERT_HEAD(&(swap->parent->focus_head), con, focused);
00146
00147 DLOG("Swapped.\n");
00148 return;
00149 }
00150
00151
00152
00153
00154
00155 if (con->parent == con_get_workspace(con))
00156 return;
00157 same_orientation = con_parent_with_orientation(con->parent, o);
00158 }
00159 } while (same_orientation == NULL);
00160
00161
00162
00163
00164 Con *above = con;
00165 while (above->parent != same_orientation)
00166 above = above->parent;
00167
00168 DLOG("above = %p\n", above);
00169 Con *next;
00170 position_t position;
00171 if (direction == TOK_UP || direction == TOK_LEFT) {
00172 position = BEFORE;
00173 next = TAILQ_PREV(above, nodes_head, nodes);
00174 } else {
00175 position = AFTER;
00176 next = TAILQ_NEXT(above, nodes);
00177 }
00178
00179
00180
00181 if (next && !con_is_leaf(next))
00182 insert_con_into(con, con_descend_focused(next), AFTER);
00183 else
00184 insert_con_into(con, above, position);
00185
00186 end:
00187
00188
00189
00190 con_focus(con);
00191
00192 tree_flatten(croot);
00193 }