feat: support resize tile window

This commit is contained in:
DreamMaoMao
2025-10-09 13:09:40 +08:00
parent 731bd9c0df
commit 3086130a2c
13 changed files with 1060 additions and 678 deletions
+1 -14
View File
@@ -16,7 +16,7 @@ This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
- Base tags not workspaces (supports separate window layouts for each tag)
- Smooth and customizable complete animations (window open/move/close, tag enter/leave,layer open/close/move)
- Excellent input method support (text input v2/v3)
- Flexible window layouts with easy switching (scroller, master, monocle, spiral, etc.)
- Flexible window layouts with easy switching (scroller, master-stack, monocle,center-master, etc.)
- Rich window states (swallow, minimize, maximize, unglobal, global, fakefullscreen, overlay, etc.)
- Simple yet powerful external configuration(support shortcuts hot-reload)
- Sway-like scratchpad and named scratchpad
@@ -24,10 +24,6 @@ This project's development is based on [dwl](https://codeberg.org/dwl/dwl/).
- Hycov-like overview
- Window effects from scenefx (blur, shadow, corner radius, opacity)
3. **Some disadvantages**
- Since it uses the fully automatic layout like dwm style, it does not allow you to manually adjust the window size when the window is in tiled state. It only allows you to use dispatch like `setmfact` or `increase_proportion` bind to adjust the tiled window ratio.
Master-Stack Layout
https://github.com/user-attachments/assets/a9d4776e-b50b-48fb-94ce-651d8a749b8a
@@ -38,23 +34,14 @@ https://github.com/user-attachments/assets/c9bf9415-fad1-4400-bcdc-3ad2d76de85a
# Supported layouts
## Horizontal Layouts
- tile
- scroller
- monocle
- grid
- dwindle
- spiral
- deck
- center_tile
## Vertical Layouts
- vertical_tile
- vertical_scroller
- vertical_monocle
- vertical_grid
- vertical_dwindle
- vertical_spiral
# Installation
+2 -3
View File
@@ -35,7 +35,7 @@ edge_scroller_pointer_focus=1
scroller_default_proportion_single=1.0
scroller_proportion_preset=0.5,0.8,1.0
# Master-Stack Layout Setting (tile,spiral,dwindle)
# Master-Stack Layout Setting
new_is_master=1
default_mfact=0.55
default_nmaster=1
@@ -102,8 +102,7 @@ globalcolor=0xb153a7ff
overlaycolor=0x14a57cff
# layout support:
# horizontal:tile,scroller,grid,monocle,spiral,dwindle,center_tile
# vertical:vertical_tile,vertical_scroller,vertical_grid,vertical_spiral,vertical_dwindle
# tile,scroller,grid,deck,monocle,center_tile,vertical_tile,vertical_scroller
tagrule=id:1,layout_name:tile
tagrule=id:2,layout_name:tile
tagrule=id:3,layout_name:tile
+7 -4
View File
@@ -17,10 +17,8 @@ bool is_horizontal_stack_layout(Monitor *m) {
return true;
if (m->pertag->curtag &&
(strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "tile") == 0 ||
strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "spiral") == 0 ||
strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "dwindle") == 0 ||
strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "deck") == 0))
(m->pertag->ltidxs[m->pertag->curtag]->id == TILE ||
m->pertag->ltidxs[m->pertag->curtag]->id == DECK))
return true;
return false;
@@ -777,6 +775,11 @@ void client_set_pending_state(Client *c) {
c->istagswitching = 0;
}
if (start_drag_window) {
c->animation.should_animate = false;
c->animation.duration = 0;
}
// 开始动画
client_commit(c);
c->dirty = true;
+6 -15
View File
@@ -199,10 +199,9 @@ typedef struct {
unsigned int new_is_master;
float default_mfact;
float default_smfact;
unsigned int default_nmaster;
int center_master_overspread;
int center_when_single_slave;
int center_when_single_stack;
unsigned int hotarea_size;
unsigned int enable_hotarea;
@@ -710,9 +709,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
} else if (strcmp(func_name, "setmfact") == 0) {
func = setmfact;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "setsmfact") == 0) {
func = setsmfact;
(*arg).f = atof(arg_value);
} else if (strcmp(func_name, "zoom") == 0) {
func = zoom;
} else if (strcmp(func_name, "exchange_client") == 0) {
@@ -1209,14 +1205,12 @@ void parse_option(Config *config, char *key, char *value) {
config->new_is_master = atoi(value);
} else if (strcmp(key, "default_mfact") == 0) {
config->default_mfact = atof(value);
} else if (strcmp(key, "default_smfact") == 0) {
config->default_smfact = atof(value);
} else if (strcmp(key, "default_nmaster") == 0) {
config->default_nmaster = atoi(value);
} else if (strcmp(key, "center_master_overspread") == 0) {
config->center_master_overspread = atoi(value);
} else if (strcmp(key, "center_when_single_slave") == 0) {
config->center_when_single_slave = atoi(value);
} else if (strcmp(key, "center_when_single_stack") == 0) {
config->center_when_single_stack = atoi(value);
} else if (strcmp(key, "hotarea_size") == 0) {
config->hotarea_size = atoi(value);
} else if (strcmp(key, "enable_hotarea") == 0) {
@@ -2412,10 +2406,9 @@ void override_config(void) {
// 主从布局设置
default_mfact = CLAMP_FLOAT(config.default_mfact, 0.1f, 0.9f);
default_smfact = CLAMP_FLOAT(config.default_smfact, 0.1f, 0.9f);
default_nmaster = CLAMP_INT(config.default_nmaster, 1, 1000);
center_master_overspread = CLAMP_INT(config.center_master_overspread, 0, 1);
center_when_single_slave = CLAMP_INT(config.center_when_single_slave, 0, 1);
center_when_single_stack = CLAMP_INT(config.center_when_single_stack, 0, 1);
new_is_master = CLAMP_INT(config.new_is_master, 0, 1);
// 概述模式设置
@@ -2542,12 +2535,11 @@ void set_value_default() {
focus_on_activate; // 收到窗口激活请求是否自动跳转聚焦
config.new_is_master = new_is_master; // 新窗口是否插在头部
config.default_mfact = default_mfact; // master 窗口比例
config.default_smfact = default_smfact; // 第一个stack比例
config.default_nmaster = default_nmaster; // 默认master数量
config.center_master_overspread =
center_master_overspread; // 中心master时是否铺满
config.center_when_single_slave =
center_when_single_slave; // 单个slave时是否居中
config.center_when_single_stack =
center_when_single_stack; // 单个stack时是否居中
config.numlockon = numlockon; // 是否打开右边小键盘
@@ -2852,7 +2844,6 @@ void reapply_master(void) {
}
m->pertag->nmasters[i] = default_nmaster;
m->pertag->mfacts[i] = default_mfact;
m->pertag->smfacts[i] = default_smfact;
m->gappih = gappih;
m->gappiv = gappiv;
m->gappoh = gappoh;
+1 -2
View File
@@ -35,10 +35,9 @@ unsigned int axis_bind_apply_timeout = 100; // 滚轮绑定动作的触发的时
unsigned int focus_on_activate = 1; // 收到窗口激活请求是否自动跳转聚焦
unsigned int new_is_master = 1; // 新窗口是否插在头部
double default_mfact = 0.55f; // master 窗口比例
double default_smfact = 0.5f; // 第一个stack窗口比例
unsigned int default_nmaster = 1; // 默认master数量
int center_master_overspread = 0; // 中心master时是否铺满
int center_when_single_slave = 1; // 单个slave时是否居中
int center_when_single_stack = 1; // 单个stack时是否居中
/* logging */
int log_level = WLR_ERROR;
unsigned int numlockon = 1; // 是否打开右边小键盘
-1
View File
@@ -27,7 +27,6 @@ void setlayout(const Arg *arg);
void switch_layout(const Arg *arg);
void switch_keyboard_layout(const Arg *arg);
void setmfact(const Arg *arg);
void setsmfact(const Arg *arg);
void quit(const Arg *arg);
void moveresize(const Arg *arg);
void exchange_client(const Arg *arg);
+39 -20
View File
@@ -263,20 +263,6 @@ void increase_proportion(const Arg *arg) {
}
}
void setsmfact(const Arg *arg) {
float f;
if (!arg || !selmon ||
!selmon->pertag->ltidxs[selmon->pertag->curtag]->arrange)
return;
f = arg->f < 1.0 ? arg->f + selmon->pertag->smfacts[selmon->pertag->curtag]
: arg->f - 1.0;
if (f < 0.1 || f > 0.9)
return;
// selmon->mfact = f;
selmon->pertag->smfacts[selmon->pertag->curtag] = f;
arrange(selmon, false);
}
/* arg > 1.0 will set mfact absolutely */
void // 17
setmfact(const Arg *arg) {
@@ -309,15 +295,15 @@ moveresize(const Arg *arg) {
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
return;
/* Float the window and tell motionnotify to grab it */
if (grabc->isfloating == 0) {
if (grabc->isfloating == 0 && arg->ui == CurMove) {
grabc->drag_to_tile = true;
setfloating(grabc, 1);
}
switch (cursor_mode = arg->ui) {
case CurMove:
grabcx = cursor->x - grabc->geom.x;
grabcy = cursor->y - grabc->geom.y;
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
@@ -325,9 +311,14 @@ moveresize(const Arg *arg) {
case CurResize:
/* Doesn't work for X11 output - the next absolute motion event
* returns the cursor to where it started */
wlr_cursor_warp_closest(cursor, NULL, grabc->geom.x + grabc->geom.width,
if (grabc->isfloating) {
wlr_cursor_warp_closest(cursor, NULL,
grabc->geom.x + grabc->geom.width,
grabc->geom.y + grabc->geom.height);
wlr_cursor_set_xcursor(cursor, cursor_mgr, "bottom_right_corner");
} else {
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
}
break;
}
}
@@ -377,10 +368,38 @@ quit(const Arg *arg) {
void resizewin(const Arg *arg) {
Client *c = NULL;
c = selmon->sel;
if (!c || c->isfullscreen)
int offsetx = 0, offsety = 0;
if (!c || c->isfullscreen || c->ismaxmizescreen)
return;
if (!c->isfloating)
togglefloating(NULL);
if (ISTILED(c)) {
switch (arg->ui) {
case NUM_TYPE_MINUS:
offsetx = -arg->i;
break;
case NUM_TYPE_PLUS:
offsetx = arg->i;
break;
default:
offsetx = arg->i;
break;
}
switch (arg->ui2) {
case NUM_TYPE_MINUS:
offsety = -arg->i2;
break;
case NUM_TYPE_PLUS:
offsety = arg->i2;
break;
default:
offsety = arg->i2;
break;
}
resize_tile_client(c, false, offsetx, offsety, 0);
return;
}
switch (arg->ui) {
case NUM_TYPE_MINUS:
+2 -11
View File
@@ -17,21 +17,12 @@ Monitor *dirtomon(enum wlr_direction dir) {
bool is_scroller_layout(Monitor *m) {
if (!m->pertag->curtag &&
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name, "scroller") == 0)
if (m->pertag->ltidxs[m->pertag->curtag]->id == SCROLLER)
return true;
if (!m->pertag->curtag &&
strcmp(m->pertag->ltidxs[m->pertag->prevtag]->name,
"vertical_scroller") == 0)
if (m->pertag->ltidxs[m->pertag->curtag]->id == VERTICAL_SCROLLER)
return true;
if (m->pertag->curtag &&
strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "scroller") == 0)
return true;
if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name,
"vertical_scroller") == 0)
return true;
return false;
}
File diff suppressed because it is too large Load Diff
+180 -182
View File
File diff suppressed because it is too large Load Diff
+20 -18
View File
@@ -4,35 +4,37 @@ static void overview(Monitor *m);
static void grid(Monitor *m);
static void scroller(Monitor *m);
static void deck(Monitor *mon);
static void dwindle(Monitor *mon);
static void spiral(Monitor *mon);
static void monocle(Monitor *m);
static void vertical_tile(Monitor *m);
static void vertical_overview(Monitor *m);
static void vertical_grid(Monitor *m);
static void vertical_scroller(Monitor *m);
static void vertical_deck(Monitor *mon);
static void vertical_dwindle(Monitor *mon);
static void vertical_spiral(Monitor *mon);
/* layout(s) */
Layout overviewlayout = {"󰃇", overview, "overview"};
enum {
SCROLLER,
TILE,
GRID,
MONOCLE,
DECK,
CENTER_TILE,
VERTICAL_SCROLLER,
VERTICAL_TILE,
};
Layout layouts[] = {
// 最少两个,不能删除少于两个
/* symbol arrange function name */
{"S", scroller, "scroller"}, // 滚动布局
{"T", tile, "tile"}, // 堆栈布局
{"G", grid, "grid"},
{"M", monocle, "monocle"},
{"D", dwindle, "dwindle"},
{"P", spiral, "spiral"},
{"K", deck, "deck"},
{"CT", center_tile, "center_tile"},
{"VS", vertical_scroller, "vertical_scroller"},
{"VT", vertical_tile, "vertical_tile"},
{"VD", vertical_dwindle, "vertical_dwindle"},
{"VP", vertical_spiral, "vertical_spiral"},
{"VG", vertical_grid, "vertical_grid"},
{"VK", vertical_deck, "vertical_deck"},
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
{"T", tile, "tile", TILE}, // 平铺布局
{"G", grid, "grid", GRID}, // 格子布局
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
{"K", deck, "deck", DECK}, // 卡片布局
{"CT", center_tile, "center_tile", CENTER_TILE}, // 居中布局
{"VS", vertical_scroller, "vertical_scroller",
VERTICAL_SCROLLER}, // 垂直滚动布局
{"VT", vertical_tile, "vertical_tile", VERTICAL_TILE}, // 垂直平铺布局
};
+72 -330
View File
@@ -1,292 +1,91 @@
void vertical_fibonacci(Monitor *mon, int s) {
unsigned int i = 0, n = 0, nx, ny, nw, nh;
void vertical_tile(Monitor *m) {
unsigned int i, n = 0, w, r, ie = enablegaps, mh, mx, tx;
Client *c = NULL;
unsigned int cur_gappih = enablegaps ? mon->gappih : 0;
unsigned int cur_gappiv = enablegaps ? mon->gappiv : 0;
unsigned int cur_gappoh = enablegaps ? mon->gappoh : 0;
unsigned int cur_gappov = enablegaps ? mon->gappov : 0;
cur_gappih = smartgaps && mon->visible_tiling_clients == 1 ? 0 : cur_gappih;
cur_gappiv = smartgaps && mon->visible_tiling_clients == 1 ? 0 : cur_gappiv;
cur_gappoh = smartgaps && mon->visible_tiling_clients == 1 ? 0 : cur_gappoh;
cur_gappov = smartgaps && mon->visible_tiling_clients == 1 ? 0 : cur_gappov;
n = mon->visible_tiling_clients;
if (n == 0)
return;
// Initial dimensions including outer gaps
nx = mon->w.x + cur_gappoh;
ny = mon->w.y + cur_gappov;
nw = mon->w.width - 2 * cur_gappoh;
nh = mon->w.height - 2 * cur_gappov;
// First pass: calculate client geometries
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, mon) || !ISTILED(c))
continue;
c->bw = mon->visible_tiling_clients == 1 && no_border_when_single &&
smartgaps
? 0
: borderpx;
if ((i % 2 && nw / 2 > 2 * c->bw) || (!(i % 2) && nh / 2 > 2 * c->bw)) {
if (i < n - 1) {
if (i % 2) {
if (i == 1) {
nw = nw * mon->pertag->smfacts[mon->pertag->curtag];
} else {
nw = (nw - cur_gappih) / 2;
}
} else {
nh = (nh - cur_gappiv) / 2;
}
if ((i % 4) == 2 && !s)
ny += nh + cur_gappiv;
else if ((i % 4) == 3 && !s)
nx += nw + cur_gappih;
}
if ((i % 4) == 0) {
if (s)
nx += nw + cur_gappih;
else
nx -= nw + cur_gappih;
} else if ((i % 4) == 1)
ny += nh + cur_gappiv;
else if ((i % 4) == 2)
nx += nw + cur_gappih;
else if ((i % 4) == 3) {
if (s)
ny += nh + cur_gappiv;
else
ny -= nh + cur_gappiv;
}
if (i == 0) {
if (n != 1)
nh = (mon->w.height - 2 * cur_gappov) *
mon->pertag->mfacts[mon->pertag->curtag];
nx = mon->w.x + cur_gappoh;
} else if (i == 1) {
nh = mon->w.height - 2 * cur_gappov - nh - cur_gappiv;
} else if (i == 2) {
nw = mon->w.width - 2 * cur_gappoh - nw - cur_gappih;
}
i++;
}
c->geom = (struct wlr_box){.x = nx, .y = ny, .width = nw, .height = nh};
}
// Second pass: apply gaps between clients
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, mon) || !ISTILED(c))
continue;
unsigned int right_gap = 0;
unsigned int bottom_gap = 0;
Client *nc = NULL;
wl_list_for_each(nc, &clients, link) {
if (!VISIBLEON(nc, mon) || !ISTILED(nc))
continue;
if (c == nc)
continue;
// Check for right neighbor
if (c->geom.y == nc->geom.y &&
c->geom.x + c->geom.width == nc->geom.x) {
right_gap = cur_gappih;
}
// Check for bottom neighbor
if (c->geom.x == nc->geom.x &&
c->geom.y + c->geom.height == nc->geom.y) {
bottom_gap = cur_gappiv;
}
}
resize(c,
(struct wlr_box){.x = c->geom.x,
.y = c->geom.y,
.width = c->geom.width - right_gap,
.height = c->geom.height - bottom_gap},
0);
}
}
void vertical_dwindle(Monitor *mon) { vertical_fibonacci(mon, 1); }
void vertical_spiral(Monitor *mon) { vertical_fibonacci(mon, 0); }
void vertical_grid(Monitor *m) {
unsigned int i, n;
unsigned int cx, cy, cw, ch;
unsigned int dy;
unsigned int rows, cols, overrows;
Client *c = NULL;
n = m->isoverview ? m->visible_clients : m->visible_tiling_clients;
if (n == 0) {
return;
}
if (n == 1) {
wl_list_for_each(c, &clients, link) {
if (c->mon != m)
continue;
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
smartgaps
? 0
: borderpx;
if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_should_ignore_focus(c)) ||
ISTILED(c))) {
ch = (m->w.height - 2 * overviewgappo) * 0.7;
cw = (m->w.width - 2 * overviewgappo) * 0.8;
c->geom.x = m->w.x + (m->w.width - cw) / 2;
c->geom.y = m->w.y + (m->w.height - ch) / 2;
c->geom.width = cw - 2 * c->bw;
c->geom.height = ch - 2 * c->bw;
resize(c, c->geom, 0);
return;
}
}
}
if (n == 2) {
ch = (m->w.height - 2 * overviewgappo - overviewgappi) / 2;
cw = (m->w.width - 2 * overviewgappo) * 0.65;
i = 0;
wl_list_for_each(c, &clients, link) {
if (c->mon != m)
continue;
c->bw = m->visible_tiling_clients == 1 && no_border_when_single &&
smartgaps
? 0
: borderpx;
if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_should_ignore_focus(c)) ||
ISTILED(c))) {
if (i == 0) {
c->geom.x = m->w.x + (m->w.width - cw) / 2 + overviewgappo;
c->geom.y = m->w.y + overviewgappo;
c->geom.width = cw - 2 * c->bw;
c->geom.height = ch - 2 * c->bw;
resize(c, c->geom, 0);
} else if (i == 1) {
c->geom.x = m->w.x + (m->w.width - cw) / 2 + overviewgappo;
c->geom.y = m->w.y + ch + overviewgappo + overviewgappi;
c->geom.width = cw - 2 * c->bw;
c->geom.height = ch - 2 * c->bw;
resize(c, c->geom, 0);
}
i++;
}
}
return;
}
for (rows = 0; rows <= n / 2; rows++) {
if (rows * rows >= n) {
break;
}
}
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
cw = (m->w.width - 2 * overviewgappo - (cols - 1) * overviewgappi) / cols;
ch = (m->w.height - 2 * overviewgappo - (rows - 1) * overviewgappi) / rows;
overrows = n % rows;
if (overrows) {
dy =
(m->w.height - overrows * ch - (overrows - 1) * overviewgappi) / 2 -
overviewgappo;
}
i = 0;
wl_list_for_each(c, &clients, link) {
if (c->mon != m)
continue;
c->bw =
m->visible_tiling_clients == 1 && no_border_when_single && smartgaps
? 0
: borderpx;
if (VISIBLEON(c, m) && !c->isunglobal &&
((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) {
cx = m->w.x + (i / rows) * (cw + overviewgappi);
cy = m->w.y + (i % rows) * (ch + overviewgappi);
if (overrows && i >= n - overrows) {
cy += dy;
}
c->geom.x = cx + overviewgappo;
c->geom.y = cy + overviewgappo;
c->geom.width = cw - 2 * c->bw;
c->geom.height = ch - 2 * c->bw;
resize(c, c->geom, 0);
i++;
}
}
}
void vertical_deck(Monitor *m) {
unsigned int mh, mx;
int i, n = 0;
Client *c = NULL;
unsigned int cur_gappiv = enablegaps ? m->gappiv : 0;
unsigned int cur_gappoh = enablegaps ? m->gappoh : 0;
unsigned int cur_gappov = enablegaps ? m->gappov : 0;
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
Client *fc = NULL;
double mfact = 0;
int master_num = 0;
int stack_num = 0;
n = m->visible_tiling_clients;
master_num = m->pertag->nmasters[m->pertag->curtag];
stack_num = n - master_num;
if (n == 0)
return;
float mfact = m->pertag ? m->pertag->mfacts[m->pertag->curtag] : m->mfact;
unsigned int cur_gapih = enablegaps ? m->gappih : 0;
unsigned int cur_gapiv = enablegaps ? m->gappiv : 0;
unsigned int cur_gapoh = enablegaps ? m->gappoh : 0;
unsigned int cur_gapov = enablegaps ? m->gappov : 0;
if (n > m->nmaster)
mh = m->nmaster ? round((m->w.height - 2 * cur_gappov) * mfact) : 0;
cur_gapih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapih;
cur_gapiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapiv;
cur_gapoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapoh;
cur_gapov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gapov;
wl_list_for_each(fc, &clients, link) {
if (VISIBLEON(fc, m) && ISTILED(fc))
break;
}
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
: m->pertag->mfacts[m->pertag->curtag];
if (n > m->pertag->nmasters[m->pertag->curtag])
mh = m->pertag->nmasters[m->pertag->curtag]
? (m->w.height + cur_gapiv * ie) * mfact
: 0;
else
mh = m->w.height - 2 * cur_gappov;
mh = m->w.height - 2 * cur_gapov + cur_gapiv * ie;
i = mx = 0;
i = 0;
mx = tx = cur_gapih;
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || !ISTILED(c))
continue;
if (i < m->nmaster) {
resize(
c,
(struct wlr_box){.x = m->w.x + cur_gappoh + mx,
.y = m->w.y + cur_gappov,
.width = (m->w.width - 2 * cur_gappoh - mx) /
(MIN(n, m->nmaster) - i),
.height = mh},
0);
mx += c->geom.width;
if (i < m->pertag->nmasters[m->pertag->curtag]) {
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
if (c->master_inner_per > 0.0f) {
w = (m->w.width - 2 * cur_gapih -
cur_gapih * ie * (master_num - 1)) *
c->master_inner_per;
c->master_mfact_per = mfact;
} else {
w = (m->w.width - mx - cur_gapih - cur_gapih * ie * (r - 1)) /
r;
c->master_inner_per = w / (m->w.width - mx - cur_gapih -
cur_gapih * ie * (r - 1));
c->master_mfact_per = mfact;
}
resize(c,
(struct wlr_box){.x = m->w.x + cur_gappoh,
.y = m->w.y + mh + cur_gappov + cur_gappiv,
.width = m->w.width - 2 * cur_gappoh,
.height = m->w.height - mh -
2 * cur_gappov - cur_gappiv},
(struct wlr_box){.x = m->w.x + mx,
.y = m->w.y + cur_gapov,
.width = w,
.height = mh - cur_gapiv * ie},
0);
if (c == focustop(m))
wlr_scene_node_raise_to_top(&c->scene->node);
mx += c->geom.width + cur_gapih * ie;
} else {
r = n - i;
if (c->stack_innder_per > 0.0f) {
w = (m->w.width - 2 * cur_gapih -
cur_gapih * ie * (stack_num - 1)) *
c->stack_innder_per;
c->master_mfact_per = mfact;
} else {
w = (m->w.width - tx - cur_gapih - cur_gapih * ie * (r - 1)) /
r;
c->stack_innder_per = w / (m->w.width - tx - cur_gapih -
cur_gapih * ie * (r - 1));
c->master_mfact_per = mfact;
}
resize(c,
(struct wlr_box){.x = m->w.x + tx,
.y = m->w.y + mh + cur_gapov,
.width = w,
.height = m->w.height - mh - 2 * cur_gapov},
0);
tx += c->geom.width + cur_gapih * ie;
}
i++;
}
@@ -418,60 +217,3 @@ void vertical_scroller(Monitor *m) {
free(tempClients);
}
void vertical_tile(Monitor *m) {
unsigned int i, n = 0, w, r, ie = enablegaps, mh, mx, tx;
Client *c = NULL;
n = m->visible_tiling_clients;
if (n == 0)
return;
unsigned int cur_gappiv = enablegaps ? m->gappiv : 0;
unsigned int cur_gappih = enablegaps ? m->gappih : 0;
unsigned int cur_gappov = enablegaps ? m->gappov : 0;
unsigned int cur_gappoh = enablegaps ? m->gappoh : 0;
cur_gappiv = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
cur_gappih = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
cur_gappov = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
cur_gappoh = smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
if (n > m->pertag->nmasters[m->pertag->curtag])
mh = m->pertag->nmasters[m->pertag->curtag]
? (m->w.height + cur_gappiv * ie) *
m->pertag->mfacts[m->pertag->curtag]
: 0;
else
mh = m->w.height - 2 * cur_gappoh + cur_gappiv * ie;
i = 0;
mx = tx = cur_gappov;
wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || !ISTILED(c))
continue;
if (i < m->pertag->nmasters[m->pertag->curtag]) {
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
w = (m->w.width - mx - cur_gappov - cur_gappiv * ie * (r - 1)) / r;
resize(c,
(struct wlr_box){.x = m->w.x + mx,
.y = m->w.y + cur_gappoh,
.width = w,
.height = mh - cur_gappih * ie},
0);
mx += c->geom.width + cur_gappiv * ie;
} else {
r = n - i;
w = (m->w.width - tx - cur_gappov - cur_gappiv * ie * (r - 1)) / r;
resize(
c,
(struct wlr_box){.x = m->w.x + tx,
.y = m->w.y + mh + cur_gappoh,
.width = w,
.height = m->w.height - mh - 2 * cur_gappoh},
0);
tx += c->geom.width + cur_gappiv * ie;
}
i++;
}
}
+56 -61
View File
@@ -248,7 +248,8 @@ struct Client {
/* Must keep these three elements in this order */
unsigned int type; /* XDGShell or X11* */
struct wlr_box geom, pending, float_geom, animainit_geom,
overview_backup_geom, current; /* layout-relative, includes border */
overview_backup_geom, current,
drag_begin_geom; /* layout-relative, includes border */
Monitor *mon;
struct wlr_scene_tree *scene;
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
@@ -337,6 +338,12 @@ struct Client {
float unfocused_opacity;
char oldmonname[128];
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
double master_mfact_per, master_inner_per, stack_innder_per;
double old_master_mfact_per, old_master_inner_per, old_stack_innder_per;
double old_scroller_pproportion;
bool ismaster;
bool cursor_in_upper_half, cursor_in_left_half;
bool isleftstack;
};
typedef struct {
@@ -410,6 +417,7 @@ typedef struct {
const char *symbol;
void (*arrange)(Monitor *);
const char *name;
unsigned int id;
} Layout;
struct Monitor {
@@ -711,6 +719,9 @@ static unsigned int get_tag_status(unsigned int tag, Monitor *m);
static void enable_adaptive_sync(Monitor *m, struct wlr_output_state *state);
static Client *get_next_stack_client(Client *c, bool reverse);
static void set_float_malposition(Client *tc);
static void set_size_per(Monitor *m, Client *c);
static void resize_tile_client(Client *grabc, bool isdrag, int offsetx,
int offsety, unsigned int time);
#include "data/static_keymap.h"
#include "dispatch/bind_declare.h"
@@ -771,6 +782,9 @@ static struct wl_list inputdevices;
static unsigned int cursor_mode;
static Client *grabc;
static int grabcx, grabcy; /* client-relative */
static int drag_begin_cursorx, drag_begin_cursory; /* client-relative */
static bool start_drag_window = false;
static int last_apply_drap_time = 0;
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1
*ext_foreign_toplevel_image_capture_source_manager_v1;
@@ -819,7 +833,6 @@ struct Pertag {
unsigned int curtag, prevtag; /* current and previous tag */
int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
float smfacts[LENGTH(tags) + 1]; /* smfacts per tag */
bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
const Layout
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
@@ -878,6 +891,7 @@ static struct wlr_xwayland *xwayland;
#include "dispatch/bind_define.h"
#include "ext-protocol/all.h"
#include "fetch/fetch.h"
#include "layout/arrange.h"
#include "layout/horizontal.h"
#include "layout/vertical.h"
@@ -1300,6 +1314,8 @@ void applyrules(Client *c) {
}
}
set_size_per(mon, c);
// if no geom rule hit and is normal winodw, use the center pos and record
// the hit size
if (!hit_rule_pos &&
@@ -1375,61 +1391,6 @@ void applyrules(Client *c) {
}
}
void // 17
arrange(Monitor *m, bool want_animation) {
Client *c = NULL;
if (!m)
return;
if (!m->wlr_output->enabled)
return;
m->visible_clients = 0;
m->visible_tiling_clients = 0;
wl_list_for_each(c, &clients, link) {
if (c->iskilling)
continue;
if (c->mon == m && (c->isglobal || c->isunglobal)) {
c->tags = m->tagset[m->seltags];
if (c->mon->sel == NULL)
focusclient(c, 0);
}
if (c->mon == m) {
if (VISIBLEON(c, m)) {
m->visible_clients++;
if (ISTILED(c))
m->visible_tiling_clients++;
set_arrange_visible(m, c, want_animation);
} else {
set_arrange_hidden(m, c, want_animation);
}
}
if (c->mon == m && c->ismaxmizescreen && !c->animation.tagouted &&
!c->animation.tagouting && VISIBLEON(c, m)) {
reset_maxmizescreen_size(c);
}
}
if (m->isoverview) {
overviewlayout.arrange(m);
} else if (m && m->pertag->curtag &&
m->pertag->ltidxs[m->pertag->curtag]->arrange) {
m->pertag->ltidxs[m->pertag->curtag]->arrange(m);
} else if (m && m->pertag->prevtag &&
m->pertag->ltidxs[m->pertag->prevtag]->arrange) {
m->pertag->ltidxs[m->pertag->prevtag]->arrange(m);
}
motionnotify(0, NULL, 0, 0, 0, 0);
checkidleinhibitor(NULL);
}
void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area,
int exclusive) {
LayerSurface *l = NULL;
@@ -1930,6 +1891,8 @@ buttonpress(struct wl_listener *listener, void *data) {
selmon->sel = grabc;
tmpc = grabc;
grabc = NULL;
start_drag_window = false;
last_apply_drap_time = 0;
if (tmpc->drag_to_tile && drag_tile_to_tile) {
place_drag_tile_client(tmpc);
} else {
@@ -2623,7 +2586,6 @@ void createmon(struct wl_listener *listener, void *data) {
for (i = 0; i <= LENGTH(tags); i++) {
m->pertag->nmasters[i] = m->nmaster;
m->pertag->mfacts[i] = m->mfact;
m->pertag->smfacts[i] = default_smfact;
m->pertag->ltidxs[i] = m->lt;
}
@@ -3463,6 +3425,9 @@ void init_client_properties(Client *c) {
c->ignore_maximize = 0;
c->ignore_minimize = 1;
c->iscustomsize = 0;
c->master_mfact_per = 0.0f;
c->master_inner_per = 0.0f;
c->stack_innder_per = 0.0f;
}
void // old fix to 0.5
@@ -3788,14 +3753,18 @@ void motionnotify(unsigned int time, struct wlr_input_device *device, double dx,
resize(grabc, grabc->float_geom, 1);
return;
} else if (cursor_mode == CurResize) {
if (grabc->isfloating) {
grabc->iscustomsize = 1;
grabc->float_geom =
(struct wlr_box){.x = grabc->geom.x,
grabc->float_geom = (struct wlr_box){
.x = grabc->geom.x,
.y = grabc->geom.y,
.width = (int)round(cursor->x) - grabc->geom.x,
.height = (int)round(cursor->y) - grabc->geom.y};
resize(grabc, grabc->float_geom, 1);
return;
} else {
resize_tile_client(grabc, true, 0, 0, time);
}
}
/* If there's no client surface under the cursor, set the cursor image
@@ -4116,12 +4085,27 @@ void exchange_two_client(Client *c1, Client *c2) {
Monitor *tmp_mon = NULL;
unsigned int tmp_tags;
double master_inner_per = 0.0f;
double master_mfact_per = 0.0f;
double stack_innder_per = 0.0f;
if (c1 == NULL || c2 == NULL ||
(!exchange_cross_monitor && c1->mon != c2->mon)) {
return;
}
master_inner_per = c1->master_inner_per;
master_mfact_per = c1->master_mfact_per;
stack_innder_per = c1->stack_innder_per;
c1->master_inner_per = c2->master_inner_per;
c1->master_mfact_per = c2->master_mfact_per;
c1->stack_innder_per = c2->stack_innder_per;
c2->master_inner_per = master_inner_per;
c2->master_mfact_per = master_mfact_per;
c2->stack_innder_per = stack_innder_per;
struct wl_list *tmp1_prev = c1->link.prev;
struct wl_list *tmp2_prev = c2->link.prev;
struct wl_list *tmp1_next = c1->link.next;
@@ -4345,6 +4329,10 @@ setfloating(Client *c, int floating) {
layers[c->isfloating ? LyrTop : LyrTile]);
}
if (!c->isfloating) {
set_size_per(c->mon, c);
}
arrange(c->mon, false);
setborder_color(c);
printstatus();
@@ -4389,12 +4377,15 @@ void setmaxmizescreen(Client *c, int maxmizescreen) {
c->ismaxmizescreen = 0;
if (c->isfloating)
setfloating(c, 1);
arrange(c->mon, false);
}
wlr_scene_node_reparent(&c->scene->node, layers[maxmizescreen ? LyrTile
: c->isfloating ? LyrTop
: LyrTile]);
if (!c->ismaxmizescreen) {
set_size_per(c->mon, c);
}
arrange(c->mon, false);
}
void setfakefullscreen(Client *c, int fakefullscreen) {
@@ -4450,6 +4441,10 @@ void setfullscreen(Client *c, int fullscreen) // 用自定义全屏代理自带
layers[fullscreen || c->isfloating ? LyrTop : LyrTile]);
}
if (!c->isfullscreen) {
set_size_per(c->mon, c);
}
arrange(c->mon, false);
}