diff --git a/README.md b/README.md
index 087bf13b..d512f39f 100644
--- a/README.md
+++ b/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.
+
+
+
+
+Thanks to the following friends for their sponsorship of this project
+
+[@tonybanters](https://github.com/tonybanters)
diff --git a/config.conf b/config.conf
index 5483a141..6cbb3a20 100644
--- a/config.conf
+++ b/config.conf
@@ -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
diff --git a/src/config/parse_config.h b/src/config/parse_config.h
index 9c278724..b2535b15 100644
--- a/src/config/parse_config.h
+++ b/src/config/parse_config.h
@@ -1080,6 +1080,9 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
} else if (strcmp(func_name, "toggle_monitor") == 0) {
func = toggle_monitor;
(*arg).v = strdup(arg_value);
+ } else if (strcmp(func_name, "scroller_stack") == 0) {
+ func = scroller_stack;
+ (*arg).i = parse_direction(arg_value);
} else {
return NULL;
}
diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h
index b197778b..22ef6123 100644
--- a/src/dispatch/bind_declare.h
+++ b/src/dispatch/bind_declare.h
@@ -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);
\ No newline at end of file
+int32_t toggle_monitor(const Arg *arg);
+int32_t scroller_stack(const Arg *arg);
\ No newline at end of file
diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h
index 19d743e7..95d365c8 100644
--- a/src/dispatch/bind_define.h
+++ b/src/dispatch/bind_define.h
@@ -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)
@@ -425,6 +426,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 +455,7 @@ int32_t resizewin(const Arg *arg) {
break;
}
resize_tile_client(c, false, offsetx, offsety, 0);
+ animations = animations_state_backup;
return 0;
}
@@ -480,6 +486,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 +557,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;
@@ -749,10 +758,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 +983,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 +1007,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;
@@ -1093,6 +1106,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 +1235,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;
}
@@ -1585,3 +1601,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;
+}
\ No newline at end of file
diff --git a/src/fetch/client.h b/src/fetch/client.h
index 0af17238..e843d691 100644
--- a/src/fetch/client.h
+++ b/src/fetch/client.h
@@ -215,6 +215,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 +273,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 +331,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 +389,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 +453,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 +533,91 @@ bool client_only_in_one_tag(Client *c) {
} else {
return false;
}
-}
\ No newline at end of file
+}
+
+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;
+}
diff --git a/src/fetch/monitor.h b/src/fetch/monitor.h
index 47a5b824..7a1ca4dc 100644
--- a/src/fetch/monitor.h
+++ b/src/fetch/monitor.h
@@ -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;
diff --git a/src/layout/arrange.h b/src/layout/arrange.h
index d668f309..6ff1dd25 100644
--- a/src/layout/arrange.h
+++ b/src/layout/arrange.h
@@ -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);
@@ -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++;
}
}
diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h
index a2f5e5c1..87b6033c 100644
--- a/src/layout/horizontal.h
+++ b/src/layout/horizontal.h
@@ -212,6 +212,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 +285,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 +312,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 +330,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 +345,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 +384,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 +409,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 +426,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 +436,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 +928,4 @@ void tgmix(Monitor *m) {
grid(m);
return;
}
-}
\ No newline at end of file
+}
diff --git a/src/layout/vertical.h b/src/layout/vertical.h
index 95138248..2c2dc661 100644
--- a/src/layout/vertical.h
+++ b/src/layout/vertical.h
@@ -199,6 +199,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 +272,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 +296,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 +314,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 +329,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 +369,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 +396,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 +415,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 +425,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);
diff --git a/src/mango.c b/src/mango.c
index b392636c..b290ccfa 100644
--- a/src/mango.c
+++ b/src/mango.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -104,6 +105,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)
@@ -378,6 +383,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;
@@ -410,6 +417,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 {
@@ -746,6 +755,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);
@@ -765,6 +775,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"
@@ -1056,6 +1073,13 @@ void swallow(Client *c, Client *w) {
c->geom = w->geom;
c->float_geom = w->float_geom;
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);
@@ -3645,7 +3669,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);
}
@@ -3753,6 +3778,9 @@ 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;
}
void // old fix to 0.5
@@ -3832,7 +3860,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);
}
@@ -4184,10 +4212,10 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
uint32_t time) {
struct timespec now;
- if (sloppyfocus && c && time && c->scene->node.enabled &&
- (surface != seat->pointer_state.focused_surface ||
- (selmon && selmon->sel && c != selmon->sel)) &&
- !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 */
@@ -4362,12 +4390,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;
@@ -4380,17 +4428,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;
@@ -4417,6 +4495,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;
@@ -4427,7 +4506,6 @@ void exchange_two_client(Client *c1, Client *c2) {
focusclient(c1, 0);
} else {
arrange(c1->mon, false, false);
- focusclient(c1, 0);
}
}
@@ -4547,6 +4625,8 @@ 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 =
@@ -4618,6 +4698,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)
@@ -4633,6 +4734,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;
@@ -4670,10 +4773,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) // 用自定义全屏代理自带全屏
@@ -4693,9 +4797,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)
@@ -4704,7 +4812,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);
}
@@ -5281,6 +5388,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;
@@ -5428,15 +5536,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) {
@@ -5457,7 +5572,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);
@@ -5504,6 +5625,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);