From fd8382a82ca9bb51265e0338a8b8cc977bfe6f45 Mon Sep 17 00:00:00 2001 From: Jon H <> Date: Wed, 18 Mar 2026 06:17:07 -0700 Subject: [PATCH] Adds stack bounded stack navigation functions --- src/config/parse_config.h | 10 ++++++-- src/dispatch/bind_declare.h | 2 ++ src/dispatch/bind_define.h | 48 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index fda401d9..d2d7cf83 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -938,7 +938,10 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, if (strcmp(func_name, "focusstack") == 0) { func = focusstack; (*arg).i = parse_circle_direction(arg_value); - } else if (strcmp(func_name, "focusdir") == 0) { + } else if (strcmp(func_name, "focusstack_bounded") == 0) { + func = focusstack_bounded; + (*arg).i = parse_circle_direction(arg_value); + } else if (strcmp(func_name, "focusdir") == 0) { func = focusdir; (*arg).i = parse_direction(arg_value); } else if (strcmp(func_name, "incnmaster") == 0) { @@ -955,7 +958,10 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "exchange_stack_client") == 0) { func = exchange_stack_client; (*arg).i = parse_circle_direction(arg_value); - } else if (strcmp(func_name, "toggleglobal") == 0) { + } else if (strcmp(func_name, "exchange_stack_client_bounded") == 0) { + func = exchange_stack_client_bounded; + (*arg).i = parse_circle_direction(arg_value); + } else if (strcmp(func_name, "toggleglobal") == 0) { func = toggleglobal; } else if (strcmp(func_name, "toggleoverview") == 0) { func = toggleoverview; diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index dbeebd33..fcfb9520 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -32,11 +32,13 @@ int32_t quit(const Arg *arg); int32_t moveresize(const Arg *arg); int32_t exchange_client(const Arg *arg); int32_t exchange_stack_client(const Arg *arg); +int32_t exchange_stack_client_bounded(const Arg *arg); int32_t killclient(const Arg *arg); int32_t toggleglobal(const Arg *arg); int32_t incnmaster(const Arg *arg); int32_t focusmon(const Arg *arg); int32_t focusstack(const Arg *arg); +int32_t focusstack_bounded(const Arg *arg); int32_t chvt(const Arg *arg); int32_t reload_config(const Arg *arg); int32_t smartmovewin(const Arg *arg); diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 68309356..6c9059dc 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -134,6 +134,27 @@ int32_t exchange_stack_client(const Arg *arg) { return 0; } +int32_t exchange_stack_client_bounded(const Arg *arg) { + if (!selmon) + return 0; + + Client *c = selmon->sel; + Client *tc = NULL; + if (!c || c->isfloating || c->isfullscreen || c->ismaximizescreen) + return 0; + /* again, lazy we just search once more if we found master */ + if (arg->i == NEXT) { + tc = get_next_stack_client(c, false); + if (tc && tc->ismaster) tc = get_next_stack_client(tc, false); + } else { + tc = get_next_stack_client(c, true); + if (tc && tc->ismaster) tc = get_next_stack_client(tc, true); + } + if (tc) + exchange_two_client(c, tc); + return 0; +} + int32_t focusdir(const Arg *arg) { Client *c = NULL; c = direction_select(arg); @@ -263,6 +284,33 @@ int32_t focusstack(const Arg *arg) { return 0; } +int32_t focusstack_bounded(const Arg *arg) { + /* Focus the next or previous client (in tiling order) on selmon */ + /* but skipping past master */ + Client *sel = focustop(selmon); + Client *tc = NULL; + + if (!sel) + return 0; + /* lazy fix we just search twice, don't make new deeper functions */ + if (arg->i == NEXT) { + tc = get_next_stack_client(sel, false); + if (tc && tc->ismaster) tc = get_next_stack_client(tc, false); + } else { + tc = get_next_stack_client(sel, true); + if (tc && tc->ismaster) tc = get_next_stack_client(tc, true); + } + /* If only one client is visible on selmon, then c == sel */ + + if (!tc) + return 0; + + focusclient(tc, 1); + if (config.warpcursor) + warp_cursor(tc); + return 0; +} + int32_t incnmaster(const Arg *arg) { if (!arg || !selmon) return 0;