diff options
Diffstat (limited to '')
-rw-r--r-- | src/remmina_masterthread_exec.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/remmina_masterthread_exec.c b/src/remmina_masterthread_exec.c new file mode 100644 index 0000000..97c2ffe --- /dev/null +++ b/src/remmina_masterthread_exec.c @@ -0,0 +1,151 @@ +/* + * Remmina - The GTK+ Remote Desktop Client + * Copyright (C) 2009-2011 Vic Lee + * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo + * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. * If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. * If you + * do not wish to do so, delete this exception statement from your + * version. * If you delete this exception statement from all source + * files in the program, then also delete it here. + * + */ + +/* Support for execution on main thread of some GTK related + * functions (due to threads deprecations in GTK) */ + +#include <gtk/gtk.h> + +#include "remmina_masterthread_exec.h" + +static pthread_t gMainThreadID; + +static gboolean remmina_masterthread_exec_callback(RemminaMTExecData *d) +{ + + /* This function is called on main GTK Thread via gdk_threads_add_idlde() + * from remmina_masterthread_exec_and_wait() */ + + if (!d->cancelled) { + switch (d->func) { + case FUNC_INIT_SAVE_CRED: + remmina_protocol_widget_save_cred(d->p.init_save_creds.gp); + break; + case FUNC_CHAT_RECEIVE: + remmina_protocol_widget_chat_receive(d->p.chat_receive.gp, d->p.chat_receive.text); + break; + case FUNC_FILE_GET_STRING: + d->p.file_get_string.retval = remmina_file_get_string( d->p.file_get_string.remminafile, d->p.file_get_string.setting ); + break; + case FUNC_FILE_SET_STRING: + remmina_file_set_string( d->p.file_set_string.remminafile, d->p.file_set_string.setting, d->p.file_set_string.value ); + break; + case FUNC_GTK_LABEL_SET_TEXT: + gtk_label_set_text( d->p.gtk_label_set_text.label, d->p.gtk_label_set_text.str ); + break; + case FUNC_FTP_CLIENT_UPDATE_TASK: + remmina_ftp_client_update_task( d->p.ftp_client_update_task.client, d->p.ftp_client_update_task.task ); + break; + case FUNC_FTP_CLIENT_GET_WAITING_TASK: + d->p.ftp_client_get_waiting_task.retval = remmina_ftp_client_get_waiting_task( d->p.ftp_client_get_waiting_task.client ); + break; + case FUNC_PROTOCOLWIDGET_EMIT_SIGNAL: + remmina_protocol_widget_emit_signal(d->p.protocolwidget_emit_signal.gp, d->p.protocolwidget_emit_signal.signal_name); + break; + case FUNC_PROTOCOLWIDGET_MPPROGRESS: + d->p.protocolwidget_mpprogress.ret_mp = remmina_protocol_widget_mpprogress(d->p.protocolwidget_mpprogress.cnnobj, d->p.protocolwidget_mpprogress.message, + d->p.protocolwidget_mpprogress.response_callback, d->p.protocolwidget_mpprogress.response_callback_data); + break; + case FUNC_PROTOCOLWIDGET_MPDESTROY: + remmina_protocol_widget_mpdestroy(d->p.protocolwidget_mpdestroy.cnnobj, d->p.protocolwidget_mpdestroy.mp); + break; + case FUNC_PROTOCOLWIDGET_MPSHOWRETRY: + remmina_protocol_widget_panel_show_retry(d->p.protocolwidget_mpshowretry.gp); + break; + case FUNC_PROTOCOLWIDGET_PANELSHOWLISTEN: + remmina_protocol_widget_panel_show_listen(d->p.protocolwidget_panelshowlisten.gp, d->p.protocolwidget_panelshowlisten.port); + break; + case FUNC_SFTP_CLIENT_CONFIRM_RESUME: +#ifdef HAVE_LIBSSH + d->p.sftp_client_confirm_resume.retval = remmina_sftp_client_confirm_resume( d->p.sftp_client_confirm_resume.client, + d->p.sftp_client_confirm_resume.path ); +#endif + break; + case FUNC_VTE_TERMINAL_SET_ENCODING_AND_PTY: +#if defined (HAVE_LIBSSH) && defined (HAVE_LIBVTE) + remmina_plugin_ssh_vte_terminal_set_encoding_and_pty( d->p.vte_terminal_set_encoding_and_pty.terminal, + d->p.vte_terminal_set_encoding_and_pty.codeset, + d->p.vte_terminal_set_encoding_and_pty.master, + d->p.vte_terminal_set_encoding_and_pty.slave); +#endif + break; + + } + pthread_mutex_lock(&d->pt_mutex); + d->complete = TRUE; + pthread_cond_signal(&d->pt_cond); + pthread_mutex_unlock(&d->pt_mutex); + }else { + /* thread has been cancelled, so we must free d memory here */ + g_free(d); + } + return G_SOURCE_REMOVE; +} + +static void remmina_masterthread_exec_cleanup_handler(gpointer data) +{ + RemminaMTExecData *d = data; + + d->cancelled = TRUE; +} + +void remmina_masterthread_exec_and_wait(RemminaMTExecData *d) +{ + d->cancelled = FALSE; + d->complete = FALSE; + pthread_cleanup_push(remmina_masterthread_exec_cleanup_handler, (void*)d); + pthread_mutex_init(&d->pt_mutex, NULL); + pthread_cond_init(&d->pt_cond, NULL); + gdk_threads_add_idle((GSourceFunc)remmina_masterthread_exec_callback, (gpointer)d); + pthread_mutex_lock(&d->pt_mutex); + while (!d->complete) + pthread_cond_wait(&d->pt_cond, &d->pt_mutex); + pthread_cleanup_pop(0); + pthread_mutex_destroy(&d->pt_mutex); + pthread_cond_destroy(&d->pt_cond); +} + +void remmina_masterthread_exec_save_main_thread_id() +{ + /* To be called from main thread at startup */ + gMainThreadID = pthread_self(); +} + +gboolean remmina_masterthread_exec_is_main_thread() +{ + return pthread_equal(gMainThreadID, pthread_self()) != 0; +} + |