From 0c179560b3f52e8de4ce28fe687c40080ed25123 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 9 Jan 2021 07:20:59 +0000 Subject: [PATCH] visibility: Stop calling GTK functions from the visibility manager The viibility manager state is changed from various handlers, which are not guaranteed to be reentrant, most notably the Wayland handler for preedit done. As the state is changed, relevant requests to synchronize user-visible UI are fired from the same handler. In case of imservice_handle_done, GTK widget show function was being called, which triggered another round of handling Wayland, leading to the done handler being called again, and flaking out. To solve this, the phase of issuing commands needs to be separate from adjusting desired state. It seems that the easiest solution is to delay the show() and hide() calls into the next GTK main loop spin. A better solution would probably inject itself directly after the change of desired state, so that *all* the side effects are delayed. --- src/server-context-service.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index 8c907848..5541e3e1 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -239,6 +239,13 @@ server_context_service_real_show_keyboard (ServerContextService *self) gtk_widget_show (GTK_WIDGET(self->window)); } +static gboolean +show_keyboard_source_func(ServerContextService *context) +{ + server_context_service_real_show_keyboard(context); + return G_SOURCE_REMOVE; +} + static void server_context_service_real_hide_keyboard (ServerContextService *self) { @@ -246,6 +253,13 @@ server_context_service_real_hide_keyboard (ServerContextService *self) self->visible = FALSE; } +static gboolean +hide_keyboard_source_func(ServerContextService *context) +{ + server_context_service_real_hide_keyboard(context); + return G_SOURCE_REMOVE; +} + static gboolean on_hide (ServerContextService *self) { @@ -266,7 +280,7 @@ server_context_service_show_keyboard (ServerContextService *self) } if (!self->visible) { - server_context_service_real_show_keyboard (self); + g_idle_add((GSourceFunc)show_keyboard_source_func, self); } } @@ -289,7 +303,7 @@ server_context_service_hide_keyboard (ServerContextService *self) g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self)); if (self->visible) { - server_context_service_real_hide_keyboard (self); + g_idle_add((GSourceFunc)hide_keyboard_source_func, self); } }