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:
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,