fix: foreign toplevel mon change

This commit is contained in:
DreamMaoMao 2026-05-07 11:24:41 +08:00
parent 42c02e3dc2
commit 18fa5a22c2
3 changed files with 58 additions and 25 deletions

View file

@ -1109,7 +1109,7 @@ int32_t tag(const Arg *arg) {
}
int32_t tagmon(const Arg *arg) {
Monitor *m = NULL, *cm = NULL;
Monitor *m = NULL, *cm = NULL, *oldmon = NULL;
if (!selmon)
return 0;
Client *c = focustop(selmon);
@ -1117,6 +1117,8 @@ int32_t tagmon(const Arg *arg) {
if (!c)
return 0;
oldmon = c->mon;
if (arg->i != UNDIR) {
m = dirtomon(arg->i);
} else if (arg->v) {
@ -1151,12 +1153,12 @@ int32_t tagmon(const Arg *arg) {
setmon(c, m, newtags, true);
client_update_oldmonname_record(c, m);
reset_foreign_tolevel(c);
reset_foreign_tolevel(c, oldmon, c->mon);
c->float_geom.width =
(int32_t)(c->float_geom.width * c->mon->w.width / selmon->w.width);
(int32_t)(c->float_geom.width * c->mon->w.width / oldmon->w.width);
c->float_geom.height =
(int32_t)(c->float_geom.height * c->mon->w.height / selmon->w.height);
(int32_t)(c->float_geom.height * c->mon->w.height / oldmon->w.height);
selmon = c->mon;
c->float_geom = setclient_coordinate_center(c, c->mon, c->float_geom, 0, 0);

View file

@ -6,7 +6,7 @@ void handle_foreign_activate_request(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_activate_request);
uint32_t target;
if (c->swallowing)
if (c->swallowing || !c->mon)
return;
if (c->isminimized) {
@ -28,7 +28,7 @@ void handle_foreign_maximize_request(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_maximize_request);
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
if (c->swallowing)
if (c->swallowing || !c->mon)
return;
if (c->ismaximizescreen && !event->maximized) {
@ -46,7 +46,7 @@ void handle_foreign_minimize_request(struct wl_listener *listener, void *data) {
Client *c = wl_container_of(listener, c, foreign_minimize_request);
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
if (c->swallowing)
if (c->swallowing || !c->mon)
return;
if (!c->isminimized && event->minimized) {
@ -71,7 +71,7 @@ void handle_foreign_fullscreen_request(struct wl_listener *listener,
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
if (c->swallowing)
if (c->swallowing || !c->mon)
return;
if (c->isfullscreen && !event->fullscreen) {
@ -98,10 +98,6 @@ void handle_foreign_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&c->foreign_fullscreen_request.link);
wl_list_remove(&c->foreign_close_request.link);
wl_list_remove(&c->foreign_destroy.link);
}
void remove_foreign_topleve(Client *c) {
wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
c->foreign_toplevel = NULL;
}
@ -144,7 +140,23 @@ void add_foreign_toplevel(Client *c) {
}
}
void reset_foreign_tolevel(Client *c) {
remove_foreign_topleve(c);
add_foreign_toplevel(c);
void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon) {
if (!c)
return;
if (!c->foreign_toplevel) {
add_foreign_toplevel(c);
return;
}
if (oldmon == newmon)
return;
if (oldmon)
wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel,
oldmon->wlr_output);
if (newmon)
wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel,
newmon->wlr_output);
}

View file

@ -653,8 +653,7 @@ static void motionnotify(uint32_t time, struct wlr_input_device *device,
double sy_unaccel);
static void motionrelative(struct wl_listener *listener, void *data);
static void reset_foreign_tolevel(Client *c);
static void remove_foreign_topleve(Client *c);
static void reset_foreign_tolevel(Client *c, Monitor *oldmon, Monitor *newmon);
static void add_foreign_topleve(Client *c);
static void exchange_two_client(Client *c1, Client *c2);
static void outputmgrapply(struct wl_listener *listener, void *data);
@ -1159,8 +1158,12 @@ void swallow(Client *c, Client *w) {
wl_list_insert(&w->link, &c->link);
wl_list_insert(&w->flink, &c->flink);
if (w->foreign_toplevel)
remove_foreign_topleve(w);
if (w->foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_output_leave(w->foreign_toplevel,
w->mon->wlr_output);
wlr_foreign_toplevel_handle_v1_destroy(w->foreign_toplevel);
w->foreign_toplevel = NULL;
}
wlr_scene_node_set_enabled(&w->scene->node, false);
wlr_scene_node_set_enabled(&c->scene->node, true);
@ -1168,6 +1171,10 @@ void swallow(Client *c, Client *w) {
if (!c->foreign_toplevel && c->mon)
add_foreign_toplevel(c);
else if (c->foreign_toplevel && c->mon) {
wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel,
c->mon->wlr_output);
}
client_pending_fullscreen_state(c, w->isfullscreen);
client_pending_maximized_state(c, w->ismaximizescreen);
@ -1182,7 +1189,7 @@ bool switch_scratchpad_client_state(Client *c) {
Monitor *oldmon = c->mon;
c->scratchpad_switching_mon = true;
c->mon = selmon;
reset_foreign_tolevel(c);
reset_foreign_tolevel(c, oldmon, c->mon);
client_update_oldmonname_record(c, selmon);
// 根据新monitor调整窗口尺寸
@ -2524,7 +2531,13 @@ void closemon(Monitor *m) {
if (c->mon == m) {
if (selmon == NULL) {
remove_foreign_topleve(c);
if (c->foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_output_leave(
c->foreign_toplevel, c->mon->wlr_output);
wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
c->foreign_toplevel = NULL;
}
c->mon = NULL;
} else {
client_change_mon(c, selmon);
@ -4452,7 +4465,11 @@ void set_minimized(Client *c) {
c->is_scratchpad_show = 0;
focusclient(focustop(selmon), 1);
arrange(c->mon, false, false);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, false);
if (c->foreign_toplevel)
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel,
false);
wl_list_remove(&c->link); // 从原来位置移除
wl_list_insert(clients.prev, &c->link); // 插入尾部
}
@ -5612,7 +5629,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);
reset_foreign_tolevel(c, oldmon, m);
resize(c, c->geom, 0);
client_reset_mon_tags(c, m, newtags);
check_match_tag_floating_rule(c, m);
@ -5659,7 +5676,9 @@ void show_hide_client(Client *c) {
}
client_pending_minimized_state(c, 0);
focusclient(c, 1);
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
if (c->foreign_toplevel)
wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, true);
}
void create_output(struct wlr_backend *backend, void *data) {
@ -6436,7 +6455,7 @@ void updatemons(struct wl_listener *listener, void *data) {
wl_list_for_each(c, &clients, link) {
if (!c->mon && client_surface(c)->mapped) {
c->mon = selmon;
reset_foreign_tolevel(c);
reset_foreign_tolevel(c, NULL, c->mon);
}
if (c->tags == 0 && !c->is_in_scratchpad) {
c->tags = selmon->tagset[selmon->seltags];