mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-23 21:37:53 -04:00
opt: optimize exchange two client
This commit is contained in:
parent
26f5e23236
commit
d7ee60e79a
1 changed files with 156 additions and 81 deletions
237
src/mango.c
237
src/mango.c
|
|
@ -5066,6 +5066,10 @@ 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;
|
||||
double grid_col_per = 0.0f;
|
||||
double grid_row_per = 0.0f;
|
||||
int32_t grid_col_idx = 0;
|
||||
int32_t grid_row_idx = 0;
|
||||
struct ScrollerStackNode *n1 = NULL;
|
||||
struct ScrollerStackNode *n2 = NULL;
|
||||
struct TagScrollerState *st1 = NULL;
|
||||
|
|
@ -5076,6 +5080,20 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* 保存并交换 grid / master / stack 等比例属性 */
|
||||
grid_col_per = c1->grid_col_per;
|
||||
grid_row_per = c1->grid_row_per;
|
||||
grid_col_idx = c1->grid_col_idx;
|
||||
grid_row_idx = c1->grid_row_idx;
|
||||
c1->grid_col_per = c2->grid_col_per;
|
||||
c1->grid_row_per = c2->grid_row_per;
|
||||
c1->grid_col_idx = c2->grid_col_idx;
|
||||
c1->grid_row_idx = c2->grid_row_idx;
|
||||
c2->grid_col_per = grid_col_per;
|
||||
c2->grid_row_per = grid_row_per;
|
||||
c2->grid_col_idx = grid_col_idx;
|
||||
c2->grid_row_idx = grid_row_idx;
|
||||
|
||||
master_inner_per = c1->master_inner_per;
|
||||
master_mfact_per = c1->master_mfact_per;
|
||||
stack_inner_per = c1->stack_inner_per;
|
||||
|
|
@ -5097,23 +5115,21 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
st1 = ensure_scroller_state(m1, tag1);
|
||||
n1 = find_scroller_node(st1, c1);
|
||||
}
|
||||
|
||||
if (c2_scroller) {
|
||||
st2 = ensure_scroller_state(m2, tag2);
|
||||
n2 = find_scroller_node(st2, c2);
|
||||
}
|
||||
|
||||
if (!n1 || !n2)
|
||||
goto exchange_common;
|
||||
|
||||
/* ---------------------------------------------------------------
|
||||
* 情况1:两个客户端都在 scroller 布局中
|
||||
* --------------------------------------------------------------- */
|
||||
if (n1 && n2) {
|
||||
|
||||
/* 跨显示器且任一方有堆叠关系时不允许交换 */
|
||||
/* 跨显示器且任一方有堆叠关系(非单客户端)时不允许交换 */
|
||||
if (m1 != m2 && (n1->prev_in_stack || n2->prev_in_stack ||
|
||||
n1->next_in_stack || n2->next_in_stack))
|
||||
return;
|
||||
|
||||
/* 获取各自的堆叠头节点 */
|
||||
/* 找到各自的堆叠头 */
|
||||
struct ScrollerStackNode *head1 = n1;
|
||||
while (head1->prev_in_stack)
|
||||
head1 = head1->prev_in_stack;
|
||||
|
|
@ -5121,14 +5137,15 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
while (head2->prev_in_stack)
|
||||
head2 = head2->prev_in_stack;
|
||||
|
||||
/* 同一堆叠内交换 */
|
||||
/* --- 1a. 同一个堆叠内交换 --- */
|
||||
if (head1 == head2) {
|
||||
float tmp_scroller = n1->scroller_proportion;
|
||||
float tmp_stack = n1->stack_proportion;
|
||||
/* 交换 scroller/stack 比例 */
|
||||
float tmp_sc = n1->scroller_proportion;
|
||||
float tmp_st = n1->stack_proportion;
|
||||
n1->scroller_proportion = n2->scroller_proportion;
|
||||
n1->stack_proportion = n2->stack_proportion;
|
||||
n2->scroller_proportion = tmp_scroller;
|
||||
n2->stack_proportion = tmp_stack;
|
||||
n2->scroller_proportion = tmp_sc;
|
||||
n2->stack_proportion = tmp_st;
|
||||
|
||||
/* 交换堆叠链表指针 */
|
||||
struct ScrollerStackNode *p1 = n1->prev_in_stack;
|
||||
|
|
@ -5170,96 +5187,154 @@ void exchange_two_client(Client *c1, Client *c2) {
|
|||
}
|
||||
|
||||
sync_scroller_state_to_clients(m1, tag1);
|
||||
arrange(m1, false, false);
|
||||
} else {
|
||||
/* 不同堆叠:交换两个堆叠整体位置 */
|
||||
if (n1 != head1 || n2 != head2) {
|
||||
/* 当前不是头部,递归交换头部 */
|
||||
exchange_two_client(head1->client, head2->client);
|
||||
return;
|
||||
/* 继续执行 exchange_common 以交换全局链表中的 c1 和 c2 */
|
||||
}
|
||||
/* --- 1b. 不同堆叠之间的整体交换 --- */
|
||||
else {
|
||||
Client *head1_c = head1->client;
|
||||
Client *head2_c = head2->client;
|
||||
Client *tail1_c = scroll_get_stack_tail_client(head1_c);
|
||||
Client *tail2_c = scroll_get_stack_tail_client(head2_c);
|
||||
|
||||
struct wl_list *p1 = head1_c->link.prev;
|
||||
struct wl_list *n1_next = tail1_c->link.next;
|
||||
struct wl_list *p2 = head2_c->link.prev;
|
||||
struct wl_list *n2_next = tail2_c->link.next;
|
||||
|
||||
if (n1_next == &head2_c->link) {
|
||||
/* [堆1] -> [堆2] 相邻 */
|
||||
p2->next = n2_next;
|
||||
n2_next->prev = p2;
|
||||
p1->next = &head2_c->link;
|
||||
head2_c->link.prev = p1;
|
||||
tail2_c->link.next = &head1_c->link;
|
||||
head1_c->link.prev = &tail2_c->link;
|
||||
} else if (n2_next == &head1_c->link) {
|
||||
/* [堆2] -> [堆1] 相邻 */
|
||||
p1->next = n1_next;
|
||||
n1_next->prev = p1;
|
||||
p2->next = &head1_c->link;
|
||||
head1_c->link.prev = p2;
|
||||
tail1_c->link.next = &head2_c->link;
|
||||
head2_c->link.prev = &tail1_c->link;
|
||||
} else {
|
||||
/* 两个堆叠不相邻 */
|
||||
p1->next = &head2_c->link;
|
||||
head2_c->link.prev = p1;
|
||||
tail2_c->link.next = n1_next;
|
||||
n1_next->prev = &tail2_c->link;
|
||||
|
||||
p2->next = &head1_c->link;
|
||||
head1_c->link.prev = p2;
|
||||
tail1_c->link.next = n2_next;
|
||||
n2_next->prev = &tail1_c->link;
|
||||
}
|
||||
|
||||
/* 跨显示器时交换 mon / tags */
|
||||
if (m1 != m2) {
|
||||
tmp_mon = c2->mon;
|
||||
tmp_tags = c2->tags;
|
||||
c2->mon = c1->mon;
|
||||
c1->mon = tmp_mon;
|
||||
c2->tags = c1->tags;
|
||||
c1->tags = tmp_tags;
|
||||
}
|
||||
/* 整体交换已完成,跳过普通交换部分,直接 arrange */
|
||||
goto arrange_and_finish;
|
||||
}
|
||||
}
|
||||
|
||||
exchange_common:
|
||||
|
||||
/* ---------------------------------------------------------------
|
||||
* 情况2:至少一方不在 scroller 中(或双方均为 NULL)
|
||||
* 执行普通的全局链表节点交换
|
||||
* --------------------------------------------------------------- */
|
||||
/* 跨显示器且任一方有堆叠关系时不允许交换 */
|
||||
if (m1 != m2 && ((n1 && n1->prev_in_stack) || (n2 && n2->prev_in_stack) ||
|
||||
(n1 && n1->next_in_stack) || (n2 && n2->next_in_stack)))
|
||||
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;
|
||||
{
|
||||
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;
|
||||
|
||||
if (c1->link.next == &c2->link) {
|
||||
c1->link.next = c2->link.next;
|
||||
c1->link.prev = &c2->link;
|
||||
c2->link.next = &c1->link;
|
||||
c2->link.prev = tmp1_prev;
|
||||
tmp1_prev->next = &c2->link;
|
||||
tmp2_next->prev = &c1->link;
|
||||
} else if (c2->link.next == &c1->link) {
|
||||
c2->link.next = c1->link.next;
|
||||
c2->link.prev = &c1->link;
|
||||
c1->link.next = &c2->link;
|
||||
c1->link.prev = tmp2_prev;
|
||||
tmp2_prev->next = &c1->link;
|
||||
tmp1_next->prev = &c2->link;
|
||||
} else {
|
||||
c2->link.next = tmp1_next;
|
||||
c2->link.prev = tmp1_prev;
|
||||
c1->link.next = tmp2_next;
|
||||
c1->link.prev = tmp2_prev;
|
||||
tmp1_prev->next = &c2->link;
|
||||
tmp1_next->prev = &c2->link;
|
||||
tmp2_prev->next = &c1->link;
|
||||
tmp2_next->prev = &c1->link;
|
||||
if (c1->link.next == &c2->link) {
|
||||
c1->link.next = c2->link.next;
|
||||
c1->link.prev = &c2->link;
|
||||
c2->link.next = &c1->link;
|
||||
c2->link.prev = tmp1_prev;
|
||||
tmp1_prev->next = &c2->link;
|
||||
tmp2_next->prev = &c1->link;
|
||||
} else if (c2->link.next == &c1->link) {
|
||||
c2->link.next = c1->link.next;
|
||||
c2->link.prev = &c1->link;
|
||||
c1->link.next = &c2->link;
|
||||
c1->link.prev = tmp2_prev;
|
||||
tmp2_prev->next = &c1->link;
|
||||
tmp1_next->prev = &c2->link;
|
||||
} else {
|
||||
c2->link.next = tmp1_next;
|
||||
c2->link.prev = tmp1_prev;
|
||||
c1->link.next = tmp2_next;
|
||||
c1->link.prev = tmp2_prev;
|
||||
tmp1_prev->next = &c2->link;
|
||||
tmp1_next->prev = &c2->link;
|
||||
tmp2_prev->next = &c1->link;
|
||||
tmp2_next->prev = &c1->link;
|
||||
}
|
||||
}
|
||||
|
||||
const Layout *layout1 = c1->mon->pertag->ltidxs[c1->mon->pertag->curtag];
|
||||
{
|
||||
const Layout *layout1 =
|
||||
c1->mon->pertag->ltidxs[c1->mon->pertag->curtag];
|
||||
const Layout *layout2 =
|
||||
c2->mon->pertag->ltidxs[c2->mon->pertag->curtag];
|
||||
|
||||
const Layout *layout2 = c2->mon->pertag->ltidxs[c2->mon->pertag->curtag];
|
||||
|
||||
if (c1->mon != c2->mon) {
|
||||
|
||||
if (layout1->id == DWINDLE && layout2->id == DWINDLE) {
|
||||
DwindleNode **c1_root =
|
||||
&m1->pertag->dwindle_root[m1->pertag->curtag];
|
||||
DwindleNode *c1node = dwindle_find_leaf(*c1_root, c1);
|
||||
|
||||
DwindleNode **c2_root =
|
||||
&m2->pertag->dwindle_root[m2->pertag->curtag];
|
||||
DwindleNode *c2node = dwindle_find_leaf(*c2_root, c2);
|
||||
|
||||
if (c1node)
|
||||
c1node->client = c2;
|
||||
|
||||
if (c2node)
|
||||
c2node->client = c1;
|
||||
if (c1->mon != c2->mon) {
|
||||
if (layout1->id == DWINDLE && layout2->id == DWINDLE) {
|
||||
DwindleNode **c1_root =
|
||||
&m1->pertag->dwindle_root[m1->pertag->curtag];
|
||||
DwindleNode *c1node = dwindle_find_leaf(*c1_root, c1);
|
||||
DwindleNode **c2_root =
|
||||
&m2->pertag->dwindle_root[m2->pertag->curtag];
|
||||
DwindleNode *c2node = dwindle_find_leaf(*c2_root, c2);
|
||||
if (c1node)
|
||||
c1node->client = c2;
|
||||
if (c2node)
|
||||
c2node->client = c1;
|
||||
}
|
||||
tmp_mon = c2->mon;
|
||||
tmp_tags = c2->tags;
|
||||
c2->mon = c1->mon;
|
||||
c1->mon = tmp_mon;
|
||||
c2->tags = c1->tags;
|
||||
c1->tags = tmp_tags;
|
||||
arrange(c1->mon, false, false);
|
||||
arrange(c2->mon, false, false);
|
||||
} else {
|
||||
if (layout1->id == DWINDLE && layout2->id == DWINDLE) {
|
||||
dwindle_swap_clients(
|
||||
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||
c2);
|
||||
}
|
||||
arrange(c1->mon, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
tmp_mon = c2->mon;
|
||||
tmp_tags = c2->tags;
|
||||
c2->mon = c1->mon;
|
||||
c1->mon = tmp_mon;
|
||||
c2->tags = c1->tags;
|
||||
c1->tags = tmp_tags;
|
||||
/* 调整焦点顺序 */
|
||||
wl_list_remove(&c2->flink);
|
||||
wl_list_insert(&c1->flink, &c2->flink);
|
||||
return;
|
||||
|
||||
arrange_and_finish:
|
||||
/* 整体交换后的统一 arrange 和焦点调整 */
|
||||
if (m1 != m2) {
|
||||
arrange(c1->mon, false, false);
|
||||
arrange(c2->mon, false, false);
|
||||
} else {
|
||||
if (layout1->id == DWINDLE && layout2->id == DWINDLE) {
|
||||
dwindle_swap_clients(
|
||||
&c1->mon->pertag->dwindle_root[c1->mon->pertag->curtag], c1,
|
||||
c2);
|
||||
}
|
||||
arrange(c1->mon, false, false);
|
||||
}
|
||||
|
||||
// In order to facilitate repeated exchanges for get_focused_stack_client
|
||||
// set c2 focus order behind c1
|
||||
wl_list_remove(&c2->flink);
|
||||
wl_list_insert(&c1->flink, &c2->flink);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue