diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h index 1993f928f..1818749ad 100644 --- 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 index e16724671..79e4dcc19 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -572,6 +572,20 @@ static void relay_handle_input_method(struct wl_listener *listener, } } +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(relay); +} + +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(relay); +} + void sway_input_method_relay_init(struct sway_seat *seat, struct sway_input_method_relay *relay) { relay->seat = seat; @@ -581,16 +595,28 @@ 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) { + // return early if finish was already called + // can be called due to seat or manager protocol object being destroyed + if (!relay->input_method_new.link.prev) return; + wl_list_remove(&relay->input_method_new.link); + wl_list_remove(&relay->input_method_manager_destroy.link); wl_list_remove(&relay->text_input_new.link); + wl_list_remove(&relay->text_input_manager_destroy.link); } void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,