feat: optimize focusdir to respect focusstack

This commit is contained in:
DreamMaoMao 2026-01-19 10:09:35 +08:00
parent 57d7801df2
commit 48c466254a
4 changed files with 90 additions and 2 deletions

View file

@ -129,6 +129,7 @@ int32_t exchange_stack_client(const Arg *arg) {
int32_t focusdir(const Arg *arg) {
Client *c = NULL;
c = direction_select(arg);
c = get_focused_stack_client(c);
if (c) {
focusclient(c, 1);
if (warpcursor)

View file

@ -369,7 +369,9 @@ Client *direction_select(const Arg *arg) {
}
return find_client_by_direction(
tc, arg, true, is_scroller_layout(selmon) && !selmon->isoverview);
tc, arg, true,
(is_scroller_layout(selmon) || is_centertile_layout(selmon)) &&
!selmon->isoverview);
}
/* We probably should change the name of this, it sounds like
@ -455,4 +457,78 @@ Client *get_scroll_stack_head(Client *c) {
scroller_stack_head = scroller_stack_head->prev_in_stack;
}
return scroller_stack_head;
}
}
bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
if (!sc || !tc)
return false;
uint32_t id = sc->mon->pertag->ltidxs[sc->mon->pertag->curtag]->id;
if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE &&
id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK &&
id != CENTER_TILE && id != RIGHT_TILE && id != TGMIX)
return false;
if (id == SCROLLER || id == VERTICAL_SCROLLER) {
if (fc->prev_in_stack)
return false;
Client *source_stack_head = get_scroll_stack_head(sc);
Client *target_stack_head = get_scroll_stack_head(tc);
if (source_stack_head == target_stack_head)
return true;
else
return false;
}
if (id == TILE || id == VERTICAL_TILE || id == DECK ||
id == VERTICAL_DECK || id == RIGHT_TILE) {
if (!fc->ismaster)
return false;
else
return true;
}
if (id == TGMIX) {
if (!fc->ismaster)
return false;
if (sc->mon->visible_tiling_clients <= 3)
return true;
}
if (id == CENTER_TILE) {
if (!fc->ismaster)
return false;
if (sc->geom.x == tc->geom.x)
return true;
else
return false;
}
return false;
}
Client *get_focused_stack_client(Client *sc) {
if (!sc || sc->isfloating)
return sc;
Client *tc = NULL;
Client *fc = focustop(sc->mon);
if (fc->isfloating || sc->isfloating)
return sc;
wl_list_for_each(tc, &fstack, flink) {
if (tc->iskilling || tc->isunglobal)
continue;
if (!VISIBLEON(tc, sc->mon))
continue;
if (tc == fc)
continue;
if (client_is_in_same_stack(sc, tc, fc)) {
return tc;
}
}
return sc;
}

View file

@ -26,6 +26,14 @@ bool is_scroller_layout(Monitor *m) {
return false;
}
bool is_centertile_layout(Monitor *m) {
if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE)
return true;
return false;
}
uint32_t get_tag_status(uint32_t tag, Monitor *m) {
Client *c = NULL;
uint32_t status = 0;

View file

@ -752,6 +752,7 @@ static struct wlr_scene_tree *
wlr_scene_tree_snapshot(struct wlr_scene_node *node,
struct wlr_scene_tree *parent);
static bool is_scroller_layout(Monitor *m);
static bool is_centertile_layout(Monitor *m);
static void create_output(struct wlr_backend *backend, void *data);
static void get_layout_abbr(char *abbr, const char *full_name);
static void apply_named_scratchpad(Client *target_client);
@ -776,6 +777,8 @@ static Client *find_client_by_direction(Client *tc, const Arg *arg,
static void exit_scroller_stack(Client *c);
static Client *get_scroll_stack_head(Client *c);
static bool client_only_in_one_tag(Client *c);
static Client *get_focused_stack_client(Client *sc);
static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"