From 0729f18dce85cb79b8aaac325a43dba0c5e96ab3 Mon Sep 17 00:00:00 2001 From: Micah Gorrell Date: Wed, 24 May 2023 10:20:30 -0600 Subject: Prevent using a wlr_layer_surface after destroying it, due to no available outputs --- dwl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index b7436bb..1ad3d05 100644 --- a/dwl.c +++ b/dwl.c @@ -836,8 +836,10 @@ createlayersurface(struct wl_listener *listener, void *data) if (!wlr_layer_surface->output) wlr_layer_surface->output = selmon ? selmon->wlr_output : NULL; - if (!wlr_layer_surface->output) + if (!wlr_layer_surface->output) { wlr_layer_surface_v1_destroy(wlr_layer_surface); + return; + } layersurface = ecalloc(1, sizeof(LayerSurface)); layersurface->type = LayerShell; -- cgit v1.2.3 From 72adab621f27f9daed87ea1b0068679e39fb3f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 8 Apr 2023 14:44:34 -0600 Subject: destroy old client popups when focusing another client Closes: https://github.com/djpohly/dwl/issues/408 --- dwl.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/dwl.c b/dwl.c index 1ad3d05..aec7427 100644 --- a/dwl.c +++ b/dwl.c @@ -1203,7 +1203,9 @@ void focusclient(Client *c, int lift) { struct wlr_surface *old = seat->keyboard_state.focused_surface; - int i, unused_lx, unused_ly; + int i, unused_lx, unused_ly, old_client_type; + Client *old_c = NULL; + LayerSurface *old_l = NULL; if (locked) return; @@ -1215,6 +1217,12 @@ focusclient(Client *c, int lift) if (c && client_surface(c) == old) return; + if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) { + struct wlr_xdg_popup *popup, *tmp; + wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link) + wlr_xdg_popup_destroy(popup); + } + /* Put the new client atop the focus stack and select its monitor */ if (c && !client_is_unmanaged(c)) { wl_list_remove(&c->flink); @@ -1235,19 +1243,17 @@ focusclient(Client *c, int lift) /* If an overlay is focused, don't focus or activate the client, * but only update its position in fstack to render its border with focuscolor * and focus it after the overlay is closed. */ - Client *w = NULL; - LayerSurface *l = NULL; - int type = toplevel_from_wlr_surface(old, &w, &l); - if (type == LayerShell && wlr_scene_node_coords(&l->scene->node, &unused_lx, &unused_ly) - && l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + if (old_client_type == LayerShell && wlr_scene_node_coords( + &old_l->scene->node, &unused_lx, &unused_ly) + && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { return; - } else if (w && w == exclusive_focus && client_wants_focus(w)) { + } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { return; /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg * and probably other clients */ - } else if (w && !client_is_unmanaged(w) && (!c || !client_wants_focus(c))) { + } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { for (i = 0; i < 4; i++) - wlr_scene_rect_set_color(w->border[i], bordercolor); + wlr_scene_rect_set_color(old_c->border[i], bordercolor); client_activate_surface(old, 0); } -- cgit v1.2.3 From a5e45924edeaeb9b763cdc75fd4ec413b2ec2ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sun, 28 May 2023 00:20:20 -0600 Subject: remove note about contact me for patch issues I am no longer able to spend much time developing dwl let alone maintaining other's patches :) --- .github/ISSUE_TEMPLATE/bug_report.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6b60803..cd9bd8d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -14,9 +14,4 @@ wlroots version: -- cgit v1.2.3 From f8884ffc2b7a4c0401f0a6710b679cd18b6b097d Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Sun, 28 May 2023 19:09:38 +0200 Subject: Set XCURSOR_SIZE --- dwl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwl.c b/dwl.c index aec7427..cd27c7c 100644 --- a/dwl.c +++ b/dwl.c @@ -2260,6 +2260,7 @@ setup(void) * images are available at all scale factors on the screen (necessary for * HiDPI support). Scaled cursors will be loaded with each output. */ cursor_mgr = wlr_xcursor_manager_create(NULL, 24); + setenv("XCURSOR_SIZE", "24", 1); /* * wlr_cursor *only* displays an image on screen. It does not move around -- cgit v1.2.3 From 3d98907b98e2ff978cc30614b739f1f4b8f7f8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 25 May 2023 22:19:29 -0600 Subject: send frame done even if output commit fails Bug: https://github.com/djpohly/dwl/issues/420 Fixes: https://github.com/djpohly/dwl/issues/353 --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index cd27c7c..02c761c 100644 --- a/dwl.c +++ b/dwl.c @@ -1895,8 +1895,8 @@ rendermon(struct wl_listener *listener, void *data) wl_list_for_each(c, &clients, link) if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) goto skip; - if (!wlr_scene_output_commit(m->scene_output)) - return; + wlr_scene_output_commit(m->scene_output); + skip: /* Let clients know a frame has been rendered */ clock_gettime(CLOCK_MONOTONIC, &now); -- cgit v1.2.3 From 9b9b79b35ebaed7a5897f748c51b2d5c4ec1ddfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Thu, 25 May 2023 22:20:12 -0600 Subject: activate lock surface in updatemons Fixes an issue when swaylock does not receive input after turn off and then turn on the outputs --- dwl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dwl.c b/dwl.c index 02c761c..918852e 100644 --- a/dwl.c +++ b/dwl.c @@ -2572,9 +2572,12 @@ updatemons(struct wl_listener *listener, void *data) wl_list_for_each(c, &clients, link) if (!c->mon && client_is_mapped(c)) setmon(c, selmon, c->tags); - if (selmon->lock_surface) + focusclient(focustop(selmon), 1); + if (selmon->lock_surface) { client_notify_enter(selmon->lock_surface->surface, wlr_seat_get_keyboard(seat)); + client_activate_surface(selmon->lock_surface->surface, 1); + } } wlr_output_manager_v1_set_configuration(output_mgr, config); -- cgit v1.2.3 From 5215712cabce273f76a5381de244c58a7d1f54f9 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Wed, 7 Jun 2023 16:24:28 -0500 Subject: 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); -- cgit v1.2.3 From df11b7a7864b416bba52e00d6ad7997d9a7c19b0 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Jun 2023 15:42:54 -0500 Subject: 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]); -- cgit v1.2.3 From 9c592da01f7648ff1efb69e851ced554b3231096 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 15 Jun 2023 23:57:16 -0500 Subject: 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); -- cgit v1.2.3 From 68a17f962e05895603d0f409fb8da4493cbe52aa Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 16 Jun 2023 00:22:11 -0500 Subject: 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) { -- cgit v1.2.3 From eda0613cc4c657a4d4f0165aa8ccd75108545981 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 25 Jun 2023 17:44:00 -0500 Subject: 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 | 69 +++++++++++++++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 37 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 }; - - 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; - } + int layer; + + 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; -- cgit v1.2.3 From fbd84aca4a2cbaa4e7daaa9d1a546d2248be8fec Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Jul 2023 14:51:09 -0500 Subject: Unify signal handling under wl_event_loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge our signal handlers into a single function and let Wayland deal with all the struct sigaction stuff. ΔSLOC: -3 --- dwl.c | 83 ++++++++++++++++++++++++++++--------------------------------------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/dwl.c b/dwl.c index 5a1b1b5..b5e146d 100644 --- a/dwl.c +++ b/dwl.c @@ -260,6 +260,7 @@ static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static Client *focustop(Monitor *m); static void fullscreennotify(struct wl_listener *listener, void *data); +static int handlesig(int signo, 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); @@ -283,7 +284,6 @@ 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 rendermon(struct wl_listener *listener, void *data); static void requeststartdrag(struct wl_listener *listener, void *data); static void resize(Client *c, struct wlr_box geo, int interact); @@ -297,7 +297,6 @@ 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); @@ -327,6 +326,8 @@ static pid_t child_pid = -1; static int locked; static void *exclusive_focus; static struct wl_display *dpy; +static struct wl_event_loop *eventloop; +static struct wl_event_source *sighandler[4]; static struct wlr_backend *backend; static struct wlr_scene *scene; static struct wlr_scene_tree *layers[NUM_LAYERS]; @@ -652,6 +653,7 @@ checkidleinhibitor(struct wlr_surface *exclude) void cleanup(void) { + int i; #ifdef XWAYLAND wlr_xwayland_destroy(xwayland); #endif @@ -667,6 +669,8 @@ cleanup(void) wlr_cursor_destroy(cursor); wlr_output_layout_destroy(output_layout); wlr_seat_destroy(seat); + for (i = 0; i < LENGTH(sighandler); i++) + wl_event_source_remove(sighandler[i]); wl_display_destroy(dpy); } @@ -820,8 +824,7 @@ createkeyboard(struct wlr_keyboard *keyboard) wlr_seat_set_keyboard(seat, keyboard); - kb->key_repeat_source = wl_event_loop_add_timer( - wl_display_get_event_loop(dpy), keyrepeat, kb); + kb->key_repeat_source = wl_event_loop_add_timer(eventloop, keyrepeat, kb); /* And add the keyboard to our list of keyboards */ wl_list_insert(&keyboards, &kb->link); @@ -1333,6 +1336,28 @@ fullscreennotify(struct wl_listener *listener, void *data) setfullscreen(c, client_wants_fullscreen(c)); } +int +handlesig(int signo, void *data) +{ + if (signo == SIGCHLD) { +#ifdef XWAYLAND + siginfo_t in; + /* wlroots expects to reap the XWayland process itself, so we + * use WNOWAIT to keep the child waitable until we know it's not + * XWayland. + */ + 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 + } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); + } + return 0; +} + void incnmaster(const Arg *arg) { @@ -1875,12 +1900,6 @@ quit(const Arg *arg) wl_display_terminate(dpy); } -void -quitsignal(int signo) -{ - quit(NULL); -} - void rendermon(struct wl_listener *listener, void *data) { @@ -1944,8 +1963,6 @@ run(char *startup_cmd) { /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SIG_IGN}; - sigemptyset(&sa.sa_mask); if (!socket) die("startup: display_add_socket_auto"); setenv("WAYLAND_DISPLAY", socket, 1); @@ -1973,8 +1990,6 @@ run(char *startup_cmd) close(piperw[1]); close(piperw[0]); } - /* If nobody is reading the status output, don't terminate */ - sigaction(SIGPIPE, &sa, NULL); printstatus(); /* At this point the outputs are initialized, choose initial selmon based on @@ -2127,20 +2142,14 @@ 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); - sigaction(SIGCHLD, &sa, NULL); - - sa.sa_handler = quitsignal; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; /* 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(); + eventloop = wl_display_get_event_loop(dpy); + for (i = 0; i < LENGTH(sighandler); i++) + sighandler[i] = wl_event_loop_add_signal(eventloop, sig[i], handlesig, NULL); /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable @@ -2155,8 +2164,8 @@ setup(void) /* Initialize the scene graph used to lay out windows */ scene = wlr_scene_create(); - for (layer = 0; layer < NUM_LAYERS; layer++) - layers[layer] = wlr_scene_tree_create(&scene->tree); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) @@ -2308,28 +2317,6 @@ 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) { -- cgit v1.2.3