diff --git a/docs/(git)/bindings/keys.md b/docs/(git)/bindings/keys.md index 5abc716b..0bed24db 100644 --- a/docs/(git)/bindings/keys.md +++ b/docs/(git)/bindings/keys.md @@ -147,9 +147,10 @@ bindr=Super,Super_L,spawn,rofi -show run | `scroller_stack` | `left/right/up/down` | Move window inside/outside scroller stack by direction. | | `incgaps` | `+/-value` | Adjust gap size. | | `togglegaps` | - | Toggle gaps. | -| `dwindle_toggle_split_direction` | - | Toggle split direction in dwindle layout. | +| `dwindle_toggle_split_direction` | - | Toggle split direction in dwindle layout. | | `dwindle_split_horizontal` | - | Set split window direction to horizontal in dwindle layout. | | `dwindle_split_vertical` | - | Set split window direction to vertical in dwindle layout. | +| `movetoroot` | `[active/id] [,unstable]` | Move selected window to the root of its dwindle tree. Add `unstable` to swap subtrees instead of default stable maximization. | ### System diff --git a/docs/(git)/ipc.md b/docs/(git)/ipc.md index 489293fa..3c720c73 100644 --- a/docs/(git)/ipc.md +++ b/docs/(git)/ipc.md @@ -76,3 +76,4 @@ mmsg dispatch exchange_client,left client,375 # operate current client mmsg dispatch exchange_client,left ```` + diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 74b36ba4..96da6f04 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1256,10 +1256,21 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, func = dwindle_split_horizontal; } else if (strcmp(func_name, "dwindle_split_vertical") == 0) { func = dwindle_split_vertical; + } else if (strcmp(func_name, "movetoroot") == 0) { + func = movetoroot; + bool unstable = false; + if (arg_value && strcmp(arg_value, "unstable") == 0) { + unstable = true; + } + if (arg_value2 && strcmp(arg_value2, "unstable") == 0) { + unstable = true; + } + (*arg).i = unstable ? 1 : 0; } else { return NULL; } return func; + } void set_env() { diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index a04ba0c1..e5806fc0 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -74,4 +74,6 @@ int32_t toggle_all_floating(const Arg *arg); int32_t dwindle_toggle_split_direction(const Arg *arg); int32_t dwindle_split_horizontal(const Arg *arg); int32_t dwindle_split_vertical(const Arg *arg); -int32_t focusid(const Arg *arg); \ No newline at end of file +int32_t focusid(const Arg *arg); +int32_t movetoroot(const Arg *arg); + diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index d6537d89..2b03352e 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -2002,4 +2002,21 @@ int32_t focusid(const Arg *arg) { Client *c = arg->tc; focusclient(c, 1); return 0; +} + +int32_t movetoroot(const Arg *arg) { + if (!selmon) + return 0; + + Client *c = arg->tc ? arg->tc : selmon->sel; + if (!c || c->isfloating) + return 0; + + if (c->mon && c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == DWINDLE) { + uint32_t tag = c->mon->pertag->curtag; + bool stable = (arg->i == 0); + dwindle_movetoroot(&c->mon->pertag->dwindle_root[tag], c, stable); + arrange(c->mon, false, false); + } + return 0; } \ No newline at end of file diff --git a/src/layout/dwindle.h b/src/layout/dwindle.h index 74e79477..5a6f884c 100644 --- a/src/layout/dwindle.h +++ b/src/layout/dwindle.h @@ -622,6 +622,45 @@ void dwindle(Monitor *m) { gap_iv); } +static void dwindle_movetoroot(DwindleNode **root, Client *c, bool stable) { + if (!root || !*root || !c) + return; + + DwindleNode *x = dwindle_find_leaf(*root, c); + if (!x || !x->parent) + return; + + if (!x->parent->parent) + return; + + DwindleNode **pNode = + (x->parent->first == x) ? &(x->parent->first) : &(x->parent->second); + + DwindleNode *pAncestor = x; + DwindleNode *pRoot = x->parent; + while (pRoot->parent) { + pAncestor = pRoot; + pRoot = pRoot->parent; + } + + DwindleNode **pSwap = + (pRoot->first == pAncestor) ? &(pRoot->second) : &(pRoot->first); + + DwindleNode *temp = *pNode; + *pNode = *pSwap; + *pSwap = temp; + + DwindleNode *parent_temp = (*pNode)->parent; + (*pNode)->parent = (*pSwap)->parent; + (*pSwap)->parent = parent_temp; + + if (stable) { + DwindleNode *temp_root_child = pRoot->first; + pRoot->first = pRoot->second; + pRoot->second = temp_root_child; + } +} + void cleanup_monitor_dwindle(Monitor *m) { for (uint32_t t = 0; t < LENGTH(tags) + 1; t++) dwindle_free_tree(m->pertag->dwindle_root[t]); diff --git a/src/mango.c b/src/mango.c index 61cf861a..3a272777 100644 --- a/src/mango.c +++ b/src/mango.c @@ -855,7 +855,9 @@ static void client_pending_maximized_state(Client *c, int32_t ismaximized); static void client_pending_minimized_state(Client *c, int32_t isminimized); static void scroller_insert_stack(Client *c, Client *target_client, bool insert_before); +static void dwindle_movetoroot(DwindleNode **root, Client *c, bool stable); static void dwindle_move_client(DwindleNode **root, Client *c, Client *target, + float ratio, int32_t dir); static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx, int32_t dy);