mirror of
https://github.com/swaywm/sway.git
synced 2025-03-03 14:14:44 +01:00
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. Therefore, finish must check whether it has already been called. This fixes a crash in wlroots listener checks. See #8509.
This commit is contained in:
parent
86bbedcce3
commit
257fb5fd6a
2 changed files with 28 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue