From 60c40c0989440fc54aa05b0e27cfbaad8c722fec Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 24 May 2021 22:03:39 -0500 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 4/4] 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`.