From 537ad7e3fdc23602254ba00ba869eab891be7966 Mon Sep 17 00:00:00 2001 From: Stivvo Date: Sat, 12 Sep 2020 00:13:05 +0200 Subject: [PATCH 1/5] Restore floating win position after mon add Compensate the coordinate changes when adding a new monitor. Every test so far confirms that monitors are always added to the left, on top of the list, so every floating window's x coordinate has to be incremented by the width of the new monitor. --- dwl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/dwl.c b/dwl.c index 414aa59..23a7211 100644 --- a/dwl.c +++ b/dwl.c @@ -195,6 +195,7 @@ static void applyexclusive(struct wlr_box *usable_area, uint32_t anchor, int32_t margin_bottom, int32_t margin_left); static void applyrules(Client *c); static void arrange(Monitor *m); +static void arrangefloat(Monitor *m, int sign); static void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, bool exclusive); static void arrangelayers(Monitor *m); @@ -469,6 +470,17 @@ arrange(Monitor *m) /* XXX recheck pointer focus here... or in resize()? */ } +void +arrangefloat(Monitor *m, int sign) +{ + Client *c; + wl_list_for_each(c, &clients, link) { + if (c->isfloating) + resize(c, c->geom.x + m->w.width * sign, c->geom.y, + c->geom.width, c->geom.height, 0); + } +} + void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, bool exclusive) { @@ -693,6 +705,7 @@ cleanupmon(struct wl_listener *listener, void *data) free(m); updatemons(); + arrangefloat(m, -1); } void @@ -821,6 +834,11 @@ createmon(struct wl_listener *listener, void *data) /* When adding monitors, the geometries of all monitors must be updated */ updatemons(); + wl_list_for_each(m, &mons, link) { + /* the first monitor in the list is the most recently added */ + arrangefloat(m, 1); + return; + } } void From bece225934216f1d047ebecc5b574ed1b15886f2 Mon Sep 17 00:00:00 2001 From: Stivvo Date: Mon, 14 Sep 2020 17:40:14 +0200 Subject: [PATCH 2/5] Handle monitor unplug Floating widndows with "x < removed monitor's width" aren't resized (they used to disappear in negative coordinates). Actually delete monitors when they are unplugged, recalculate sgeom and give a new monitor to clients that were on the removed one with setmon() arrangefloat() funcion has been exploded to save iterations in cleanupmon(). Also if a monitor that supports auto suspension is turned off, dwl will count it as unplugged (it will become unreachable and all clients will be moved to the leftmost monitor). However, if at least one monitor isn't plugged in, dwl will still crash the same as before. Unlike sway, when the output configuration is changed and restored, (unplug + plug the same monitor for example) previous application positions aren't kept. This is due to the fact that on sway every workspace is unique among all monitors. --- dwl.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/dwl.c b/dwl.c index 23a7211..6f2e800 100644 --- a/dwl.c +++ b/dwl.c @@ -195,7 +195,6 @@ static void applyexclusive(struct wlr_box *usable_area, uint32_t anchor, int32_t margin_bottom, int32_t margin_left); static void applyrules(Client *c); static void arrange(Monitor *m); -static void arrangefloat(Monitor *m, int sign); static void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, bool exclusive); static void arrangelayers(Monitor *m); @@ -470,17 +469,6 @@ arrange(Monitor *m) /* XXX recheck pointer focus here... or in resize()? */ } -void -arrangefloat(Monitor *m, int sign) -{ - Client *c; - wl_list_for_each(c, &clients, link) { - if (c->isfloating) - resize(c, c->geom.x + m->w.width * sign, c->geom.y, - c->geom.width, c->geom.height, 0); - } -} - void arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, bool exclusive) { @@ -699,13 +687,29 @@ void cleanupmon(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; - Monitor *m = wlr_output->data; + Monitor *m = wlr_output->data, *newmon; + Client *c; wl_list_remove(&m->destroy.link); - free(m); + wl_list_remove(&m->frame.link); + wl_list_remove(&m->link); + wlr_output_layout_remove(output_layout, m->wlr_output); + sgeom = *wlr_output_layout_get_box(output_layout, NULL); updatemons(); - arrangefloat(m, -1); + + wl_list_for_each(newmon, &mons, link) { + wl_list_for_each(c, &clients, link) { + if (c->isfloating && c->geom.x > m->m.width) { + resize(c, c->geom.x - m->w.width, c->geom.y, + c->geom.width, c->geom.height, 0); + } + if (c->mon == m) + setmon(c, newmon, 0); + } + break; + } + free(m); } void @@ -836,7 +840,12 @@ createmon(struct wl_listener *listener, void *data) updatemons(); wl_list_for_each(m, &mons, link) { /* the first monitor in the list is the most recently added */ - arrangefloat(m, 1); + Client *c; + wl_list_for_each(c, &clients, link) { + if (c->isfloating) + resize(c, c->geom.x + m->w.width, c->geom.y, + c->geom.width, c->geom.height, 0); + } return; } } From d8f752c9b46f8ef2286cddd45628b6db576b8ddf Mon Sep 17 00:00:00 2001 From: Stivvo Date: Tue, 15 Sep 2020 12:11:40 +0200 Subject: [PATCH 3/5] Keep client tags on unplug When unplugging a monitor, each client is moved to the same tag number as before on the new monitor --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 6f2e800..bdd89fc 100644 --- a/dwl.c +++ b/dwl.c @@ -705,7 +705,7 @@ cleanupmon(struct wl_listener *listener, void *data) c->geom.width, c->geom.height, 0); } if (c->mon == m) - setmon(c, newmon, 0); + setmon(c, newmon, c->tags); } break; } From f21d3796b842ea944fb05049cd0d6fa2614dce64 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sat, 17 Oct 2020 20:15:59 +0200 Subject: [PATCH 4/5] Move sgeom assignment There is no need to repeat this. This needs to be reculalculated in my output-management implementation too, and since I'm already calling updatemons, this patch avoids having to repeat the assignment again. --- dwl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index bdd89fc..5d8a75c 100644 --- a/dwl.c +++ b/dwl.c @@ -695,7 +695,6 @@ cleanupmon(struct wl_listener *listener, void *data) wl_list_remove(&m->link); wlr_output_layout_remove(output_layout, m->wlr_output); - sgeom = *wlr_output_layout_get_box(output_layout, NULL); updatemons(); wl_list_for_each(newmon, &mons, link) { @@ -831,7 +830,6 @@ createmon(struct wl_listener *listener, void *data) * output (such as DPI, scale factor, manufacturer, etc). */ wlr_output_layout_add_auto(output_layout, wlr_output); - sgeom = *wlr_output_layout_get_box(output_layout, NULL); for (size_t i = 0; i < nlayers; ++i) wl_list_init(&m->layers[i]); @@ -2151,6 +2149,7 @@ unmapnotify(struct wl_listener *listener, void *data) void updatemons() { + sgeom = *wlr_output_layout_get_box(output_layout, NULL); Monitor *m; wl_list_for_each(m, &mons, link) { /* Get the effective monitor geometry to use for surfaces */ From 7017a0c64d3a58635cb5e088fab890c4efa02737 Mon Sep 17 00:00:00 2001 From: Stivvo Date: Sun, 18 Oct 2020 18:37:55 +0200 Subject: [PATCH 5/5] fix compile error mixed declaration --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 5d8a75c..48a4fbe 100644 --- a/dwl.c +++ b/dwl.c @@ -2149,8 +2149,8 @@ unmapnotify(struct wl_listener *listener, void *data) void updatemons() { - sgeom = *wlr_output_layout_get_box(output_layout, NULL); Monitor *m; + sgeom = *wlr_output_layout_get_box(output_layout, NULL); wl_list_for_each(m, &mons, link) { /* Get the effective monitor geometry to use for surfaces */ m->m = m->w = *wlr_output_layout_get_box(output_layout, m->wlr_output);