feat: option monocle_new_in_group

This commit is contained in:
DreamMaoMao 2026-06-25 20:23:02 +08:00
parent 83a33e01a3
commit fe47c19f4c
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 ## Switching Layouts
| Setting | Default | Description | | Setting | Default | Description |
| :--- | :--- | :--- | | :--- | :--- | :--- |

View file

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

View file

@ -258,6 +258,9 @@ typedef struct {
int32_t dwindle_manual_split; int32_t dwindle_manual_split;
float dwindle_split_ratio; float dwindle_split_ratio;
/* monocle layoput */
int32_t monocle_new_in_group;
int32_t hotarea_size; int32_t hotarea_size;
int32_t hotarea_corner; int32_t hotarea_corner;
int32_t enable_hotarea; int32_t enable_hotarea;
@ -1671,6 +1674,8 @@ bool parse_option(Config *config, char *key, char *value) {
config->dwindle_manual_split = atoi(value); config->dwindle_manual_split = atoi(value);
} else if (strcmp(key, "dwindle_split_ratio") == 0) { } else if (strcmp(key, "dwindle_split_ratio") == 0) {
config->dwindle_split_ratio = atof(value); 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) { } else if (strcmp(key, "hotarea_size") == 0) {
config->hotarea_size = atoi(value); config->hotarea_size = atoi(value);
} else if (strcmp(key, "hotarea_corner") == 0) { } else if (strcmp(key, "hotarea_corner") == 0) {
@ -3418,6 +3423,8 @@ void override_config(void) {
config.dwindle_manual_split = CLAMP_INT(config.dwindle_manual_split, 0, 1); config.dwindle_manual_split = CLAMP_INT(config.dwindle_manual_split, 0, 1);
config.dwindle_split_ratio = config.dwindle_split_ratio =
CLAMP_FLOAT(config.dwindle_split_ratio, 0.05f, 0.95f); 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_size = CLAMP_INT(config.hotarea_size, 1, 1000);
config.hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3); config.hotarea_corner = CLAMP_INT(config.hotarea_corner, 0, 3);
config.enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1); config.enable_hotarea = CLAMP_INT(config.enable_hotarea, 0, 1);
@ -3562,6 +3569,8 @@ void set_value_default() {
config.dwindle_manual_split = 0; config.dwindle_manual_split = 0;
config.dwindle_split_ratio = 0.5f; config.dwindle_split_ratio = 0.5f;
config.monocle_new_in_group = 0;
config.log_level = WLR_ERROR; config.log_level = WLR_ERROR;
config.numlockon = 0; config.numlockon = 0;
config.capslock = 0; config.capslock = 0;

View file

@ -157,28 +157,20 @@ int32_t focusdir(const Arg *arg) {
return 0; return 0;
} }
int32_t groupjoin(const Arg *arg) { void group_join_client(Client *need_join_client, Client *need_replace_client) {
if (!selmon)
return 0;
Monitor *oldmon = NULL; 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) if (!need_replace_client || !need_replace_client->mon)
return 0; return;
if (need_join_client == need_replace_client) 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) { if (need_join_client->group_next || need_join_client->group_prev) {
groupleave(&(Arg){.tc = need_join_client}); groupleave(&(Arg){.tc = need_join_client});
@ -210,7 +202,19 @@ int32_t groupjoin(const Arg *arg) {
if (oldmon) { if (oldmon) {
arrange(oldmon, false, false); 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; return 0;
} }
@ -346,16 +350,57 @@ int32_t focusstack(const Arg *arg) {
if (!sel) if (!sel)
return 0; return 0;
if (arg->i == NEXT) { if (arg->i == NEXT) {
tc = get_next_stack_client(sel, false); tc = get_next_stack_client(sel, false);
} else { } else {
tc = get_next_stack_client(sel, true); 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) if (!tc)
return 0; return 0;
focusclient(tc, 1); focusclient(tc, 1);
if (config.warpcursor) if (config.warpcursor)
warp_cursor(tc); warp_cursor(tc);
return 0; return 0;

View file

@ -320,6 +320,17 @@ Client *focustop(Monitor *m) {
return NULL; 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) { Client *get_next_stack_client(Client *c, bool reverse) {
if (!c || !c->mon) if (!c || !c->mon)
return NULL; return NULL;
@ -455,3 +466,29 @@ Client *get_focused_stack_client(Client *sc, Client *custom_focus_client) {
} }
return sc; 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

@ -956,6 +956,8 @@ static bool mango_scene_output_commit(struct wlr_scene_output *scene_output,
struct wlr_output_state *state); struct wlr_output_state *state);
static bool mango_output_commit(Monitor *m); static bool mango_output_commit(Monitor *m);
static bool check_tearing_frame_allow(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 "data/static_keymap.h"
#include "dispatch/bind_declare.h" #include "dispatch/bind_declare.h"
@ -1880,6 +1882,11 @@ void applyrules(Client *c) {
wl_list_insert(fstack.prev, &c->flink); 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); setmon(c, mon, newtags, should_init_get_focus);
if (!c->isfloating) { if (!c->isfloating) {