From 5215712cabce273f76a5381de244c58a7d1f54f9 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Wed, 7 Jun 2023 16:24:28 -0500 Subject: [PATCH 1/5] Stray whitespace fixes --- config.def.h | 6 +++--- dwl.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index c6a4950..447ba00 100644 --- a/config.def.h +++ b/config.def.h @@ -65,9 +65,9 @@ LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; /* You can choose between: -LIBINPUT_CONFIG_CLICK_METHOD_NONE -LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS -LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER +LIBINPUT_CONFIG_CLICK_METHOD_NONE +LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS +LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER */ static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; diff --git a/dwl.c b/dwl.c index 918852e..d741cbd 100644 --- a/dwl.c +++ b/dwl.c @@ -1047,7 +1047,7 @@ createpointer(struct wlr_pointer *pointer) if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) libinput_device_config_scroll_set_method (libinput_device, scroll_method); - + if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) libinput_device_config_click_set_method (libinput_device, click_method); From df11b7a7864b416bba52e00d6ad7997d9a7c19b0 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Jun 2023 15:42:54 -0500 Subject: [PATCH 2/5] fix startup_cmd SIGCHLD handler Ignored handlers are not reset by exec() calls --- dwl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dwl.c b/dwl.c index d741cbd..19adafe 100644 --- a/dwl.c +++ b/dwl.c @@ -1963,6 +1963,8 @@ run(char *startup_cmd) if ((child_pid = fork()) < 0) die("startup: fork:"); if (child_pid == 0) { + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); dup2(piperw[0], STDIN_FILENO); close(piperw[0]); close(piperw[1]); From 9c592da01f7648ff1efb69e851ced554b3231096 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Jun 2023 23:57:16 -0500 Subject: [PATCH 3/5] Reset ignored signal handler in spawn() as well --- dwl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwl.c b/dwl.c index 19adafe..9402935 100644 --- a/dwl.c +++ b/dwl.c @@ -2327,6 +2327,9 @@ void spawn(const Arg *arg) { if (fork() == 0) { + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SIG_DFL}; + sigemptyset(&sa.sa_mask); + sigaction(SIGCHLD, &sa, NULL); dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); From 68a17f962e05895603d0f409fb8da4493cbe52aa Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 16 Jun 2023 00:22:11 -0500 Subject: [PATCH 4/5] Don't bother with ignoring SIGCHLD It added complexity, especially with the differences in behavior between handled and ignored signals across an exec(). --- dwl.c | 73 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/dwl.c b/dwl.c index 9402935..da3a516 100644 --- a/dwl.c +++ b/dwl.c @@ -297,6 +297,7 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); static void setpsel(struct wl_listener *listener, void *data); static void setsel(struct wl_listener *listener, void *data); static void setup(void); +static void sigchld(int unused); static void spawn(const Arg *arg); static void startdrag(struct wl_listener *listener, void *data); static void tag(const Arg *arg); @@ -397,7 +398,6 @@ static void configurex11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data); static Atom getatom(xcb_connection_t *xc, const char *name); static void sethints(struct wl_listener *listener, void *data); -static void sigchld(int unused); static void xwaylandready(struct wl_listener *listener, void *data); static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; static struct wl_listener xwayland_ready = {.notify = xwaylandready}; @@ -1963,8 +1963,6 @@ run(char *startup_cmd) if ((child_pid = fork()) < 0) die("startup: fork:"); if (child_pid == 0) { - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); dup2(piperw[0], STDIN_FILENO); close(piperw[0]); close(piperw[1]); @@ -2129,27 +2127,19 @@ setsel(struct wl_listener *listener, void *data) void setup(void) { - struct sigaction sa_term = {.sa_flags = SA_RESTART, .sa_handler = quitsignal}; - struct sigaction sa_sigchld = { -#ifdef XWAYLAND - .sa_flags = SA_RESTART, - .sa_handler = sigchld, -#else - .sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART, - .sa_handler = SIG_IGN, -#endif - }; - sigemptyset(&sa_term.sa_mask); - sigemptyset(&sa_sigchld.sa_mask); + /* Set up signal handlers */ + struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = sigchld}; + sigemptyset(&sa.sa_mask); + sigaction(SIGCHLD, &sa, NULL); + + sa.sa_handler = quitsignal; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + /* The Wayland display is managed by libwayland. It handles accepting * clients from the Unix socket, manging Wayland globals, and so on. */ dpy = wl_display_create(); - /* Set up signal handlers */ - sigaction(SIGCHLD, &sa_sigchld, NULL); - sigaction(SIGINT, &sa_term, NULL); - sigaction(SIGTERM, &sa_term, NULL); - /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable * backend based on the current environment, such as opening an X11 window @@ -2323,13 +2313,32 @@ setup(void) #endif } +void +sigchld(int unused) +{ +#ifdef XWAYLAND + siginfo_t in; + /* We should be able to remove this function in favor of a simple + * struct sigaction sa = {.sa_handler = SIG_IGN}; + * sigaction(SIGCHLD, &sa, NULL); + * but the Xwayland implementation in wlroots currently prevents us from + * setting our own disposition for SIGCHLD. + */ + /* WNOWAIT leaves the child in a waitable state, in case this is the + * XWayland process + */ + while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid + && (!xwayland || in.si_pid != xwayland->server->pid)) + waitpid(in.si_pid, NULL, 0); +#else + while (waitpid(-1, NULL, WNOHANG) > 0); +#endif +} + void spawn(const Arg *arg) { if (fork() == 0) { - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SIG_DFL}; - sigemptyset(&sa.sa_mask); - sigaction(SIGCHLD, &sa, NULL); dup2(STDERR_FILENO, STDOUT_FILENO); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); @@ -2772,24 +2781,6 @@ sethints(struct wl_listener *listener, void *data) } } -void -sigchld(int unused) -{ - siginfo_t in; - /* We should be able to remove this function in favor of a simple - * struct sigaction sa = {.sa_handler = SIG_IGN}; - * sigaction(SIGCHLD, &sa, NULL); - * but the Xwayland implementation in wlroots currently prevents us from - * setting our own disposition for SIGCHLD. - */ - /* WNOWAIT leaves the child in a waitable state, in case this is the - * XWayland process - */ - while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid - && (!xwayland || in.si_pid != xwayland->server->pid)) - waitpid(in.si_pid, NULL, 0); -} - void xwaylandready(struct wl_listener *listener, void *data) { From eda0613cc4c657a4d4f0165aa8ccd75108545981 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 25 Jun 2023 17:44:00 -0500 Subject: [PATCH 5/5] Separate drag icon from layers array and Lyr enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we treat the drag icon as distinct from other layers (it doesn't have contents that are interactive, focusable, etc.), then we can iterate over layers meaningfully with a simple for loop. ΔSLOC: -8 --- dwl.c | 67 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/dwl.c b/dwl.c index da3a516..5a1b1b5 100644 --- a/dwl.c +++ b/dwl.c @@ -74,7 +74,7 @@ /* enums */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { XDGShell, LayerShell, X11Managed, X11Unmanaged }; /* client types */ -enum { LyrBg, LyrBottom, LyrTop, LyrOverlay, LyrTile, LyrFloat, LyrFS, LyrDragIcon, LyrBlock, NUM_LAYERS }; /* scene layers */ +enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ #ifdef XWAYLAND enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ @@ -330,6 +330,8 @@ static struct wl_display *dpy; static struct wlr_backend *backend; static struct wlr_scene *scene; static struct wlr_scene_tree *layers[NUM_LAYERS]; +/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ +static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay }; static struct wlr_renderer *drw; static struct wlr_allocator *alloc; static struct wlr_compositor *compositor; @@ -736,17 +738,16 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit); struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface; struct wlr_output *wlr_output = wlr_layer_surface->output; + struct wlr_scene_tree *layer = layers[layermap[wlr_layer_surface->current.layer]]; /* For some reason this layersurface have no monitor, this can be because * its monitor has just been destroyed */ if (!wlr_output || !(layersurface->mon = wlr_output->data)) return; - if (layers[wlr_layer_surface->current.layer] != layersurface->scene->node.parent) { - wlr_scene_node_reparent(&layersurface->scene->node, - layers[wlr_layer_surface->current.layer]); - wlr_scene_node_reparent(&layersurface->popups->node, - layers[wlr_layer_surface->current.layer]); + if (layer != layersurface->scene->node.parent) { + wlr_scene_node_reparent(&layersurface->scene->node, layer); + wlr_scene_node_reparent(&layersurface->popups->node, layer); wl_list_remove(&layersurface->link); wl_list_insert(&layersurface->mon->layers[wlr_layer_surface->current.layer], &layersurface->link); @@ -832,6 +833,7 @@ createlayersurface(struct wl_listener *listener, void *data) struct wlr_layer_surface_v1 *wlr_layer_surface = data; LayerSurface *layersurface; struct wlr_layer_surface_v1_state old_state; + struct wlr_scene_tree *l = layers[layermap[wlr_layer_surface->pending.layer]]; if (!wlr_layer_surface->output) wlr_layer_surface->output = selmon ? selmon->wlr_output : NULL; @@ -856,11 +858,9 @@ createlayersurface(struct wl_listener *listener, void *data) layersurface->mon = wlr_layer_surface->output->data; wlr_layer_surface->data = layersurface; - layersurface->scene_layer = wlr_scene_layer_surface_v1_create( - layers[wlr_layer_surface->pending.layer], wlr_layer_surface); + layersurface->scene_layer = wlr_scene_layer_surface_v1_create(l, wlr_layer_surface); layersurface->scene = layersurface->scene_layer->tree; - layersurface->popups = wlr_layer_surface->surface->data = - wlr_scene_tree_create(layers[wlr_layer_surface->pending.layer]); + layersurface->popups = wlr_layer_surface->surface->data = wlr_scene_tree_create(l); layersurface->scene->node.data = layersurface; @@ -2127,6 +2127,8 @@ setsel(struct wl_listener *listener, void *data) void setup(void) { + int layer; + /* Set up signal handlers */ struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = sigchld}; sigemptyset(&sa.sa_mask); @@ -2153,15 +2155,8 @@ setup(void) /* Initialize the scene graph used to lay out windows */ scene = wlr_scene_create(); - layers[LyrBg] = wlr_scene_tree_create(&scene->tree); - layers[LyrBottom] = wlr_scene_tree_create(&scene->tree); - layers[LyrTile] = wlr_scene_tree_create(&scene->tree); - layers[LyrFloat] = wlr_scene_tree_create(&scene->tree); - layers[LyrFS] = wlr_scene_tree_create(&scene->tree); - layers[LyrTop] = wlr_scene_tree_create(&scene->tree); - layers[LyrOverlay] = wlr_scene_tree_create(&scene->tree); - layers[LyrDragIcon] = wlr_scene_tree_create(&scene->tree); - layers[LyrBlock] = wlr_scene_tree_create(&scene->tree); + for (layer = 0; layer < NUM_LAYERS; layer++) + layers[layer] = wlr_scene_tree_create(&scene->tree); /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) @@ -2350,11 +2345,13 @@ void startdrag(struct wl_listener *listener, void *data) { struct wlr_drag *drag = data; + struct wlr_scene_tree *icon; if (!drag->icon) return; - drag->icon->data = wlr_scene_subsurface_tree_create(layers[LyrDragIcon], drag->icon->surface); + drag->icon->data = icon = wlr_scene_subsurface_tree_create(&scene->tree, drag->icon->surface); + wlr_scene_node_place_below(&icon->node, &layers[LyrBlock]->node); motionnotify(0); wl_signal_add(&drag->icon->events.destroy, &drag_icon_destroy); } @@ -2652,24 +2649,22 @@ xytonode(double x, double y, struct wlr_surface **psurface, struct wlr_surface *surface = NULL; Client *c = NULL; LayerSurface *l = NULL; - const int *layer; - int focus_order[] = { LyrBlock, LyrOverlay, LyrTop, LyrFS, LyrFloat, LyrTile, LyrBottom, LyrBg }; + int layer; - for (layer = focus_order; layer < END(focus_order); layer++) { - if ((node = wlr_scene_node_at(&layers[*layer]->node, x, y, nx, ny))) { - if (node->type == WLR_SCENE_NODE_BUFFER) - surface = wlr_scene_surface_from_buffer( - wlr_scene_buffer_from_node(node))->surface; - /* Walk the tree to find a node that knows the client */ - for (pnode = node; pnode && !c; pnode = &pnode->parent->node) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; - } + for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + + if (node->type == WLR_SCENE_NODE_BUFFER) + surface = wlr_scene_surface_from_buffer( + wlr_scene_buffer_from_node(node))->surface; + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; } - if (surface) - break; } if (psurface) *psurface = surface;