feat: move clients

This commit is contained in:
ernestoCruz05 2026-06-06 11:41:18 +01:00
parent 3ab2780b84
commit c3e747b74b
5 changed files with 80 additions and 6 deletions

View file

@ -1018,6 +1018,9 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
} else if (strcmp(func_name, "exchange_client") == 0) { } else if (strcmp(func_name, "exchange_client") == 0) {
func = exchange_client; func = exchange_client;
(*arg).i = parse_direction(arg_value); (*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "move_client") == 0) {
func = move_client;
(*arg).i = parse_direction(arg_value);
} else if (strcmp(func_name, "exchange_stack_client") == 0) { } else if (strcmp(func_name, "exchange_stack_client") == 0) {
func = exchange_stack_client; func = exchange_stack_client;
(*arg).i = parse_circle_direction(arg_value); (*arg).i = parse_circle_direction(arg_value);

View file

@ -31,6 +31,7 @@ int32_t setmfact(const Arg *arg);
int32_t quit(const Arg *arg); int32_t quit(const Arg *arg);
int32_t moveresize(const Arg *arg); int32_t moveresize(const Arg *arg);
int32_t exchange_client(const Arg *arg); int32_t exchange_client(const Arg *arg);
int32_t move_client(const Arg *arg);
int32_t exchange_stack_client(const Arg *arg); int32_t exchange_stack_client(const Arg *arg);
int32_t killclient(const Arg *arg); int32_t killclient(const Arg *arg);
int32_t toggleglobal(const Arg *arg); int32_t toggleglobal(const Arg *arg);

View file

@ -111,6 +111,33 @@ int32_t exchange_client(const Arg *arg) {
return 0; return 0;
} }
int32_t move_client(const Arg *arg) {
if (!selmon)
return 0;
Client *c = arg->tc ? arg->tc : selmon->sel;
if (!c || c->isfloating)
return 0;
if ((c->isfullscreen || c->ismaximizescreen) && !is_scroller_layout(c->mon))
return 0;
Client *tc = direction_select(arg);
tc = get_focused_stack_client(tc, arg->tc);
if (!tc)
return 0;
if (c->mon && c->mon->pertag->ltidxs[c->mon->pertag->curtag]->id == DWINDLE) {
uint32_t tag = c->mon->pertag->curtag;
dwindle_move_client(&c->mon->pertag->dwindle_root[tag], c, tc,
config.dwindle_split_ratio, arg->i, false);
arrange(c->mon, false, false);
} else {
move_two_client(c, tc, arg->i);
}
return 0;
}
int32_t exchange_stack_client(const Arg *arg) { int32_t exchange_stack_client(const Arg *arg) {
if (!selmon) if (!selmon)
return 0; return 0;

View file

@ -286,15 +286,33 @@ static void dwindle_assign(DwindleNode *node, int32_t ax, int32_t ay,
} }
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target, static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
float ratio, int32_t dir) { float ratio, int32_t dir, bool lock) {
if (!c || !target || c == target) if (!c || !target || c == target)
return; return;
if (!dwindle_find_leaf(*root, c) || !dwindle_find_leaf(*root, target)) DwindleNode *c_leaf = dwindle_find_leaf(*root, c);
DwindleNode *t_leaf = dwindle_find_leaf(*root, target);
if (!c_leaf || !t_leaf)
return; return;
dwindle_remove(root, c);
bool as_first = (dir == UP || dir == LEFT); if (c_leaf->parent && c_leaf->parent == t_leaf->parent) {
DwindleNode *p = c_leaf->parent;
DwindleNode *tmp = p->first;
p->first = p->second;
p->second = tmp;
return;
}
bool split_h = (dir == LEFT || dir == RIGHT); bool split_h = (dir == LEFT || dir == RIGHT);
dwindle_insert(root, c, target, ratio, as_first, split_h, true); bool as_first;
if (dir == LEFT || dir == RIGHT) {
int cy = c->geom.y + c->geom.height / 2;
int ty = target->geom.y + target->geom.height / 2;
as_first = (cy < ty);
} else {
as_first = (dir == UP);
}
dwindle_remove(root, c);
dwindle_insert(root, c, target, ratio, as_first, split_h, lock);
} }
static void dwindle_swap_clients(Client *c1, Client *c2) { static void dwindle_swap_clients(Client *c1, Client *c2) {

View file

@ -717,6 +717,7 @@ static void motionrelative(struct wl_listener *listener, void *data);
static void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon); static void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon);
static void add_foreign_topleve(Client *c); static void add_foreign_topleve(Client *c);
static void exchange_two_client(Client *c1, Client *c2); static void exchange_two_client(Client *c1, Client *c2);
static void move_two_client(Client *c, Client *target, int32_t dir);
static void outputmgrapply(struct wl_listener *listener, void *data); static void outputmgrapply(struct wl_listener *listener, void *data);
static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config,
int32_t test); int32_t test);
@ -878,7 +879,7 @@ static void client_pending_minimized_state(Client *c, int32_t isminimized);
static void scroller_insert_stack(Client *c, Client *target_client, static void scroller_insert_stack(Client *c, Client *target_client,
bool insert_before); bool insert_before);
static void dwindle_move_client(DwindleNode **root, Client *c, Client *target, static void dwindle_move_client(DwindleNode **root, Client *c, Client *target,
float ratio, int32_t dir); float ratio, int32_t dir, bool lock);
static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx, static void dwindle_resize_client_step(Monitor *m, Client *c, int32_t dx,
int32_t dy); int32_t dy);
static void dwindle_resize_client(Monitor *m, Client *c); static void dwindle_resize_client(Monitor *m, Client *c);
@ -5177,6 +5178,30 @@ void exchange_two_client(Client *c1, Client *c2) {
finish_exchange_arrange_and_focus(c1, c2, m1, m2); finish_exchange_arrange_and_focus(c1, c2, m1, m2);
} }
static void move_two_client(Client *c, Client *target, int32_t dir) {
if (c == NULL || target == NULL || c == target ||
(!config.exchange_cross_monitor && c->mon != target->mon)) {
return;
}
Monitor *m = c->mon;
const Layout *layout = m->pertag->ltidxs[m->pertag->curtag];
if (layout->id == SCROLLER) {
exchange_two_scroller_clients(c, target);
return;
}
wl_list_remove(&c->link);
if (dir == UP || dir == LEFT) {
wl_list_insert(target->link.prev, &c->link);
} else {
wl_list_insert(&target->link, &c->link);
}
arrange(m, false, false);
}
void set_activation_env() { void set_activation_env() {
if (!getenv("DBUS_SESSION_BUS_ADDRESS")) { if (!getenv("DBUS_SESSION_BUS_ADDRESS")) {
wlr_log(WLR_INFO, "Not updating dbus execution environment: " wlr_log(WLR_INFO, "Not updating dbus execution environment: "