diff --git a/include/util/signal.h b/include/util/signal.h new file mode 100644 index 000000000..714b56f44 --- /dev/null +++ b/include/util/signal.h @@ -0,0 +1,8 @@ +#ifndef UTIL_SIGNAL_H +#define UTIL_SIGNAL_H + +#include + +void wlr_signal_emit_final(struct wl_signal *signal, void *data); + +#endif diff --git a/types/output/output.c b/types/output/output.c index 636d155d2..271cf289f 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -11,6 +11,7 @@ #include "types/wlr_output.h" #include "util/env.h" #include "util/global.h" +#include "util/signal.h" #define OUTPUT_VERSION 4 @@ -375,7 +376,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, } void wlr_output_finish(struct wlr_output *output) { - wl_signal_emit_mutable(&output->events.destroy, output); + wlr_signal_emit_final(&output->events.destroy, output); wlr_addon_set_finish(&output->addons); assert(wl_list_empty(&output->events.frame.listener_list)); diff --git a/util/meson.build b/util/meson.build index d67911e52..4c399130a 100644 --- a/util/meson.build +++ b/util/meson.build @@ -11,6 +11,7 @@ wlr_files += files( 'region.c', 'set.c', 'shm.c', + 'signal.c', 'time.c', 'token.c', 'transform.c', diff --git a/util/signal.c b/util/signal.c new file mode 100644 index 000000000..531a51b7e --- /dev/null +++ b/util/signal.c @@ -0,0 +1,18 @@ +#include "util/signal.h" + +void wlr_signal_emit_final(struct wl_signal *signal, void *data) { + + // We need to run all listeners one final time. To support all types of list mutations and to + // ensure that all listeners including those added during this execution is run, we run until + // the list is empty, removing listeners just before we run them. To not affect the behavior of + // the listener, we re-initialize the listener's link element. + while (signal->listener_list.next != &signal->listener_list) { + struct wl_list *pos = signal->listener_list.next; + struct wl_listener *l = wl_container_of(pos, l, link); + + wl_list_remove(pos); + wl_list_init(pos); + + l->notify(l, data); + } +}