From 433385f7f18abb607c4feff6d6c7fa817071a710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 24 Jan 2024 12:12:09 -0600 Subject: [PATCH 01/12] do not arrange monitor if it's disabled (wlroots!4520) This causes us to send negative values to xdg-configures (e.g a bug in our end) References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4520 (cherry picked from commit 4043fc3093a73174cb63653ba9e742b4738f2ee5) --- dwl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwl.c b/dwl.c index bf02a6d..239f7d7 100644 --- a/dwl.c +++ b/dwl.c @@ -458,6 +458,10 @@ void arrange(Monitor *m) { Client *c; + + if (!m->wlr_output->enabled) + return; + wl_list_for_each(c, &clients, link) { if (c->mon == m) { wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m)); From ac6074f4fdb8cc263c877f08e16a5805d3bb22d2 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Wed, 24 Jan 2024 22:47:50 +0100 Subject: [PATCH 02/12] implement the virtual pointer protocol This is used by programs like warpd. --- dwl.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/dwl.c b/dwl.c index 239f7d7..76ed8aa 100644 --- a/dwl.c +++ b/dwl.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -328,6 +329,7 @@ static void updatetitle(struct wl_listener *listener, void *data); static void urgent(struct wl_listener *listener, void *data); static void view(const Arg *arg); static void virtualkeyboard(struct wl_listener *listener, void *data); +static void virtualpointer(struct wl_listener *listener, void *data); static Monitor *xytomon(double x, double y); static void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); @@ -361,6 +363,7 @@ static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; static struct wlr_cursor *cursor; @@ -2330,6 +2333,9 @@ setup(void) LISTEN_STATIC(&backend->events.new_input, inputdevice); virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy); LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard); + virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy); + LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer); + seat = wlr_seat_create(dpy, "seat0"); LISTEN_STATIC(&seat->events.request_set_cursor, setcursor); LISTEN_STATIC(&seat->events.request_set_selection, setsel); @@ -2731,6 +2737,17 @@ virtualkeyboard(struct wl_listener *listener, void *data) wlr_keyboard_group_add_keyboard(vkb_group.wlr_group, &keyboard->keyboard); } +void +virtualpointer(struct wl_listener *listener, void *data) +{ + struct wlr_virtual_pointer_v1_new_pointer_event *event = data; + struct wlr_pointer pointer = event->new_pointer->pointer; + + wlr_cursor_attach_input_device(cursor, &pointer.base); + if (event->suggested_output) + wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output); +} + Monitor * xytomon(double x, double y) { From 863634a61cd953ea82d5fd1e4fa4d04e8b48a23f Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Thu, 25 Jan 2024 09:04:14 +0100 Subject: [PATCH 03/12] configure xwayland surfaces without monitors For wine clients often configurex11() is called before mapnotify() and therefore c->mon is NULL. configurex11 just returns early in that case, letting these clients stay in the wrong size. For example only the top left part of winecfg and wine uninstaller is drawn, or confirmation dialogs like when closing wine notepad are too big. Fix this by configuring their surfaces like before 88d386b. --- dwl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 76ed8aa..c8283b7 100644 --- a/dwl.c +++ b/dwl.c @@ -2844,8 +2844,12 @@ configurex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, configure); struct wlr_xwayland_surface_configure_event *event = data; - if (!c->mon) + /* TODO: figure out if there is another way to do this */ + if (!c->mon) { + wlr_xwayland_surface_configure(c->surface.xwayland, + event->x, event->y, event->width, event->height); return; + } if (c->isfloating || client_is_unmanaged(c)) resize(c, (struct wlr_box){.x = event->x, .y = event->y, .width = event->width, .height = event->height}, 0); From 9830a991ff3d310223fb8389d108423b914afb67 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Fri, 26 Jan 2024 08:54:53 -0600 Subject: [PATCH 04/12] Correct specifier-data_type mismatches --- dwl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index c8283b7..3fac808 100644 --- a/dwl.c +++ b/dwl.c @@ -1823,8 +1823,8 @@ printstatus(void) appid = client_get_appid(c); printf("%s title %s\n", m->wlr_output->name, title ? title : broken); printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken); - printf("%s fullscreen %u\n", m->wlr_output->name, c->isfullscreen); - printf("%s floating %u\n", m->wlr_output->name, c->isfloating); + printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); + printf("%s floating %d\n", m->wlr_output->name, c->isfloating); sel = c->tags; } else { printf("%s title \n", m->wlr_output->name); @@ -1835,8 +1835,8 @@ printstatus(void) } printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, - m->tagset[m->seltags], sel, urg); + printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", + m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); } fflush(stdout); From 5c936efc427f2d326dab3f8d22cb34159b8292b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 30 Jan 2024 22:54:54 -0600 Subject: [PATCH 05/12] Revert "No need to call updatemons ourselves" Fixes: https://codeberg.org/dwl/dwl/issues/577 This reverts commit 26d7c9689f6e7eb699f2a63c2093c2a27e411ea3. --- dwl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwl.c b/dwl.c index 3fac808..ae8df11 100644 --- a/dwl.c +++ b/dwl.c @@ -1764,6 +1764,9 @@ apply_or_test: else wlr_output_configuration_v1_send_failed(config); wlr_output_configuration_v1_destroy(config); + + /* TODO: use a wrapper function? */ + updatemons(NULL, NULL); } void From 45e3694fc8e91642cf970bd1586bd1a16dbc8a31 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 09:01:09 +0100 Subject: [PATCH 06/12] remove useless wlr_scene_node_reparent() calls These don't do anything because wlr_scene_node_reparent() is immediately called again by setfloating() through setmon(). They are also a source of confusion because if you change the wlr_scene_node_reparent() call in applyrules() it takes a while to understand why it doesn't work. --- dwl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/dwl.c b/dwl.c index ae8df11..f407477 100644 --- a/dwl.c +++ b/dwl.c @@ -453,7 +453,6 @@ applyrules(Client *c) } } } - wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); setmon(c, mon, newtags); } @@ -1546,7 +1545,6 @@ mapnotify(struct wl_listener *listener, void *data) /* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */ if (c->type == XDGShell && (p = client_get_parent(c))) { c->isfloating = 1; - wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); setmon(c, p->mon, p->tags); } else { applyrules(c); From 17c5cbbf7b6c3a5373f46e6fb6e88daada325479 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 09:06:20 +0100 Subject: [PATCH 07/12] make XWayland clients inherit tags and monitors Revert 3213088 because the linked bug can no longer be reproduced with wlroots 0.17, and update client_get_parent() so it doesn't segfault with XWayland surfaces. This also allows reusing the p variable in the next commit. --- client.h | 7 +++++-- dwl.c | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client.h b/client.h index 0753da8..8a379d0 100644 --- a/client.h +++ b/client.h @@ -172,8 +172,11 @@ client_get_parent(Client *c) { Client *p = NULL; #ifdef XWAYLAND - if (client_is_x11(c) && c->surface.xwayland->parent) - toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + if (client_is_x11(c)) { + if (c->surface.xwayland->parent) + toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + return p; + } #endif if (c->surface.xdg->toplevel->parent) toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); diff --git a/dwl.c b/dwl.c index f407477..b04b66a 100644 --- a/dwl.c +++ b/dwl.c @@ -1542,8 +1542,7 @@ mapnotify(struct wl_listener *listener, void *data) * we always consider floating, clients that have parent and thus * we set the same tags and monitor than its parent, if not * try to apply rules for them */ - /* TODO: https://github.com/djpohly/dwl/pull/334#issuecomment-1330166324 */ - if (c->type == XDGShell && (p = client_get_parent(c))) { + if ((p = client_get_parent(c))) { c->isfloating = 1; setmon(c, p->mon, p->tags); } else { From 298949bbc4eae8cedb9cdd11cfc9ebd139ac5d5f Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Sun, 28 Jan 2024 18:30:36 +0100 Subject: [PATCH 08/12] place child clients above fullscreen clients When a child window of a fullscreen client is mapped, the fullscreen is disabled, and if the previously fullscreen client is floating the child window is rendered below it and cannot be seen, causing confusion, though it is still focused and interactable. Fix this by putting children of fullscreen clients in LyrFS instead of LyrFloat, and by returning before the unset_fullscreen code is called when they are mapped. focusstack() now lets you switch focus from a fullscreen client to its child windows, otherwise if you switch focus from the child window to the fullscreen client you could not focus the child window again and the fullscreen client would stay unresponsive. Child clients are not reparented to LyrFloat after leaving fullscreen, so you could spawn a child window, focus back the fullscreen client, unfullscreen it, and the child window would still be drawn above other floating clients. Avoid dealing with this edge case to keep the line count low. These cases can be tested by pressing Ctrl+o in applications with an open file dialog. --- client.h | 12 ++++++++++++ dwl.c | 13 ++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/client.h b/client.h index 8a379d0..fe9dffc 100644 --- a/client.h +++ b/client.h @@ -183,6 +183,18 @@ client_get_parent(Client *c) return p; } +static inline int +client_has_children(Client *c) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return !wl_list_empty(&c->surface.xwayland->children); +#endif + /* surface.xdg->link is never empty because it always contains at least the + * surface itself. */ + return wl_list_length(&c->surface.xdg->link) > 1; +} + static inline const char * client_get_title(Client *c) { diff --git a/dwl.c b/dwl.c index b04b66a..95ebee8 100644 --- a/dwl.c +++ b/dwl.c @@ -1256,7 +1256,7 @@ focusstack(const Arg *arg) { /* Focus the next or previous client (in tiling order) on selmon */ Client *c, *sel = focustop(selmon); - if (!sel || sel->isfullscreen) + if (!sel || (sel->isfullscreen && !client_has_children(sel))) return; if (arg->i > 0) { wl_list_for_each(c, &sel->link, link) { @@ -1496,7 +1496,8 @@ void mapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ - Client *p, *w, *c = wl_container_of(listener, c, map); + Client *p = NULL; + Client *w, *c = wl_container_of(listener, c, map); Monitor *m; int i; @@ -1553,7 +1554,7 @@ mapnotify(struct wl_listener *listener, void *data) unset_fullscreen: m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); wl_list_for_each(w, &clients, link) { - if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags)) + if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) setfullscreen(w, 0); } } @@ -2044,11 +2045,13 @@ setcursorshape(struct wl_listener *listener, void *data) void setfloating(Client *c, int floating) { + Client *p = client_get_parent(c); c->isfloating = floating; if (!c->mon) return; - wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen - ? LyrFS : c->isfloating ? LyrFloat : LyrTile]); + wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen || + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); arrange(c->mon); printstatus(); } From 3c98c4c24de39dea298bbf289b8fd8e7942a6901 Mon Sep 17 00:00:00 2001 From: Benjamin Chausse Date: Tue, 6 Feb 2024 00:39:01 +0000 Subject: [PATCH 09/12] Fix link to patches website Signed-off-by: Benjamin Chausse --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d22cf3..09233c7 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Wayland without restarting the entire display server, so any changes will take effect the next time dwl is executed. As in the dwm community, we encourage users to share patches they have created. -Check out the [patches page on our wiki]! +Check out the [patches repository]! ## Running dwl @@ -169,6 +169,7 @@ inspiration, and to the various contributors to the project, including: [Wayland]: https://wayland.freedesktop.org/ [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://codeberg.org/dwl/dwl/src/branch/wlroots-next +[patches repository]: https://codeberg.org/dwl/dwl-patches [patches page on our wiki]: https://codeberg.org/dwl/dwl/wiki/Patches [s6]: https://skarnet.org/software/s6/ [anopa]: https://jjacky.com/anopa/ From 089480e0b674156928e63a1db7888c312eeea68b Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Tue, 6 Feb 2024 01:25:56 +0000 Subject: [PATCH 10/12] Update and correct patches/patches-wiki links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Hernández Hernández --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 09233c7..5b3d4f6 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Wayland without restarting the entire display server, so any changes will take effect the next time dwl is executed. As in the dwm community, we encourage users to share patches they have created. -Check out the [patches repository]! +Check out the dwl [patches repository] and [patches wiki]! ## Running dwl @@ -170,7 +170,7 @@ inspiration, and to the various contributors to the project, including: [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://codeberg.org/dwl/dwl/src/branch/wlroots-next [patches repository]: https://codeberg.org/dwl/dwl-patches -[patches page on our wiki]: https://codeberg.org/dwl/dwl/wiki/Patches +[patches wiki]: https://codeberg.org/dwl/dwl-patches/wiki [s6]: https://skarnet.org/software/s6/ [anopa]: https://jjacky.com/anopa/ [runit]: http://smarden.org/runit/faq.html#userservices From 5ae245beedd587a2c9748168ef494abd5a92469c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 7 Feb 2024 02:21:26 +0000 Subject: [PATCH 11/12] fix minimum size continuation of 4043fc3093a73174cb63653ba9e742b4738f2ee5 --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 95ebee8..e999923 100644 --- a/dwl.c +++ b/dwl.c @@ -412,8 +412,8 @@ void applybounds(Client *c, struct wlr_box *bbox) { /* set minimum possible */ - c->geom.width = MAX(1, c->geom.width); - c->geom.height = MAX(1, c->geom.height); + c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); + c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height); if (c->geom.x >= bbox->x + bbox->width) c->geom.x = bbox->x + bbox->width - c->geom.width; From 8006e7920085947673517c3e296a1e308f935f75 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 16 Jan 2024 19:11:18 +0100 Subject: [PATCH 12/12] allow toggling the layout before selecting a different one --- dwl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index e999923..fa76db2 100644 --- a/dwl.c +++ b/dwl.c @@ -871,7 +871,8 @@ createmon(struct wl_listener *listener, void *data) m->m.y = r->y; m->mfact = r->mfact; m->nmaster = r->nmaster; - m->lt[0] = m->lt[1] = r->lt; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); wlr_output_state_set_scale(&state, r->scale); wlr_output_state_set_transform(&state, r->rr);