From 4567979b16b0509bb80b6102ecb9b601b3cf6fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Fri, 18 Aug 2023 21:37:22 -0600 Subject: [PATCH 01/12] don't resize clients on commit It creates an infinite commit-resize loop when scale != 1 --- dwl.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dwl.c b/dwl.c index 93f66ef..655ded0 100644 --- a/dwl.c +++ b/dwl.c @@ -768,12 +768,6 @@ void commitnotify(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, commit); - struct wlr_box box = {0}; - client_get_geometry(c, &box); - - if (c->mon && !wlr_box_empty(&box) && (box.width != c->geom.width - 2 * c->bw - || box.height != c->geom.height - 2 * c->bw)) - c->isfloating ? resize(c, c->geom, 1) : arrange(c->mon); /* mark a pending resize as completed */ if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) From 4eb54b55f36e770a42e9fc6a4701911b6aaac441 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 21 Jul 2023 20:13:38 -0400 Subject: [PATCH 02/12] No need to send surface.leave/enter events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scene graph implementation sends these for us, and it does so more accurately than our overly-simplified approach. Layer shell surfaces don't appear to receive these events at all, according to my WAYLAND_DEBUG experiments with bemenu and dtao. ΔSLOC: -4 --- dwl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index 655ded0..ddf7cad 100644 --- a/dwl.c +++ b/dwl.c @@ -1525,7 +1525,6 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, map); - wlr_surface_send_enter(l->layer_surface->surface, l->mon->wlr_output); motionnotify(0); } @@ -2091,15 +2090,12 @@ setmon(Client *c, Monitor *m, uint32_t newtags) c->mon = m; c->prev = c->geom; - /* TODO leave/enter is not optimal but works */ - if (oldmon) { - wlr_surface_send_leave(client_surface(c), oldmon->wlr_output); + /* Scene graph sends surface leave/enter events on move and resize */ + if (oldmon) arrange(oldmon); - } if (m) { /* Make sure window actually overlaps with the monitor */ resize(c, c->geom, 0); - wlr_surface_send_enter(client_surface(c), m->wlr_output); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ } From d7569870b62233099af65ce6a048e2ec50d92b7b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 21 Jul 2023 20:28:12 -0400 Subject: [PATCH 03/12] Style: use early-return to clarify code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an early return to avoid indenting the main logic instead of wrapping the tail of a function in an if statement. No functional change, except for a handful of places where printstatus() was being called spuriously (tag, toggletag, toggleview). ΔSLOC: 0 --- dwl.c | 96 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/dwl.c b/dwl.c index ddf7cad..7f1e471 100644 --- a/dwl.c +++ b/dwl.c @@ -1132,15 +1132,16 @@ destroylocksurface(struct wl_listener *listener, void *data) m->lock_surface = NULL; wl_list_remove(&m->destroy_lock_surface.link); - if (lock_surface->surface == seat->keyboard_state.focused_surface) { - if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { - surface = wl_container_of(cur_lock->surfaces.next, surface, link); - client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); - } else if (!locked) { - focusclient(focustop(selmon), 1); - } else { - wlr_seat_keyboard_clear_focus(seat); - } + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; + + if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { + focusclient(focustop(selmon), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); } } @@ -1446,12 +1447,13 @@ keypress(struct wl_listener *listener, void *data) wl_event_source_timer_update(kb->key_repeat_source, 0); } - if (!handled) { - /* Pass unhandled keycodes along to the client. */ - wlr_seat_set_keyboard(seat, kb->wlr_keyboard); - wlr_seat_keyboard_notify_key(seat, event->time_msec, - event->keycode, event->state); - } + if (handled) + return; + + /* Pass unhandled keycodes along to the client. */ + wlr_seat_set_keyboard(seat, kb->wlr_keyboard); + wlr_seat_keyboard_notify_key(seat, event->time_msec, + event->keycode, event->state); } void @@ -1477,13 +1479,14 @@ keyrepeat(void *data) { Keyboard *kb = data; int i; - if (kb->nsyms && kb->wlr_keyboard->repeat_info.rate > 0) { - wl_event_source_timer_update(kb->key_repeat_source, - 1000 / kb->wlr_keyboard->repeat_info.rate); + if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0) + return 0; - for (i = 0; i < kb->nsyms; i++) - keybinding(kb->mods, kb->keysyms[i]); - } + wl_event_source_timer_update(kb->key_repeat_source, + 1000 / kb->wlr_keyboard->repeat_info.rate); + + for (i = 0; i < kb->nsyms; i++) + keybinding(kb->mods, kb->keysyms[i]); return 0; } @@ -2332,11 +2335,12 @@ void tag(const Arg *arg) { Client *sel = focustop(selmon); - if (sel && arg->ui & TAGMASK) { - sel->tags = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2406,11 +2410,12 @@ toggletag(const Arg *arg) if (!sel) return; newtags = sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - sel->tags = newtags; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!newtags) + return; + + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2419,11 +2424,12 @@ toggleview(const Arg *arg) { uint32_t newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0; - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!newtagset) + return; + + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2580,10 +2586,11 @@ urgent(struct wl_listener *listener, void *data) struct wlr_xdg_activation_v1_request_activate_event *event = data; Client *c = NULL; toplevel_from_wlr_surface(event->surface, &c, NULL); - if (c && c != focustop(selmon)) { - c->isurgent = 1; - printstatus(); - } + if (!c || c == focustop(selmon)) + return; + + c->isurgent = 1; + printstatus(); } void @@ -2742,10 +2749,11 @@ void sethints(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, set_hints); - if (c != focustop(selmon)) { - c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); - printstatus(); - } + if (c == focustop(selmon)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); + printstatus(); } void From 4b8c1bf31e9619db58eadf593617ba060d62418d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Tue, 22 Aug 2023 14:48:29 -0600 Subject: [PATCH 04/12] return nothing in xytonode() we do not use the node --- dwl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index 7f1e471..4ff5c37 100644 --- a/dwl.c +++ b/dwl.c @@ -315,7 +315,7 @@ 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 Monitor *xytomon(double x, double y); -static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface, +static void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); static void zoom(const Arg *arg); @@ -2620,7 +2620,7 @@ xytomon(double x, double y) return o ? o->data : NULL; } -struct wlr_scene_node * +void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny) { @@ -2649,7 +2649,6 @@ xytonode(double x, double y, struct wlr_surface **psurface, if (psurface) *psurface = surface; if (pc) *pc = c; if (pl) *pl = l; - return node; } void From 9be85c11174e0d3e8e122039142af45f87c1151d Mon Sep 17 00:00:00 2001 From: Ben Collerson Date: Wed, 28 Jun 2023 15:53:15 +1000 Subject: [PATCH 05/12] tagcount should have been a #define --- config.def.h | 4 ++-- dwl.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 447ba00..d3795fb 100644 --- a/config.def.h +++ b/config.def.h @@ -7,8 +7,8 @@ static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; -/* tagging - tagcount must be no greater than 31 */ -static const int tagcount = 9; +/* tagging - TAGCOUNT must be no greater than 31 */ +#define TAGCOUNT (9) static const Rule rules[] = { /* app_id title tags mask isfloating monitor */ diff --git a/dwl.c b/dwl.c index 4ff5c37..170fa29 100644 --- a/dwl.c +++ b/dwl.c @@ -67,7 +67,7 @@ #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) #define END(A) ((A) + LENGTH(A)) -#define TAGMASK ((1u << tagcount) - 1) +#define TAGMASK ((1u << TAGCOUNT) - 1) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #define IDLE_NOTIFY_ACTIVITY wlr_idle_notify_activity(idle, seat), wlr_idle_notifier_v1_notify_activity(idle_notifier, seat) From e5367753bb90add013ee5d170a110064298ac2c4 Mon Sep 17 00:00:00 2001 From: Ben Collerson Date: Wed, 23 Aug 2023 14:16:24 +1000 Subject: [PATCH 06/12] just add define --- config.def.h | 3 ++- dwl.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index d3795fb..1677f6f 100644 --- a/config.def.h +++ b/config.def.h @@ -7,8 +7,9 @@ static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; -/* tagging - TAGCOUNT must be no greater than 31 */ +/* tagging - tagcount must be no greater than 31 */ #define TAGCOUNT (9) +static const int tagcount = TAGCOUNT; static const Rule rules[] = { /* app_id title tags mask isfloating monitor */ diff --git a/dwl.c b/dwl.c index 170fa29..4ff5c37 100644 --- a/dwl.c +++ b/dwl.c @@ -67,7 +67,7 @@ #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) #define END(A) ((A) + LENGTH(A)) -#define TAGMASK ((1u << TAGCOUNT) - 1) +#define TAGMASK ((1u << tagcount) - 1) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #define IDLE_NOTIFY_ACTIVITY wlr_idle_notify_activity(idle, seat), wlr_idle_notifier_v1_notify_activity(idle_notifier, seat) From c1d8b77f7fb4f082b7eb43474a788e9b5fe04e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Wed, 23 Aug 2023 00:16:21 -0600 Subject: [PATCH 07/12] prefer IRC over Discord I regularly check the discord server, but it is much more likely that I will be online on IRC, and djpohly does not seem to be active on either. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05f149c..1ac5b4b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # dwl - dwm for Wayland -Join us on our [Discord server] or at [#dwl] on irc.libera.chat. +Join us on our IRC channel: [#dwl on Libera Chat] +Or on our [Discord server]. dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is intended to fill the same space in the Wayland world that dwm does in X11, @@ -143,7 +144,7 @@ inspiration, and to the various contributors to the project, including: [Discord server]: https://discord.gg/jJxZnrGPWN -[#dwl]: https://web.libera.chat/?channels=#dwl +[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl [Wayland]: https://wayland.freedesktop.org/ [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://github.com/djpohly/dwl/tree/wlroots-next From aea8dd6ae122bdc99e104afe019479d45755f239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 3 Sep 2023 11:44:30 -0600 Subject: [PATCH 08/12] return early if the client doesn't have monitor in setfloating there is still a bug, but for now this prevents a segfault Bug: https://github.com/djpohly/dwl/issues/472 --- dwl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dwl.c b/dwl.c index 4ff5c37..edea5b1 100644 --- a/dwl.c +++ b/dwl.c @@ -2026,6 +2026,8 @@ void setfloating(Client *c, int floating) { c->isfloating = floating; + if (!c->mon) + return; wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); arrange(c->mon); printstatus(); From 960c32a7d83703a64ec0a363d8a11f3c1c51bf20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 3 Sep 2023 20:39:33 -0600 Subject: [PATCH 09/12] call setfloating in setmon since in the previous commit we may not applying floating in clients this is to make sure we do --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index edea5b1..4118fd8 100644 --- a/dwl.c +++ b/dwl.c @@ -2103,6 +2103,7 @@ setmon(Client *c, Monitor *m, uint32_t newtags) resize(c, c->geom, 0); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); } focusclient(focustop(selmon), 1); } From 755fcae2afbed51f38c167bdc56a5437cda8137a Mon Sep 17 00:00:00 2001 From: Angelo Antony <83206032+alterego-blip@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:05:37 +0530 Subject: [PATCH 10/12] fix typo --- dwl.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.1 b/dwl.1 index cae1036..6f164e6 100644 --- a/dwl.1 +++ b/dwl.1 @@ -101,7 +101,7 @@ These environment variables are used by A directory where temporary user files, such as the Wayland socket, are stored. .It Ev XDG_CONFIG_DIR -A directory containung configuration of various programs and +A directory containing configuration of various programs and libraries, including libxkbcommon. .It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET Tell how to connect to an underlying X11 or Wayland server. From 773bd04764f8407f90bf5bd10d62cd1712594892 Mon Sep 17 00:00:00 2001 From: Weiseguy Date: Fri, 22 Sep 2023 06:50:35 -0500 Subject: [PATCH 11/12] Add desktop entry file --- Makefile | 5 ++++- dwl.desktop | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 dwl.desktop diff --git a/Makefile b/Makefile index ccca079..09c2c53 100644 --- a/Makefile +++ b/Makefile @@ -52,8 +52,11 @@ install: dwl mkdir -p $(DESTDIR)$(MANDIR)/man1 cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 + mkdir -p $(DESTDIR)$(PREFIX)/share/wayland-sessions + cp -f dwl.desktop $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 + rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop .SUFFIXES: .c .o .c.o: diff --git a/dwl.desktop b/dwl.desktop new file mode 100644 index 0000000..e1380f7 --- /dev/null +++ b/dwl.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=dwl +Comment=dwm for Wayland +Exec=dwl +Type=Application From 5baf195523934519d7659ae34ad287ca60a5654c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 24 Sep 2023 11:24:39 -0600 Subject: [PATCH 12/12] allow specify DATADIR (to install desktop file) --- Makefile | 8 ++++---- config.mk | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 09c2c53..ff6e518 100644 --- a/Makefile +++ b/Makefile @@ -52,11 +52,11 @@ install: dwl mkdir -p $(DESTDIR)$(MANDIR)/man1 cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 - mkdir -p $(DESTDIR)$(PREFIX)/share/wayland-sessions - cp -f dwl.desktop $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop - chmod 644 $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop + mkdir -p $(DESTDIR)$(DATADIR)/wayland-sessions + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 $(DESTDIR)$(PREFIX)/share/wayland-sessions/dwl.desktop + rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop .SUFFIXES: .c .o .c.o: diff --git a/config.mk b/config.mk index f50156f..4bc9b9d 100644 --- a/config.mk +++ b/config.mk @@ -6,6 +6,7 @@ PKG_CONFIG = pkg-config # paths PREFIX = /usr/local MANDIR = $(PREFIX)/share/man +DATADIR = $(PREFIX)/share XWAYLAND = XLIBS =