From 3868217466a2264f2645b5f63c74d0ae1a28acd6 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Sun, 7 Feb 2021 00:31:01 -0600 Subject: [PATCH 01/47] Added interface to output information about tags, the currently selected monitor, and the focused client to a file for use by a status bar --- dwl.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/dwl.c b/dwl.c index 5b5e35e..8e43829 100644 --- a/dwl.c +++ b/dwl.c @@ -280,6 +280,7 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); +static void statusbar(void); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); @@ -1116,6 +1117,7 @@ focusclient(Client *c, int lift) wl_list_insert(&fstack, &c->flink); selmon = c->mon; } + statusbar(); /* Deactivate old client if focus is changing */ if (old && (!c || client_surface(c) != old)) { @@ -1914,6 +1916,7 @@ setlayout(const Arg *arg) selmon->lt[selmon->sellt] = (Layout *)arg->v; /* TODO change layout symbol? */ arrange(selmon); + statusbar(); } /* arg > 1.0 will set mfact absolutely */ @@ -2155,6 +2158,39 @@ spawn(const Arg *arg) } } +void +statusbar(void) +{ + Monitor *m = NULL; + Client *c = NULL; + FILE *taginfo; + const char *title; + char fname[30]=""; + unsigned int activetags; + + //Add WAYLAND_DISPLAY to filename so each session has a predictable file + snprintf(fname, 30, "/tmp/dwltags-%s", getenv("WAYLAND_DISPLAY")); + + if (!(taginfo = fopen(fname, "w"))) + return; + + wl_list_for_each(m, &mons, link) { + activetags=0; + wl_list_for_each(c, &clients, link) { + if (c->mon == m) + activetags |= c->tags; + } + if (focustop(m)) + fprintf(taginfo, "%s\n", client_get_title(focustop(m))); + else + fprintf(taginfo, "\n"); + + fprintf(taginfo, "%u %u %u %s\n", m == selmon, + activetags, m->tagset[m->seltags], selmon->lt[selmon->sellt]->symbol); + } + fclose (taginfo); +} + void tag(const Arg *arg) { From 27598bd04a17f78d3a3fb27d61fe72ffd9ae1f32 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Sun, 7 Feb 2021 01:03:04 -0600 Subject: [PATCH 02/47] added statusbar update when tags are updated --- dwl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwl.c b/dwl.c index 8e43829..7e9a2fd 100644 --- a/dwl.c +++ b/dwl.c @@ -2200,6 +2200,7 @@ tag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } + statusbar(); } void @@ -2269,6 +2270,7 @@ toggletag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } + statusbar(); } void @@ -2281,6 +2283,7 @@ toggleview(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } + statusbar(); } void @@ -2361,6 +2364,7 @@ view(const Arg *arg) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; focusclient(focustop(selmon), 1); arrange(selmon); + statusbar(); } void From a1e24075d81924926e5be4844e4e6faa8e0d744e Mon Sep 17 00:00:00 2001 From: David Donahue Date: Mon, 8 Feb 2021 18:12:24 -0600 Subject: [PATCH 03/47] Removed unused variable from statusbar --- dwl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dwl.c b/dwl.c index 7e9a2fd..534c7ac 100644 --- a/dwl.c +++ b/dwl.c @@ -2164,7 +2164,6 @@ statusbar(void) Monitor *m = NULL; Client *c = NULL; FILE *taginfo; - const char *title; char fname[30]=""; unsigned int activetags; From 3e82fad9c4c8bcc1712bfe83e37280c8ef498e0b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 14 Feb 2021 12:43:10 -0600 Subject: [PATCH 04/47] fix style on space-indented function --- dwl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index 5b5e35e..72f1046 100644 --- a/dwl.c +++ b/dwl.c @@ -2411,11 +2411,11 @@ zoom(const Arg *arg) void activatex11(struct wl_listener *listener, void *data) { - Client *c = wl_container_of(listener, c, activate); + Client *c = wl_container_of(listener, c, activate); - /* Only "managed" windows can be activated */ - if (c->type == X11Managed) - wlr_xwayland_surface_activate(c->surface.xwayland, 1); + /* Only "managed" windows can be activated */ + if (c->type == X11Managed) + wlr_xwayland_surface_activate(c->surface.xwayland, 1); } void From 8ed88822ca4448b06c2d7e6155d8022152b78017 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:08:58 -0600 Subject: [PATCH 05/47] Revert "remove EGL parameter from backend_autocreate" This reverts commit 0ff13cf216056a36a261f4eed53c6a864989a9fb. --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 72f1046..6803594 100644 --- a/dwl.c +++ b/dwl.c @@ -1995,7 +1995,7 @@ setup(void) * backend uses the renderer, for example, to fall back to software cursors * if the backend does not support hardware cursors (some older GPUs * don't). */ - if (!(backend = wlr_backend_autocreate(dpy))) + if (!(backend = wlr_backend_autocreate(dpy, NULL))) BARF("couldn't create backend"); /* If we don't provide a renderer, autocreate makes a GLES2 renderer for us. From a11f2bbc7a4068321767bd7e8c7eee1aee278bc9 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:09:00 -0600 Subject: [PATCH 06/47] Revert "fix undeclared WLR_KEY_PRESSED" This reverts commit 67896e9d8b98f679faf4456e26e82057c1884789. --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 6803594..4098f86 100644 --- a/dwl.c +++ b/dwl.c @@ -1284,7 +1284,7 @@ keypress(struct wl_listener *listener, void *data) wlr_idle_notify_activity(idle, seat); /* On _press_, attempt to process a compositor keybinding. */ - if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) + if (event->state == WLR_KEY_PRESSED) for (i = 0; i < nsyms; i++) handled = keybinding(mods, syms[i]) || handled; From ed8e80d9613599770ed2b11a3bc1d0057c075510 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:11:30 -0600 Subject: [PATCH 07/47] Revert "document that we currently follow wlroots-git" This reverts commit 9677f99dc3d5cb93ee6797609fd358fdfd3b3a3a. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2777613..f504672 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Feature *non-goals* include: ## Building dwl -dwl has only two dependencies: wlroots-git and wayland-protocols. Simply install these and run `make`. +dwl has only two dependencies: wlroots 0.12 and wayland-protocols. Simply install these and run `make`. To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From 47984509443e9be8776e96b9b21e81d5305d68a6 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:13:47 -0600 Subject: [PATCH 08/47] Revert "Revert "document that we currently follow wlroots-git"" This reverts commit ed8e80d9613599770ed2b11a3bc1d0057c075510. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f504672..2777613 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Feature *non-goals* include: ## Building dwl -dwl has only two dependencies: wlroots 0.12 and wayland-protocols. Simply install these and run `make`. +dwl has only two dependencies: wlroots-git and wayland-protocols. Simply install these and run `make`. To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From e8192b4fc920cba6c272a48fa86ca51bfd73f101 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:13:48 -0600 Subject: [PATCH 09/47] Revert "Revert "fix undeclared WLR_KEY_PRESSED"" This reverts commit a11f2bbc7a4068321767bd7e8c7eee1aee278bc9. --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 4098f86..6803594 100644 --- a/dwl.c +++ b/dwl.c @@ -1284,7 +1284,7 @@ keypress(struct wl_listener *listener, void *data) wlr_idle_notify_activity(idle, seat); /* On _press_, attempt to process a compositor keybinding. */ - if (event->state == WLR_KEY_PRESSED) + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) for (i = 0; i < nsyms; i++) handled = keybinding(mods, syms[i]) || handled; From c1eb2b49cdc7d85fb52c877ce47cd2a677cf3d5c Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:13:49 -0600 Subject: [PATCH 10/47] Revert "Revert "remove EGL parameter from backend_autocreate"" This reverts commit 8ed88822ca4448b06c2d7e6155d8022152b78017. --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 6803594..72f1046 100644 --- a/dwl.c +++ b/dwl.c @@ -1995,7 +1995,7 @@ setup(void) * backend uses the renderer, for example, to fall back to software cursors * if the backend does not support hardware cursors (some older GPUs * don't). */ - if (!(backend = wlr_backend_autocreate(dpy, NULL))) + if (!(backend = wlr_backend_autocreate(dpy))) BARF("couldn't create backend"); /* If we don't provide a renderer, autocreate makes a GLES2 renderer for us. From 9f90011ea28a4b0fde87c4478a793f9da8b71ea6 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 16 Feb 2021 13:20:42 -0600 Subject: [PATCH 11/47] add note about wlroots-next branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f504672..92c6221 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Feature *non-goals* include: ## Building dwl -dwl has only two dependencies: wlroots 0.12 and wayland-protocols. Simply install these and run `make`. +dwl has only two dependencies: wlroots 0.12 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From 87b16e6095379ce0e0a44c73926d5cbaf9a269d9 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 1 Mar 2021 11:17:10 -0600 Subject: [PATCH 12/47] Defaults should match dwm/Xorg default behavior --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 4aefa2b..ceb5b34 100644 --- a/config.def.h +++ b/config.def.h @@ -49,7 +49,7 @@ static const int repeat_delay = 600; /* Trackpad */ static const int tap_to_click = 1; -static const int natural_scrolling = 1; +static const int natural_scrolling = 0; #define MODKEY WLR_MODIFIER_ALT #define TAGKEYS(KEY,SKEY,TAG) \ From 2d71c9b9ff19d76ed3e78f67ed84d4ae03edd99d Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 1 Mar 2021 11:21:15 -0600 Subject: [PATCH 13/47] Add default menu command dwm config parity --- config.def.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index ceb5b34..f287384 100644 --- a/config.def.h +++ b/config.def.h @@ -62,11 +62,13 @@ static const int natural_scrolling = 0; #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ -static const char *termcmd[] = { "alacritty", NULL }; +static const char *termcmd[] = { "alacritty", NULL }; +static const char *menucmd[] = { "bemenu-run", NULL }; static const Key keys[] = { /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ /* modifier key function argument */ + { MODKEY, XKB_p, spawn, {.v = menucmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, From 02eed717ca912f126c1bbabc0a8a7fa19a197f3c Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 1 Mar 2021 11:22:08 -0600 Subject: [PATCH 14/47] add explanatory command about Ctrl-Alt-Bksp/Fx --- config.def.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.def.h b/config.def.h index f287384..9384ef6 100644 --- a/config.def.h +++ b/config.def.h @@ -101,6 +101,8 @@ static const Key keys[] = { TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + + /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, #define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), From fd498e1910d51def032d2b68f52cd89db7ba15f6 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 1 Mar 2021 11:25:28 -0600 Subject: [PATCH 15/47] clarify a bit about status bars --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92c6221..7fe130d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ dwl is a compact, hackable compositor for Wayland based on [wlroots](https://git dwl is not meant to provide every feature under the sun. Instead, like dwm, it sticks to features which are necessary, simple, and straightforward to implement given the base on which it is built. Implemented default features are: -- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. The built-in status bar is an exception to avoid taking a dependency on FreeType or Pango and increasing the SLOC +- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. Providing a built-in status bar is an exception to this goal, to avoid dependencies on font rendering and/or drawing libraries when an external bar could work well. - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support - Various Wayland protocols @@ -21,7 +21,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots -- Communication from the compositor to status bars. A straightforward possibility would be to use stdout or a provided file descriptor. +- Provide information to external status bars via stdout or another file descriptor - Implement the input-inhibitor protocol to support screen lockers - Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Layer shell popups (used by Waybar) From 593b7eec3c58f3a332669cdea49a103017cfadf1 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Mon, 1 Mar 2021 13:19:25 -0600 Subject: [PATCH 16/47] updated output format for better expansibility and easier parsing --- dwl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index 534c7ac..a5d2dba 100644 --- a/dwl.c +++ b/dwl.c @@ -2180,12 +2180,13 @@ statusbar(void) activetags |= c->tags; } if (focustop(m)) - fprintf(taginfo, "%s\n", client_get_title(focustop(m))); + fprintf(taginfo, "%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); else - fprintf(taginfo, "\n"); + fprintf(taginfo, "%s title \n", m->wlr_output->name); - fprintf(taginfo, "%u %u %u %s\n", m == selmon, - activetags, m->tagset[m->seltags], selmon->lt[selmon->sellt]->symbol); + fprintf(taginfo, "%s selmon %u\n", m->wlr_output->name, m == selmon); + fprintf(taginfo, "%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); + fprintf(taginfo, "%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); } fclose (taginfo); } From f5e7caac0029de10617eac1082a0e8bed27d41e3 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Mon, 1 Mar 2021 13:49:29 -0600 Subject: [PATCH 17/47] Changed output to stdout instead of a file --- dwl.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/dwl.c b/dwl.c index a5d2dba..8193b2c 100644 --- a/dwl.c +++ b/dwl.c @@ -2163,16 +2163,8 @@ statusbar(void) { Monitor *m = NULL; Client *c = NULL; - FILE *taginfo; - char fname[30]=""; unsigned int activetags; - //Add WAYLAND_DISPLAY to filename so each session has a predictable file - snprintf(fname, 30, "/tmp/dwltags-%s", getenv("WAYLAND_DISPLAY")); - - if (!(taginfo = fopen(fname, "w"))) - return; - wl_list_for_each(m, &mons, link) { activetags=0; wl_list_for_each(c, &clients, link) { @@ -2180,15 +2172,15 @@ statusbar(void) activetags |= c->tags; } if (focustop(m)) - fprintf(taginfo, "%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); + fprintf(stdout, "%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); else - fprintf(taginfo, "%s title \n", m->wlr_output->name); + fprintf(stdout, "%s title \n", m->wlr_output->name); - fprintf(taginfo, "%s selmon %u\n", m->wlr_output->name, m == selmon); - fprintf(taginfo, "%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); - fprintf(taginfo, "%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); + fprintf(stdout, "%s selmon %u\n", m->wlr_output->name, m == selmon); + fprintf(stdout, "%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); + fprintf(stdout, "%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); } - fclose (taginfo); + fflush(stdout); } void From 5b51bb82e234010aea5b72aa97d8679928efe259 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Mon, 1 Mar 2021 14:38:00 -0600 Subject: [PATCH 18/47] Fixed tab formatting in 6 locations where statusbar() is called --- dwl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dwl.c b/dwl.c index 8193b2c..b0b9ef1 100644 --- a/dwl.c +++ b/dwl.c @@ -1117,7 +1117,7 @@ focusclient(Client *c, int lift) wl_list_insert(&fstack, &c->flink); selmon = c->mon; } - statusbar(); + statusbar(); /* Deactivate old client if focus is changing */ if (old && (!c || client_surface(c) != old)) { @@ -1916,7 +1916,7 @@ setlayout(const Arg *arg) selmon->lt[selmon->sellt] = (Layout *)arg->v; /* TODO change layout symbol? */ arrange(selmon); - statusbar(); + statusbar(); } /* arg > 1.0 will set mfact absolutely */ @@ -2192,7 +2192,7 @@ tag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + statusbar(); } void @@ -2262,7 +2262,7 @@ toggletag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + statusbar(); } void @@ -2275,7 +2275,7 @@ toggleview(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + statusbar(); } void @@ -2356,7 +2356,7 @@ view(const Arg *arg) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; focusclient(focustop(selmon), 1); arrange(selmon); - statusbar(); + statusbar(); } void From 15f5d31f98565ef740c0aa70b01765c2e564501c Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 3 Mar 2021 11:29:53 -0600 Subject: [PATCH 19/47] correct key constant name Fixes #94. --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 9384ef6..089aa37 100644 --- a/config.def.h +++ b/config.def.h @@ -68,7 +68,7 @@ static const char *menucmd[] = { "bemenu-run", NULL }; static const Key keys[] = { /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ /* modifier key function argument */ - { MODKEY, XKB_p, spawn, {.v = menucmd} }, + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, From 7cee5060bc400bb0d81472e9c449cc1bc63b0409 Mon Sep 17 00:00:00 2001 From: David Donahue Date: Sat, 6 Mar 2021 12:20:56 -0600 Subject: [PATCH 20/47] added redirect from stdout to stderr for spawned processes to prevent conflicts with the statusbar outputs --- dwl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dwl.c b/dwl.c index b0b9ef1..f3018da 100644 --- a/dwl.c +++ b/dwl.c @@ -1846,6 +1846,7 @@ run(char *startup_cmd) if (startup_pid < 0) EBARF("startup: fork"); if (startup_pid == 0) { + dup2(STDERR_FILENO, STDOUT_FILENO); execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); EBARF("startup: execl"); } @@ -2152,6 +2153,7 @@ void spawn(const Arg *arg) { if (fork() == 0) { + dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]); From 1fa72b07728ebb396a9f236921b81c369bb12ccb Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 10 Mar 2021 09:50:09 -0600 Subject: [PATCH 21/47] remove sigchld function Explicitly setting the handler for SIGCHLD to SIG_IGN tells the OS to reap zombie processes automatically, which is what we wanted anyway. --- dwl.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/dwl.c b/dwl.c index 4098f86..0853f1e 100644 --- a/dwl.c +++ b/dwl.c @@ -278,7 +278,6 @@ static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); -static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -1984,8 +1983,9 @@ setup(void) * clients from the Unix socket, manging Wayland globals, and so on. */ dpy = wl_display_create(); - /* clean up child processes immediately */ - sigchld(0); + /* Indicate explicitly to the OS that we are not interested in info + * about child processes (per POSIX.1-2001) */ + signal(SIGCHLD, SIG_IGN); /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable @@ -2136,15 +2136,6 @@ setup(void) #endif } -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - EBARF("can't install SIGCHLD handler"); - while (0 < waitpid(-1, NULL, WNOHANG)) - ; -} - void spawn(const Arg *arg) { From 43b6e804cf4d0e850db72a8a53b8b36130b21435 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 13 Mar 2021 10:42:33 -0600 Subject: [PATCH 22/47] Revert "remove sigchld function" This reverts commit 1fa72b07728ebb396a9f236921b81c369bb12ccb. Fixes #97. --- dwl.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/dwl.c b/dwl.c index 0853f1e..2f9cc29 100644 --- a/dwl.c +++ b/dwl.c @@ -278,6 +278,7 @@ static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); +static void sigchld(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -1983,9 +1984,8 @@ setup(void) * clients from the Unix socket, manging Wayland globals, and so on. */ dpy = wl_display_create(); - /* Indicate explicitly to the OS that we are not interested in info - * about child processes (per POSIX.1-2001) */ - signal(SIGCHLD, SIG_IGN); + /* clean up child processes immediately */ + sigchld(0); /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable @@ -2136,6 +2136,20 @@ setup(void) #endif } +void +sigchld(int unused) +{ + /* We should be able to remove this function in favor of a simple + * signal(SIGCHLD, SIG_IGN); + * but the Xwayland implementation in wlroots currently prevents us from + * setting our own disposition for SIGCHLD. + */ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + EBARF("can't install SIGCHLD handler"); + while (0 < waitpid(-1, NULL, WNOHANG)) + ; +} + void spawn(const Arg *arg) { From ecc60878b3739bf15fb5affbc6c35b500aa41f4c Mon Sep 17 00:00:00 2001 From: David Donahue Date: Sat, 13 Mar 2021 11:20:33 -0600 Subject: [PATCH 23/47] changed fprintf(stdout) instances to printf(), changed function name from statusbar to printstatus --- dwl.c | 64 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/dwl.c b/dwl.c index f3018da..e18f807 100644 --- a/dwl.c +++ b/dwl.c @@ -260,6 +260,7 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int static void outputmgrtest(struct wl_listener *listener, void *data); static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, uint32_t time); +static void printstatus(void); static void quit(const Arg *arg); static void render(struct wlr_surface *surface, int sx, int sy, void *data); static void renderclients(Monitor *m, struct timespec *now); @@ -280,7 +281,6 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setup(void); static void sigchld(int unused); static void spawn(const Arg *arg); -static void statusbar(void); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); @@ -1117,7 +1117,7 @@ focusclient(Client *c, int lift) wl_list_insert(&fstack, &c->flink); selmon = c->mon; } - statusbar(); + printstatus(); /* Deactivate old client if focus is changing */ if (old && (!c || client_surface(c) != old)) { @@ -1604,6 +1604,31 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, focusclient(c, 0); } +void +printstatus(void) +{ + Monitor *m = NULL; + Client *c = NULL; + unsigned int activetags; + + wl_list_for_each(m, &mons, link) { + activetags=0; + wl_list_for_each(c, &clients, link) { + if (c->mon == m) + activetags |= c->tags; + } + if (focustop(m)) + printf("%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); + else + printf("%s title \n", m->wlr_output->name); + + printf("%s selmon %u\n", m->wlr_output->name, m == selmon); + printf("%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); + printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); + } + fflush(stdout); +} + void quit(const Arg *arg) { @@ -1917,7 +1942,7 @@ setlayout(const Arg *arg) selmon->lt[selmon->sellt] = (Layout *)arg->v; /* TODO change layout symbol? */ arrange(selmon); - statusbar(); + printstatus(); } /* arg > 1.0 will set mfact absolutely */ @@ -2160,31 +2185,6 @@ spawn(const Arg *arg) } } -void -statusbar(void) -{ - Monitor *m = NULL; - Client *c = NULL; - unsigned int activetags; - - wl_list_for_each(m, &mons, link) { - activetags=0; - wl_list_for_each(c, &clients, link) { - if (c->mon == m) - activetags |= c->tags; - } - if (focustop(m)) - fprintf(stdout, "%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); - else - fprintf(stdout, "%s title \n", m->wlr_output->name); - - fprintf(stdout, "%s selmon %u\n", m->wlr_output->name, m == selmon); - fprintf(stdout, "%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); - fprintf(stdout, "%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); - } - fflush(stdout); -} - void tag(const Arg *arg) { @@ -2194,7 +2194,7 @@ tag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + printstatus(); } void @@ -2264,7 +2264,7 @@ toggletag(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + printstatus(); } void @@ -2277,7 +2277,7 @@ toggleview(const Arg *arg) focusclient(focustop(selmon), 1); arrange(selmon); } - statusbar(); + printstatus(); } void @@ -2358,7 +2358,7 @@ view(const Arg *arg) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; focusclient(focustop(selmon), 1); arrange(selmon); - statusbar(); + printstatus(); } void From 38ba6d2277cb521c1366c99f4845659e7b5ba451 Mon Sep 17 00:00:00 2001 From: Stivvo Date: Thu, 25 Mar 2021 10:05:12 -0500 Subject: [PATCH 24/47] Fullscreen: simplifications and fixes Merges #69. --- dwl.c | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/dwl.c b/dwl.c index e807330..ead6ec2 100644 --- a/dwl.c +++ b/dwl.c @@ -175,7 +175,6 @@ struct Monitor { unsigned int tagset[2]; double mfact; int nmaster; - Client *fullscreenclient; }; typedef struct { @@ -249,7 +248,6 @@ static void keypressmod(struct wl_listener *listener, void *data); static void killclient(const Arg *arg); static void maplayersurfacenotify(struct wl_listener *listener, void *data); static void mapnotify(struct wl_listener *listener, void *data); -static void maximizeclient(Client *c); static void monocle(Monitor *m); static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time); @@ -485,8 +483,6 @@ arrange(Monitor *m) { if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); - else if (m->fullscreenclient) - maximizeclient(m->fullscreenclient); /* TODO recheck pointer focus here... or in resize()? */ } @@ -885,9 +881,6 @@ createnotify(struct wl_listener *listener, void *data) if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) return; - wl_list_for_each(c, &clients, link) - if (c->isfullscreen && VISIBLEON(c, c->mon)) - setfullscreen(c, 0); /* Allocate a Client for this surface */ c = xdg_surface->data = calloc(1, sizeof(*c)); @@ -1042,14 +1035,8 @@ void togglefullscreen(const Arg *arg) { Client *sel = selclient(); - setfullscreen(sel, !sel->isfullscreen); -} - -void -maximizeclient(Client *c) -{ - resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); - /* used for fullscreen clients */ + if (sel) + setfullscreen(sel, !sel->isfullscreen); } void @@ -1064,13 +1051,11 @@ setfullscreen(Client *c, int fullscreen) c->prevy = c->geom.y; c->prevheight = c->geom.height; c->prevwidth = c->geom.width; - c->mon->fullscreenclient = c; - maximizeclient(c); + resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); } else { /* restore previous size instead of arrange for floating windows since * client positions are set by the user and cannot be recalculated */ resize(c, c->prevx, c->prevy, c->prevwidth, c->prevheight, 0); - c->mon->fullscreenclient = NULL; arrange(c->mon); } } @@ -1337,7 +1322,7 @@ void mapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ - Client *c = wl_container_of(listener, c, map), *oldfocus = selclient(); + Client *c = wl_container_of(listener, c, map); if (client_is_unmanaged(c)) { /* Insert this independent into independents lists. */ @@ -1356,14 +1341,6 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - - if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus - && !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) { - maximizeclient(c->mon->fullscreenclient); - focusclient(c->mon->fullscreenclient, 1); - /* give the focus back the fullscreen client on that monitor if exists, - * is focused and the new client isn't floating */ - } } void @@ -1372,12 +1349,9 @@ monocle(Monitor *m) Client *c; wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating) + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) continue; - if (c->isfullscreen) - maximizeclient(c); - else - resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0); + resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0); } } @@ -2229,11 +2203,9 @@ tile(Monitor *m) mw = m->w.width; i = my = ty = 0; wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || c->isfloating) + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) continue; - if (c->isfullscreen) - maximizeclient(c); - else if (i < m->nmaster) { + if (i < m->nmaster) { h = (m->w.height - my) / (MIN(n, m->nmaster) - i); resize(c, m->w.x, m->w.y + my, mw, h, 0); my += c->geom.height; From db647f2df63c35270f23a970f29a8f155466d9ea Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 29 Mar 2021 17:04:37 -0500 Subject: [PATCH 25/47] fix labels on issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/enhancement-idea.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2a18c75..9b9eef4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Something in dwl isn't working correctly title: '' -labels: 'Type: bug' +labels: 'A: bug' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/enhancement-idea.md b/.github/ISSUE_TEMPLATE/enhancement-idea.md index 92c6c8c..0ac096d 100644 --- a/.github/ISSUE_TEMPLATE/enhancement-idea.md +++ b/.github/ISSUE_TEMPLATE/enhancement-idea.md @@ -2,7 +2,7 @@ name: Enhancement idea about: Suggest a feature or improvement title: '' -labels: 'Type: enhancement' +labels: 'A: enhancement' assignees: '' --- From 3c83e0cfb8cfb20cab2775b8da0925fb26a35678 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 30 Mar 2021 13:56:04 -0500 Subject: [PATCH 26/47] don't move/resize if already moving/resizing Fixes #102. The "ideal" behavior might be to ignore buttons other than the one being used for the action, but this is super-simple and still seems reasonable. --- dwl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index ead6ec2..54cfcfe 100644 --- a/dwl.c +++ b/dwl.c @@ -1454,8 +1454,7 @@ motionrelative(struct wl_listener *listener, void *data) void moveresize(const Arg *arg) { - grabc = xytoclient(cursor->x, cursor->y); - if (!grabc) + if (cursor_mode != CurNormal || !(grabc = xytoclient(cursor->x, cursor->y))) return; /* Float the window and tell motionnotify to grab it */ From 3a72cd924c45d4bc01f4d8477c14fdf2854f2dd0 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 8 Apr 2021 07:11:13 -0500 Subject: [PATCH 27/47] fix README for main branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 260280a..22dfa07 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Feature *non-goals* include: ## Building dwl -dwl has only two dependencies: wlroots-git and wayland-protocols. Simply install these and run `make`. +dwl has only two dependencies: wlroots 0.13 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From 84b26ef1bae83cdf0f305d2c81d345c8ef73d0d0 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 8 Apr 2021 07:12:50 -0500 Subject: [PATCH 28/47] Revert "fix README for main branch" This reverts commit 3a72cd924c45d4bc01f4d8477c14fdf2854f2dd0. There is probably an easier way to keep this difference, but hey, this works for me. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22dfa07..260280a 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Feature *non-goals* include: ## Building dwl -dwl has only two dependencies: wlroots 0.13 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). +dwl has only two dependencies: wlroots-git and wayland-protocols. Simply install these and run `make`. To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From 9071ce6c848ce214939fb84f85ae77de86de88d7 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 9 Apr 2021 12:37:49 -0500 Subject: [PATCH 29/47] nuke CSDs, hopefully for good! --- dwl.c | 45 ++++++--------------------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/dwl.c b/dwl.c index 0deae84..d463985 100644 --- a/dwl.c +++ b/dwl.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -228,18 +229,15 @@ static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); static void createlayersurface(struct wl_listener *listener, void *data); static void createpointer(struct wlr_input_device *device); -static void createxdeco(struct wl_listener *listener, void *data); static void cursorframe(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); -static void destroyxdeco(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static void fullscreennotify(struct wl_listener *listener, void *data); static Client *focustop(Monitor *m); -static void getxdecomode(struct wl_listener *listener, void *data); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); static int keybinding(uint32_t mods, xkb_keysym_t sym); @@ -312,7 +310,6 @@ static struct wl_list stack; /* stacking z-order */ static struct wl_list independents; static struct wlr_idle *idle; static struct wlr_layer_shell_v1 *layer_shell; -static struct wlr_xdg_decoration_manager_v1 *xdeco_mgr; static struct wlr_output_manager_v1 *output_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; @@ -344,7 +341,6 @@ static struct wl_listener layout_change = {.notify = updatemons}; static struct wl_listener new_input = {.notify = inputdevice}; static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; static struct wl_listener new_output = {.notify = createmon}; -static struct wl_listener new_xdeco = {.notify = createxdeco}; static struct wl_listener new_xdg_surface = {.notify = createnotify}; static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface}; static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; @@ -958,18 +954,6 @@ createpointer(struct wlr_input_device *device) wlr_cursor_attach_input_device(cursor, device); } -void -createxdeco(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; - Decoration *d = wlr_deco->data = calloc(1, sizeof(*d)); - - LISTEN(&wlr_deco->events.request_mode, &d->request_mode, getxdecomode); - LISTEN(&wlr_deco->events.destroy, &d->destroy, destroyxdeco); - - getxdecomode(&d->request_mode, wlr_deco); -} - void cursorframe(struct wl_listener *listener, void *data) { @@ -1020,17 +1004,6 @@ destroynotify(struct wl_listener *listener, void *data) free(c); } -void -destroyxdeco(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; - Decoration *d = wlr_deco->data; - - wl_list_remove(&d->destroy.link); - wl_list_remove(&d->request_mode.link); - free(d); -} - void togglefullscreen(const Arg *arg) { @@ -1185,14 +1158,6 @@ focustop(Monitor *m) return NULL; } -void -getxdecomode(struct wl_listener *listener, void *data) -{ - struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; - wlr_xdg_toplevel_decoration_v1_set_mode(wlr_deco, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); -} - void incnmaster(const Arg *arg) { @@ -2051,9 +2016,11 @@ setup(void) xdg_shell = wlr_xdg_shell_create(dpy); wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface); - /* Use xdg_decoration protocol to negotiate server-side decorations */ - xdeco_mgr = wlr_xdg_decoration_manager_v1_create(dpy); - wl_signal_add(&xdeco_mgr->events.new_toplevel_decoration, &new_xdeco); + /* Use decoration protocols to negotiate server-side decorations */ + wlr_server_decoration_manager_set_default_mode( + wlr_server_decoration_manager_create(dpy), + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + wlr_xdg_decoration_manager_v1_create(dpy); /* * Creates a cursor, which is a wlroots utility for tracking the cursor From b372d4b55e256b96fe926c512499ed90c460d66f Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 14 Apr 2021 11:15:26 -0500 Subject: [PATCH 30/47] pipe status info into -s command Unlike with X window managers, the display socket in Wayland isn't set up prior to starting the compositor. Because of this, you can't pipe the compositor's output directly into a program which needs access to $WAYLAND_DISPLAY, which is a typical setup for this purpose. Existing scripts have been forced to create a pipe/FIFO or a temporary file as an intermediary. Instead, send the status info directly to stdin of the -s command, which *does* have access to $WAYLAND_DISPLAY. Fixes #103. --- dwl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index d463985..f4b9b3a 100644 --- a/dwl.c +++ b/dwl.c @@ -1805,15 +1805,22 @@ run(char *startup_cmd) setenv("WAYLAND_DISPLAY", socket, 1); if (startup_cmd) { + int piperw[2]; + pipe(piperw); startup_pid = fork(); if (startup_pid < 0) EBARF("startup: fork"); if (startup_pid == 0) { - dup2(STDERR_FILENO, STDOUT_FILENO); + dup2(piperw[0], STDIN_FILENO); + close(piperw[1]); execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL); EBARF("startup: execl"); } + dup2(piperw[1], STDOUT_FILENO); + close(piperw[0]); } + /* If nobody is reading the status output, don't terminate */ + signal(SIGPIPE, SIG_IGN); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event From 6a0dec69ec47ed8143f13016e629e5502d6339a2 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Apr 2021 13:03:21 -0500 Subject: [PATCH 31/47] re-compile if config.mk changes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a0d1cc3..1362db8 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ idle-protocol.o: idle-protocol.h config.h: | config.def.h cp config.def.h $@ -dwl.o: config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h +dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o From 4170a90fbccb5823f536d7b77c2ba40e5358002b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Apr 2021 13:04:31 -0500 Subject: [PATCH 32/47] group phony targets together in Makefile --- Makefile | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 1362db8..fe6ff04 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,14 @@ LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p))) all: dwl +clean: + rm -f dwl *.o *-protocol.h *-protocol.c + +install: dwl + install -D dwl $(PREFIX)/bin/dwl + +.PHONY: all clean install + # wayland-scanner is a tool which generates C headers and rigging for Wayland # protocols, which are specified in XML. wlroots requires you to rig these up # to your build system yourself and provide them in the include path. @@ -50,12 +58,3 @@ config.h: | config.def.h dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o - -clean: - rm -f dwl *.o *-protocol.h *-protocol.c - -install: dwl - install -D dwl $(PREFIX)/bin/dwl - -.DEFAULT_GOAL=dwl -.PHONY: clean From 3727f4a7b3d230226f0082581444344d563e0f9c Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Apr 2021 13:05:05 -0500 Subject: [PATCH 33/47] update status info if focused client changes title Fixes #108. --- dwl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dwl.c b/dwl.c index d463985..c5308f5 100644 --- a/dwl.c +++ b/dwl.c @@ -96,6 +96,7 @@ typedef struct { struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; + struct wl_listener set_title; struct wl_listener fullscreen; struct wlr_box geom; /* layout-relative, includes border */ Monitor *mon; @@ -288,6 +289,7 @@ static void unmaplayersurface(LayerSurface *layersurface); static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); static void updatemons(struct wl_listener *listener, void *data); +static void updatetitle(struct wl_listener *listener, void *data); static void view(const Arg *arg); static void virtualkeyboard(struct wl_listener *listener, void *data); static Client *xytoclient(double x, double y); @@ -891,6 +893,7 @@ createnotify(struct wl_listener *listener, void *data) LISTEN(&xdg_surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify); LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify); + LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle); LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify); c->isfullscreen = 0; @@ -994,6 +997,7 @@ destroynotify(struct wl_listener *listener, void *data) wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); wl_list_remove(&c->destroy.link); + wl_list_remove(&c->set_title.link); wl_list_remove(&c->fullscreen.link); #ifdef XWAYLAND if (c->type == X11Managed) @@ -2291,6 +2295,14 @@ updatemons(struct wl_listener *listener, void *data) wlr_output_manager_v1_set_configuration(output_mgr, config); } +void +updatetitle(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) + printstatus(); +} + void view(const Arg *arg) { @@ -2427,6 +2439,7 @@ createnotifyx11(struct wl_listener *listener, void *data) activatex11); LISTEN(&xwayland_surface->events.request_configure, &c->configure, configurex11); + LISTEN(&xwayland_surface->events.set_title, &c->set_title, updatetitle); LISTEN(&xwayland_surface->events.destroy, &c->destroy, destroynotify); LISTEN(&xwayland_surface->events.request_fullscreen, &c->fullscreen, fullscreennotify); From d57db4cac927126d1d006becf5f2ed743ac21474 Mon Sep 17 00:00:00 2001 From: Jason Goulet-Lipman Date: Mon, 19 Apr 2021 09:05:35 -0400 Subject: [PATCH 34/47] added uninstall target --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fe6ff04..5ff69e9 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,10 @@ clean: install: dwl install -D dwl $(PREFIX)/bin/dwl -.PHONY: all clean install +uninstall: + rm -f $(PREFIX)/bin/dwl + +.PHONY: all clean install uninstall # wayland-scanner is a tool which generates C headers and rigging for Wayland # protocols, which are specified in XML. wlroots requires you to rig these up From 1b139a860dacbca8c4b3f8d24930b3f829534206 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 18 May 2021 11:33:12 -0500 Subject: [PATCH 35/47] update README --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 22dfa07..51aecf8 100644 --- a/README.md +++ b/README.md @@ -14,26 +14,27 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. Providing a built-in status bar is an exception to this goal, to avoid dependencies on font rendering and/or drawing libraries when an external bar could work well. - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support +- Provide information to external status bars via stdout/stdin - Various Wayland protocols -- XWayland support as provided by wlroots +- XWayland support as provided by wlroots (can be enabled in `config.mk`) - Zero flickering - Wayland users naturally expect that "every frame is perfect" Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots -- Provide information to external status bars via stdout or another file descriptor +- Implement urgent/focus-request once the xdg-activation protocol [hits wlroots](https://github.com/swaywm/wlroots/pull/2718) - Implement the input-inhibitor protocol to support screen lockers - Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Layer shell popups (used by Waybar) - Basic yes/no damage tracking to avoid needless redraws - More in-depth damage region tracking ([which may improve power usage](https://mozillagfx.wordpress.com/2019/10/22/dramatically-reduced-power-usage-in-firefox-70-on-macos-with-core-animation/)) - Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12) -- Implement urgent/attention/focus-request once it's part of the xdg-shell protocol (https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/9) -Feature *non-goals* include: +Feature *non-goals* for the main codebase include: - Client-side decoration (any more than is necessary to tell the clients not to) - Client-initiated window management, such as move, resize, and close, which can be done through the compositor +- Animations and visual effects ## Building dwl From 93a58abf2955aa01b7c148b85490d443ab017fb7 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 22 May 2021 14:22:37 -0500 Subject: [PATCH 36/47] Wait until map to set window's tiled state Workaround for a bug in Chromium where it fails to attach a buffer to the surface. Fixes #119. --- dwl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index d7e798b..30a64f8 100644 --- a/dwl.c +++ b/dwl.c @@ -885,10 +885,6 @@ createnotify(struct wl_listener *listener, void *data) c->surface.xdg = xdg_surface; c->bw = borderpx; - /* Tell the client not to try anything fancy */ - wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | - WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); - LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify); LISTEN(&xdg_surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify); @@ -1308,6 +1304,10 @@ mapnotify(struct wl_listener *listener, void *data) c->geom.width += 2 * c->bw; c->geom.height += 2 * c->bw; + /* Tell the client not to try anything fancy */ + wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | + WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + /* Set initial monitor, tags, floating status, and focus */ applyrules(c); } From d8cf65c74f3b7132302027cfbf940de8548d7d17 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 22 May 2021 21:18:48 -0500 Subject: [PATCH 37/47] implement urgency hint --- README.md | 2 +- dwl.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 51aecf8..dc75cef 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s - Configurable multi-monitor layout support, including position and rotation - Configurable HiDPI/multi-DPI support - Provide information to external status bars via stdout/stdin +- Urgency hints via xdg-activate protocol - Various Wayland protocols - XWayland support as provided by wlroots (can be enabled in `config.mk`) - Zero flickering - Wayland users naturally expect that "every frame is perfect" @@ -22,7 +23,6 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s Features under consideration (possibly as patches) are: - Protocols made trivial by wlroots -- Implement urgent/focus-request once the xdg-activation protocol [hits wlroots](https://github.com/swaywm/wlroots/pull/2718) - Implement the input-inhibitor protocol to support screen lockers - Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring - Layer shell popups (used by Waybar) diff --git a/dwl.c b/dwl.c index d7e798b..4d0bc84 100644 --- a/dwl.c +++ b/dwl.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,7 @@ typedef struct { #endif int bw; unsigned int tags; - int isfloating; + int isfloating, isurgent; uint32_t resize; /* configure serial of a pending resize */ int prevx; int prevy; @@ -290,6 +291,7 @@ static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); static void updatemons(struct wl_listener *listener, void *data); 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 Client *xytoclient(double x, double y); @@ -306,6 +308,7 @@ static struct wlr_renderer *drw; static struct wlr_compositor *compositor; static struct wlr_xdg_shell *xdg_shell; +static struct wlr_xdg_activation_v1 *activation; static struct wl_list clients; /* tiling order */ static struct wl_list fstack; /* focus order */ static struct wl_list stack; /* stacking z-order */ @@ -347,6 +350,7 @@ static struct wl_listener new_xdg_surface = {.notify = createnotify}; static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface}; static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; +static struct wl_listener request_activate = {.notify = urgent}; static struct wl_listener request_cursor = {.notify = setcursor}; static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_sel = {.notify = setsel}; @@ -1078,6 +1082,7 @@ focusclient(Client *c, int lift) wl_list_remove(&c->flink); wl_list_insert(&fstack, &c->flink); selmon = c->mon; + c->isurgent = 0; } printstatus(); @@ -1550,22 +1555,29 @@ void printstatus(void) { Monitor *m = NULL; - Client *c = NULL; - unsigned int activetags; + Client *c; + unsigned int occ, urg, sel; wl_list_for_each(m, &mons, link) { - activetags=0; + occ = urg = 0; wl_list_for_each(c, &clients, link) { - if (c->mon == m) - activetags |= c->tags; + if (c->mon != m) + continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; } - if (focustop(m)) + if ((c = focustop(m))) { printf("%s title %s\n", m->wlr_output->name, client_get_title(focustop(m))); - else + sel = c->tags; + } else { printf("%s title \n", m->wlr_output->name); + sel = 0; + } printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]); + printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags], + sel, urg); printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); } fflush(stdout); @@ -1825,6 +1837,7 @@ run(char *startup_cmd) } /* If nobody is reading the status output, don't terminate */ signal(SIGPIPE, SIG_IGN); + printstatus(); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event @@ -1997,6 +2010,10 @@ setup(void) wlr_primary_selection_v1_device_manager_create(dpy); wlr_viewporter_create(dpy); + /* Initializes the interface used to implement urgency hints */ + activation = wlr_xdg_activation_v1_create(dpy); + wl_signal_add(&activation->events.request_activate, &request_activate); + /* Creates an output layout, which a wlroots utility for working with an * arrangement of screens in a physical layout. */ output_layout = wlr_output_layout_create(); @@ -2310,6 +2327,21 @@ updatetitle(struct wl_listener *listener, void *data) printstatus(); } +void +urgent(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c; + + if (!wlr_surface_is_xdg_surface(event->surface)) + return; + c = wlr_xdg_surface_from_wlr_surface(event->surface)->data; + if (c != selclient()) { + c->isurgent = 1; + printstatus(); + } +} + void view(const Arg *arg) { From 9ab5e01d5b3864f151c222d001a8a2152f29b518 Mon Sep 17 00:00:00 2001 From: Sevz17 Date: Sun, 23 May 2021 11:24:32 -0500 Subject: [PATCH 38/47] before set tiled verify if client is xdg-shell, then set tile --- dwl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dwl.c b/dwl.c index 30a64f8..3a562b9 100644 --- a/dwl.c +++ b/dwl.c @@ -1304,9 +1304,17 @@ mapnotify(struct wl_listener *listener, void *data) c->geom.width += 2 * c->bw; c->geom.height += 2 * c->bw; +#ifdef XWAYLAND + if (c->type == XDGShell) { + /* Tell the client not to try anything fancy */ + wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | + WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); + } +#else /* Tell the client not to try anything fancy */ wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); +#endif /* Set initial monitor, tags, floating status, and focus */ applyrules(c); From 06ca86009296c1b8753cba259fd797703a281bbd Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 23 May 2021 18:28:13 -0500 Subject: [PATCH 39/47] factor xwayland hackiness out into client.h --- client.h | 11 +++++++++++ dwl.c | 11 +---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/client.h b/client.h index f4735c2..56e3089 100644 --- a/client.h +++ b/client.h @@ -141,6 +141,17 @@ client_set_size(Client *c, uint32_t width, uint32_t height) return wlr_xdg_toplevel_set_size(c->surface.xdg, width, height); } +static inline void +client_set_tiled(Client *c, uint32_t edges) +{ +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | + WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); +} + static inline struct wlr_surface * client_surface(Client *c) { diff --git a/dwl.c b/dwl.c index 3a562b9..9188f06 100644 --- a/dwl.c +++ b/dwl.c @@ -1304,17 +1304,8 @@ mapnotify(struct wl_listener *listener, void *data) c->geom.width += 2 * c->bw; c->geom.height += 2 * c->bw; -#ifdef XWAYLAND - if (c->type == XDGShell) { - /* Tell the client not to try anything fancy */ - wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | - WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); - } -#else /* Tell the client not to try anything fancy */ - wlr_xdg_toplevel_set_tiled(c->surface.xdg, WLR_EDGE_TOP | - WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); -#endif + client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); /* Set initial monitor, tags, floating status, and focus */ applyrules(c); From 60c40c0989440fc54aa05b0e27cfbaad8c722fec Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 24 May 2021 22:03:39 -0500 Subject: [PATCH 40/47] print status on output create Along with starting the -s command earlier, this will allow the initial monitor setup to generate printstatus info. --- dwl.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/dwl.c b/dwl.c index 9188f06..e0b404e 100644 --- a/dwl.c +++ b/dwl.c @@ -842,11 +842,13 @@ createmon(struct wl_listener *listener, void *data) LISTEN(&wlr_output->events.frame, &m->frame, rendermon); LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); - wl_list_insert(&mons, &m->link); wlr_output_enable(wlr_output, 1); if (!wlr_output_commit(wlr_output)) return; + wl_list_insert(&mons, &m->link); + printstatus(); + /* Adds this to the output layout in the order it was configured in. * * The output layout utility automatically adds a wl_output global to the @@ -1786,27 +1788,9 @@ run(char *startup_cmd) const char *socket = wl_display_add_socket_auto(dpy); if (!socket) BARF("startup: display_add_socket_auto"); - - /* Start the backend. This will enumerate outputs and inputs, become the DRM - * master, etc */ - if (!wlr_backend_start(backend)) - BARF("startup: backend_start"); - - /* Now that outputs are initialized, choose initial selmon based on - * cursor position, and set default cursor image */ - selmon = xytomon(cursor->x, cursor->y); - - /* TODO hack to get cursor to display in its initial location (100, 100) - * instead of (0, 0) and then jumping. still may not be fully - * initialized, as the image/coordinates are not transformed for the - * monitor when displayed here */ - wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); - wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); - - /* Set the WAYLAND_DISPLAY environment variable to our socket and run the - * startup command if requested. */ setenv("WAYLAND_DISPLAY", socket, 1); + /* Now that the socket exists, run the startup command */ if (startup_cmd) { int piperw[2]; pipe(piperw); @@ -1825,6 +1809,22 @@ run(char *startup_cmd) /* If nobody is reading the status output, don't terminate */ signal(SIGPIPE, SIG_IGN); + /* Start the backend. This will enumerate outputs and inputs, become the DRM + * master, etc */ + if (!wlr_backend_start(backend)) + BARF("startup: backend_start"); + + /* Now that outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ + selmon = xytomon(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully + * initialized, as the image/coordinates are not transformed for the + * monitor when displayed here */ + wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); + wlr_xcursor_manager_set_cursor_image(cursor_mgr, "left_ptr", cursor); + /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event * loop configuration to listen to libinput events, DRM events, generate From 823cefd2920085a0f74899fb679020005a1b6e0b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 25 May 2021 02:52:33 -0500 Subject: [PATCH 41/47] handle ephemeral pageflip failures If a transient failure occurs in wlr_output_commit, re-render until it doesn't happen. This could possibly be removed if we decide to implement damage tracking in the future. --- dwl.c | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/dwl.c b/dwl.c index e0b404e..a38f452 100644 --- a/dwl.c +++ b/dwl.c @@ -1726,38 +1726,42 @@ rendermon(struct wl_listener *listener, void *data) } } - /* wlr_output_attach_render makes the OpenGL context current. */ - if (!wlr_output_attach_render(m->wlr_output, NULL)) - return; + /* HACK: This loop is the simplest way to handle ephemeral pageflip + * failures but probably not the best. Revisit if damage tracking is + * added. */ + do { + /* wlr_output_attach_render makes the OpenGL context current. */ + if (!wlr_output_attach_render(m->wlr_output, NULL)) + return; - if (render) { - /* Begin the renderer (calls glViewport and some other GL sanity checks) */ - wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); - wlr_renderer_clear(drw, rootcolor); + if (render) { + /* Begin the renderer (calls glViewport and some other GL sanity checks) */ + wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); + wlr_renderer_clear(drw, rootcolor); - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); - renderclients(m, &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); + renderclients(m, &now); #ifdef XWAYLAND - renderindependents(m->wlr_output, &now); + renderindependents(m->wlr_output, &now); #endif - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); - /* Hardware cursors are rendered by the GPU on a separate plane, and can be - * moved around without re-rendering what's beneath them - which is more - * efficient. However, not all hardware supports hardware cursors. For this - * reason, wlroots provides a software fallback, which we ask it to render - * here. wlr_cursor handles configuring hardware vs software cursors for you, - * and this function is a no-op when hardware cursors are in use. */ - wlr_output_render_software_cursors(m->wlr_output, NULL); + /* Hardware cursors are rendered by the GPU on a separate plane, and can be + * moved around without re-rendering what's beneath them - which is more + * efficient. However, not all hardware supports hardware cursors. For this + * reason, wlroots provides a software fallback, which we ask it to render + * here. wlr_cursor handles configuring hardware vs software cursors for you, + * and this function is a no-op when hardware cursors are in use. */ + wlr_output_render_software_cursors(m->wlr_output, NULL); - /* Conclude rendering and swap the buffers, showing the final frame - * on-screen. */ - wlr_renderer_end(drw); - } + /* Conclude rendering and swap the buffers, showing the final frame + * on-screen. */ + wlr_renderer_end(drw); + } - wlr_output_commit(m->wlr_output); + } while (!wlr_output_commit(m->wlr_output)); } void From bd2f7fbb4082d947ec2738cd31d403e9f0c10f50 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 26 May 2021 23:30:49 -0500 Subject: [PATCH 42/47] exit cleanly on INT/TERM --- dwl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index a38f452..a8e1dcd 100644 --- a/dwl.c +++ b/dwl.c @@ -259,6 +259,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, uint32_t time); static void printstatus(void); static void quit(const Arg *arg); +static void quitsignal(int signo); static void render(struct wlr_surface *surface, int sx, int sy, void *data); static void renderclients(Monitor *m, struct timespec *now); static void renderlayer(struct wl_list *layer_surfaces, struct timespec *now); @@ -1578,6 +1579,12 @@ quit(const Arg *arg) wl_display_terminate(dpy); } +void +quitsignal(int signo) +{ + quit(NULL); +} + void render(struct wlr_surface *surface, int sx, int sy, void *data) { @@ -1965,8 +1972,10 @@ setup(void) * clients from the Unix socket, manging Wayland globals, and so on. */ dpy = wl_display_create(); - /* clean up child processes immediately */ + /* Set up signal handlers */ sigchld(0); + signal(SIGINT, quitsignal); + signal(SIGTERM, quitsignal); /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable From c6f96d5391b43268f05787c4171ddc5ed4cbf0b8 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 3 Jun 2021 01:41:10 -0500 Subject: [PATCH 43/47] mention `-devel` packages It seems like there are people trying dwl who aren't as familiar with how their distros do development, so let's give them a pointer in the right direction. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51aecf8..5041c1b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Feature *non-goals* for the main codebase include: ## Building dwl -dwl has only two dependencies: wlroots 0.13 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). +dwl has only two dependencies: wlroots and wayland-protocols. Simply install these (and their `-devel` versions if your distro has separate development packages) and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. From 3b05eadeaf5e2de4caf127cfa07642342cccddbc Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 30 Jun 2021 14:46:20 -0500 Subject: [PATCH 44/47] update notes about starting dwl Includes mention of video/input groups --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa9d1cc..5b3e4cb 100644 --- a/README.md +++ b/README.md @@ -50,14 +50,19 @@ As in the dwm community, we encourage users to share patches they have created. ## Running dwl -dwl can be run as-is, with no arguments. In an existing Wayland or X11 session, this will open a window to act as a virtual display. When run from a TTY, the Wayland server will take over the entire virtual terminal. Clients started by dwl will have `WAYLAND_DISPLAY` set in their environment, and other clients can be started from outside the session by setting this variable accordingly. +dwl can be run on any of the backends supported by wlroots. This means you can run it as a separate window inside either an X11 or Wayland session, as well as directly from a VT console. Depending on your distro's setup, you may need to add your user to the `video` and `input` groups before you can run dwl on a VT. -You can also specify a startup program using the `-s` option. The argument to this option will be run at startup as a shell command (using `sh -c`) and can serve a similar function to `.xinitrc`: starting a service manager or other startup applications. Unlike `.xinitrc`, the display server will not shut down when this process terminates. Instead, as dwl is shutting down, it will send this process a SIGTERM and wait for it to terminate (if it hasn't already). This makes it ideal not only for initialization but also for execing into a user-level service manager like s6 or `systemd --user`. +When dwl is run with no arguments, it will launch the server and begin handling any shortcuts configured in `config.h`. There is no status bar or other decoration initially; these are instead clients that can be run within the Wayland session. + +If you would like to run a script or command automatically at startup, you can specify the command using the `-s` option. The argument to this option will be parsed as a shell command (using `sh -c`) and can serve a similar function to `.xinitrc`. Unlike `.xinitrc`, the display server will not shut down when this process terminates. Instead, as dwl is shutting down, it will send this process a SIGTERM and wait for it to terminate (if it hasn't already). This makes it ideal for execing into a user service manager like [s6](https://skarnet.org/software/s6/), [anopa](https://jjacky.com/anopa/), [runit](http://smarden.org/runit/faq.html#userservices), or [`systemd --user`](https://wiki.archlinux.org/title/Systemd/User). + +Note: The `-s` command is run as a *child process* of dwl, which means that it does not have the ability to affect the environment of dwl or of any processes that it spawns. If you need to set environment variables that affect the entire dwl session (such as `XDG_RUNTIME_DIR` in the note below), these must be set prior to running dwl. Note: Wayland requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager such as `elogind` or `systemd-logind`. If your system doesn't do this automatically, you will need to configure it prior to launching `dwl`, e.g.: export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u) mkdir -p $XDG_RUNTIME_DIR + dwl ## Replacements for X applications From 52e6bf47354b624e220cbff6df33d06ba1c3581e Mon Sep 17 00:00:00 2001 From: David Donahue Date: Thu, 1 Jul 2021 15:20:30 -0500 Subject: [PATCH 45/47] Moved printstatus() call in focusclient() to prevent printstatus being called on every frame when things like dmenu are up --- dwl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index a2a0b69..9c31de2 100644 --- a/dwl.c +++ b/dwl.c @@ -1083,7 +1083,6 @@ focusclient(Client *c, int lift) selmon = c->mon; c->isurgent = 0; } - printstatus(); /* Deactivate old client if focus is changing */ if (old && (!c || client_surface(c) != old)) { @@ -1106,6 +1105,8 @@ focusclient(Client *c, int lift) } } + printstatus(); + if (!c) { /* With no client, all we have left is to clear focus */ wlr_seat_keyboard_notify_clear_focus(seat); From d175a58d733723fdeb307943b034fe7fda6086ed Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Mon, 2 Aug 2021 16:33:38 +0200 Subject: [PATCH 46/47] implement the presentation time protocol This lets applications, such as mpv with --video-sync=display-resample, know accurately when frames are displayed and ensure smooth video playback. --- dwl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dwl.c b/dwl.c index a2a0b69..20b01b0 100644 --- a/dwl.c +++ b/dwl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,7 @@ static struct wl_list independents; static struct wlr_idle *idle; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; +static struct wlr_presentation *presentation; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_cursor *cursor; @@ -1653,6 +1655,8 @@ render(struct wlr_surface *surface, int sx, int sy, void *data) /* This lets the client know that we've displayed that frame and it can * prepare another one now if it likes. */ wlr_surface_send_frame_done(surface, rdata->when); + + wlr_presentation_surface_sampled_on_output(presentation, surface, output); } void @@ -2116,6 +2120,8 @@ setup(void) wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.test, &output_mgr_test); + presentation = wlr_presentation_create(dpy, backend); + #ifdef XWAYLAND /* * Initialise the XWayland X server. From d4e08c07629b4534e45b292614899a6b9bb876bd Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 23 Aug 2021 18:59:31 -0500 Subject: [PATCH 47/47] update deprecated xkb function name --- dwl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index b898537..2c1634b 100644 --- a/dwl.c +++ b/dwl.c @@ -793,7 +793,7 @@ createkeyboard(struct wlr_input_device *device) /* Prepare an XKB keymap and assign it to the keyboard. */ context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - keymap = xkb_map_new_from_names(context, &xkb_rules, + keymap = xkb_keymap_new_from_names(context, &xkb_rules, XKB_KEYMAP_COMPILE_NO_FLAGS); wlr_keyboard_set_keymap(device->keyboard, keymap);