mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-09 23:50:21 -04:00
feat: dwindwl first test
This commit is contained in:
parent
cfc7773dfa
commit
89e5de3976
6 changed files with 541 additions and 0 deletions
|
|
@ -242,6 +242,14 @@ typedef struct {
|
|||
int32_t center_master_overspread;
|
||||
int32_t center_when_single_stack;
|
||||
|
||||
/* dwindle layout */
|
||||
int32_t dwindle_vsplit;
|
||||
int32_t dwindle_hsplit;
|
||||
int32_t dwindle_preserve_split;
|
||||
int32_t dwindle_smart_split;
|
||||
int32_t dwindle_smart_resize;
|
||||
float dwindle_split_ratio;
|
||||
|
||||
uint32_t hotarea_size;
|
||||
uint32_t hotarea_corner;
|
||||
uint32_t enable_hotarea;
|
||||
|
|
@ -1615,6 +1623,18 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->center_master_overspread = atoi(value);
|
||||
} else if (strcmp(key, "center_when_single_stack") == 0) {
|
||||
config->center_when_single_stack = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_vsplit") == 0) {
|
||||
config->dwindle_vsplit = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_hsplit") == 0) {
|
||||
config->dwindle_hsplit = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_preserve_split") == 0) {
|
||||
config->dwindle_preserve_split = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_smart_split") == 0) {
|
||||
config->dwindle_smart_split = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_smart_resize") == 0) {
|
||||
config->dwindle_smart_resize = atoi(value);
|
||||
} else if (strcmp(key, "dwindle_split_ratio") == 0) {
|
||||
config->dwindle_split_ratio = atof(value);
|
||||
} else if (strcmp(key, "hotarea_size") == 0) {
|
||||
config->hotarea_size = atoi(value);
|
||||
} else if (strcmp(key, "hotarea_corner") == 0) {
|
||||
|
|
@ -3179,6 +3199,14 @@ void override_config(void) {
|
|||
config.center_when_single_stack =
|
||||
CLAMP_INT(config.center_when_single_stack, 0, 1);
|
||||
config.new_is_master = CLAMP_INT(config.new_is_master, 0, 1);
|
||||
config.dwindle_vsplit = CLAMP_INT(config.dwindle_vsplit, 0, 2);
|
||||
config.dwindle_hsplit = CLAMP_INT(config.dwindle_hsplit, 0, 2);
|
||||
config.dwindle_preserve_split =
|
||||
CLAMP_INT(config.dwindle_preserve_split, 0, 1);
|
||||
config.dwindle_smart_split = CLAMP_INT(config.dwindle_smart_split, 0, 1);
|
||||
config.dwindle_smart_resize = CLAMP_INT(config.dwindle_smart_resize, 0, 1);
|
||||
config.dwindle_split_ratio =
|
||||
CLAMP_FLOAT(config.dwindle_split_ratio, 0.05f, 0.95f);
|
||||
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);
|
||||
|
|
@ -3318,6 +3346,13 @@ void set_value_default() {
|
|||
config.center_master_overspread = 0;
|
||||
config.center_when_single_stack = 1;
|
||||
|
||||
config.dwindle_vsplit = 0;
|
||||
config.dwindle_hsplit = 0;
|
||||
config.dwindle_preserve_split = 0;
|
||||
config.dwindle_smart_split = 0;
|
||||
config.dwindle_smart_resize = 0;
|
||||
config.dwindle_split_ratio = 0.5f;
|
||||
|
||||
config.log_level = WLR_ERROR;
|
||||
config.numlockon = 0;
|
||||
config.capslock = 0;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ int32_t exchange_client(const Arg *arg) {
|
|||
|
||||
Client *tc = direction_select(arg);
|
||||
tc = get_focused_stack_client(tc);
|
||||
|
||||
if (!tc)
|
||||
return 0;
|
||||
|
||||
exchange_two_client(c, tc);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -488,6 +488,29 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
}
|
||||
}
|
||||
|
||||
void resize_tile_dwindle(Client *grabc, bool isdrag, int32_t offsetx,
|
||||
int32_t offsety, uint32_t time, bool isvertical) {
|
||||
|
||||
if (!start_drag_window) {
|
||||
dwindle_resize_client_step(grabc->mon, grabc, offsetx, offsety);
|
||||
}
|
||||
|
||||
if (isdrag) {
|
||||
int32_t dx = (int32_t)round(cursor->x) - drag_begin_cursorx;
|
||||
int32_t dy = (int32_t)round(cursor->y) - drag_begin_cursory;
|
||||
dwindle_resize_client(grabc->mon, grabc, dx, dy);
|
||||
} else if (last_apply_drap_time == 0 ||
|
||||
time - last_apply_drap_time >
|
||||
config.drag_tile_refresh_interval) {
|
||||
dwindle_resize_client(grabc->mon, grabc, offsetx, offsety);
|
||||
last_apply_drap_time = time;
|
||||
}
|
||||
|
||||
if (!isdrag) {
|
||||
start_drag_window = false;
|
||||
}
|
||||
}
|
||||
|
||||
void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
||||
int32_t offsety, uint32_t time, bool isvertical) {
|
||||
Client *tc = NULL;
|
||||
|
|
@ -706,6 +729,8 @@ void resize_tile_client(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, false);
|
||||
} else if (current_layout->id == VERTICAL_SCROLLER) {
|
||||
resize_tile_scroller(grabc, isdrag, offsetx, offsety, time, true);
|
||||
} else if (current_layout->id == DWINDLE) {
|
||||
resize_tile_dwindle(grabc, isdrag, offsetx, offsety, time, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
435
src/layout/dwindle.h
Normal file
435
src/layout/dwindle.h
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
typedef struct DwindleNode DwindleNode;
|
||||
struct DwindleNode {
|
||||
bool is_split;
|
||||
bool split_h;
|
||||
bool split_locked;
|
||||
float ratio;
|
||||
float drag_init_ratio;
|
||||
int32_t container_x;
|
||||
int32_t container_y;
|
||||
int32_t container_w;
|
||||
int32_t container_h;
|
||||
DwindleNode *parent;
|
||||
DwindleNode *first;
|
||||
DwindleNode *second;
|
||||
Client *client;
|
||||
};
|
||||
|
||||
static DwindleNode *dwindle_locked_h_node = NULL;
|
||||
static DwindleNode *dwindle_locked_v_node = NULL;
|
||||
|
||||
static DwindleNode *dwindle_new_leaf(Client *c) {
|
||||
DwindleNode *n = calloc(1, sizeof(DwindleNode));
|
||||
n->client = c;
|
||||
return n;
|
||||
}
|
||||
|
||||
static DwindleNode *dwindle_find_leaf(DwindleNode *node, Client *c) {
|
||||
if (!node)
|
||||
return NULL;
|
||||
if (!node->is_split)
|
||||
return node->client == c ? node : NULL;
|
||||
DwindleNode *r = dwindle_find_leaf(node->first, c);
|
||||
return r ? r : dwindle_find_leaf(node->second, c);
|
||||
}
|
||||
|
||||
static DwindleNode *dwindle_first_leaf(DwindleNode *node) {
|
||||
if (!node)
|
||||
return NULL;
|
||||
while (node->is_split)
|
||||
node = node->first;
|
||||
return node;
|
||||
}
|
||||
|
||||
static void dwindle_free_tree(DwindleNode *node) {
|
||||
if (!node)
|
||||
return;
|
||||
dwindle_free_tree(node->first);
|
||||
dwindle_free_tree(node->second);
|
||||
free(node);
|
||||
}
|
||||
|
||||
static void dwindle_insert(DwindleNode **root, Client *new_c, Client *focused,
|
||||
float ratio, bool as_first) {
|
||||
DwindleNode *new_leaf = dwindle_new_leaf(new_c);
|
||||
|
||||
if (!*root) {
|
||||
*root = new_leaf;
|
||||
return;
|
||||
}
|
||||
|
||||
DwindleNode *target = focused ? dwindle_find_leaf(*root, focused) : NULL;
|
||||
if (!target)
|
||||
target = dwindle_first_leaf(*root);
|
||||
|
||||
DwindleNode *split = calloc(1, sizeof(DwindleNode));
|
||||
split->is_split = true;
|
||||
split->ratio = ratio;
|
||||
if (as_first) {
|
||||
split->first = new_leaf;
|
||||
split->second = target;
|
||||
} else {
|
||||
split->first = target;
|
||||
split->second = new_leaf;
|
||||
}
|
||||
split->parent = target->parent;
|
||||
target->parent = split;
|
||||
new_leaf->parent = split;
|
||||
|
||||
if (!split->parent) {
|
||||
*root = split;
|
||||
} else {
|
||||
if (split->parent->first == target)
|
||||
split->parent->first = split;
|
||||
else
|
||||
split->parent->second = split;
|
||||
}
|
||||
}
|
||||
|
||||
static void dwindle_remove(DwindleNode **root, Client *c) {
|
||||
DwindleNode *leaf = dwindle_find_leaf(*root, c);
|
||||
if (!leaf)
|
||||
return;
|
||||
|
||||
DwindleNode *parent = leaf->parent;
|
||||
if (!parent) {
|
||||
free(leaf);
|
||||
*root = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
DwindleNode *sibling =
|
||||
(parent->first == leaf) ? parent->second : parent->first;
|
||||
DwindleNode *grandparent = parent->parent;
|
||||
sibling->parent = grandparent;
|
||||
|
||||
/* Preserve split direction on sibling split-nodes when requested. */
|
||||
if (!sibling->is_split ||
|
||||
(!config.dwindle_preserve_split && !config.dwindle_smart_split)) {
|
||||
sibling->container_w = 0;
|
||||
sibling->container_h = 0;
|
||||
}
|
||||
|
||||
if (!grandparent) {
|
||||
*root = sibling;
|
||||
} else {
|
||||
if (grandparent->first == parent)
|
||||
grandparent->first = sibling;
|
||||
else
|
||||
grandparent->second = sibling;
|
||||
}
|
||||
|
||||
free(leaf);
|
||||
free(parent);
|
||||
}
|
||||
|
||||
static void dwindle_assign(DwindleNode *node, int32_t ax, int32_t ay,
|
||||
int32_t aw, int32_t ah, int32_t gap_h,
|
||||
int32_t gap_v) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (!node->is_split) {
|
||||
if (node->client) {
|
||||
struct wlr_box box = {ax, ay, MAX(1, aw), MAX(1, ah)};
|
||||
resize(node->client, box, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node->split_locked && node->container_w == 0 && node->container_h == 0)
|
||||
node->split_h = (aw >= ah);
|
||||
node->container_x = ax;
|
||||
node->container_y = ay;
|
||||
node->container_w = aw;
|
||||
node->container_h = ah;
|
||||
if (node->split_h) {
|
||||
int32_t w1 = MAX(1, (int32_t)(aw * node->ratio) - gap_h / 2);
|
||||
dwindle_assign(node->first, ax, ay, w1, ah, gap_h, gap_v);
|
||||
dwindle_assign(node->second, ax + w1 + gap_h, ay, aw - w1 - gap_h, ah,
|
||||
gap_h, gap_v);
|
||||
} else {
|
||||
int32_t h1 = MAX(1, (int32_t)(ah * node->ratio) - gap_v / 2);
|
||||
dwindle_assign(node->first, ax, ay, aw, h1, gap_h, gap_v);
|
||||
dwindle_assign(node->second, ax, ay + h1 + gap_v, aw, ah - h1 - gap_v,
|
||||
gap_h, gap_v);
|
||||
}
|
||||
}
|
||||
|
||||
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
|
||||
float ratio, int32_t dir) {
|
||||
if (!c || !target || c == target)
|
||||
return;
|
||||
if (!dwindle_find_leaf(*root, c) || !dwindle_find_leaf(*root, target))
|
||||
return;
|
||||
dwindle_remove(root, c);
|
||||
bool as_first = (dir == UP || dir == LEFT);
|
||||
dwindle_insert(root, c, target, ratio, as_first);
|
||||
}
|
||||
|
||||
static void dwindle_swap_clients(DwindleNode **root, Client *a, Client *b) {
|
||||
DwindleNode *la = dwindle_find_leaf(*root, a);
|
||||
DwindleNode *lb = dwindle_find_leaf(*root, b);
|
||||
if (!la || !lb || la == lb)
|
||||
return;
|
||||
la->client = b;
|
||||
lb->client = a;
|
||||
}
|
||||
|
||||
static void dwindle_resize_client(Monitor *m, Client *c, int32_t dx,
|
||||
int32_t dy) {
|
||||
uint32_t tag = m->pertag->curtag;
|
||||
DwindleNode *leaf = dwindle_find_leaf(m->pertag->dwindle_root[tag], c);
|
||||
if (!leaf)
|
||||
return;
|
||||
|
||||
if (!start_drag_window) {
|
||||
start_drag_window = true;
|
||||
dwindle_locked_h_node = NULL;
|
||||
dwindle_locked_v_node = NULL;
|
||||
DwindleNode *node = leaf->parent;
|
||||
while (node) {
|
||||
if (node->split_h && !dwindle_locked_h_node) {
|
||||
dwindle_locked_h_node = node;
|
||||
node->drag_init_ratio = node->ratio;
|
||||
}
|
||||
if (!node->split_h && !dwindle_locked_v_node) {
|
||||
dwindle_locked_v_node = node;
|
||||
node->drag_init_ratio = node->ratio;
|
||||
}
|
||||
if (dwindle_locked_h_node && dwindle_locked_v_node)
|
||||
break;
|
||||
node = node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dwindle_locked_h_node && !dwindle_locked_v_node)
|
||||
return;
|
||||
|
||||
if (dwindle_locked_h_node) {
|
||||
float cw = (float)MAX(1, dwindle_locked_h_node->container_w);
|
||||
float ox = (float)(cursor->x - drag_begin_cursorx);
|
||||
if (config.dwindle_smart_resize) {
|
||||
/* Move the boundary toward the cursor: invert direction when
|
||||
* the drag started on the right side of the split line. */
|
||||
float split_x = dwindle_locked_h_node->container_x +
|
||||
cw * dwindle_locked_h_node->drag_init_ratio;
|
||||
if (drag_begin_cursorx >= split_x)
|
||||
ox = -ox;
|
||||
}
|
||||
dwindle_locked_h_node->ratio =
|
||||
dwindle_locked_h_node->drag_init_ratio + ox / cw;
|
||||
dwindle_locked_h_node->ratio =
|
||||
CLAMP_FLOAT(dwindle_locked_h_node->ratio, 0.05f, 0.95f);
|
||||
}
|
||||
|
||||
if (dwindle_locked_v_node) {
|
||||
float ch = (float)MAX(1, dwindle_locked_v_node->container_h);
|
||||
float oy = (float)(cursor->y - drag_begin_cursory);
|
||||
if (config.dwindle_smart_resize) {
|
||||
/* Same logic for the vertical split line. */
|
||||
float split_y = dwindle_locked_v_node->container_y +
|
||||
ch * dwindle_locked_v_node->drag_init_ratio;
|
||||
if (drag_begin_cursory >= split_y)
|
||||
oy = -oy;
|
||||
}
|
||||
dwindle_locked_v_node->ratio =
|
||||
dwindle_locked_v_node->drag_init_ratio + oy / ch;
|
||||
dwindle_locked_v_node->ratio =
|
||||
CLAMP_FLOAT(dwindle_locked_v_node->ratio, 0.05f, 0.95f);
|
||||
}
|
||||
|
||||
int32_t n = m->visible_tiling_clients;
|
||||
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||
if (config.smartgaps && n == 1)
|
||||
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||
|
||||
dwindle_assign(m->pertag->dwindle_root[tag], m->w.x + gap_oh,
|
||||
m->w.y + gap_ov, m->w.width - 2 * gap_oh,
|
||||
m->w.height - 2 * gap_ov, gap_ih, gap_iv);
|
||||
}
|
||||
|
||||
static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx,
|
||||
int32_t dy) {
|
||||
uint32_t tag = m->pertag->curtag;
|
||||
DwindleNode *leaf = dwindle_find_leaf(m->pertag->dwindle_root[tag], c);
|
||||
if (!leaf)
|
||||
return;
|
||||
|
||||
DwindleNode *h_node = NULL;
|
||||
DwindleNode *v_node = NULL;
|
||||
DwindleNode *node = leaf->parent;
|
||||
drag_begin_cursorx = cursor->x;
|
||||
drag_begin_cursory = cursor->y;
|
||||
|
||||
while (node) {
|
||||
if (node->split_h && !h_node)
|
||||
h_node = node;
|
||||
if (!node->split_h && !v_node)
|
||||
v_node = node;
|
||||
if (h_node && v_node)
|
||||
break;
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
if (!h_node && !v_node)
|
||||
return;
|
||||
|
||||
if (h_node && dx) {
|
||||
float cw = (float)MAX(1, h_node->container_w);
|
||||
float delta = (float)dx / cw;
|
||||
h_node->ratio = CLAMP_FLOAT(h_node->ratio + delta, 0.05f, 0.95f);
|
||||
}
|
||||
|
||||
if (v_node && dy) {
|
||||
float ch = (float)MAX(1, v_node->container_h);
|
||||
float delta = (float)dy / ch;
|
||||
v_node->ratio = CLAMP_FLOAT(v_node->ratio + delta, 0.05f, 0.95f);
|
||||
}
|
||||
|
||||
int32_t n_clients = m->visible_tiling_clients;
|
||||
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||
if (config.smartgaps && n_clients == 1)
|
||||
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||
|
||||
dwindle_assign(m->pertag->dwindle_root[tag], m->w.x + gap_oh,
|
||||
m->w.y + gap_ov, m->w.width - 2 * gap_oh,
|
||||
m->w.height - 2 * gap_ov, gap_ih, gap_iv);
|
||||
}
|
||||
|
||||
static void dwindle_remove_client(Client *c) {
|
||||
Monitor *m;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
for (uint32_t t = 0; t < LENGTH(tags) + 1; t++)
|
||||
dwindle_remove(&m->pertag->dwindle_root[t], c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert a new client respecting dwindle_vsplit, dwindle_hsplit, and
|
||||
* dwindle_smart_split config options. */
|
||||
static void dwindle_insert_with_config(DwindleNode **root, Client *new_c,
|
||||
Client *focused, float ratio) {
|
||||
bool as_first = false;
|
||||
|
||||
if (focused) {
|
||||
struct wlr_box *fg = &focused->geom;
|
||||
double fcx = fg->x + fg->width * 0.5;
|
||||
double fcy = fg->y + fg->height * 0.5;
|
||||
|
||||
if (config.dwindle_smart_split) {
|
||||
/* Divide the focused window into 4 triangles using its diagonals.
|
||||
* The triangle the cursor falls in determines both the split axis
|
||||
* and which side the new window appears on. */
|
||||
double nx = (cursor->x - fcx) / (fg->width * 0.5);
|
||||
double ny = (cursor->y - fcy) / (fg->height * 0.5);
|
||||
bool do_split_h;
|
||||
if (fabs(ny) > fabs(nx)) {
|
||||
do_split_h = false;
|
||||
as_first = (ny < 0); /* top triangle → new window on top */
|
||||
} else {
|
||||
do_split_h = true;
|
||||
as_first = (nx < 0); /* left triangle → new window on left */
|
||||
}
|
||||
dwindle_insert(root, new_c, focused, ratio, as_first);
|
||||
DwindleNode *leaf = dwindle_find_leaf(*root, new_c);
|
||||
if (leaf && leaf->parent) {
|
||||
leaf->parent->split_h = do_split_h;
|
||||
leaf->parent->split_locked = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Predict likely split direction from the focused window's shape. */
|
||||
bool likely_h = (fg->width >= fg->height);
|
||||
if (likely_h) {
|
||||
if (config.dwindle_hsplit == 0)
|
||||
as_first = (cursor->x < fcx); /* follow mouse */
|
||||
else
|
||||
as_first = (config.dwindle_hsplit == 2); /* 2=left, 1=right */
|
||||
} else {
|
||||
if (config.dwindle_vsplit == 0)
|
||||
as_first = (cursor->y < fcy); /* follow mouse */
|
||||
else
|
||||
as_first = (config.dwindle_vsplit == 2); /* 2=top, 1=bottom */
|
||||
}
|
||||
}
|
||||
|
||||
dwindle_insert(root, new_c, focused, ratio, as_first);
|
||||
}
|
||||
|
||||
void dwindle(Monitor *m) {
|
||||
int32_t n = m->visible_tiling_clients;
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
uint32_t tag = m->pertag->curtag;
|
||||
DwindleNode **root = &m->pertag->dwindle_root[tag];
|
||||
float ratio = config.dwindle_split_ratio;
|
||||
|
||||
Client *vis[512];
|
||||
int32_t count = 0;
|
||||
Client *c;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (VISIBLEON(c, m) && ISTILED(c))
|
||||
vis[count++] = c;
|
||||
if (count >= 512)
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
DwindleNode *leaves[512];
|
||||
int32_t lc = 0;
|
||||
|
||||
DwindleNode *stack[1024];
|
||||
int32_t sp = 0;
|
||||
if (*root)
|
||||
stack[sp++] = *root;
|
||||
while (sp > 0) {
|
||||
DwindleNode *nd = stack[--sp];
|
||||
if (!nd->is_split) {
|
||||
leaves[lc++] = nd;
|
||||
} else {
|
||||
if (nd->second)
|
||||
stack[sp++] = nd->second;
|
||||
if (nd->first)
|
||||
stack[sp++] = nd->first;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < lc; i++) {
|
||||
bool found = false;
|
||||
for (int32_t j = 0; j < count; j++)
|
||||
if (vis[j] == leaves[i]->client) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
dwindle_remove(root, leaves[i]->client);
|
||||
}
|
||||
}
|
||||
|
||||
Client *focused = focustop(m);
|
||||
if (focused && !dwindle_find_leaf(*root, focused))
|
||||
focused = m->sel;
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
if (!dwindle_find_leaf(*root, vis[i]))
|
||||
dwindle_insert_with_config(root, vis[i], focused, ratio);
|
||||
}
|
||||
|
||||
int32_t gap_ih = enablegaps ? m->gappih : 0;
|
||||
int32_t gap_iv = enablegaps ? m->gappiv : 0;
|
||||
int32_t gap_oh = enablegaps ? m->gappoh : 0;
|
||||
int32_t gap_ov = enablegaps ? m->gappov : 0;
|
||||
if (config.smartgaps && n == 1)
|
||||
gap_ih = gap_iv = gap_oh = gap_ov = 0;
|
||||
|
||||
dwindle_assign(*root, m->w.x + gap_oh, m->w.y + gap_ov,
|
||||
m->w.width - 2 * gap_oh, m->w.height - 2 * gap_ov, gap_ih,
|
||||
gap_iv);
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ static void vertical_grid(Monitor *m);
|
|||
static void vertical_scroller(Monitor *m);
|
||||
static void vertical_deck(Monitor *mon);
|
||||
static void tgmix(Monitor *m);
|
||||
static void dwindle(Monitor *m);
|
||||
|
||||
/* layout(s) */
|
||||
Layout overviewlayout = {"", overview, "overview"};
|
||||
|
|
@ -29,6 +30,7 @@ enum {
|
|||
VERTICAL_DECK,
|
||||
RIGHT_TILE,
|
||||
TGMIX,
|
||||
DWINDLE,
|
||||
};
|
||||
|
||||
Layout layouts[] = {
|
||||
|
|
@ -47,4 +49,5 @@ Layout layouts[] = {
|
|||
{"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局
|
||||
{"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局
|
||||
{"TG", tgmix, "tgmix", TGMIX}, // 混合布局
|
||||
{"DW", dwindle, "dwindle", DWINDLE},
|
||||
};
|
||||
39
src/mango.c
39
src/mango.c
|
|
@ -560,6 +560,8 @@ typedef struct {
|
|||
struct wl_listener destroy;
|
||||
} SessionLock;
|
||||
|
||||
typedef struct DwindleNode DwindleNode;
|
||||
|
||||
/* function declarations */
|
||||
static void applybounds(
|
||||
Client *c,
|
||||
|
|
@ -815,6 +817,12 @@ static void client_pending_maximized_state(Client *c, int32_t ismaximized);
|
|||
static void client_pending_minimized_state(Client *c, int32_t isminimized);
|
||||
static void scroller_insert_stack(Client *c, Client *target_client,
|
||||
bool insert_before);
|
||||
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
|
||||
float ratio, int32_t dir);
|
||||
static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx,
|
||||
int32_t dy);
|
||||
static void dwindle_resize_client(Monitor *m, Client *c, int32_t dx,
|
||||
int32_t dy);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -946,6 +954,7 @@ struct Pertag {
|
|||
int32_t no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
|
||||
int32_t no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
|
||||
int32_t open_as_floating[LENGTH(tags) + 1]; /* open_as_floating per tag */
|
||||
struct DwindleNode *dwindle_root[LENGTH(tags) + 1];
|
||||
const Layout
|
||||
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
||||
};
|
||||
|
|
@ -1018,6 +1027,7 @@ static struct wl_event_source *sync_keymap;
|
|||
#include "ext-protocol/all.h"
|
||||
#include "fetch/fetch.h"
|
||||
#include "layout/arrange.h"
|
||||
#include "layout/dwindle.h"
|
||||
#include "layout/horizontal.h"
|
||||
#include "layout/vertical.h"
|
||||
|
||||
|
|
@ -1179,6 +1189,17 @@ void swallow(Client *c, Client *w) {
|
|||
client_pending_fullscreen_state(c, w->isfullscreen);
|
||||
client_pending_maximized_state(c, w->ismaximizescreen);
|
||||
client_pending_minimized_state(c, w->isminimized);
|
||||
|
||||
Monitor *m;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
for (uint32_t t = 0; t < LENGTH(tags) + 1; t++) {
|
||||
DwindleNode **root = &m->pertag->dwindle_root[t];
|
||||
dwindle_remove(root, c);
|
||||
DwindleNode *wn = dwindle_find_leaf(*root, w);
|
||||
if (wn)
|
||||
wn->client = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool switch_scratchpad_client_state(Client *c) {
|
||||
|
|
@ -2194,6 +2215,13 @@ void place_drag_tile_client(Client *c) {
|
|||
try_scroller_drop(c, closest, 1);
|
||||
return;
|
||||
}
|
||||
if (layout->id == DWINDLE) {
|
||||
uint32_t tag = c->mon->pertag->curtag;
|
||||
bool insert_before = closest->drop_direction == LEFT ||
|
||||
closest->drop_direction == UP;
|
||||
dwindle_insert(&c->mon->pertag->dwindle_root[tag], c, closest,
|
||||
config.dwindle_split_ratio, insert_before);
|
||||
}
|
||||
|
||||
if (closest->drop_direction == LEFT || closest->drop_direction == UP) {
|
||||
wl_list_remove(&c->link);
|
||||
|
|
@ -5101,10 +5129,20 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
tmp_tags = c2->tags;
|
||||
setmon(c2, c1->mon, c1->tags, false);
|
||||
setmon(c1, tmp_mon, tmp_tags, false);
|
||||
if (c1->mon &&
|
||||
c1->mon->pertag->ltidxs[c1->mon->pertag->curtag]->id == DWINDLE)
|
||||
dwindle_swap_clients(
|
||||
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||
c2);
|
||||
arrange(c1->mon, false, false);
|
||||
arrange(c2->mon, false, false);
|
||||
focusclient(c1, 0);
|
||||
} else {
|
||||
if (c1->mon &&
|
||||
c1->mon->pertag->ltidxs[c1->mon->pertag->curtag]->id == DWINDLE)
|
||||
dwindle_swap_clients(
|
||||
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||
c2);
|
||||
arrange(c1->mon, false, false);
|
||||
}
|
||||
|
||||
|
|
@ -6343,6 +6381,7 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
c->next_in_stack = NULL;
|
||||
c->prev_in_stack = NULL;
|
||||
|
||||
dwindle_remove_client(c);
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue