mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-02-05 04:06:28 -05:00
Compare commits
50 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e898417a7 | ||
|
|
65fcd58949 | ||
|
|
2bda8e3bf1 | ||
|
|
a4faf2c494 | ||
|
|
b0f839468c | ||
|
|
8ba259fbb7 | ||
|
|
16e361e1ca | ||
|
|
336f873d83 | ||
|
|
50b67ac539 | ||
|
|
0546a2d4c4 | ||
|
|
eb0607501d | ||
|
|
bcee63fa76 | ||
|
|
5172444e08 | ||
|
|
ca09aa69db | ||
|
|
aa5241fb7b | ||
|
|
672706c71f | ||
|
|
d9f679a8e3 | ||
|
|
4591b69e4d | ||
|
|
e535aea28b | ||
|
|
30692f6da0 | ||
|
|
2e6e23633e | ||
|
|
6624d80522 | ||
|
|
05010a1114 | ||
|
|
00de523039 | ||
|
|
f1cca251b8 | ||
|
|
0652f99e6e | ||
|
|
334bc076a0 | ||
|
|
49921eadfa | ||
|
|
d78526d1e9 | ||
|
|
1124d47786 | ||
|
|
5942c5d807 | ||
|
|
04ac4bf99c | ||
|
|
fc13b0ff15 | ||
|
|
43257ad49c | ||
|
|
eff11a5912 | ||
|
|
34aa2e019e | ||
|
|
48c466254a | ||
|
|
57d7801df2 | ||
|
|
00f56fa3aa | ||
|
|
deaa26c779 | ||
|
|
e0d69ece59 | ||
|
|
48737bb58c | ||
|
|
c0f38e8a36 | ||
|
|
bc1f310e1c | ||
|
|
06a4acd992 | ||
|
|
373377eb17 | ||
|
|
764eb44b9b | ||
|
|
8e8c513beb | ||
|
|
4efb8c5e06 | ||
|
|
5a714b7562 |
15 changed files with 1575 additions and 449 deletions
12
README.md
12
README.md
|
|
@ -285,3 +285,15 @@ Read The Friendly Manual on packaging software in your distribution first.
|
|||
- https://github.com/swaywm/sway - Sample of Wayland protocol
|
||||
|
||||
- https://github.com/wlrfx/scenefx - Make it simple to add window effect.
|
||||
|
||||
|
||||
# Sponsor
|
||||
At present, I can only accept sponsorship through an encrypted connection.
|
||||
If you find this project helpful to you, you can offer sponsorship in the following ways.
|
||||
|
||||
<img width="650" height="870" alt="image" src="https://github.com/user-attachments/assets/8c860317-90d2-4071-971d-f1a92b674469" />
|
||||
|
||||
|
||||
Thanks to the following friends for their sponsorship of this project
|
||||
|
||||
[@tonybanters](https://github.com/tonybanters)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ focused_opacity=1.0
|
|||
unfocused_opacity=1.0
|
||||
|
||||
# Animation Configuration(support type:zoom,slide)
|
||||
# tag_animation_direction: 0-horizontal,1-vertical
|
||||
# tag_animation_direction: 1-horizontal,0-vertical
|
||||
animations=1
|
||||
layer_animations=1
|
||||
animation_type_open=slide
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
project('mango', ['c', 'cpp'],
|
||||
version : '0.10.10',
|
||||
version : '0.12.0',
|
||||
)
|
||||
|
||||
subdir('protocols')
|
||||
|
|
|
|||
|
|
@ -363,7 +363,6 @@ void apply_border(Client *c) {
|
|||
current_corner_location = set_client_corner_location(c);
|
||||
}
|
||||
|
||||
// Handle no-border cases
|
||||
if (hit_no_border && smartgaps) {
|
||||
c->bw = 0;
|
||||
c->fake_no_border = true;
|
||||
|
|
@ -981,6 +980,12 @@ void resize(Client *c, struct wlr_box geo, int32_t interact) {
|
|||
c->bw = 0;
|
||||
}
|
||||
|
||||
bool hit_no_border = check_hit_no_border(c);
|
||||
if (hit_no_border && smartgaps) {
|
||||
c->bw = 0;
|
||||
c->fake_no_border = true;
|
||||
}
|
||||
|
||||
// c->geom 是真实的窗口大小和位置,跟过度的动画无关,用于计算布局
|
||||
c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
c->geom.height - 2 * c->bw);
|
||||
|
|
@ -1049,20 +1054,11 @@ void client_set_focused_opacity_animation(Client *c) {
|
|||
sizeof(c->opacity_animation.target_border_color));
|
||||
c->opacity_animation.target_opacity = c->focused_opacity;
|
||||
c->opacity_animation.time_started = get_now_in_ms();
|
||||
if (c->opacity_animation.running) {
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity =
|
||||
c->opacity_animation.current_opacity;
|
||||
} else {
|
||||
memcpy(c->opacity_animation.initial_border_color, border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
memcpy(c->opacity_animation.current_border_color, border_color,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.initial_opacity = c->unfocused_opacity;
|
||||
c->opacity_animation.current_opacity = c->unfocused_opacity;
|
||||
}
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity;
|
||||
|
||||
c->opacity_animation.running = true;
|
||||
}
|
||||
|
||||
|
|
@ -1082,20 +1078,10 @@ void client_set_unfocused_opacity_animation(Client *c) {
|
|||
c->opacity_animation.target_opacity = c->unfocused_opacity;
|
||||
c->opacity_animation.time_started = get_now_in_ms();
|
||||
|
||||
if (c->opacity_animation.running) {
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity =
|
||||
c->opacity_animation.current_opacity;
|
||||
} else {
|
||||
memcpy(c->opacity_animation.initial_border_color, border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
memcpy(c->opacity_animation.current_border_color, border_color,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.initial_opacity = c->focused_opacity;
|
||||
c->opacity_animation.current_opacity = c->focused_opacity;
|
||||
}
|
||||
memcpy(c->opacity_animation.initial_border_color,
|
||||
c->opacity_animation.current_border_color,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
c->opacity_animation.initial_opacity = c->opacity_animation.current_opacity;
|
||||
|
||||
c->opacity_animation.running = true;
|
||||
}
|
||||
|
|
@ -1130,7 +1116,12 @@ bool client_apply_focus_opacity(Client *c) {
|
|||
if (target_opacity > opacity) {
|
||||
target_opacity = opacity;
|
||||
}
|
||||
memcpy(c->opacity_animation.current_border_color,
|
||||
c->opacity_animation.target_border_color,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.current_opacity = target_opacity;
|
||||
client_set_opacity(c, target_opacity);
|
||||
client_set_border_color(c, c->opacity_animation.target_border_color);
|
||||
} else if (animations && c->opacity_animation.running) {
|
||||
|
||||
struct timespec now;
|
||||
|
|
@ -1161,7 +1152,7 @@ bool client_apply_focus_opacity(Client *c) {
|
|||
eased_progress;
|
||||
}
|
||||
client_set_border_color(c, c->opacity_animation.current_border_color);
|
||||
if (linear_progress == 1.0f) {
|
||||
if (linear_progress >= 1.0f) {
|
||||
c->opacity_animation.running = false;
|
||||
} else {
|
||||
return true;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -47,8 +47,9 @@ int32_t log_level = WLR_ERROR;
|
|||
uint32_t numlockon = 0; // 是否打开右边小键盘
|
||||
uint32_t capslock = 0; // 是否启用快捷键
|
||||
|
||||
uint32_t ov_tab_mode = 0; // alt tab切换模式
|
||||
uint32_t hotarea_size = 10; // 热区大小,10x10
|
||||
uint32_t ov_tab_mode = 0; // alt tab切换模式
|
||||
uint32_t hotarea_size = 10; // 热区大小,10x10
|
||||
uint32_t hotarea_corner = BOTTOM_LEFT;
|
||||
uint32_t enable_hotarea = 1; // 是否启用鼠标热区
|
||||
int32_t smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||
int32_t sloppyfocus = 1; /* focus follows mouse */
|
||||
|
|
@ -62,7 +63,7 @@ float scratchpad_height_ratio = 0.9;
|
|||
int32_t scroller_structs = 20;
|
||||
float scroller_default_proportion = 0.9;
|
||||
float scroller_default_proportion_single = 1.0;
|
||||
int32_t scroller_ignore_proportion_single = 0;
|
||||
int32_t scroller_ignore_proportion_single = 1;
|
||||
int32_t scroller_focus_center = 0;
|
||||
int32_t scroller_prefer_center = 0;
|
||||
int32_t focus_cross_monitor = 0;
|
||||
|
|
@ -101,12 +102,14 @@ int32_t overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */
|
|||
* behavior */
|
||||
float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
|
||||
|
||||
int32_t warpcursor = 1; /* Warp cursor to focused client */
|
||||
int32_t warpcursor = 1;
|
||||
int32_t drag_corner = 3;
|
||||
int32_t drag_warp_cursor = 1;
|
||||
int32_t xwayland_persistence = 1; /* xwayland persistence */
|
||||
int32_t syncobj_enable = 0;
|
||||
int32_t adaptive_sync = 0;
|
||||
int32_t allow_lock_transparent = 0;
|
||||
double drag_refresh_interval = 16.0;
|
||||
double drag_tile_refresh_interval = 16.0;
|
||||
double drag_floating_refresh_interval = 8.0;
|
||||
int32_t allow_tearing = TEARING_DISABLED;
|
||||
int32_t allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||
|
||||
|
|
@ -233,4 +236,3 @@ double shadows_blur = 15;
|
|||
int32_t shadows_position_x = 0;
|
||||
int32_t shadows_position_y = 0;
|
||||
float shadowscolor[] = COLOR(0x000000ff);
|
||||
;
|
||||
|
|
|
|||
|
|
@ -68,4 +68,5 @@ int32_t toggle_trackpad_enable(const Arg *arg);
|
|||
int32_t setoption(const Arg *arg);
|
||||
int32_t disable_monitor(const Arg *arg);
|
||||
int32_t enable_monitor(const Arg *arg);
|
||||
int32_t toggle_monitor(const Arg *arg);
|
||||
int32_t toggle_monitor(const Arg *arg);
|
||||
int32_t scroller_stack(const Arg *arg);
|
||||
|
|
@ -129,6 +129,7 @@ int32_t exchange_stack_client(const Arg *arg) {
|
|||
int32_t focusdir(const Arg *arg) {
|
||||
Client *c = NULL;
|
||||
c = direction_select(arg);
|
||||
c = get_focused_stack_client(c);
|
||||
if (c) {
|
||||
focusclient(c, 1);
|
||||
if (warpcursor)
|
||||
|
|
@ -337,6 +338,9 @@ int32_t killclient(const Arg *arg) {
|
|||
}
|
||||
|
||||
int32_t moveresize(const Arg *arg) {
|
||||
const char *cursors[] = {"nw-resize", "ne-resize", "sw-resize",
|
||||
"se-resize"};
|
||||
|
||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
return 0;
|
||||
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
|
||||
|
|
@ -362,10 +366,29 @@ int32_t moveresize(const Arg *arg) {
|
|||
/* Doesn't work for X11 output - the next absolute motion event
|
||||
* returns the cursor to where it started */
|
||||
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");
|
||||
rzcorner = drag_corner;
|
||||
grabcx = (int)round(cursor->x);
|
||||
grabcy = (int)round(cursor->y);
|
||||
if (rzcorner == 4)
|
||||
/* identify the closest corner index */
|
||||
rzcorner = (grabcx - grabc->geom.x <
|
||||
grabc->geom.x + grabc->geom.width - grabcx
|
||||
? 0
|
||||
: 1) +
|
||||
(grabcy - grabc->geom.y <
|
||||
grabc->geom.y + grabc->geom.height - grabcy
|
||||
? 0
|
||||
: 2);
|
||||
|
||||
if (drag_warp_cursor) {
|
||||
grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width
|
||||
: grabc->geom.x;
|
||||
grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height
|
||||
: grabc->geom.y;
|
||||
wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
|
||||
}
|
||||
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]);
|
||||
} else {
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab");
|
||||
}
|
||||
|
|
@ -425,6 +448,10 @@ int32_t resizewin(const Arg *arg) {
|
|||
if (!c || c->isfullscreen || c->ismaximizescreen)
|
||||
return 0;
|
||||
|
||||
int32_t animations_state_backup = animations;
|
||||
if (!c->isfloating)
|
||||
animations = 0;
|
||||
|
||||
if (ISTILED(c)) {
|
||||
switch (arg->ui) {
|
||||
case NUM_TYPE_MINUS:
|
||||
|
|
@ -450,6 +477,7 @@ int32_t resizewin(const Arg *arg) {
|
|||
break;
|
||||
}
|
||||
resize_tile_client(c, false, offsetx, offsety, 0);
|
||||
animations = animations_state_backup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -480,6 +508,7 @@ int32_t resizewin(const Arg *arg) {
|
|||
c->iscustomsize = 1;
|
||||
c->float_geom = c->geom;
|
||||
resize(c, c->geom, 0);
|
||||
animations = animations_state_backup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -550,12 +579,14 @@ int32_t set_proportion(const Arg *arg) {
|
|||
!scroller_ignore_proportion_single)
|
||||
return 0;
|
||||
|
||||
if (selmon->sel) {
|
||||
Client *tc = selmon->sel;
|
||||
|
||||
if (tc) {
|
||||
tc = get_scroll_stack_head(tc);
|
||||
uint32_t max_client_width =
|
||||
selmon->w.width - 2 * scroller_structs - gappih;
|
||||
selmon->sel->scroller_proportion = arg->f;
|
||||
selmon->sel->geom.width = max_client_width * arg->f;
|
||||
// resize(selmon->sel, selmon->sel->geom, 0);
|
||||
tc->scroller_proportion = arg->f;
|
||||
tc->geom.width = max_client_width * arg->f;
|
||||
arrange(selmon, false, false);
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -740,7 +771,7 @@ int32_t centerwin(const Arg *arg) {
|
|||
return 0;
|
||||
|
||||
if (c->isfloating) {
|
||||
c->float_geom = setclient_coordinate_center(c, c->geom, 0, 0);
|
||||
c->float_geom = setclient_coordinate_center(c, c->mon, c->geom, 0, 0);
|
||||
c->iscustomsize = 1;
|
||||
resize(c, c->float_geom, 1);
|
||||
return 0;
|
||||
|
|
@ -749,10 +780,13 @@ int32_t centerwin(const Arg *arg) {
|
|||
if (!is_scroller_layout(selmon))
|
||||
return 0;
|
||||
|
||||
Client *stack_head = get_scroll_stack_head(c);
|
||||
if (selmon->pertag->ltidxs[selmon->pertag->curtag]->id == SCROLLER) {
|
||||
c->geom.x = selmon->w.x + (selmon->w.width - c->geom.width) / 2;
|
||||
stack_head->geom.x =
|
||||
selmon->w.x + (selmon->w.width - stack_head->geom.width) / 2;
|
||||
} else {
|
||||
c->geom.y = selmon->w.y + (selmon->w.height - c->geom.height) / 2;
|
||||
stack_head->geom.y =
|
||||
selmon->w.y + (selmon->w.height - stack_head->geom.height) / 2;
|
||||
}
|
||||
|
||||
arrange(selmon, false, false);
|
||||
|
|
@ -971,11 +1005,13 @@ int32_t switch_proportion_preset(const Arg *arg) {
|
|||
!scroller_ignore_proportion_single)
|
||||
return 0;
|
||||
|
||||
if (selmon->sel) {
|
||||
Client *tc = selmon->sel;
|
||||
|
||||
if (tc) {
|
||||
tc = get_scroll_stack_head(tc);
|
||||
for (int32_t i = 0; i < config.scroller_proportion_preset_count; i++) {
|
||||
if (config.scroller_proportion_preset[i] ==
|
||||
selmon->sel->scroller_proportion) {
|
||||
tc->scroller_proportion) {
|
||||
if (i == config.scroller_proportion_preset_count - 1) {
|
||||
target_proportion = config.scroller_proportion_preset[0];
|
||||
break;
|
||||
|
|
@ -993,9 +1029,8 @@ int32_t switch_proportion_preset(const Arg *arg) {
|
|||
|
||||
uint32_t max_client_width =
|
||||
selmon->w.width - 2 * scroller_structs - gappih;
|
||||
selmon->sel->scroller_proportion = target_proportion;
|
||||
selmon->sel->geom.width = max_client_width * target_proportion;
|
||||
// resize(selmon->sel, selmon->sel->geom, 0);
|
||||
tc->scroller_proportion = target_proportion;
|
||||
tc->geom.width = max_client_width * target_proportion;
|
||||
arrange(selmon, false, false);
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1055,7 +1090,7 @@ int32_t tagmon(const Arg *arg) {
|
|||
c->float_geom.height =
|
||||
(int32_t)(c->float_geom.height * c->mon->w.height / selmon->w.height);
|
||||
selmon = c->mon;
|
||||
c->float_geom = setclient_coordinate_center(c, c->float_geom, 0, 0);
|
||||
c->float_geom = setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);
|
||||
|
||||
// 重新计算居中的坐标
|
||||
// 重新计算居中的坐标
|
||||
|
|
@ -1093,6 +1128,7 @@ int32_t tagsilent(const Arg *arg) {
|
|||
clear_fullscreen_flag(fc);
|
||||
}
|
||||
}
|
||||
exit_scroller_stack(target_client);
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(target_client->mon, false, false);
|
||||
return 0;
|
||||
|
|
@ -1221,9 +1257,11 @@ int32_t toggleglobal(const Arg *arg) {
|
|||
selmon->sel->isnamedscratchpad = 0;
|
||||
}
|
||||
selmon->sel->isglobal ^= 1;
|
||||
// selmon->sel->tags =
|
||||
// selmon->sel->isglobal ? TAGMASK : selmon->tagset[selmon->seltags];
|
||||
// focustop(selmon);
|
||||
if (selmon->sel->isglobal &&
|
||||
(selmon->sel->prev_in_stack || selmon->sel->next_in_stack)) {
|
||||
exit_scroller_stack(selmon->sel);
|
||||
arrange(selmon, false, false);
|
||||
}
|
||||
setborder_color(selmon->sel);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1406,9 +1444,14 @@ int32_t viewcrossmon(const Arg *arg) {
|
|||
}
|
||||
|
||||
int32_t tagcrossmon(const Arg *arg) {
|
||||
if (!selmon->sel)
|
||||
if (!selmon || !selmon->sel)
|
||||
return 0;
|
||||
|
||||
if (regex_match(selmon->wlr_output->name, arg->v)) {
|
||||
tag_client(arg, selmon->sel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tagmon(&(Arg){.ui = arg->ui, .i = UNDIR, .v = arg->v});
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1585,3 +1628,106 @@ int32_t toggle_monitor(const Arg *arg) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t scroller_stack(const Arg *arg) {
|
||||
Client *c = selmon->sel;
|
||||
Client *stack_head = NULL;
|
||||
Client *source_stack_head = NULL;
|
||||
if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon))
|
||||
return 0;
|
||||
|
||||
if (c && (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal))
|
||||
return 0;
|
||||
|
||||
bool is_horizontal_layout =
|
||||
c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true
|
||||
: false;
|
||||
|
||||
Client *target_client = find_client_by_direction(c, arg, false, true);
|
||||
|
||||
if (target_client && (!client_only_in_one_tag(target_client) ||
|
||||
target_client->isglobal || target_client->isunglobal))
|
||||
return 0;
|
||||
|
||||
if (target_client) {
|
||||
stack_head = get_scroll_stack_head(target_client);
|
||||
}
|
||||
|
||||
if (c) {
|
||||
source_stack_head = get_scroll_stack_head(c);
|
||||
}
|
||||
|
||||
if (stack_head == source_stack_head) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c->isfullscreen) {
|
||||
setfullscreen(c, 0);
|
||||
}
|
||||
|
||||
if (c->ismaximizescreen) {
|
||||
setmaximizescreen(c, 0);
|
||||
}
|
||||
|
||||
if (c->prev_in_stack) {
|
||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
||||
(!is_horizontal_layout && arg->i == UP)) {
|
||||
exit_scroller_stack(c);
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(source_stack_head->link.prev, &c->link);
|
||||
arrange(selmon, false, false);
|
||||
|
||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
||||
exit_scroller_stack(c);
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&source_stack_head->link, &c->link);
|
||||
arrange(selmon, false, false);
|
||||
}
|
||||
return 0;
|
||||
} else if (c->next_in_stack) {
|
||||
Client *next_in_stack = c->next_in_stack;
|
||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
||||
(!is_horizontal_layout && arg->i == UP)) {
|
||||
exit_scroller_stack(c);
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(next_in_stack->link.prev, &c->link);
|
||||
arrange(selmon, false, false);
|
||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
||||
exit_scroller_stack(c);
|
||||
wl_list_remove(&c->link);
|
||||
wl_list_insert(&next_in_stack->link, &c->link);
|
||||
arrange(selmon, false, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!target_client || target_client->mon != c->mon) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
exit_scroller_stack(c);
|
||||
|
||||
// Find the tail of target_client's stack
|
||||
Client *stack_tail = target_client;
|
||||
while (stack_tail->next_in_stack) {
|
||||
stack_tail = stack_tail->next_in_stack;
|
||||
}
|
||||
|
||||
// Add c to the stack
|
||||
stack_tail->next_in_stack = c;
|
||||
c->prev_in_stack = stack_tail;
|
||||
c->next_in_stack = NULL;
|
||||
|
||||
if (stack_head->ismaximizescreen) {
|
||||
setmaximizescreen(stack_head, 0);
|
||||
}
|
||||
|
||||
if (stack_head->isfullscreen) {
|
||||
setfullscreen(stack_head, 0);
|
||||
}
|
||||
|
||||
arrange(selmon, false, false);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -12,7 +12,9 @@ bool check_hit_no_border(Client *c) {
|
|||
}
|
||||
}
|
||||
|
||||
if (no_border_when_single && c && c->mon && c->mon->visible_clients == 1) {
|
||||
if (no_border_when_single && c && c->mon &&
|
||||
((ISSCROLLTILED(c) && c->mon->visible_scroll_tiling_clients == 1) ||
|
||||
c->mon->visible_clients == 1)) {
|
||||
hit_no_border = true;
|
||||
}
|
||||
return hit_no_border;
|
||||
|
|
@ -74,12 +76,12 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
|||
return target_client;
|
||||
}
|
||||
struct wlr_box // 计算客户端居中坐标
|
||||
setclient_coordinate_center(Client *c, struct wlr_box geom, int32_t offsetx,
|
||||
int32_t offsety) {
|
||||
setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom,
|
||||
int32_t offsetx, int32_t offsety) {
|
||||
struct wlr_box tempbox;
|
||||
int32_t offset = 0;
|
||||
int32_t len = 0;
|
||||
Monitor *m = c->mon ? c->mon : selmon;
|
||||
Monitor *m = tm ? tm : selmon;
|
||||
|
||||
uint32_t cbw = check_hit_no_border(c) ? c->bw : 0;
|
||||
|
||||
|
|
@ -215,6 +217,27 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.y < sel_y &&
|
||||
tempClients[_i]->mon == tc->mon &&
|
||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
||||
int64_t tmp_distance =
|
||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||
if (tmp_distance < distance) {
|
||||
distance = tmp_distance;
|
||||
tempFocusClients = tempClients[_i];
|
||||
}
|
||||
if (tempClients[_i]->mon == tc->mon &&
|
||||
tmp_distance < same_monitor_distance) {
|
||||
same_monitor_distance = tmp_distance;
|
||||
tempSameMonitorFocusClients = tempClients[_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.y < sel_y) {
|
||||
|
|
@ -252,6 +275,27 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.y > sel_y &&
|
||||
tempClients[_i]->mon == tc->mon &&
|
||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
||||
int64_t tmp_distance =
|
||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||
if (tmp_distance < distance) {
|
||||
distance = tmp_distance;
|
||||
tempFocusClients = tempClients[_i];
|
||||
}
|
||||
if (tempClients[_i]->mon == tc->mon &&
|
||||
tmp_distance < same_monitor_distance) {
|
||||
same_monitor_distance = tmp_distance;
|
||||
tempSameMonitorFocusClients = tempClients[_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.y > sel_y) {
|
||||
|
|
@ -289,6 +333,27 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.x < sel_x &&
|
||||
tempClients[_i]->mon == tc->mon &&
|
||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
||||
int64_t tmp_distance =
|
||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||
if (tmp_distance < distance) {
|
||||
distance = tmp_distance;
|
||||
tempFocusClients = tempClients[_i];
|
||||
}
|
||||
if (tempClients[_i]->mon == tc->mon &&
|
||||
tmp_distance < same_monitor_distance) {
|
||||
same_monitor_distance = tmp_distance;
|
||||
tempSameMonitorFocusClients = tempClients[_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.x < sel_x) {
|
||||
|
|
@ -326,6 +391,27 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.x > sel_x &&
|
||||
tempClients[_i]->mon == tc->mon &&
|
||||
client_is_in_same_stack(tc, tempClients[_i], NULL)) {
|
||||
int32_t dis_x = tempClients[_i]->geom.x - sel_x;
|
||||
int32_t dis_y = tempClients[_i]->geom.y - sel_y;
|
||||
int64_t tmp_distance =
|
||||
dis_x * dis_x + dis_y * dis_y; // 计算距离
|
||||
if (tmp_distance < distance) {
|
||||
distance = tmp_distance;
|
||||
tempFocusClients = tempClients[_i];
|
||||
}
|
||||
if (tempClients[_i]->mon == tc->mon &&
|
||||
tmp_distance < same_monitor_distance) {
|
||||
same_monitor_distance = tmp_distance;
|
||||
tempSameMonitorFocusClients = tempClients[_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tempFocusClients) {
|
||||
for (int32_t _i = 0; _i <= last; _i++) {
|
||||
if (tempClients[_i]->geom.x > sel_x) {
|
||||
|
|
@ -369,7 +455,9 @@ Client *direction_select(const Arg *arg) {
|
|||
}
|
||||
|
||||
return find_client_by_direction(
|
||||
tc, arg, true, is_scroller_layout(selmon) && !selmon->isoverview);
|
||||
tc, arg, true,
|
||||
(is_scroller_layout(selmon) || is_centertile_layout(selmon)) &&
|
||||
!selmon->isoverview);
|
||||
}
|
||||
|
||||
/* We probably should change the name of this, it sounds like
|
||||
|
|
@ -447,4 +535,91 @@ bool client_only_in_one_tag(Client *c) {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Client *get_scroll_stack_head(Client *c) {
|
||||
Client *scroller_stack_head = c;
|
||||
|
||||
if (!scroller_stack_head)
|
||||
return NULL;
|
||||
|
||||
while (scroller_stack_head->prev_in_stack) {
|
||||
scroller_stack_head = scroller_stack_head->prev_in_stack;
|
||||
}
|
||||
return scroller_stack_head;
|
||||
}
|
||||
|
||||
bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc) {
|
||||
if (!sc || !tc)
|
||||
return false;
|
||||
|
||||
uint32_t id = sc->mon->pertag->ltidxs[sc->mon->pertag->curtag]->id;
|
||||
|
||||
if (id != SCROLLER && id != VERTICAL_SCROLLER && id != TILE &&
|
||||
id != VERTICAL_TILE && id != DECK && id != VERTICAL_DECK &&
|
||||
id != CENTER_TILE && id != RIGHT_TILE && id != TGMIX)
|
||||
return false;
|
||||
|
||||
if (id == SCROLLER || id == VERTICAL_SCROLLER) {
|
||||
Client *source_stack_head = get_scroll_stack_head(sc);
|
||||
Client *target_stack_head = get_scroll_stack_head(tc);
|
||||
Client *fc_head = fc ? get_scroll_stack_head(fc) : NULL;
|
||||
if (fc && fc->prev_in_stack && fc_head == source_stack_head)
|
||||
return false;
|
||||
if (source_stack_head == target_stack_head)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id == TILE || id == VERTICAL_TILE || id == DECK ||
|
||||
id == VERTICAL_DECK || id == RIGHT_TILE) {
|
||||
if (fc && !fc->ismaster)
|
||||
return false;
|
||||
else if (!sc->ismaster)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == TGMIX) {
|
||||
if (fc && !fc->ismaster)
|
||||
return false;
|
||||
if (!sc->ismaster && sc->mon->visible_tiling_clients <= 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == CENTER_TILE) {
|
||||
if (fc && !fc->ismaster)
|
||||
return false;
|
||||
if (!sc->ismaster && sc->geom.x == tc->geom.x)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Client *get_focused_stack_client(Client *sc) {
|
||||
if (!sc || sc->isfloating)
|
||||
return sc;
|
||||
|
||||
Client *tc = NULL;
|
||||
Client *fc = focustop(sc->mon);
|
||||
|
||||
if (fc->isfloating || sc->isfloating)
|
||||
return sc;
|
||||
|
||||
wl_list_for_each(tc, &fstack, flink) {
|
||||
if (tc->iskilling || tc->isunglobal)
|
||||
continue;
|
||||
if (!VISIBLEON(tc, sc->mon))
|
||||
continue;
|
||||
if (tc == fc)
|
||||
continue;
|
||||
|
||||
if (client_is_in_same_stack(sc, tc, fc)) {
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ bool is_scroller_layout(Monitor *m) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool is_centertile_layout(Monitor *m) {
|
||||
|
||||
if (m->pertag->ltidxs[m->pertag->curtag]->id == CENTER_TILE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t get_tag_status(uint32_t tag, Monitor *m) {
|
||||
Client *c = NULL;
|
||||
uint32_t status = 0;
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
}
|
||||
|
||||
if (last_apply_drap_time == 0 ||
|
||||
time - last_apply_drap_time > drag_refresh_interval) {
|
||||
time - last_apply_drap_time > drag_tile_refresh_interval) {
|
||||
arrange(grabc->mon, false, false);
|
||||
last_apply_drap_time = time;
|
||||
}
|
||||
|
|
@ -367,7 +367,7 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
}
|
||||
|
||||
if (last_apply_drap_time == 0 ||
|
||||
time - last_apply_drap_time > drag_refresh_interval) {
|
||||
time - last_apply_drap_time > drag_tile_refresh_interval) {
|
||||
arrange(grabc->mon, false, false);
|
||||
last_apply_drap_time = time;
|
||||
}
|
||||
|
|
@ -378,6 +378,8 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
int32_t offsety, uint32_t time, bool isvertical) {
|
||||
float delta_x, delta_y;
|
||||
float new_scroller_proportion;
|
||||
float new_stack_proportion;
|
||||
Client *stack_head = get_scroll_stack_head(grabc);
|
||||
|
||||
if (grabc && grabc->mon->visible_tiling_clients == 1 &&
|
||||
!scroller_ignore_proportion_single)
|
||||
|
|
@ -389,7 +391,8 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
start_drag_window = true;
|
||||
|
||||
// 记录初始状态
|
||||
grabc->old_scroller_pproportion = grabc->scroller_proportion;
|
||||
stack_head->old_scroller_pproportion = stack_head->scroller_proportion;
|
||||
grabc->old_stack_proportion = grabc->stack_proportion;
|
||||
|
||||
grabc->cursor_in_left_half =
|
||||
cursor->x < grabc->geom.x + grabc->geom.width / 2;
|
||||
|
|
@ -409,15 +412,26 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
grabc->old_master_inner_per = grabc->master_inner_per;
|
||||
grabc->old_stack_inner_per = grabc->stack_inner_per;
|
||||
grabc->drag_begin_geom = grabc->geom;
|
||||
grabc->old_scroller_pproportion = grabc->scroller_proportion;
|
||||
stack_head->old_scroller_pproportion =
|
||||
stack_head->scroller_proportion;
|
||||
grabc->old_stack_proportion = grabc->stack_proportion;
|
||||
grabc->cursor_in_upper_half = false;
|
||||
grabc->cursor_in_left_half = false;
|
||||
}
|
||||
|
||||
delta_x = (float)(offsetx) * (grabc->old_scroller_pproportion) /
|
||||
grabc->drag_begin_geom.width;
|
||||
delta_y = (float)(offsety) * (grabc->old_scroller_pproportion) /
|
||||
grabc->drag_begin_geom.height;
|
||||
if (isvertical) {
|
||||
delta_y = (float)(offsety) *
|
||||
(stack_head->old_scroller_pproportion) /
|
||||
grabc->drag_begin_geom.height;
|
||||
delta_x = (float)(offsetx) * (grabc->old_stack_proportion) /
|
||||
grabc->drag_begin_geom.width;
|
||||
} else {
|
||||
delta_x = (float)(offsetx) *
|
||||
(stack_head->old_scroller_pproportion) /
|
||||
grabc->drag_begin_geom.width;
|
||||
delta_y = (float)(offsety) * (grabc->old_stack_proportion) /
|
||||
grabc->drag_begin_geom.height;
|
||||
}
|
||||
|
||||
bool moving_up;
|
||||
bool moving_down;
|
||||
|
|
@ -452,18 +466,81 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
delta_x = -fabsf(delta_x);
|
||||
}
|
||||
|
||||
if (isvertical) {
|
||||
if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) {
|
||||
delta_x = delta_x * -1.0f;
|
||||
}
|
||||
if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) {
|
||||
if (moving_right) {
|
||||
delta_x = -fabsf(delta_x);
|
||||
} else {
|
||||
delta_x = fabsf(delta_x);
|
||||
}
|
||||
}
|
||||
if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) {
|
||||
if (moving_left) {
|
||||
delta_x = -fabsf(delta_x);
|
||||
} else {
|
||||
delta_x = fabsf(delta_x);
|
||||
}
|
||||
}
|
||||
|
||||
if (isdrag) {
|
||||
if (moving_up) {
|
||||
delta_y = -fabsf(delta_y);
|
||||
} else {
|
||||
delta_y = fabsf(delta_y);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!grabc->next_in_stack && grabc->prev_in_stack && !isdrag) {
|
||||
delta_y = delta_y * -1.0f;
|
||||
}
|
||||
if (!grabc->next_in_stack && grabc->prev_in_stack && isdrag) {
|
||||
if (moving_down) {
|
||||
delta_y = -fabsf(delta_y);
|
||||
} else {
|
||||
delta_y = fabsf(delta_y);
|
||||
}
|
||||
}
|
||||
if (!grabc->prev_in_stack && grabc->next_in_stack && isdrag) {
|
||||
if (moving_up) {
|
||||
delta_y = -fabsf(delta_y);
|
||||
} else {
|
||||
delta_y = fabsf(delta_y);
|
||||
}
|
||||
}
|
||||
|
||||
if (isdrag) {
|
||||
if (moving_left) {
|
||||
delta_x = -fabsf(delta_x);
|
||||
} else {
|
||||
delta_x = fabsf(delta_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 直接设置新的比例,基于初始值 + 变化量
|
||||
if (isvertical) {
|
||||
new_scroller_proportion = grabc->old_scroller_pproportion + delta_y;
|
||||
new_scroller_proportion =
|
||||
stack_head->old_scroller_pproportion + delta_y;
|
||||
new_stack_proportion = grabc->old_stack_proportion + delta_x;
|
||||
|
||||
} else {
|
||||
new_scroller_proportion = grabc->old_scroller_pproportion + delta_x;
|
||||
new_scroller_proportion =
|
||||
stack_head->old_scroller_pproportion + delta_x;
|
||||
new_stack_proportion = grabc->old_stack_proportion + delta_y;
|
||||
}
|
||||
|
||||
// 应用限制,确保比例在合理范围内
|
||||
new_scroller_proportion =
|
||||
fmaxf(0.1f, fminf(1.0f, new_scroller_proportion));
|
||||
new_stack_proportion = fmaxf(0.1f, fminf(1.0f, new_stack_proportion));
|
||||
|
||||
grabc->scroller_proportion = new_scroller_proportion;
|
||||
grabc->stack_proportion = new_stack_proportion;
|
||||
|
||||
stack_head->scroller_proportion = new_scroller_proportion;
|
||||
|
||||
if (!isdrag) {
|
||||
arrange(grabc->mon, false, false);
|
||||
|
|
@ -471,7 +548,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx,
|
|||
}
|
||||
|
||||
if (last_apply_drap_time == 0 ||
|
||||
time - last_apply_drap_time > drag_refresh_interval) {
|
||||
time - last_apply_drap_time > drag_tile_refresh_interval) {
|
||||
arrange(grabc->mon, false, false);
|
||||
last_apply_drap_time = time;
|
||||
}
|
||||
|
|
@ -605,14 +682,20 @@ arrange(Monitor *m, bool want_animation, bool from_view) {
|
|||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
|
||||
if (!client_only_in_one_tag(c) || c->isglobal || c->isunglobal) {
|
||||
exit_scroller_stack(c);
|
||||
}
|
||||
|
||||
if (from_view && (c->isglobal || c->isunglobal)) {
|
||||
set_size_per(m, c);
|
||||
}
|
||||
|
||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||
c->tags = m->tagset[m->seltags];
|
||||
if (c->mon->sel == NULL)
|
||||
focusclient(c, 0);
|
||||
}
|
||||
|
||||
if (from_view && m->sel == NULL && c->isglobal && VISIBLEON(c, m)) {
|
||||
focusclient(c, 1);
|
||||
}
|
||||
|
||||
if (VISIBLEON(c, m)) {
|
||||
|
|
@ -627,7 +710,7 @@ arrange(Monitor *m, bool want_animation, bool from_view) {
|
|||
m->visible_tiling_clients++;
|
||||
}
|
||||
|
||||
if (ISSCROLLTILED(c)) {
|
||||
if (ISSCROLLTILED(c) && !c->prev_in_stack) {
|
||||
m->visible_scroll_tiling_clients++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ void deck(Monitor *m) {
|
|||
Client *c = NULL;
|
||||
Client *fc = NULL;
|
||||
float mfact;
|
||||
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||
|
||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||
|
|
@ -142,8 +143,8 @@ void deck(Monitor *m) {
|
|||
: m->pertag->mfacts[m->pertag->curtag];
|
||||
|
||||
// Calculate master width including outer gaps
|
||||
if (n > m->nmaster)
|
||||
mw = m->nmaster ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
|
||||
if (n > nmasters)
|
||||
mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
|
||||
else
|
||||
mw = m->w.width - 2 * cur_gappoh;
|
||||
|
||||
|
|
@ -151,7 +152,7 @@ void deck(Monitor *m) {
|
|||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || !ISTILED(c))
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
if (i < nmasters) {
|
||||
c->master_mfact_per = mfact;
|
||||
// Master area clients
|
||||
resize(
|
||||
|
|
@ -160,7 +161,7 @@ void deck(Monitor *m) {
|
|||
.y = m->w.y + cur_gappov + my,
|
||||
.width = mw,
|
||||
.height = (m->w.height - 2 * cur_gappov - my) /
|
||||
(MIN(n, m->nmaster) - i)},
|
||||
(MIN(n, nmasters) - i)},
|
||||
0);
|
||||
my += c->geom.height;
|
||||
} else {
|
||||
|
|
@ -212,6 +213,66 @@ void horizontal_scroll_adjust_fullandmax(Client *c,
|
|||
target_geom->y = m->w.y + (m->w.height - target_geom->height) / 2;
|
||||
}
|
||||
|
||||
void arrange_stack(Client *scroller_stack_head, struct wlr_box geometry,
|
||||
int32_t gappiv) {
|
||||
int32_t stack_size = 0;
|
||||
Client *iter = scroller_stack_head;
|
||||
|
||||
while (iter) {
|
||||
stack_size++;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
if (stack_size == 0)
|
||||
return;
|
||||
|
||||
float total_proportion = 0.0f;
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) {
|
||||
iter->stack_proportion =
|
||||
stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1);
|
||||
}
|
||||
total_proportion += iter->stack_proportion;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
iter->stack_proportion = iter->stack_proportion / total_proportion;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
int32_t client_height;
|
||||
int32_t current_y = geometry.y;
|
||||
int32_t remain_client_height = geometry.height - (stack_size - 1) * gappiv;
|
||||
float remain_proportion = 1.0f;
|
||||
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
|
||||
client_height =
|
||||
remain_client_height * (iter->stack_proportion / remain_proportion);
|
||||
|
||||
struct wlr_box client_geom = {.x = geometry.x,
|
||||
.y = current_y,
|
||||
.width = geometry.width,
|
||||
.height = client_height};
|
||||
resize(iter, client_geom, 0);
|
||||
remain_proportion -= iter->stack_proportion;
|
||||
remain_client_height -= client_height;
|
||||
current_y += client_height + gappiv;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
}
|
||||
|
||||
void horizontal_check_scroller_root_inside_mon(Client *c,
|
||||
struct wlr_box *geometry) {
|
||||
if (!GEOMINSIDEMON(geometry, c->mon)) {
|
||||
geometry->x = c->mon->w.x + (c->mon->w.width - geometry->width) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动布局
|
||||
void scroller(Monitor *m) {
|
||||
int32_t i, n, j;
|
||||
|
|
@ -225,6 +286,7 @@ void scroller(Monitor *m) {
|
|||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||
|
||||
cur_gappih =
|
||||
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappih;
|
||||
|
|
@ -251,7 +313,7 @@ void scroller(Monitor *m) {
|
|||
// 第二次遍历,填充 tempClients
|
||||
j = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c)) {
|
||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) {
|
||||
tempClients[j] = c;
|
||||
j++;
|
||||
}
|
||||
|
|
@ -269,7 +331,8 @@ void scroller(Monitor *m) {
|
|||
target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion;
|
||||
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
|
||||
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
|
||||
resize(c, target_geom, 0);
|
||||
horizontal_check_scroller_root_inside_mon(c, &target_geom);
|
||||
arrange_stack(c, target_geom, cur_gappiv);
|
||||
free(tempClients); // 释放内存
|
||||
return;
|
||||
}
|
||||
|
|
@ -283,6 +346,11 @@ void scroller(Monitor *m) {
|
|||
root_client = center_tiled_select(m);
|
||||
}
|
||||
|
||||
// root_client might be in a stack, find the stack head
|
||||
if (root_client) {
|
||||
root_client = get_scroll_stack_head(root_client);
|
||||
}
|
||||
|
||||
if (!root_client) {
|
||||
free(tempClients); // 释放内存
|
||||
return;
|
||||
|
|
@ -317,10 +385,14 @@ void scroller(Monitor *m) {
|
|||
&target_geom);
|
||||
if (tempClients[focus_client_index]->isfullscreen) {
|
||||
target_geom.x = m->m.x;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
horizontal_check_scroller_root_inside_mon(
|
||||
tempClients[focus_client_index], &target_geom);
|
||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
||||
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
||||
target_geom.x = m->w.x + cur_gappoh;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
horizontal_check_scroller_root_inside_mon(
|
||||
tempClients[focus_client_index], &target_geom);
|
||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
||||
} else if (need_scroller) {
|
||||
if (scroller_focus_center ||
|
||||
((!m->prevsel ||
|
||||
|
|
@ -338,10 +410,14 @@ void scroller(Monitor *m) {
|
|||
scroller_structs)
|
||||
: m->w.x + scroller_structs;
|
||||
}
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
horizontal_check_scroller_root_inside_mon(
|
||||
tempClients[focus_client_index], &target_geom);
|
||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
||||
} else {
|
||||
target_geom.x = c->geom.x;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
horizontal_check_scroller_root_inside_mon(
|
||||
tempClients[focus_client_index], &target_geom);
|
||||
arrange_stack(tempClients[focus_client_index], target_geom, cur_gappiv);
|
||||
}
|
||||
|
||||
for (i = 1; i <= focus_client_index; i++) {
|
||||
|
|
@ -351,7 +427,7 @@ void scroller(Monitor *m) {
|
|||
target_geom.x = tempClients[focus_client_index - i + 1]->geom.x -
|
||||
cur_gappih - target_geom.width;
|
||||
|
||||
resize(c, target_geom, 0);
|
||||
arrange_stack(c, target_geom, cur_gappiv);
|
||||
}
|
||||
|
||||
for (i = 1; i < n - focus_client_index; i++) {
|
||||
|
|
@ -361,7 +437,7 @@ void scroller(Monitor *m) {
|
|||
target_geom.x = tempClients[focus_client_index + i - 1]->geom.x +
|
||||
cur_gappih +
|
||||
tempClients[focus_client_index + i - 1]->geom.width;
|
||||
resize(c, target_geom, 0);
|
||||
arrange_stack(c, target_geom, cur_gappiv);
|
||||
}
|
||||
|
||||
free(tempClients); // 最后释放内存
|
||||
|
|
@ -853,4 +929,4 @@ void tgmix(Monitor *m) {
|
|||
grid(m);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ static void tgmix(Monitor *m);
|
|||
Layout overviewlayout = {"", overview, "overview"};
|
||||
|
||||
enum {
|
||||
SCROLLER,
|
||||
TILE,
|
||||
SCROLLER,
|
||||
GRID,
|
||||
MONOCLE,
|
||||
DECK,
|
||||
|
|
@ -34,8 +34,8 @@ enum {
|
|||
Layout layouts[] = {
|
||||
// 最少两个,不能删除少于两个
|
||||
/* symbol arrange function name */
|
||||
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
||||
{"T", tile, "tile", TILE}, // 平铺布局
|
||||
{"S", scroller, "scroller", SCROLLER}, // 滚动布局
|
||||
{"G", grid, "grid", GRID}, // 格子布局
|
||||
{"M", monocle, "monocle", MONOCLE}, // 单屏布局
|
||||
{"K", deck, "deck", DECK}, // 卡片布局
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ void vertical_deck(Monitor *m) {
|
|||
Client *c = NULL;
|
||||
Client *fc = NULL;
|
||||
float mfact;
|
||||
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
||||
|
||||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||
|
|
@ -134,8 +135,8 @@ void vertical_deck(Monitor *m) {
|
|||
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
||||
: m->pertag->mfacts[m->pertag->curtag];
|
||||
|
||||
if (n > m->nmaster)
|
||||
mh = m->nmaster ? round((m->w.height - 2 * cur_gappov) * mfact) : 0;
|
||||
if (n > nmasters)
|
||||
mh = nmasters ? round((m->w.height - 2 * cur_gappov) * mfact) : 0;
|
||||
else
|
||||
mh = m->w.height - 2 * cur_gappov;
|
||||
|
||||
|
|
@ -143,13 +144,13 @@ void vertical_deck(Monitor *m) {
|
|||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || !ISTILED(c))
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
if (i < nmasters) {
|
||||
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),
|
||||
(MIN(n, nmasters) - i),
|
||||
.height = mh},
|
||||
0);
|
||||
mx += c->geom.width;
|
||||
|
|
@ -199,6 +200,66 @@ void vertical_scroll_adjust_fullandmax(Client *c, struct wlr_box *target_geom) {
|
|||
target_geom->x = m->w.x + (m->w.width - target_geom->width) / 2;
|
||||
}
|
||||
|
||||
void arrange_stack_vertical(Client *scroller_stack_head,
|
||||
struct wlr_box geometry, int32_t gappih) {
|
||||
int32_t stack_size = 0;
|
||||
Client *iter = scroller_stack_head;
|
||||
|
||||
while (iter) {
|
||||
stack_size++;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
if (stack_size == 0)
|
||||
return;
|
||||
|
||||
float total_proportion = 0.0f;
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
if (iter->stack_proportion <= 0.0f || iter->stack_proportion >= 1.0f) {
|
||||
iter->stack_proportion =
|
||||
stack_size == 1 ? 1.0f : 1.0f / (stack_size - 1);
|
||||
}
|
||||
total_proportion += iter->stack_proportion;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
iter->stack_proportion = iter->stack_proportion / total_proportion;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
|
||||
int32_t client_width;
|
||||
int32_t current_x = geometry.x;
|
||||
int32_t remain_client_width = geometry.width - (stack_size - 1) * gappih;
|
||||
float remain_proportion = 1.0f;
|
||||
|
||||
iter = scroller_stack_head;
|
||||
while (iter) {
|
||||
|
||||
client_width =
|
||||
remain_client_width * (iter->stack_proportion / remain_proportion);
|
||||
|
||||
struct wlr_box client_geom = {.y = geometry.y,
|
||||
.x = current_x,
|
||||
.height = geometry.height,
|
||||
.width = client_width};
|
||||
resize(iter, client_geom, 0);
|
||||
remain_proportion -= iter->stack_proportion;
|
||||
remain_client_width -= client_width;
|
||||
current_x += client_width + gappih;
|
||||
iter = iter->next_in_stack;
|
||||
}
|
||||
}
|
||||
|
||||
void vertical_check_scroller_root_inside_mon(Client *c,
|
||||
struct wlr_box *geometry) {
|
||||
if (!GEOMINSIDEMON(geometry, c->mon)) {
|
||||
geometry->y = c->mon->w.y + (c->mon->w.height - geometry->height) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// 竖屏滚动布局
|
||||
void vertical_scroller(Monitor *m) {
|
||||
int32_t i, n, j;
|
||||
|
|
@ -212,6 +273,7 @@ void vertical_scroller(Monitor *m) {
|
|||
int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
|
||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
||||
|
||||
cur_gappiv =
|
||||
smartgaps && m->visible_scroll_tiling_clients == 1 ? 0 : cur_gappiv;
|
||||
|
|
@ -235,7 +297,7 @@ void vertical_scroller(Monitor *m) {
|
|||
|
||||
j = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c)) {
|
||||
if (VISIBLEON(c, m) && ISSCROLLTILED(c) && !c->prev_in_stack) {
|
||||
tempClients[j] = c;
|
||||
j++;
|
||||
}
|
||||
|
|
@ -253,7 +315,8 @@ void vertical_scroller(Monitor *m) {
|
|||
target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion;
|
||||
target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2;
|
||||
target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2;
|
||||
resize(c, target_geom, 0);
|
||||
vertical_check_scroller_root_inside_mon(c, &target_geom);
|
||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
||||
free(tempClients);
|
||||
return;
|
||||
}
|
||||
|
|
@ -267,6 +330,11 @@ void vertical_scroller(Monitor *m) {
|
|||
root_client = center_tiled_select(m);
|
||||
}
|
||||
|
||||
// root_client might be in a stack, find the stack head
|
||||
if (root_client) {
|
||||
root_client = get_scroll_stack_head(root_client);
|
||||
}
|
||||
|
||||
if (!root_client) {
|
||||
free(tempClients);
|
||||
return;
|
||||
|
|
@ -302,10 +370,16 @@ void vertical_scroller(Monitor *m) {
|
|||
|
||||
if (tempClients[focus_client_index]->isfullscreen) {
|
||||
target_geom.y = m->m.y;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
||||
&target_geom);
|
||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
||||
cur_gappih);
|
||||
} else if (tempClients[focus_client_index]->ismaximizescreen) {
|
||||
target_geom.y = m->w.y + cur_gappov;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
||||
&target_geom);
|
||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
||||
cur_gappih);
|
||||
} else if (need_scroller) {
|
||||
if (scroller_focus_center ||
|
||||
((!m->prevsel ||
|
||||
|
|
@ -323,10 +397,16 @@ void vertical_scroller(Monitor *m) {
|
|||
scroller_structs)
|
||||
: m->w.y + scroller_structs;
|
||||
}
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
||||
&target_geom);
|
||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
||||
cur_gappih);
|
||||
} else {
|
||||
target_geom.y = c->geom.y;
|
||||
resize(tempClients[focus_client_index], target_geom, 0);
|
||||
vertical_check_scroller_root_inside_mon(tempClients[focus_client_index],
|
||||
&target_geom);
|
||||
arrange_stack_vertical(tempClients[focus_client_index], target_geom,
|
||||
cur_gappih);
|
||||
}
|
||||
|
||||
for (i = 1; i <= focus_client_index; i++) {
|
||||
|
|
@ -336,7 +416,7 @@ void vertical_scroller(Monitor *m) {
|
|||
target_geom.y = tempClients[focus_client_index - i + 1]->geom.y -
|
||||
cur_gappiv - target_geom.height;
|
||||
|
||||
resize(c, target_geom, 0);
|
||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
||||
}
|
||||
|
||||
for (i = 1; i < n - focus_client_index; i++) {
|
||||
|
|
@ -346,7 +426,7 @@ void vertical_scroller(Monitor *m) {
|
|||
target_geom.y = tempClients[focus_client_index + i - 1]->geom.y +
|
||||
cur_gappiv +
|
||||
tempClients[focus_client_index + i - 1]->geom.height;
|
||||
resize(c, target_geom, 0);
|
||||
arrange_stack_vertical(c, target_geom, cur_gappih);
|
||||
}
|
||||
|
||||
free(tempClients);
|
||||
|
|
|
|||
426
src/mango.c
426
src/mango.c
|
|
@ -21,6 +21,7 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wayland-util.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/backend/libinput.h>
|
||||
|
|
@ -101,6 +102,10 @@
|
|||
(A->geom.x >= A->mon->m.x && A->geom.y >= A->mon->m.y && \
|
||||
A->geom.x + A->geom.width <= A->mon->m.x + A->mon->m.width && \
|
||||
A->geom.y + A->geom.height <= A->mon->m.y + A->mon->m.height)
|
||||
#define GEOMINSIDEMON(A, M) \
|
||||
(A->x >= M->m.x && A->y >= M->m.y && \
|
||||
A->x + A->width <= M->m.x + M->m.width && \
|
||||
A->y + A->height <= M->m.y + M->m.height)
|
||||
#define ISTILED(A) \
|
||||
(A && !(A)->isfloating && !(A)->isminimized && !(A)->iskilling && \
|
||||
!(A)->ismaximizescreen && !(A)->isfullscreen && !(A)->isunglobal)
|
||||
|
|
@ -138,6 +143,8 @@
|
|||
#define BAKED_POINTS_COUNT 256
|
||||
|
||||
/* enums */
|
||||
enum { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
|
||||
|
||||
enum { VERTICAL, HORIZONTAL };
|
||||
enum { SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT };
|
||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
|
|
@ -375,6 +382,8 @@ struct Client {
|
|||
bool is_pending_open_animation;
|
||||
bool is_restoring_from_ov;
|
||||
float scroller_proportion;
|
||||
float stack_proportion;
|
||||
float old_stack_proportion;
|
||||
bool need_output_flush;
|
||||
struct dwl_animation animation;
|
||||
struct dwl_opacity_animation opacity_animation;
|
||||
|
|
@ -407,6 +416,8 @@ struct Client {
|
|||
int32_t allow_shortcuts_inhibit;
|
||||
float scroller_proportion_single;
|
||||
bool isfocusing;
|
||||
struct Client *next_in_stack;
|
||||
struct Client *prev_in_stack;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -469,6 +480,7 @@ typedef struct {
|
|||
char *animation_type_open;
|
||||
char *animation_type_close;
|
||||
bool need_output_flush;
|
||||
bool being_unmapped;
|
||||
} LayerSurface;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -491,11 +503,8 @@ struct Monitor {
|
|||
struct wlr_box m; /* monitor area, layout-relative */
|
||||
struct wlr_box w; /* window area, layout-relative */
|
||||
struct wl_list layers[4]; /* LayerSurface::link */
|
||||
const Layout *lt;
|
||||
uint32_t seltags;
|
||||
uint32_t tagset[2];
|
||||
double mfact;
|
||||
int32_t nmaster;
|
||||
|
||||
struct wl_list dwl_ipc_outputs;
|
||||
int32_t gappih; /* horizontal gap between windows */
|
||||
|
|
@ -584,7 +593,7 @@ static void cursorwarptohint(void);
|
|||
static void destroydecoration(struct wl_listener *listener, void *data);
|
||||
static void destroydragicon(struct wl_listener *listener, void *data);
|
||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
|
||||
static void destroylayernodenotify(struct wl_listener *listener, void *data);
|
||||
static void destroylock(SessionLock *lock, int32_t unlocked);
|
||||
static void destroylocksurface(struct wl_listener *listener, void *data);
|
||||
static void destroynotify(struct wl_listener *listener, void *data);
|
||||
|
|
@ -689,7 +698,7 @@ static void show_scratchpad(Client *c);
|
|||
static void show_hide_client(Client *c);
|
||||
static void tag_client(const Arg *arg, Client *target_client);
|
||||
|
||||
static struct wlr_box setclient_coordinate_center(Client *c,
|
||||
static struct wlr_box setclient_coordinate_center(Client *c, Monitor *m,
|
||||
struct wlr_box geom,
|
||||
int32_t offsetx,
|
||||
int32_t offsety);
|
||||
|
|
@ -743,6 +752,7 @@ static struct wlr_scene_tree *
|
|||
wlr_scene_tree_snapshot(struct wlr_scene_node *node,
|
||||
struct wlr_scene_tree *parent);
|
||||
static bool is_scroller_layout(Monitor *m);
|
||||
static bool is_centertile_layout(Monitor *m);
|
||||
static void create_output(struct wlr_backend *backend, void *data);
|
||||
static void get_layout_abbr(char *abbr, const char *full_name);
|
||||
static void apply_named_scratchpad(Client *target_client);
|
||||
|
|
@ -762,6 +772,13 @@ static void init_client_properties(Client *c);
|
|||
static float *get_border_color(Client *c);
|
||||
static void clear_fullscreen_and_maximized_state(Monitor *m);
|
||||
static void request_fresh_all_monitors(void);
|
||||
static Client *find_client_by_direction(Client *tc, const Arg *arg,
|
||||
bool findfloating, bool ignore_align);
|
||||
static void exit_scroller_stack(Client *c);
|
||||
static Client *get_scroll_stack_head(Client *c);
|
||||
static bool client_only_in_one_tag(Client *c);
|
||||
static Client *get_focused_stack_client(Client *sc);
|
||||
static bool client_is_in_same_stack(Client *sc, Client *tc, Client *fc);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -824,6 +841,7 @@ static struct wl_list inputdevices;
|
|||
static struct wl_list keyboard_shortcut_inhibitors;
|
||||
static uint32_t cursor_mode;
|
||||
static Client *grabc;
|
||||
static int32_t rzcorner;
|
||||
static int32_t grabcx, grabcy; /* client-relative */
|
||||
static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */
|
||||
static bool start_drag_window = false;
|
||||
|
|
@ -880,6 +898,7 @@ struct Pertag {
|
|||
int32_t nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
|
||||
float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
|
||||
bool no_hide[LENGTH(tags) + 1]; /* no_hide per tag */
|
||||
bool no_render_border[LENGTH(tags) + 1]; /* no_render_border per tag */
|
||||
const Layout
|
||||
*ltidxs[LENGTH(tags) + 1]; /* matrix of tags and layouts indexes */
|
||||
};
|
||||
|
|
@ -950,9 +969,9 @@ static struct wlr_xwayland *xwayland;
|
|||
|
||||
void client_change_mon(Client *c, Monitor *m) {
|
||||
setmon(c, m, c->tags, true);
|
||||
reset_foreign_tolevel(c);
|
||||
if (c->isfloating) {
|
||||
c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0);
|
||||
c->float_geom = c->geom =
|
||||
setclient_coordinate_center(c, c->mon, c->geom, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1019,7 +1038,7 @@ void show_scratchpad(Client *c) {
|
|||
: c->mon->w.height * scratchpad_height_ratio;
|
||||
// 重新计算居中的坐标
|
||||
c->float_geom = c->geom = c->animainit_geom = c->animation.current =
|
||||
setclient_coordinate_center(c, c->geom, 0, 0);
|
||||
setclient_coordinate_center(c, c->mon, c->geom, 0, 0);
|
||||
c->iscustomsize = 1;
|
||||
resize(c, c->geom, 0);
|
||||
}
|
||||
|
|
@ -1051,7 +1070,17 @@ void swallow(Client *c, Client *w) {
|
|||
c->tags = w->tags;
|
||||
c->geom = w->geom;
|
||||
c->float_geom = w->float_geom;
|
||||
c->stack_inner_per = w->stack_inner_per;
|
||||
c->master_inner_per = w->master_inner_per;
|
||||
c->master_mfact_per = w->master_mfact_per;
|
||||
c->scroller_proportion = w->scroller_proportion;
|
||||
c->next_in_stack = w->next_in_stack;
|
||||
c->prev_in_stack = w->prev_in_stack;
|
||||
if (w->next_in_stack)
|
||||
w->next_in_stack->prev_in_stack = c;
|
||||
if (w->prev_in_stack)
|
||||
w->prev_in_stack->next_in_stack = c;
|
||||
c->stack_proportion = w->stack_proportion;
|
||||
wl_list_insert(&w->link, &c->link);
|
||||
wl_list_insert(&w->flink, &c->flink);
|
||||
|
||||
|
|
@ -1089,7 +1118,8 @@ bool switch_scratchpad_client_state(Client *c) {
|
|||
c->float_geom.height = (int32_t)(c->float_geom.height *
|
||||
c->mon->w.height / oldmon->w.height);
|
||||
|
||||
c->float_geom = setclient_coordinate_center(c, c->float_geom, 0, 0);
|
||||
c->float_geom =
|
||||
setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);
|
||||
|
||||
// 只有显示状态的scratchpad才需要聚焦和返回true
|
||||
if (c->is_scratchpad_show) {
|
||||
|
|
@ -1190,17 +1220,59 @@ void toggle_hotarea(int32_t x_root, int32_t y_root) {
|
|||
if (grabc)
|
||||
return;
|
||||
|
||||
unsigned hx = selmon->m.x + hotarea_size;
|
||||
unsigned hy = selmon->m.y + selmon->m.height - hotarea_size;
|
||||
// 根据热角位置计算不同的热区坐标
|
||||
unsigned hx, hy;
|
||||
|
||||
if (enable_hotarea == 1 && selmon->is_in_hotarea == 0 && y_root > hy &&
|
||||
x_root < hx && x_root >= selmon->m.x &&
|
||||
y_root <= (selmon->m.y + selmon->m.height)) {
|
||||
switch (hotarea_corner) {
|
||||
case BOTTOM_RIGHT: // 右下角
|
||||
hx = selmon->m.x + selmon->m.width - hotarea_size;
|
||||
hy = selmon->m.y + selmon->m.height - hotarea_size;
|
||||
break;
|
||||
case TOP_LEFT: // 左上角
|
||||
hx = selmon->m.x + hotarea_size;
|
||||
hy = selmon->m.y + hotarea_size;
|
||||
break;
|
||||
case TOP_RIGHT: // 右上角
|
||||
hx = selmon->m.x + selmon->m.width - hotarea_size;
|
||||
hy = selmon->m.y + hotarea_size;
|
||||
break;
|
||||
case BOTTOM_LEFT: // 左下角(默认)
|
||||
default:
|
||||
hx = selmon->m.x + hotarea_size;
|
||||
hy = selmon->m.y + selmon->m.height - hotarea_size;
|
||||
break;
|
||||
}
|
||||
|
||||
// 判断鼠标是否在热区内
|
||||
int in_hotarea = 0;
|
||||
|
||||
switch (hotarea_corner) {
|
||||
case BOTTOM_RIGHT: // 右下角
|
||||
in_hotarea = (y_root > hy && x_root > hx &&
|
||||
x_root <= (selmon->m.x + selmon->m.width) &&
|
||||
y_root <= (selmon->m.y + selmon->m.height));
|
||||
break;
|
||||
case TOP_LEFT: // 左上角
|
||||
in_hotarea = (y_root < hy && x_root < hx && x_root >= selmon->m.x &&
|
||||
y_root >= selmon->m.y);
|
||||
break;
|
||||
case TOP_RIGHT: // 右上角
|
||||
in_hotarea = (y_root < hy && x_root > hx &&
|
||||
x_root <= (selmon->m.x + selmon->m.width) &&
|
||||
y_root >= selmon->m.y);
|
||||
break;
|
||||
case BOTTOM_LEFT: // 左下角(默认)
|
||||
default:
|
||||
in_hotarea = (y_root > hy && x_root < hx && x_root >= selmon->m.x &&
|
||||
y_root <= (selmon->m.y + selmon->m.height));
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable_hotarea == 1 && selmon->is_in_hotarea == 0 && in_hotarea) {
|
||||
toggleoverview(&arg);
|
||||
selmon->is_in_hotarea = 1;
|
||||
} else if (enable_hotarea == 1 && selmon->is_in_hotarea == 1 &&
|
||||
(y_root <= hy || x_root >= hx || x_root < selmon->m.x ||
|
||||
y_root > (selmon->m.y + selmon->m.height))) {
|
||||
!in_hotarea) {
|
||||
selmon->is_in_hotarea = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1345,7 +1417,7 @@ void applyrules(Client *c) {
|
|||
if (r->offsetx || r->offsety) {
|
||||
c->iscustompos = 1;
|
||||
c->float_geom = c->geom = setclient_coordinate_center(
|
||||
c, c->float_geom, r->offsetx, r->offsety);
|
||||
c, mon, c->float_geom, r->offsetx, r->offsety);
|
||||
}
|
||||
if (c->isfloating) {
|
||||
c->geom = c->float_geom.width > 0 && c->float_geom.height > 0
|
||||
|
|
@ -1363,7 +1435,8 @@ void applyrules(Client *c) {
|
|||
// the hit size
|
||||
if (!c->iscustompos &&
|
||||
(!client_is_x11(c) || (c->geom.x == 0 && c->geom.y == 0))) {
|
||||
c->float_geom = c->geom = setclient_coordinate_center(c, c->geom, 0, 0);
|
||||
c->float_geom = c->geom =
|
||||
setclient_coordinate_center(c, mon, c->geom, 0, 0);
|
||||
} else {
|
||||
c->float_geom = c->geom;
|
||||
}
|
||||
|
|
@ -1451,6 +1524,9 @@ void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area,
|
|||
!layer_surface->initialized)
|
||||
continue;
|
||||
|
||||
if (l->being_unmapped)
|
||||
continue;
|
||||
|
||||
wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area,
|
||||
usable_area);
|
||||
wlr_scene_node_set_position(&l->popups->node, l->scene->node.x,
|
||||
|
|
@ -1949,7 +2025,6 @@ buttonpress(struct wl_listener *listener, void *data) {
|
|||
selmon = xytomon(cursor->x, cursor->y);
|
||||
client_update_oldmonname_record(grabc, selmon);
|
||||
setmon(grabc, selmon, 0, true);
|
||||
reset_foreign_tolevel(grabc);
|
||||
selmon->prevsel = ISTILED(selmon->sel) ? selmon->sel : NULL;
|
||||
selmon->sel = grabc;
|
||||
tmpc = grabc;
|
||||
|
|
@ -2267,6 +2342,15 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 检查surface是否有buffer
|
||||
// 空buffer,只是隐藏,不改变mapped状态
|
||||
if (l->mapped && !layer_surface->surface->buffer) {
|
||||
wlr_scene_node_set_enabled(&l->scene->node, false);
|
||||
return;
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&l->scene->node, true);
|
||||
}
|
||||
|
||||
get_layer_target_geometry(l, &box);
|
||||
|
||||
if (animations && layer_animations && !l->noanim && l->mapped &&
|
||||
|
|
@ -2415,12 +2499,12 @@ void commitpopup(struct wl_listener *listener, void *data) {
|
|||
struct wlr_box box;
|
||||
int32_t type = -1;
|
||||
|
||||
if (!popup->base->initial_commit)
|
||||
return;
|
||||
if (!popup || !popup->base->initial_commit)
|
||||
goto commitpopup_listen_free;
|
||||
|
||||
type = toplevel_from_wlr_surface(popup->base->surface, &c, &l);
|
||||
if (!popup->parent || type < 0)
|
||||
return;
|
||||
if (!popup->parent || !popup->parent->data || type < 0)
|
||||
goto commitpopup_listen_free;
|
||||
|
||||
wlr_scene_node_raise_to_top(popup->parent->data);
|
||||
|
||||
|
|
@ -2428,13 +2512,14 @@ void commitpopup(struct wl_listener *listener, void *data) {
|
|||
wlr_scene_xdg_surface_create(popup->parent->data, popup->base);
|
||||
if ((l && !l->mon) || (c && !c->mon)) {
|
||||
wlr_xdg_popup_destroy(popup);
|
||||
return;
|
||||
goto commitpopup_listen_free;
|
||||
}
|
||||
box = type == LayerShell ? l->mon->m : c->mon->w;
|
||||
box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x);
|
||||
box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
|
||||
commitpopup_listen_free:
|
||||
wl_list_remove(&listener->link);
|
||||
free(listener);
|
||||
}
|
||||
|
|
@ -2562,8 +2647,6 @@ void createlayersurface(struct wl_listener *listener, void *data) {
|
|||
LISTEN(&surface->events.commit, &l->surface_commit,
|
||||
commitlayersurfacenotify);
|
||||
LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify);
|
||||
LISTEN(&layer_surface->events.destroy, &l->destroy,
|
||||
destroylayersurfacenotify);
|
||||
|
||||
l->layer_surface = layer_surface;
|
||||
l->mon = layer_surface->output->data;
|
||||
|
|
@ -2576,6 +2659,8 @@ void createlayersurface(struct wl_listener *listener, void *data) {
|
|||
: scene_layer);
|
||||
l->scene->node.data = l->popups->node.data = l;
|
||||
|
||||
LISTEN(&l->scene->node.events.destroy, &l->destroy, destroylayernodenotify);
|
||||
|
||||
wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link);
|
||||
wlr_surface_send_enter(surface, layer_surface->output);
|
||||
}
|
||||
|
|
@ -2638,7 +2723,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
struct wlr_output *wlr_output = data;
|
||||
const ConfigMonitorRule *r;
|
||||
uint32_t i;
|
||||
int32_t ji, jk;
|
||||
int32_t ji, vrr;
|
||||
struct wlr_output_state state;
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_mode *internal_mode = NULL;
|
||||
|
|
@ -2674,30 +2759,19 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
m->sel = NULL;
|
||||
m->is_in_hotarea = 0;
|
||||
float scale = 1;
|
||||
m->mfact = default_mfact;
|
||||
m->nmaster = default_nmaster;
|
||||
enum wl_output_transform rr = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
wlr_output_state_set_scale(&state, scale);
|
||||
wlr_output_state_set_transform(&state, rr);
|
||||
|
||||
m->lt = &layouts[0];
|
||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||
if (config.monitor_rules_count < 1)
|
||||
break;
|
||||
|
||||
r = &config.monitor_rules[ji];
|
||||
if (!r->name || regex_match(r->name, wlr_output->name)) {
|
||||
m->mfact = r->mfact;
|
||||
m->nmaster = r->nmaster;
|
||||
m->m.x = r->x;
|
||||
m->m.y = r->y;
|
||||
if (r->layout) {
|
||||
for (jk = 0; jk < LENGTH(layouts); jk++) {
|
||||
if (strcmp(layouts[jk].name, r->layout) == 0) {
|
||||
m->lt = &layouts[jk];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (regex_match(r->name, wlr_output->name)) {
|
||||
m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x;
|
||||
m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y;
|
||||
vrr = r->vrr >= 0 ? r->vrr : 0;
|
||||
scale = r->scale;
|
||||
rr = r->rr;
|
||||
|
||||
|
|
@ -2714,6 +2788,13 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
(int32_t)roundf(r->refresh * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
if (vrr) {
|
||||
enable_adaptive_sync(m, &state);
|
||||
} else {
|
||||
wlr_output_state_set_adaptive_sync_enabled(&state, false);
|
||||
}
|
||||
|
||||
wlr_output_state_set_scale(&state, r->scale);
|
||||
wlr_output_state_set_transform(&state, r->rr);
|
||||
break;
|
||||
|
|
@ -2728,10 +2809,6 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
wlr_output_state_set_mode(&state,
|
||||
wlr_output_preferred_mode(wlr_output));
|
||||
|
||||
if (adaptive_sync) {
|
||||
enable_adaptive_sync(m, &state);
|
||||
}
|
||||
|
||||
/* Set up event listeners */
|
||||
LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
|
||||
LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
|
||||
|
|
@ -2756,9 +2833,9 @@ 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->ltidxs[i] = m->lt;
|
||||
m->pertag->nmasters[i] = default_nmaster;
|
||||
m->pertag->mfacts[i] = default_mfact;
|
||||
m->pertag->ltidxs[i] = &layouts[0];
|
||||
}
|
||||
|
||||
// apply tag rule
|
||||
|
|
@ -2780,7 +2857,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
* output (such as DPI, scale factor, manufacturer, etc).
|
||||
*/
|
||||
m->scene_output = wlr_scene_output_create(scene, wlr_output);
|
||||
if (m->m.x == -1 && m->m.y == -1)
|
||||
if (m->m.x == INT32_MAX || m->m.y == INT32_MAX)
|
||||
wlr_output_layout_add_auto(output_layout, wlr_output);
|
||||
else
|
||||
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
|
||||
|
|
@ -2897,9 +2974,14 @@ void configure_pointer(struct libinput_device *device) {
|
|||
if (libinput_device_config_send_events_get_modes(device))
|
||||
libinput_device_config_send_events_set_mode(device, send_events_mode);
|
||||
|
||||
if (libinput_device_config_accel_is_available(device)) {
|
||||
if (accel_profile && libinput_device_config_accel_is_available(device)) {
|
||||
libinput_device_config_accel_set_profile(device, accel_profile);
|
||||
libinput_device_config_accel_set_speed(device, accel_speed);
|
||||
} else {
|
||||
// profile cannot be directly applied to 0, need to set to 1 first
|
||||
libinput_device_config_accel_set_profile(device, 1);
|
||||
libinput_device_config_accel_set_profile(device, 0);
|
||||
libinput_device_config_accel_set_speed(device, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3044,7 +3126,7 @@ void destroyidleinhibitor(struct wl_listener *listener, void *data) {
|
|||
free(listener);
|
||||
}
|
||||
|
||||
void destroylayersurfacenotify(struct wl_listener *listener, void *data) {
|
||||
void destroylayernodenotify(struct wl_listener *listener, void *data) {
|
||||
LayerSurface *l = wl_container_of(listener, l, destroy);
|
||||
|
||||
wl_list_remove(&l->link);
|
||||
|
|
@ -3052,7 +3134,6 @@ void destroylayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&l->map.link);
|
||||
wl_list_remove(&l->unmap.link);
|
||||
wl_list_remove(&l->surface_commit.link);
|
||||
wlr_scene_node_destroy(&l->scene->node);
|
||||
wlr_scene_node_destroy(&l->popups->node);
|
||||
free(l);
|
||||
}
|
||||
|
|
@ -3633,7 +3714,8 @@ void keypressmod(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
void pending_kill_client(Client *c) {
|
||||
// c->iskilling = 1; //不可以提前标记已经杀掉,因为有些客户端可能拒绝
|
||||
if (!c || c->iskilling)
|
||||
return;
|
||||
client_send_close(c);
|
||||
}
|
||||
|
||||
|
|
@ -3741,6 +3823,15 @@ void init_client_properties(Client *c) {
|
|||
c->float_geom.height = 0;
|
||||
c->float_geom.x = 0;
|
||||
c->float_geom.y = 0;
|
||||
c->stack_proportion = 0.0f;
|
||||
c->next_in_stack = NULL;
|
||||
c->prev_in_stack = NULL;
|
||||
memcpy(c->opacity_animation.initial_border_color, bordercolor,
|
||||
sizeof(c->opacity_animation.initial_border_color));
|
||||
memcpy(c->opacity_animation.current_border_color, bordercolor,
|
||||
sizeof(c->opacity_animation.current_border_color));
|
||||
c->opacity_animation.initial_opacity = c->unfocused_opacity;
|
||||
c->opacity_animation.current_opacity = c->unfocused_opacity;
|
||||
}
|
||||
|
||||
void // old fix to 0.5
|
||||
|
|
@ -3820,7 +3911,7 @@ mapnotify(struct wl_listener *listener, void *data) {
|
|||
|
||||
if (selmon->sel && ISSCROLLTILED(selmon->sel) &&
|
||||
VISIBLEON(selmon->sel, selmon)) {
|
||||
at_client = selmon->sel;
|
||||
at_client = get_scroll_stack_head(selmon->sel);
|
||||
} else {
|
||||
at_client = center_tiled_select(selmon);
|
||||
}
|
||||
|
|
@ -3957,6 +4048,30 @@ void motionabsolute(struct wl_listener *listener, void *data) {
|
|||
motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy);
|
||||
}
|
||||
|
||||
void resize_floating_window(Client *grabc) {
|
||||
int cdx = (int)round(cursor->x) - grabcx;
|
||||
int cdy = (int)round(cursor->y) - grabcy;
|
||||
|
||||
cdx = !(rzcorner & 1) && grabc->geom.width - 2 * (int)grabc->bw - cdx < 1
|
||||
? 0
|
||||
: cdx;
|
||||
cdy = !(rzcorner & 2) && grabc->geom.height - 2 * (int)grabc->bw - cdy < 1
|
||||
? 0
|
||||
: cdy;
|
||||
|
||||
const struct wlr_box box = {
|
||||
.x = grabc->geom.x + (rzcorner & 1 ? 0 : cdx),
|
||||
.y = grabc->geom.y + (rzcorner & 2 ? 0 : cdy),
|
||||
.width = grabc->geom.width + (rzcorner & 1 ? cdx : -cdx),
|
||||
.height = grabc->geom.height + (rzcorner & 2 ? cdy : -cdy)};
|
||||
|
||||
grabc->float_geom = box;
|
||||
|
||||
resize(grabc, box, 1);
|
||||
grabcx += cdx;
|
||||
grabcy += cdy;
|
||||
}
|
||||
|
||||
void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
||||
double dy, double dx_unaccel, double dy_unaccel) {
|
||||
double sx = 0, sy = 0, sx_confined, sy_confined;
|
||||
|
|
@ -4034,14 +4149,9 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx,
|
|||
} else if (cursor_mode == CurResize) {
|
||||
if (grabc->isfloating) {
|
||||
grabc->iscustomsize = 1;
|
||||
grabc->float_geom = (struct wlr_box){
|
||||
.x = grabc->geom.x,
|
||||
.y = grabc->geom.y,
|
||||
.width = (int32_t)round(cursor->x) - grabc->geom.x,
|
||||
.height = (int32_t)round(cursor->y) - grabc->geom.y};
|
||||
if (last_apply_drap_time == 0 ||
|
||||
time - last_apply_drap_time > drag_refresh_interval) {
|
||||
resize(grabc, grabc->float_geom, 1);
|
||||
time - last_apply_drap_time > drag_floating_refresh_interval) {
|
||||
resize_floating_window(grabc);
|
||||
last_apply_drap_time = time;
|
||||
}
|
||||
return;
|
||||
|
|
@ -4172,8 +4282,10 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
|||
uint32_t time) {
|
||||
struct timespec now;
|
||||
|
||||
if (surface != seat->pointer_state.focused_surface && sloppyfocus && time &&
|
||||
c && c->scene->node.enabled && !client_is_unmanaged(c))
|
||||
if (sloppyfocus && !start_drag_window && c && time &&
|
||||
c->scene->node.enabled && !c->animation.tagining &&
|
||||
(surface != seat->pointer_state.focused_surface) &&
|
||||
!client_is_unmanaged(c) && VISIBLEON(c, c->mon))
|
||||
focusclient(c, 0);
|
||||
|
||||
/* If surface is NULL, clear pointer focus */
|
||||
|
|
@ -4348,12 +4460,32 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
double master_inner_per = 0.0f;
|
||||
double master_mfact_per = 0.0f;
|
||||
double stack_inner_per = 0.0f;
|
||||
float scroller_proportion = 0.0f;
|
||||
float stack_proportion = 0.0f;
|
||||
|
||||
if (c1 == NULL || c2 == NULL ||
|
||||
(!exchange_cross_monitor && c1->mon != c2->mon)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (c1->mon != c2->mon && (c1->prev_in_stack || c2->prev_in_stack ||
|
||||
c1->next_in_stack || c2->next_in_stack))
|
||||
return;
|
||||
|
||||
Client *c1head = get_scroll_stack_head(c1);
|
||||
Client *c2head = get_scroll_stack_head(c2);
|
||||
|
||||
// 交换布局参数
|
||||
if (c1head == c2head) {
|
||||
scroller_proportion = c1->scroller_proportion;
|
||||
stack_proportion = c1->stack_proportion;
|
||||
|
||||
c1->scroller_proportion = c2->scroller_proportion;
|
||||
c1->stack_proportion = c2->stack_proportion;
|
||||
c2->scroller_proportion = scroller_proportion;
|
||||
c2->stack_proportion = stack_proportion;
|
||||
}
|
||||
|
||||
master_inner_per = c1->master_inner_per;
|
||||
master_mfact_per = c1->master_mfact_per;
|
||||
stack_inner_per = c1->stack_inner_per;
|
||||
|
|
@ -4366,17 +4498,47 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
c2->master_mfact_per = master_mfact_per;
|
||||
c2->stack_inner_per = stack_inner_per;
|
||||
|
||||
// 交换栈链表连接
|
||||
Client *tmp1_next_in_stack = c1->next_in_stack;
|
||||
Client *tmp1_prev_in_stack = c1->prev_in_stack;
|
||||
Client *tmp2_next_in_stack = c2->next_in_stack;
|
||||
Client *tmp2_prev_in_stack = c2->prev_in_stack;
|
||||
|
||||
// 处理相邻节点的情况
|
||||
if (c1->next_in_stack == c2) {
|
||||
c1->next_in_stack = tmp2_next_in_stack;
|
||||
c2->next_in_stack = c1;
|
||||
c1->prev_in_stack = c2;
|
||||
c2->prev_in_stack = tmp1_prev_in_stack;
|
||||
if (tmp1_prev_in_stack)
|
||||
tmp1_prev_in_stack->next_in_stack = c2;
|
||||
if (tmp2_next_in_stack)
|
||||
tmp2_next_in_stack->prev_in_stack = c1;
|
||||
} else if (c2->next_in_stack == c1) {
|
||||
c2->next_in_stack = tmp1_next_in_stack;
|
||||
c1->next_in_stack = c2;
|
||||
c2->prev_in_stack = c1;
|
||||
c1->prev_in_stack = tmp2_prev_in_stack;
|
||||
if (tmp2_prev_in_stack)
|
||||
tmp2_prev_in_stack->next_in_stack = c1;
|
||||
if (tmp1_next_in_stack)
|
||||
tmp1_next_in_stack->prev_in_stack = c2;
|
||||
} else if (is_scroller_layout(c1->mon) &&
|
||||
(c1->prev_in_stack || c2->prev_in_stack)) {
|
||||
Client *c1head = get_scroll_stack_head(c1);
|
||||
Client *c2head = get_scroll_stack_head(c2);
|
||||
exchange_two_client(c1head, c2head);
|
||||
focusclient(c1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 交换全局链表连接
|
||||
struct wl_list *tmp1_prev = c1->link.prev;
|
||||
struct wl_list *tmp2_prev = c2->link.prev;
|
||||
struct wl_list *tmp1_next = c1->link.next;
|
||||
struct wl_list *tmp2_next = c2->link.next;
|
||||
|
||||
// wl_list
|
||||
// 是双向链表,其中clients是头部节点,它的下一个节点是第一个客户端的链表节点
|
||||
// 最后一个客户端的链表节点的下一个节点也指向clients,但clients本身不是客户端的链表节点
|
||||
// 客户端遍历从clients的下一个节点开始,到检测到客户端节点的下一个是clients结束
|
||||
|
||||
// 当c1和c2为相邻节点时
|
||||
// 处理相邻节点的情况
|
||||
if (c1->link.next == &c2->link) {
|
||||
c1->link.next = c2->link.next;
|
||||
c1->link.prev = &c2->link;
|
||||
|
|
@ -4403,6 +4565,7 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
tmp2_next->prev = &c1->link;
|
||||
}
|
||||
|
||||
// 处理跨监视器交换
|
||||
if (exchange_cross_monitor) {
|
||||
tmp_mon = c2->mon;
|
||||
tmp_tags = c2->tags;
|
||||
|
|
@ -4413,7 +4576,6 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
focusclient(c1, 0);
|
||||
} else {
|
||||
arrange(c1->mon, false, false);
|
||||
focusclient(c1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4517,6 +4679,7 @@ setfloating(Client *c, int32_t floating) {
|
|||
|
||||
Client *fc = NULL;
|
||||
struct wlr_box target_box;
|
||||
int32_t old_floating_state = c->isfloating;
|
||||
c->isfloating = floating;
|
||||
bool window_size_outofrange = false;
|
||||
|
||||
|
|
@ -4533,9 +4696,12 @@ setfloating(Client *c, int32_t floating) {
|
|||
c->bw = c->isnoborder ? 0 : borderpx;
|
||||
}
|
||||
|
||||
exit_scroller_stack(c);
|
||||
|
||||
// 重新计算居中的坐标
|
||||
if (!client_is_x11(c) && !c->iscustompos)
|
||||
target_box = setclient_coordinate_center(c, target_box, 0, 0);
|
||||
target_box =
|
||||
setclient_coordinate_center(c, c->mon, target_box, 0, 0);
|
||||
else
|
||||
target_box = c->geom;
|
||||
|
||||
|
|
@ -4551,7 +4717,7 @@ setfloating(Client *c, int32_t floating) {
|
|||
}
|
||||
if (window_size_outofrange) {
|
||||
c->float_geom =
|
||||
setclient_coordinate_center(c, c->float_geom, 0, 0);
|
||||
setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);
|
||||
}
|
||||
resize(c, c->float_geom, 0);
|
||||
} else {
|
||||
|
|
@ -4583,7 +4749,7 @@ setfloating(Client *c, int32_t floating) {
|
|||
layers[c->isfloating ? LyrTop : LyrTile]);
|
||||
}
|
||||
|
||||
if (!c->isfloating) {
|
||||
if (!c->isfloating && old_floating_state) {
|
||||
set_size_per(c->mon, c);
|
||||
}
|
||||
|
||||
|
|
@ -4603,6 +4769,27 @@ void reset_maximizescreen_size(Client *c) {
|
|||
resize(c, c->geom, 0);
|
||||
}
|
||||
|
||||
void exit_scroller_stack(Client *c) {
|
||||
// If c is already in a stack, remove it.
|
||||
if (c->prev_in_stack) {
|
||||
c->prev_in_stack->next_in_stack = c->next_in_stack;
|
||||
}
|
||||
|
||||
if (!c->prev_in_stack && c->next_in_stack) {
|
||||
c->next_in_stack->scroller_proportion = c->scroller_proportion;
|
||||
wl_list_remove(&c->next_in_stack->link);
|
||||
wl_list_insert(&c->link, &c->next_in_stack->link);
|
||||
}
|
||||
|
||||
if (c->next_in_stack) {
|
||||
c->next_in_stack->prev_in_stack = c->prev_in_stack;
|
||||
}
|
||||
|
||||
c->prev_in_stack = NULL;
|
||||
c->next_in_stack = NULL;
|
||||
c->stack_proportion = 0.0f;
|
||||
}
|
||||
|
||||
void setmaximizescreen(Client *c, int32_t maximizescreen) {
|
||||
struct wlr_box maximizescreen_box;
|
||||
if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling)
|
||||
|
|
@ -4611,6 +4798,7 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
|
|||
if (c->mon->isoverview)
|
||||
return;
|
||||
|
||||
int32_t old_maximizescreen_state = c->ismaximizescreen;
|
||||
c->ismaximizescreen = maximizescreen;
|
||||
|
||||
if (maximizescreen) {
|
||||
|
|
@ -4618,6 +4806,8 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
|
|||
if (c->isfullscreen)
|
||||
setfullscreen(c, 0);
|
||||
|
||||
exit_scroller_stack(c);
|
||||
|
||||
if (c->isfloating)
|
||||
c->float_geom = c->geom;
|
||||
|
||||
|
|
@ -4638,7 +4828,7 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) {
|
|||
|
||||
wlr_scene_node_reparent(&c->scene->node,
|
||||
layers[c->isfloating ? LyrTop : LyrTile]);
|
||||
if (!c->ismaximizescreen) {
|
||||
if (!c->ismaximizescreen && old_maximizescreen_state) {
|
||||
set_size_per(c->mon, c);
|
||||
}
|
||||
|
||||
|
|
@ -4655,10 +4845,11 @@ void setfakefullscreen(Client *c, int32_t fakefullscreen) {
|
|||
c->isfakefullscreen = fakefullscreen;
|
||||
if (!c->mon)
|
||||
return;
|
||||
|
||||
if (c->isfullscreen)
|
||||
setfullscreen(c, 0);
|
||||
else
|
||||
client_set_fullscreen(c, fakefullscreen);
|
||||
|
||||
client_set_fullscreen(c, fakefullscreen);
|
||||
}
|
||||
|
||||
void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自带全屏
|
||||
|
|
@ -4670,6 +4861,7 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
|
|||
if (c->mon->isoverview)
|
||||
return;
|
||||
|
||||
int32_t old_fullscreen_state = c->isfullscreen;
|
||||
c->isfullscreen = fullscreen;
|
||||
|
||||
client_set_fullscreen(c, fullscreen);
|
||||
|
|
@ -4678,9 +4870,13 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
|
|||
if (c->ismaximizescreen)
|
||||
setmaximizescreen(c, 0);
|
||||
|
||||
exit_scroller_stack(c);
|
||||
|
||||
if (c->isfloating)
|
||||
c->float_geom = c->geom;
|
||||
|
||||
c->isfakefullscreen = 0;
|
||||
|
||||
c->bw = 0;
|
||||
wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层
|
||||
if (!is_scroller_layout(c->mon) || c->isfloating)
|
||||
|
|
@ -4689,7 +4885,6 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
|
|||
} else {
|
||||
c->bw = c->isnoborder ? 0 : borderpx;
|
||||
c->isfullscreen = 0;
|
||||
c->isfakefullscreen = 0;
|
||||
if (c->isfloating)
|
||||
setfloating(c, 1);
|
||||
}
|
||||
|
|
@ -4704,7 +4899,7 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自
|
|||
layers[fullscreen || c->isfloating ? LyrTop : LyrTile]);
|
||||
}
|
||||
|
||||
if (!c->isfullscreen) {
|
||||
if (!c->isfullscreen && old_fullscreen_state) {
|
||||
set_size_per(c->mon, c);
|
||||
}
|
||||
|
||||
|
|
@ -4833,6 +5028,7 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
|
|||
arrange(oldmon, false, false);
|
||||
if (m) {
|
||||
/* Make sure window actually overlaps with the monitor */
|
||||
reset_foreign_tolevel(c);
|
||||
resize(c, c->geom, 0);
|
||||
c->tags =
|
||||
newtags ? newtags
|
||||
|
|
@ -4844,21 +5040,6 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) {
|
|||
if (focus && !client_is_x11_popup(c)) {
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
|
||||
if (m) {
|
||||
|
||||
if (c->foreign_toplevel) {
|
||||
remove_foreign_topleve(c);
|
||||
}
|
||||
|
||||
add_foreign_toplevel(c);
|
||||
if (m->sel && m->sel->foreign_toplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(
|
||||
m->sel->foreign_toplevel, false);
|
||||
if (c->foreign_toplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
void setpsel(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -5251,6 +5432,7 @@ void tag_client(const Arg *arg, Client *target_client) {
|
|||
Client *fc = NULL;
|
||||
if (target_client && arg->ui & TAGMASK) {
|
||||
|
||||
exit_scroller_stack(target_client);
|
||||
target_client->tags = arg->ui & TAGMASK;
|
||||
target_client->istagswitching = 1;
|
||||
|
||||
|
|
@ -5380,6 +5562,7 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
LayerSurface *l = wl_container_of(listener, l, unmap);
|
||||
|
||||
l->mapped = 0;
|
||||
l->being_unmapped = true;
|
||||
|
||||
init_fadeout_layers(l);
|
||||
|
||||
|
|
@ -5391,6 +5574,9 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) {
|
|||
if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
|
||||
focusclient(focustop(selmon), 1);
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
l->being_unmapped = false;
|
||||
wlr_scene_node_destroy(&l->shadow->node);
|
||||
l->shadow = NULL;
|
||||
}
|
||||
|
||||
void unmapnotify(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -5398,15 +5584,22 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
*/
|
||||
Client *c = wl_container_of(listener, c, unmap);
|
||||
Monitor *m = NULL;
|
||||
Client *nextfocus = NULL;
|
||||
Client *next_in_stack = c->next_in_stack;
|
||||
Client *prev_in_stack = c->prev_in_stack;
|
||||
c->iskilling = 1;
|
||||
|
||||
if (animations && !c->is_clip_to_hide && !c->isminimized &&
|
||||
(!c->mon || VISIBLEON(c, c->mon)))
|
||||
init_fadeout_client(c);
|
||||
|
||||
// If the client is in a stack, remove it from the stack
|
||||
|
||||
if (c->swallowedby) {
|
||||
c->swallowedby->mon = c->mon;
|
||||
swallow(c->swallowedby, c);
|
||||
} else {
|
||||
exit_scroller_stack(c);
|
||||
}
|
||||
|
||||
if (c == grabc) {
|
||||
|
|
@ -5427,7 +5620,13 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
if (c->mon && c->mon == selmon) {
|
||||
Client *nextfocus = focustop(selmon);
|
||||
if (next_in_stack && !c->swallowedby) {
|
||||
nextfocus = next_in_stack;
|
||||
} else if (prev_in_stack && !c->swallowedby) {
|
||||
nextfocus = prev_in_stack;
|
||||
} else {
|
||||
nextfocus = focustop(selmon);
|
||||
}
|
||||
|
||||
if (nextfocus) {
|
||||
focusclient(nextfocus, 0);
|
||||
|
|
@ -5474,6 +5673,10 @@ void unmapnotify(struct wl_listener *listener, void *data) {
|
|||
c->swallowing = NULL;
|
||||
}
|
||||
|
||||
c->stack_proportion = 0.0f;
|
||||
c->next_in_stack = NULL;
|
||||
c->prev_in_stack = NULL;
|
||||
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
|
|
@ -5591,7 +5794,8 @@ void updatemons(struct wl_listener *listener, void *data) {
|
|||
if (selmon && selmon->wlr_output->enabled) {
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!c->mon && client_surface(c)->mapped) {
|
||||
client_change_mon(c, selmon);
|
||||
c->mon = selmon;
|
||||
reset_foreign_tolevel(c);
|
||||
}
|
||||
}
|
||||
focusclient(focustop(selmon), 1);
|
||||
|
|
@ -5953,17 +6157,22 @@ int32_t main(int32_t argc, char *argv[]) {
|
|||
char *startup_cmd = NULL;
|
||||
int32_t c;
|
||||
|
||||
while ((c = getopt(argc, argv, "s:c:hdv")) != -1) {
|
||||
if (c == 's')
|
||||
while ((c = getopt(argc, argv, "s:c:hdvp")) != -1) {
|
||||
if (c == 's') {
|
||||
startup_cmd = optarg;
|
||||
else if (c == 'd')
|
||||
} else if (c == 'd') {
|
||||
log_level = WLR_DEBUG;
|
||||
else if (c == 'v')
|
||||
die("mango " VERSION);
|
||||
else if (c == 'c')
|
||||
} else if (c == 'v') {
|
||||
printf("mango " VERSION "\n");
|
||||
return EXIT_SUCCESS;
|
||||
} else if (c == 'c') {
|
||||
cli_config_path = optarg;
|
||||
else
|
||||
} else if (c == 'p') {
|
||||
parse_config();
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if (optind < argc)
|
||||
goto usage;
|
||||
|
|
@ -5977,7 +6186,14 @@ int32_t main(int32_t argc, char *argv[]) {
|
|||
run(startup_cmd);
|
||||
cleanup();
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
usage:
|
||||
die("Usage: %s [-v] [-d] [-c config file] [-s startup command]", argv[0]);
|
||||
printf("Usage: mango [OPTIONS]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -v Show mango version\n"
|
||||
" -d Enable debug log\n"
|
||||
" -c <file> Use custom configuration file\n"
|
||||
" -s <command> Execute startup command\n"
|
||||
" -p Check configuration file error\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue