feat: option monocle_new_in_group

This commit is contained in:
DreamMaoMao 2026-06-25 20:23:02 +08:00
parent 9e5a5f3a42
commit 1a3a314852
6 changed files with 132 additions and 18 deletions

View file

@ -117,6 +117,18 @@ dwindle_drop_simple_split=1
---
## Monocle Layout
The Monocle layout is similar to the Center Tile layout, but it places windows in a single column instead of a row.
### Configuration
| Setting | Default | Description |
| :--- | :--- | :--- |
| `monocle_new_in_group` | `0` | New windows are auto grouped in the focused window. |
---
## Switching Layouts
| Setting | Default | Description |
| :--- | :--- | :--- |

View file

@ -137,6 +137,9 @@ void client_add_group_bar(Client *c) {
}
void client_focus_group_member(Client *c) {
if (!c)
return;
if (!c->group_prev && !c->group_next)
return;
@ -191,7 +194,8 @@ void client_check_tab_node_visible(Client *c) {
if (!c->mon->isoverview && cur->group_bar &&
(cur->group_next || cur->group_prev) && VISIBLEON(c, c->mon) &&
ISNORMAL(c) && !c->isfullscreen &&
(!is_monocle_layout(c->mon) || c == c->mon->sel)) {
(!is_monocle_layout(c->mon) || config.monocle_new_in_group ||
c == c->mon->sel)) {
wlr_scene_node_set_enabled(&cur->group_bar->scene_buffer->node,
true);
} else {

View file

@ -264,6 +264,9 @@ typedef struct {
int32_t dwindle_manual_split;
float dwindle_split_ratio;
/* monocle layoput */
int32_t monocle_new_in_group;
int32_t hotarea_size;
int32_t hotarea_corner;
int32_t enable_hotarea;
@ -1729,6 +1732,8 @@ bool parse_option(Config *config, char *key, char *value) {
config->dwindle_manual_split = atoi(value);
} else if (strcmp(key, "dwindle_split_ratio") == 0) {
config->dwindle_split_ratio = atof(value);
} else if (strcmp(key, "monocle_new_in_group") == 0) {
config->monocle_new_in_group = atoi(value);
} else if (strcmp(key, "hotarea_size") == 0) {
config->hotarea_size = atoi(value);
} else if (strcmp(key, "hotarea_corner") == 0) {
@ -3509,6 +3514,8 @@ void override_config(void) {
config.dwindle_manual_split = CLAMP_INT(config.dwindle_manual_split, 0, 1);
config.dwindle_split_ratio =
CLAMP_FLOAT(config.dwindle_split_ratio, 0.05f, 0.95f);
config.monocle_new_in_group = CLAMP_INT(config.monocle_new_in_group, 0, 1);
config.hotarea_size = CLAMP_INT(config.hotarea_size, 1, 1000);
config.hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3);
config.enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1);
@ -3678,6 +3685,8 @@ void set_value_default() {
config.dwindle_manual_split = 0;
config.dwindle_split_ratio = 0.5f;
config.monocle_new_in_group = 0;
config.log_level = WLR_ERROR;
config.numlockon = 0;
config.capslock = 0;

View file

@ -156,28 +156,20 @@ int32_t focusdir(const Arg *arg) {
return 0;
}
int32_t groupjoin(const Arg *arg) {
if (!selmon)
return 0;
void group_join_client(Client *need_join_client, Client *need_replace_client) {
Monitor *oldmon = NULL;
Client *need_join_client = arg->tc ? arg->tc : selmon->sel;
if (!need_join_client || !need_join_client->mon)
return 0;
if (need_join_client->mon->isoverview)
return 0;
Client *need_replace_client = NULL;
need_replace_client = direction_select(arg);
if (!need_replace_client || !need_replace_client->mon)
return 0;
return;
if (need_join_client == need_replace_client)
return 0;
return;
if (!need_join_client)
return;
if (need_join_client->mon && need_join_client->mon->isoverview)
return;
if (need_join_client->group_next || need_join_client->group_prev) {
groupleave(&(Arg){.tc = need_join_client});
@ -209,7 +201,19 @@ int32_t groupjoin(const Arg *arg) {
if (oldmon) {
arrange(oldmon, false, false);
}
}
int32_t groupjoin(const Arg *arg) {
if (!selmon)
return 0;
Client *need_join_client = arg->tc ? arg->tc : selmon->sel;
Client *need_replace_client = NULL;
need_replace_client = direction_select(arg);
group_join_client(need_join_client, need_replace_client);
return 0;
}
@ -345,16 +349,57 @@ int32_t focusstack(const Arg *arg) {
if (!sel)
return 0;
if (arg->i == NEXT) {
tc = get_next_stack_client(sel, false);
} else {
tc = get_next_stack_client(sel, true);
}
if (!sel->mon->isoverview) {
if (!sel->group_next && !sel->group_prev) {
if (arg->i == NEXT) {
tc = client_get_group_head(tc);
if (tc)
client_focus_group_member(tc);
} else {
tc = client_get_group_tail(tc);
if (tc)
client_focus_group_member(tc);
}
} else {
if (arg->i == NEXT) {
if (sel->group_next) {
tc = sel->group_next;
} else if (!tc) {
tc = client_get_group_head(sel);
} else {
tc = client_get_group_head(tc);
}
if (tc) {
client_focus_group_member(tc);
}
}
if (arg->i == PREV) {
if (sel->group_prev) {
tc = sel->group_prev;
} else if (!tc) {
tc = client_get_group_tail(sel);
} else {
tc = client_get_group_tail(tc);
}
if (tc) {
client_focus_group_member(tc);
}
}
}
}
if (!tc)
return 0;
focusclient(tc, 1);
if (config.warpcursor)
warp_cursor(tc);
return 0;

View file

@ -320,6 +320,17 @@ Client *focustop(Monitor *m) {
return NULL;
}
Client *focustiletop(Monitor *m) {
Client *c = NULL;
wl_list_for_each(c, &fstack, flink) {
if (c->iskilling || c->isunglobal || !ISSCROLLTILED(c))
continue;
if (VISIBLEON(c, m))
return c;
}
return NULL;
}
Client *get_next_stack_client(Client *c, bool reverse) {
if (!c || !c->mon)
return NULL;
@ -454,4 +465,30 @@ Client *get_focused_stack_client(Client *sc, Client *custom_focus_client) {
}
}
return sc;
}
Client *client_get_group_head(Client *c) {
if (!c || !c->mon)
return NULL;
Client *head = c;
while (head->group_prev) {
head = head->group_prev;
}
return head;
}
Client *client_get_group_tail(Client *c) {
if (!c || !c->mon)
return NULL;
Client *tail = c;
while (tail->group_next) {
tail = tail->group_next;
}
return tail;
}

View file

@ -961,6 +961,8 @@ static bool mango_scene_output_commit(struct wlr_scene_output *scene_output,
struct wlr_output_state *state);
static bool mango_output_commit(Monitor *m);
static bool check_tearing_frame_allow(Monitor *m);
static Client *client_get_group_head(Client *c);
static Client *client_get_group_tail(Client *c);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
@ -1891,6 +1893,11 @@ void applyrules(Client *c) {
wl_list_insert(fstack.prev, &c->flink);
}
if (config.monocle_new_in_group && mon && ISTILED(c) &&
is_monocle_layout(mon)) {
group_join_client(c, focustiletop(mon));
}
setmon(c, mon, newtags, should_init_get_focus);
if (!c->isfloating) {