mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-26 21:37:31 -04:00
feat: support drag tile position for scroller layout
This commit is contained in:
parent
586ee8e699
commit
975142d46a
2 changed files with 173 additions and 61 deletions
|
|
@ -1763,21 +1763,15 @@ int32_t toggle_monitor(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t scroller_stack(const Arg *arg) {
|
int32_t scroller_apply_stack(Client *c, Client *target_client,
|
||||||
if (!selmon)
|
int32_t direction) {
|
||||||
return 0;
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
Client *source_stack_head = NULL;
|
||||||
|
Client *stack_head = NULL;
|
||||||
bool is_horizontal_layout =
|
bool is_horizontal_layout =
|
||||||
c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true
|
c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == SCROLLER ? true
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
Client *target_client = find_client_by_direction(c, arg, false, true);
|
|
||||||
|
|
||||||
if (target_client) {
|
if (target_client) {
|
||||||
stack_head = get_scroll_stack_head(target_client);
|
stack_head = get_scroll_stack_head(target_client);
|
||||||
}
|
}
|
||||||
|
|
@ -1796,32 +1790,32 @@ int32_t scroller_stack(const Arg *arg) {
|
||||||
setmaximizescreen(c, 0);
|
setmaximizescreen(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->prev_in_stack) {
|
if (c->prev_in_stack && direction != UNDIR) {
|
||||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
if ((is_horizontal_layout && direction == LEFT) ||
|
||||||
(!is_horizontal_layout && arg->i == UP)) {
|
(!is_horizontal_layout && direction == UP)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(source_stack_head->link.prev, &c->link);
|
wl_list_insert(source_stack_head->link.prev, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
|
|
||||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
} else if ((is_horizontal_layout && direction == RIGHT) ||
|
||||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
(!is_horizontal_layout && direction == DOWN)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(&source_stack_head->link, &c->link);
|
wl_list_insert(&source_stack_head->link, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (c->next_in_stack) {
|
} else if (c->next_in_stack && direction != UNDIR) {
|
||||||
Client *next_in_stack = c->next_in_stack;
|
Client *next_in_stack = c->next_in_stack;
|
||||||
if ((is_horizontal_layout && arg->i == LEFT) ||
|
if ((is_horizontal_layout && direction == LEFT) ||
|
||||||
(!is_horizontal_layout && arg->i == UP)) {
|
(!is_horizontal_layout && direction == UP)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(next_in_stack->link.prev, &c->link);
|
wl_list_insert(next_in_stack->link.prev, &c->link);
|
||||||
arrange(selmon, false, false);
|
arrange(selmon, false, false);
|
||||||
} else if ((is_horizontal_layout && arg->i == RIGHT) ||
|
} else if ((is_horizontal_layout && direction == RIGHT) ||
|
||||||
(!is_horizontal_layout && arg->i == DOWN)) {
|
(!is_horizontal_layout && direction == DOWN)) {
|
||||||
exit_scroller_stack(c);
|
exit_scroller_stack(c);
|
||||||
wl_list_remove(&c->link);
|
wl_list_remove(&c->link);
|
||||||
wl_list_insert(&next_in_stack->link, &c->link);
|
wl_list_insert(&next_in_stack->link, &c->link);
|
||||||
|
|
@ -1832,37 +1826,31 @@ int32_t scroller_stack(const Arg *arg) {
|
||||||
|
|
||||||
if (!target_client || target_client->mon != c->mon) {
|
if (!target_client || target_client->mon != c->mon) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
c->isglobal = target_client->isglobal = 0;
|
|
||||||
c->isunglobal = target_client->isglobal = 0;
|
|
||||||
c->tags = target_client->tags = get_tags_first_tag(target_client->tags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_scroller_stack(c);
|
|
||||||
|
|
||||||
// Find the tail of target_client's stack
|
// Find the tail of target_client's stack
|
||||||
Client *stack_tail = target_client;
|
Client *stack_tail = target_client;
|
||||||
while (stack_tail->next_in_stack) {
|
while (stack_tail->next_in_stack) {
|
||||||
stack_tail = stack_tail->next_in_stack;
|
stack_tail = stack_tail->next_in_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add c to the stack
|
scroller_insert_stack(c, stack_tail, false);
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t scroller_stack(const Arg *arg) {
|
||||||
|
if (!selmon)
|
||||||
|
return 0;
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *target_client = find_client_by_direction(c, arg, false, true);
|
||||||
|
|
||||||
|
return scroller_apply_stack(c, target_client, arg->i);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t toggle_all_floating(const Arg *arg) {
|
int32_t toggle_all_floating(const Arg *arg) {
|
||||||
if (!selmon || !selmon->sel)
|
if (!selmon || !selmon->sel)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
168
src/mango.c
168
src/mango.c
|
|
@ -810,6 +810,8 @@ static void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen);
|
static void client_pending_fullscreen_state(Client *c, int32_t isfullscreen);
|
||||||
static void client_pending_maximized_state(Client *c, int32_t ismaximized);
|
static void client_pending_maximized_state(Client *c, int32_t ismaximized);
|
||||||
static void client_pending_minimized_state(Client *c, int32_t isminimized);
|
static void client_pending_minimized_state(Client *c, int32_t isminimized);
|
||||||
|
static void scroller_insert_stack(Client *c, Client *target_client,
|
||||||
|
bool insert_before);
|
||||||
|
|
||||||
#include "data/static_keymap.h"
|
#include "data/static_keymap.h"
|
||||||
#include "dispatch/bind_declare.h"
|
#include "dispatch/bind_declare.h"
|
||||||
|
|
@ -2045,33 +2047,155 @@ void hold_end(struct wl_listener *listener, void *data) {
|
||||||
event->time_msec, event->cancelled);
|
event->time_msec, event->cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void place_drag_tile_client(Client *c) {
|
Client *find_closest_tiled_client(Client *c) {
|
||||||
Client *tc = NULL;
|
Client *tc, *closest = NULL;
|
||||||
Client *closest_client = NULL;
|
long min_dist = LONG_MAX;
|
||||||
long min_distant = LONG_MAX;
|
|
||||||
long temp_distant;
|
|
||||||
int32_t x, y;
|
|
||||||
|
|
||||||
wl_list_for_each(tc, &clients, link) {
|
wl_list_for_each(tc, &clients, link) {
|
||||||
if (tc != c && ISTILED(tc) && VISIBLEON(tc, c->mon)) {
|
if (tc == c || !ISTILED(tc) || !VISIBLEON(tc, c->mon))
|
||||||
x = tc->geom.x + (int32_t)(tc->geom.width / 2) - cursor->x;
|
continue;
|
||||||
y = tc->geom.y + (int32_t)(tc->geom.height / 2) - cursor->y;
|
|
||||||
temp_distant = x * x + y * y;
|
int32_t dx = tc->geom.x + (int32_t)(tc->geom.width / 2) - cursor->x;
|
||||||
if (temp_distant < min_distant) {
|
int32_t dy = tc->geom.y + (int32_t)(tc->geom.height / 2) - cursor->y;
|
||||||
min_distant = temp_distant;
|
long dist = (long)dx * dx + (long)dy * dy;
|
||||||
closest_client = tc;
|
|
||||||
}
|
if (dist < min_dist) {
|
||||||
|
min_dist = dist;
|
||||||
|
closest = tc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (closest_client && closest_client->link.prev != &c->link) {
|
|
||||||
wl_list_remove(&c->link);
|
return closest;
|
||||||
c->link.next = &closest_client->link;
|
}
|
||||||
c->link.prev = closest_client->link.prev;
|
|
||||||
closest_client->link.prev->next = &c->link;
|
void scroller_insert_stack(Client *c, Client *target_client,
|
||||||
closest_client->link.prev = &c->link;
|
bool insert_before) {
|
||||||
} else if (closest_client) {
|
Client *stack_head = NULL;
|
||||||
exchange_two_client(c, closest_client);
|
|
||||||
|
if (!target_client || target_client->mon != c->mon) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
c->isglobal = target_client->isglobal = 0;
|
||||||
|
c->isunglobal = target_client->isunglobal = 0;
|
||||||
|
c->tags = target_client->tags = get_tags_first_tag(target_client->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->isfullscreen) {
|
||||||
|
setfullscreen(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ismaximizescreen) {
|
||||||
|
setmaximizescreen(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_scroller_stack(c);
|
||||||
|
stack_head = get_scroll_stack_head(target_client);
|
||||||
|
|
||||||
|
if (insert_before) {
|
||||||
|
if (target_client->prev_in_stack) {
|
||||||
|
target_client->prev_in_stack->next_in_stack = c;
|
||||||
|
}
|
||||||
|
c->prev_in_stack = target_client->prev_in_stack;
|
||||||
|
c->next_in_stack = target_client;
|
||||||
|
target_client->prev_in_stack = c;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (target_client->next_in_stack) {
|
||||||
|
target_client->next_in_stack->prev_in_stack = c;
|
||||||
|
}
|
||||||
|
c->next_in_stack = target_client->next_in_stack;
|
||||||
|
c->prev_in_stack = target_client;
|
||||||
|
target_client->next_in_stack = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_head->ismaximizescreen) {
|
||||||
|
setmaximizescreen(stack_head, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_head->isfullscreen) {
|
||||||
|
setfullscreen(stack_head, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange(c->mon, false, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void try_scroller_drop(Client *c, Client *closest, int vertical) {
|
||||||
|
double ratio_main, ratio_cross;
|
||||||
|
int32_t main_pos, cross_pos;
|
||||||
|
int32_t main_size, cross_size;
|
||||||
|
Client *stack_head = NULL;
|
||||||
|
|
||||||
|
if (vertical) {
|
||||||
|
main_pos = cursor->y;
|
||||||
|
cross_pos = cursor->x;
|
||||||
|
main_size = closest->geom.height;
|
||||||
|
cross_size = closest->geom.width;
|
||||||
|
} else {
|
||||||
|
main_pos = cursor->x;
|
||||||
|
cross_pos = cursor->y;
|
||||||
|
main_size = closest->geom.width;
|
||||||
|
cross_size = closest->geom.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratio_main =
|
||||||
|
(double)(main_pos - (vertical ? closest->geom.y : closest->geom.x)) /
|
||||||
|
main_size;
|
||||||
|
ratio_cross =
|
||||||
|
(double)(cross_pos - (vertical ? closest->geom.x : closest->geom.y)) /
|
||||||
|
cross_size;
|
||||||
|
|
||||||
|
if (ratio_main > 0.3 && ratio_main < 0.7 &&
|
||||||
|
(ratio_cross < 0.3 || ratio_cross > 0.7)) {
|
||||||
|
setfloating(c, 0);
|
||||||
|
if (ratio_cross < 0.3) {
|
||||||
|
scroller_insert_stack(c, closest, true);
|
||||||
|
} else {
|
||||||
|
scroller_insert_stack(c, closest, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_head = get_scroll_stack_head(closest);
|
||||||
|
|
||||||
|
if (ratio_main < 0.3) {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(stack_head->link.prev, &c->link);
|
||||||
|
} else {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(&stack_head->link, &c->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
setfloating(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void place_drag_tile_client(Client *c) {
|
||||||
|
Client *closest = find_closest_tiled_client(c);
|
||||||
|
|
||||||
|
if (closest && closest->mon) {
|
||||||
|
const Layout *layout =
|
||||||
|
closest->mon->pertag->ltidxs[closest->mon->pertag->curtag];
|
||||||
|
|
||||||
|
if (layout) {
|
||||||
|
if (layout->id == SCROLLER) {
|
||||||
|
try_scroller_drop(c, closest, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (layout->id == VERTICAL_SCROLLER) {
|
||||||
|
try_scroller_drop(c, closest, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest->link.prev != &c->link) {
|
||||||
|
wl_list_remove(&c->link);
|
||||||
|
wl_list_insert(closest->link.prev, &c->link);
|
||||||
|
} else {
|
||||||
|
exchange_two_client(c, closest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setfloating(c, 0);
|
setfloating(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue