sway

i3-compatible Wayland compositor
git clone https://git.awy.one/sway
Log | Files | Refs | README | LICENSE

commit 53126cdceb6dbf6ee163ca0db960cf3900870075
parent 92c82e6952394b714d7818deb1d46d616a39dfc0
Author: Ferdinand Bachmann <ferdinand.bachmann@yrlf.at>
Date:   Tue, 18 Feb 2025 22:45:53 +0100

input/text_input: remove event listeners on destroy

sway_input_method_relay can be destroyed from two sources, either the
seat is destroyed or the manager protocol objects are destroyed due
compositor exit.

This fixes a crash in wlroots listener checks. See #8509.

Diffstat:
Minclude/sway/input/text_input.h | 2++
Msway/input/text_input.c | 38++++++++++++++++++++++++++++++++++++--
2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h @@ -25,8 +25,10 @@ struct sway_input_method_relay { struct wlr_input_method_v2 *input_method; // doesn't have to be present struct wl_listener text_input_new; + struct wl_listener text_input_manager_destroy; struct wl_listener input_method_new; + struct wl_listener input_method_manager_destroy; struct wl_listener input_method_commit; struct wl_listener input_method_new_popup_surface; struct wl_listener input_method_grab_keyboard; diff --git a/sway/input/text_input.c b/sway/input/text_input.c @@ -597,6 +597,34 @@ static void relay_handle_input_method(struct wl_listener *listener, } } +static void sway_input_method_relay_finish_text_input(struct sway_input_method_relay *relay) { + wl_list_remove(&relay->text_input_new.link); + wl_list_remove(&relay->text_input_manager_destroy.link); + wl_list_init(&relay->text_input_new.link); + wl_list_init(&relay->text_input_manager_destroy.link); +} + +static void relay_handle_text_input_manager_destroy(struct wl_listener *listener, void *data) { + struct sway_input_method_relay *relay = wl_container_of(listener, relay, + text_input_manager_destroy); + + sway_input_method_relay_finish_text_input(relay); +} + +static void sway_input_method_relay_finish_input_method(struct sway_input_method_relay *relay) { + wl_list_remove(&relay->input_method_new.link); + wl_list_remove(&relay->input_method_manager_destroy.link); + wl_list_init(&relay->input_method_new.link); + wl_list_init(&relay->input_method_manager_destroy.link); +} + +static void relay_handle_input_method_manager_destroy(struct wl_listener *listener, void *data) { + struct sway_input_method_relay *relay = wl_container_of(listener, relay, + input_method_manager_destroy); + + sway_input_method_relay_finish_input_method(relay); +} + void sway_input_method_relay_init(struct sway_seat *seat, struct sway_input_method_relay *relay) { relay->seat = seat; @@ -606,16 +634,22 @@ void sway_input_method_relay_init(struct sway_seat *seat, relay->text_input_new.notify = relay_handle_text_input; wl_signal_add(&server.text_input->events.text_input, &relay->text_input_new); + relay->text_input_manager_destroy.notify = relay_handle_text_input_manager_destroy; + wl_signal_add(&server.text_input->events.destroy, + &relay->text_input_manager_destroy); relay->input_method_new.notify = relay_handle_input_method; wl_signal_add( &server.input_method->events.input_method, &relay->input_method_new); + relay->input_method_manager_destroy.notify = relay_handle_input_method_manager_destroy; + wl_signal_add(&server.input_method->events.destroy, + &relay->input_method_manager_destroy); } void sway_input_method_relay_finish(struct sway_input_method_relay *relay) { - wl_list_remove(&relay->input_method_new.link); - wl_list_remove(&relay->text_input_new.link); + sway_input_method_relay_finish_text_input(relay); + sway_input_method_relay_finish_input_method(relay); } void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,