feat: carousel-like behaviour when swapping tags

This commit is contained in:
ernestoCruz05 2026-05-15 13:48:46 +01:00 committed by DreamMaoMao
parent c655df244a
commit 0d4a43e5e1
4 changed files with 57 additions and 19 deletions

View file

@ -15,7 +15,11 @@ void set_tagin_animation(Monitor *m, Client *c) {
return;
}
if (m->pertag->curtag > m->pertag->prevtag) {
bool going_forward = m->carousel_anim_dir
? m->carousel_anim_dir > 0
: m->pertag->curtag > m->pertag->prevtag;
if (going_forward) {
c->animainit_geom.x = config.tag_animation_direction == VERTICAL
? c->animation.current.x
@ -75,7 +79,10 @@ void set_tagout_animation(Monitor *m, Client *c) {
return;
}
if (m->pertag->curtag > m->pertag->prevtag) {
bool going_forward = m->carousel_anim_dir
? m->carousel_anim_dir > 0
: m->pertag->curtag > m->pertag->prevtag;
if (going_forward) {
c->pending = c->geom;
c->pending.x =
config.tag_animation_direction == VERTICAL

View file

@ -306,6 +306,7 @@ typedef struct {
uint32_t gappoh;
uint32_t gappov;
uint32_t borderpx;
int32_t tag_carousel;
float scratchpad_width_ratio;
float scratchpad_height_ratio;
float rootcolor[4];
@ -1697,6 +1698,8 @@ bool parse_option(Config *config, char *key, char *value) {
config->scratchpad_height_ratio = atof(value);
} else if (strcmp(key, "borderpx") == 0) {
config->borderpx = atoi(value);
} else if (strcmp(key, "tag_carousel") == 0) {
config->tag_carousel = atoi(value);
} else if (strcmp(key, "rootcolor") == 0) {
int64_t color = parse_color(value);
if (color == -1) {
@ -3342,6 +3345,7 @@ void set_value_default() {
config.idleinhibit_ignore_visible = 0;
config.borderpx = 4;
config.tag_carousel = 0;
config.overviewgappi = 5;
config.overviewgappo = 30;
config.cursor_hide_timeout = 0;

View file

@ -1242,9 +1242,18 @@ int32_t tagtoleft(const Arg *arg) {
return 0;
if (selmon->sel != NULL &&
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 &&
selmon->tagset[selmon->seltags] > 1) {
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] >> 1, .i = arg->i});
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1) {
uint32_t target = selmon->tagset[selmon->seltags] >> 1;
if (target == 0) {
if (!config.tag_carousel)
return 0;
target = (1 << (LENGTH(tags) - 1)) & TAGMASK;
selmon->carousel_anim_dir = -1;
}
tag(&(Arg){.ui = target & TAGMASK, .i = arg->i});
selmon->carousel_anim_dir = 0;
}
return 0;
}
@ -1254,9 +1263,18 @@ int32_t tagtoright(const Arg *arg) {
return 0;
if (selmon->sel != NULL &&
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 &&
selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
tag(&(Arg){.ui = selmon->tagset[selmon->seltags] << 1, .i = arg->i});
__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1) {
uint32_t target = selmon->tagset[selmon->seltags] << 1;
if (!(target & TAGMASK)) {
if (!config.tag_carousel)
return 0;
target = 1;
selmon->carousel_anim_dir = 1;
}
tag(&(Arg){.ui = target & TAGMASK, .i = arg->i});
selmon->carousel_anim_dir = 0;
}
return 0;
}
@ -1499,22 +1517,24 @@ int32_t viewtoleft(const Arg *arg) {
if (!selmon)
return 0;
uint32_t target = selmon->tagset[selmon->seltags];
if (selmon->isoverview || selmon->pertag->curtag == 0) {
if (selmon->isoverview || selmon->pertag->curtag == 0)
return 0;
}
uint32_t target = selmon->tagset[selmon->seltags];
target >>= 1;
if (target == 0) {
return 0;
if (!config.tag_carousel)
return 0;
target = (1 << (LENGTH(tags) - 1)) & TAGMASK;
selmon->carousel_anim_dir = -1;
}
if (!selmon || (target) == selmon->tagset[selmon->seltags])
if (target == selmon->tagset[selmon->seltags])
return 0;
view(&(Arg){.ui = target & TAGMASK, .i = arg->i}, true);
selmon->carousel_anim_dir = 0;
return 0;
}
@ -1522,19 +1542,24 @@ int32_t viewtoright(const Arg *arg) {
if (!selmon)
return 0;
if (selmon->isoverview || selmon->pertag->curtag == 0) {
if (selmon->isoverview || selmon->pertag->curtag == 0)
return 0;
}
uint32_t target = selmon->tagset[selmon->seltags];
target <<= 1;
if (!selmon || (target) == selmon->tagset[selmon->seltags])
return 0;
if (!(target & TAGMASK)) {
return 0;
if (!config.tag_carousel)
return 0;
target = 1;
selmon->carousel_anim_dir = 1;
}
if (target == selmon->tagset[selmon->seltags])
return 0;
view(&(Arg){.ui = target & TAGMASK, .i = arg->i}, true);
selmon->carousel_anim_dir = 0;
return 0;
}

View file

@ -553,6 +553,7 @@ struct Monitor {
char last_surface_ws_name[256];
struct wlr_ext_workspace_group_handle_v1 *ext_group;
bool iscleanuping;
int8_t carousel_anim_dir;
};
typedef struct {
@ -3216,6 +3217,7 @@ void createmon(struct wl_listener *listener, void *data) {
m->skiping_frame = false;
m->resizing_count_pending = 0;
m->resizing_count_current = 0;
m->carousel_anim_dir = 0;
m->wlr_output = wlr_output;
m->wlr_output->data = m;