Commit 55299216 authored by Giovanni Panozzo's avatar Giovanni Panozzo

Switched to GTK+3.6 threading model, make pthreads compulsory.

parent 782b8c50
......@@ -103,14 +103,10 @@ set(REMMINA_LOCALEDIR "${CMAKE_INSTALL_FULL_DATADIR}/locale")
set(REMMINA_PLUGINDIR "${CMAKE_INSTALL_FULL_LIBDIR}/remmina/plugins")
find_required_package(GTK)
find_suggested_package(PTHREAD)
find_required_package(PTHREAD)
find_suggested_package(GCRYPT)
find_suggested_package(AVAHI)
if(PTHREAD_FOUND)
add_definitions(-DHAVE_PTHREAD)
endif()
if(GCRYPT_FOUND)
add_definitions(-DHAVE_LIBGCRYPT)
endif()
......
......@@ -44,9 +44,7 @@
#include <string.h>
#include <unistd.h>
#include <signal.h>
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
......@@ -68,22 +66,14 @@
typedef void (*PThreadCleanupFunc)(void*);
/* Wrapper macros to make the compiler happy on both signle/multi-threaded mode */
#ifdef HAVE_PTHREAD
#define IDLE_ADD gdk_threads_add_idle
#define TIMEOUT_ADD gdk_threads_add_timeout
#define CANCEL_ASYNC pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);pthread_testcancel();
#define CANCEL_DEFER pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
#define THREADS_ENTER gdk_threads_enter();pthread_cleanup_push((PThreadCleanupFunc)gdk_threads_leave,NULL);
#define THREADS_LEAVE pthread_cleanup_pop(TRUE);
#else
#define IDLE_ADD g_idle_add
#define TIMEOUT_ADD g_timeout_add
#define CANCEL_ASYNC
#define CANCEL_DEFER
#define THREADS_ENTER
#define THREADS_LEAVE
#endif
#define THREADS_ENTER _Pragma("GCC error \"THREADS_ENTER has been deprecated in Remmina 1.2\"")
#define THREADS_LEAVE _Pragma("GCC error \"THREADS_LEAVE has been deprecated in Remmina 1.2\"")
#define MAX_X_DISPLAY_NUMBER 99
#define X_UNIX_SOCKET "/tmp/.X11-unix/X%d"
......
......@@ -56,6 +56,77 @@ static gchar *remmina_kbtype = "pc102/us";
static pthread_mutex_t remmina_nx_init_mutex;
static GArray *remmina_nx_window_id_array;
/* --------- Support for execution on main thread of GTK functions -------------- */
struct onMainThread_cb_data {
enum { FUNC_GTK_SOCKET_ADD_ID } func;
GtkSocket* sk;
Window w;
/* Mutex for thread synchronization */
pthread_mutex_t mu;
/* Flag to catch cancellations */
gboolean cancelled;
};
static gboolean onMainThread_cb(struct onMainThread_cb_data *d)
{
if ( !d->cancelled ) {
switch( d->func ) {
case FUNC_GTK_SOCKET_ADD_ID:
gtk_socket_add_id( d->sk, d->w );
break;
}
pthread_mutex_unlock( &d->mu );
} else {
/* thread has been cancelled, so we must free d memory here */
g_free( d );
}
return G_SOURCE_REMOVE;
}
static void onMainThread_cleanup_handler( struct onMainThread_cb_data *d )
{
d->cancelled = TRUE;
}
static void onMainThread_schedule_callback_and_wait( struct onMainThread_cb_data *d )
{
d->cancelled = FALSE;
pthread_cleanup_push( onMainThread_cleanup_handler, (void *)d );
pthread_mutex_init( &d->mu, NULL );
pthread_mutex_lock( &d->mu );
gdk_threads_add_idle( (GSourceFunc)onMainThread_cb, (gpointer) d );
pthread_mutex_lock( &d->mu );
pthread_cleanup_pop(0);
pthread_mutex_unlock( &d->mu );
pthread_mutex_destroy( &d->mu );
}
static void onMainThread_gtk_socket_add_id( GtkSocket* sk, Window w)
{
struct onMainThread_cb_data *d;
d = (struct onMainThread_cb_data *)g_malloc( sizeof(struct onMainThread_cb_data) );
d->func = FUNC_GTK_SOCKET_ADD_ID;
d->sk = sk;
d->w = w;
onMainThread_schedule_callback_and_wait( d );
g_free(d);
}
/* --------------------------------------- */
static gboolean remmina_plugin_nx_try_window_id(Window window_id)
{
gint i;
......@@ -115,8 +186,7 @@ gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userda
RemminaProtocolWidget *gp = (RemminaProtocolWidget*) userdata;
gint ret;
THREADS_ENTER ret = remmina_plugin_nx_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY);
THREADS_LEAVE
ret = remmina_plugin_nx_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY);
if (ret != GTK_RESPONSE_OK)
return FALSE;
......@@ -267,8 +337,8 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp)
/* Login */
s1 = g_strdup(remmina_plugin_nx_service->file_get_string(remminafile, "username"));
THREADS_ENTER s2 = remmina_plugin_nx_service->file_get_secret(remminafile, "password");
THREADS_LEAVE
s2 = remmina_plugin_nx_service->file_get_secret(remminafile, "password");
if (s1 && s2)
{
ret = remmina_nx_session_login(nx, s1, s2);
......@@ -278,8 +348,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp)
g_free(s1);
g_free(s2);
THREADS_ENTER ret = remmina_plugin_nx_service->protocol_plugin_init_authuserpwd(gp, FALSE);
THREADS_LEAVE
ret = remmina_plugin_nx_service->protocol_plugin_init_authuserpwd(gp, FALSE);
if (ret != GTK_RESPONSE_OK)
return FALSE;
......@@ -294,9 +363,7 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp)
if (!ret)
return FALSE;
THREADS_ENTER
remmina_plugin_nx_service->protocol_plugin_init_save_cred(gp);
THREADS_LEAVE
/* Prepare the session type and application */
cs = remmina_plugin_nx_service->file_get_string(remminafile, "exec");
......@@ -455,9 +522,8 @@ static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp)
return FALSE;
/* embed it */
THREADS_ENTER
gtk_socket_add_id(GTK_SOCKET(gpdata->socket), gpdata->window_id);
THREADS_LEAVE
onMainThread_gtk_socket_add_id(GTK_SOCKET(gpdata->socket), gpdata->window_id);
return TRUE;
}
......
......@@ -780,6 +780,23 @@ static void remmina_rdp_event_cursor(RemminaProtocolWidget* gp, RemminaPluginRdp
}
}
static void remmina_rdp_ui_event_update_scale(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
{
remmina_rdp_event_update_scale(gp);
}
static void remmina_rdp_event_process_event(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
{
switch (ui->event.type)
{
case REMMINA_RDP_UI_EVENT_UPDATE_SCALE:
remmina_rdp_ui_event_update_scale(gp, ui);
break;
}
}
gboolean remmina_rdp_event_queue_ui(RemminaProtocolWidget* gp)
{
rfContext* rfi;
......@@ -791,29 +808,40 @@ gboolean remmina_rdp_event_queue_ui(RemminaProtocolWidget* gp)
if (ui)
{
switch (ui->type)
{
case REMMINA_RDP_UI_UPDATE_REGION:
remmina_rdp_event_update_region(gp, ui);
break;
if ( !rfi->thread_cancelled ) {
switch (ui->type)
{
case REMMINA_RDP_UI_UPDATE_REGION:
remmina_rdp_event_update_region(gp, ui);
break;
case REMMINA_RDP_UI_CONNECTED:
remmina_rdp_event_connected(gp, ui);
break;
case REMMINA_RDP_UI_CONNECTED:
remmina_rdp_event_connected(gp, ui);
break;
case REMMINA_RDP_UI_CURSOR:
remmina_rdp_event_cursor(gp, ui);
break;
case REMMINA_RDP_UI_CURSOR:
remmina_rdp_event_cursor(gp, ui);
break;
case REMMINA_RDP_UI_CLIPBOARD:
remmina_rdp_event_process_clipboard(gp, ui);
break;
case REMMINA_RDP_UI_CLIPBOARD:
remmina_rdp_event_process_clipboard(gp, ui);
break;
default:
break;
case REMMINA_RDP_UI_EVENT:
remmina_rdp_event_process_event(gp,ui);
break;
default:
break;
}
}
rf_object_free(gp, ui);
// Should we signal the subthread to unlock ?
if ( ui->sync )
pthread_mutex_unlock(&ui->sync_wait_mutex);
return TRUE;
}
else
......
......@@ -16,7 +16,7 @@
*
* 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., 59 Temple Place, Suite 330,
* Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* In addition, as a special exception, the copyright holders give
......@@ -46,6 +46,7 @@
static void rf_desktop_resize(rdpContext* context)
{
RemminaProtocolWidget* gp;
RemminaPluginRdpUiObject* ui;
rfContext* rfi;
rfi = (rfContext*) context;
......@@ -58,9 +59,11 @@ static void rf_desktop_resize(rdpContext* context)
UNLOCK_BUFFER(TRUE)
THREADS_ENTER
remmina_rdp_event_update_scale(gp);
THREADS_LEAVE
ui = g_new0(RemminaPluginRdpUiObject, 1);
ui->sync = TRUE; // Wait for completion too
ui->type = REMMINA_RDP_UI_EVENT;
ui->event.type = REMMINA_RDP_UI_EVENT_UPDATE_SCALE;
rf_queue_ui(gp, ui);
remmina_plugin_service->protocol_plugin_emit_signal(gp, "desktop-resize");
}
......
......@@ -120,12 +120,36 @@ void rf_queue_ui(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
rfi = GET_DATA(gp);
g_async_queue_push(rfi->ui_queue, ui);
if (ui->sync) {
pthread_mutex_init(&ui->sync_wait_mutex,NULL);
pthread_mutex_lock(&ui->sync_wait_mutex);
}
LOCK_BUFFER(TRUE)
if (!rfi->ui_handler)
rfi->ui_handler = IDLE_ADD((GSourceFunc) remmina_rdp_event_queue_ui, gp);
UNLOCK_BUFFER(TRUE)
if ( ui->sync ) {
struct timeval tv;
double tms;
/* Wait for main thread function completion before returning */
gettimeofday(&tv, NULL);
tms = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
printf("Waiting for main thread to complete its job %f\n",tms);
pthread_mutex_lock(&ui->sync_wait_mutex);
gettimeofday(&tv, NULL);
tms = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
printf("Got lock, ending %f\n",tms);
pthread_mutex_unlock(&ui->sync_wait_mutex);
}
}
void rf_object_free(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* obj)
......@@ -193,6 +217,7 @@ static void rf_desktop_resize(rdpContext* context)
{
rfContext* rfi;
RemminaProtocolWidget* gp;
RemminaPluginRdpUiObject* ui;
rfi = (rfContext*) context;
gp = rfi->protocol_widget;
......@@ -204,9 +229,13 @@ static void rf_desktop_resize(rdpContext* context)
UNLOCK_BUFFER(TRUE)
THREADS_ENTER
remmina_rdp_event_update_scale(gp);
THREADS_LEAVE
/* Call to remmina_rdp_event_update_scale(gp) on the main UI thread */
ui = g_new0(RemminaPluginRdpUiObject, 1);
ui->sync = TRUE; // Wait for completion too
ui->type = REMMINA_RDP_UI_EVENT;
ui->event.type = REMMINA_RDP_UI_EVENT_UPDATE_SCALE;
rf_queue_ui(gp, ui);
remmina_plugin_service->protocol_plugin_emit_signal(gp, "desktop-resize");
}
......@@ -368,9 +397,7 @@ static BOOL remmina_rdp_authenticate(freerdp* instance, char** username, char**
gp = rfi->protocol_widget;
remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
THREADS_ENTER
ret = remmina_plugin_service->protocol_plugin_init_authuserpwd(gp, TRUE);
THREADS_LEAVE
if (ret == GTK_RESPONSE_OK)
{
......@@ -421,9 +448,7 @@ static BOOL remmina_rdp_verify_certificate(freerdp* instance, char* subject, cha
rfi = (rfContext*) instance->context;
gp = rfi->protocol_widget;
THREADS_ENTER
status = remmina_plugin_service->protocol_plugin_init_certificate(gp, subject, issuer, fingerprint);
THREADS_LEAVE
if (status == GTK_RESPONSE_OK)
return True;
......@@ -439,9 +464,7 @@ static BOOL remmina_rdp_verify_changed_certificate(freerdp* instance, char* subj
rfi = (rfContext*) instance->context;
gp = rfi->protocol_widget;
THREADS_ENTER
status = remmina_plugin_service->protocol_plugin_changed_certificate(gp, subject, issuer, new_fingerprint, old_fingerprint);
THREADS_LEAVE
if (status == GTK_RESPONSE_OK)
return True;
......@@ -650,9 +673,7 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget* gp)
if (remmina_plugin_service->file_get_string(remminafile, "domain"))
rfi->settings->Domain = strdup(remmina_plugin_service->file_get_string(remminafile, "domain"));
THREADS_ENTER
s = remmina_plugin_service->file_get_secret(remminafile, "password");
THREADS_LEAVE
if (s)
{
......@@ -887,10 +908,12 @@ static gpointer remmina_rdp_main_thread(gpointer data)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
CANCEL_ASYNC
gp = (RemminaProtocolWidget*) data;
rfi = GET_DATA(gp);
remmina_rdp_main(gp);
rfi->thread = 0;
IDLE_ADD((GSourceFunc) remmina_plugin_service->protocol_plugin_close_connection, gp);
return NULL;
......@@ -965,10 +988,12 @@ static gboolean remmina_rdp_close_connection(RemminaProtocolWidget* gp)
if (rfi->thread)
{
rfi->thread_cancelled = TRUE; // Avoid all rf_queue function to run
pthread_cancel(rfi->thread);
if (rfi->thread)
pthread_join(rfi->thread, NULL);
}
pthread_mutex_destroy(&rfi->mutex);
......
......@@ -118,6 +118,7 @@ struct rf_context
pthread_mutex_t mutex;
gboolean scale;
gboolean user_cancelled;
gboolean thread_cancelled;
CliprdrClientContext* cliprdr;
......@@ -204,7 +205,8 @@ typedef enum
REMMINA_RDP_UI_CURSOR,
REMMINA_RDP_UI_RFX,
REMMINA_RDP_UI_NOCODEC,
REMMINA_RDP_UI_CLIPBOARD
REMMINA_RDP_UI_CLIPBOARD,
REMMINA_RDP_UI_EVENT
} RemminaPluginRdpUiType;
typedef enum
......@@ -224,9 +226,16 @@ typedef enum
REMMINA_RDP_POINTER_DEFAULT
} RemminaPluginRdpUiPointerType;
typedef enum
{
REMMINA_RDP_UI_EVENT_UPDATE_SCALE
} RemminaPluginRdpUiEeventType;
struct remmina_plugin_rdp_ui_object
{
RemminaPluginRdpUiType type;
gboolean sync;
pthread_mutex_t sync_wait_mutex;
union
{
struct
......@@ -263,6 +272,9 @@ struct remmina_plugin_rdp_ui_object
rfClipboard* clipboard;
} clipboard;
struct {
RemminaPluginRdpUiEeventType type;
} event;
};
};
typedef struct remmina_plugin_rdp_ui_object RemminaPluginRdpUiObject;
......
......@@ -82,12 +82,9 @@ typedef struct _RemminaPluginVncData
GQueue *vnc_event_queue;
gint vnc_event_pipe[2];
#ifdef HAVE_PTHREAD
pthread_t thread;
pthread_mutex_t buffer_mutex;
#else
gint thread;
#endif
} RemminaPluginVncData;
static RemminaPluginService *remmina_plugin_service = NULL;
......@@ -97,13 +94,9 @@ static int dot_cursor_y_hot = 2;
static const gchar * dot_cursor_xpm[] =
{ "5 5 3 1", " c None", ". c #000000", "+ c #FFFFFF", " ... ", ".+++.", ".+ +.", ".+++.", " ... " };
#ifdef HAVE_PTHREAD
#define LOCK_BUFFER(t) if(t){CANCEL_DEFER}pthread_mutex_lock(&gpdata->buffer_mutex);
#define UNLOCK_BUFFER(t) pthread_mutex_unlock(&gpdata->buffer_mutex);if(t){CANCEL_ASYNC}
#else
#define LOCK_BUFFER(t)
#define UNLOCK_BUFFER(t)
#endif
enum
{
......@@ -138,6 +131,82 @@ typedef struct _RemminaPluginVncEvent
} event_data;
} RemminaPluginVncEvent;
/* --------- Support for execution on main thread of GUI functions -------------- */
static void remmina_plugin_vnc_update_scale(RemminaProtocolWidget *gp, gboolean scale);
struct onMainThread_cb_data {
enum { FUNC_GTK_WIDGET_QUEUE_DRAW_AREA, FUNC_UPDATE_SCALE } func;
GtkWidget *widget;
gint x, y, width, height;
RemminaProtocolWidget* gp;
gboolean scale;
/* Mutex for thread synchronization */
pthread_mutex_t mu;
/* Flag to catch cancellations */
gboolean cancelled;
};
static gboolean onMainThread_cb(struct onMainThread_cb_data *d)
{
if ( !d->cancelled ) {
switch( d->func ) {
case FUNC_GTK_WIDGET_QUEUE_DRAW_AREA:
gtk_widget_queue_draw_area( d->widget, d->x, d->y, d->width, d->height );
break;
case FUNC_UPDATE_SCALE:
remmina_plugin_vnc_update_scale( d->gp, d->scale );
break;
}
pthread_mutex_unlock( &d->mu );
} else {
/* thread has been cancelled, so we must free d memory here */
g_free( d );
}
return G_SOURCE_REMOVE;
}
static void onMainThread_cleanup_handler( struct onMainThread_cb_data *d )
{
d->cancelled = TRUE;
}
static void onMainThread_schedule_callback_and_wait( struct onMainThread_cb_data *d )
{
d->cancelled = FALSE;
pthread_cleanup_push( onMainThread_cleanup_handler, (void *)d );
pthread_mutex_init( &d->mu, NULL );
pthread_mutex_lock( &d->mu );
gdk_threads_add_idle( (GSourceFunc)onMainThread_cb, (gpointer) d );
pthread_mutex_lock( &d->mu );
pthread_cleanup_pop(0);
pthread_mutex_unlock( &d->mu );
pthread_mutex_destroy( &d->mu );
}
static void onMainThread_gtk_widget_queue_draw_area(GtkWidget *widget, gint x, gint y, gint width, gint height )
{
struct onMainThread_cb_data *d;
d = (struct onMainThread_cb_data *)g_malloc( sizeof(struct onMainThread_cb_data) );
d->func = FUNC_GTK_WIDGET_QUEUE_DRAW_AREA;
d->widget = widget;
d->x = x; d->y = y; d->width = width; d->height = height;
onMainThread_schedule_callback_and_wait( d );
g_free(d);
}
/* --------------------------------------- */
static void remmina_plugin_vnc_event_push(RemminaProtocolWidget *gp, gint event_type, gpointer p1, gpointer p2, gpointer p3)
{
RemminaPluginVncData *gpdata;
......@@ -303,9 +372,7 @@ UNLOCK_BUFFER (in_thread)
{
if (in_thread)
{
THREADS_ENTER
gtk_widget_queue_draw_area(GTK_WIDGET(gp), 0, 0, width, height);
THREADS_LEAVE
onMainThread_gtk_widget_queue_draw_area(GTK_WIDGET(gp), 0, 0, width, height);
}
else
{
......@@ -324,11 +391,25 @@ static gboolean remmina_plugin_vnc_update_scale_buffer_main(RemminaProtocolWidge
static void remmina_plugin_vnc_update_scale(RemminaProtocolWidget *gp, gboolean scale)
{
/* This function can be called from a non main thread */
RemminaPluginVncData *gpdata;
RemminaFile *remminafile;
gint width, height;
gint hscale, vscale;
if ( !remmina_plugin_service->is_main_thread() ) {
struct onMainThread_cb_data *d;
d = (struct onMainThread_cb_data *)g_malloc( sizeof(struct onMainThread_cb_data) );
d->func = FUNC_UPDATE_SCALE;
d->gp = gp;
d->scale = scale;
onMainThread_schedule_callback_and_wait( d );
g_free(d);
return;
}
gpdata = (RemminaPluginVncData*) g_object_get_data(G_OBJECT(gp), "plugin-data");
remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
......@@ -585,9 +666,8 @@ static rfbBool remmina_plugin_vnc_rfb_allocfb(rfbClient *cl)
g_object_unref(old_pixbuf);
scale = remmina_plugin_service->protocol_plugin_get_scale(gp);
THREADS_ENTER
remmina_plugin_vnc_update_scale( gp, scale);
THREADS_LEAVE
if (gpdata->scale_handler == 0)
remmina_plugin_vnc_update_scale_buffer(gp, TRUE);
......@@ -824,13 +904,11 @@ remmina_plugin_vnc_rfb_password(rfbClient *cl)
if (gpdata->auth_first)
{
THREADS_ENTER pwd = remmina_plugin_service->file_get_secret(remminafile, "password");
THREADS_LEAVE
pwd = remmina_plugin_service->file_get_secret(remminafile, "password");
}
if (!pwd)
{
THREADS_ENTER ret = remmina_plugin_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_PROTOCOL);
THREADS_LEAVE
ret = remmina_plugin_service->protocol_plugin_init_authpwd(gp, REMMINA_AUTHPWD_TYPE_PROTOCOL);
if (ret == GTK_RESPONSE_OK)
{
......@@ -867,9 +945,9 @@ remmina_plugin_vnc_rfb_credential (rfbClient *cl, int credentialType)
case rfbCredentialTypeUser:
s1 = g_strdup (remmina_plugin_service->file_get_string (remminafile, "username"));
THREADS_ENTER
s2 = remmina_plugin_service->file_get_secret (remminafile, "password");
THREADS_LEAVE
if (gpdata->auth_first && s1 && s2)
{
cred->userCredential.username = s1;
......@@ -880,9 +958,8 @@ remmina_plugin_vnc_rfb_credential (rfbClient *cl, int credentialType)
g_free(s1);
g_free(s2);
THREADS_ENTER
ret = remmina_plugin_service->protocol_plugin_init_authuserpwd (gp, FALSE);
THREADS_LEAVE
if (ret == GTK_RESPONSE_OK)
{
......@@ -909,9 +986,8 @@ remmina_plugin_vnc_rfb_credential (rfbClient *cl, int credentialType)
}
else
{
THREADS_ENTER
ret = remmina_plugin_service->protocol_plugin_init_authx509 (gp);
THREADS_LEAVE
if (ret == GTK_RESPONSE_OK)
{
......@@ -1064,9 +1140,7 @@ static void remmina_plugin_vnc_rfb_chat(rfbClient* cl, int value, char *text)
break;
default:
/* value is the text length */
THREADS_ENTER
remmina_plugin_service->protocol_plugin_chat_receive(gp, text);
THREADS_LEAVE
break;
}
}
......@@ -1277,9 +1351,8 @@ static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp)
if (!gpdata->connected)
break;
THREADS_ENTER
remmina_plugin_service->protocol_plugin_init_show_retry(gp);
THREADS_LEAVE
/* It's safer to sleep a while before reconnect */
sleep(2);
......@@ -1299,9 +1372,7 @@ static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp)
return FALSE;
}
THREADS_ENTER
remmina_plugin_service->protocol_plugin_init_save_cred(gp);
THREADS_LEAVE
gpdata->client = cl;
......@@ -1327,7 +1398,7 @@ static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp)
return FALSE;
}
#ifdef HAVE_PTHREAD
static gpointer
remmina_plugin_vnc_main_thread (gpointer data)
{
......@@ -1337,7 +1408,7 @@ remmina_plugin_vnc_main_thread (gpointer data)
remmina_plugin_vnc_main ((RemminaProtocolWidget*) data);
return NULL;
}
#endif
static gboolean remmina_plugin_vnc_on_motion(GtkWidget *widget, GdkEventMotion *event, RemminaProtocolWidget *gp)
{
......@@ -1644,7 +1715,7 @@ static gboolean remmina_plugin_vnc_open_connection(RemminaProtocolWidget *gp)
"owner-change", G_CALLBACK(remmina_plugin_vnc_on_cuttext), gp);
}
#ifdef HAVE_PTHREAD
if (pthread_create (&gpdata->thread, NULL, remmina_plugin_vnc_main_thread, gp))
{
/* I don't think this will ever happen... */
......@@ -1652,9 +1723,6 @@ static gboolean remmina_plugin_vnc_open_connection(RemminaProtocolWidget *gp)
g_timeout_add (0, (GSourceFunc) remmina_plugin_vnc_main, gp);
gpdata->thread = 0;
}
#else
g_timeout_add(0, (GSourceFunc) remmina_plugin_vnc_main, gp);
#endif
return TRUE;
}
......@@ -1727,9 +1795,9 @@ static gboolean remmina_plugin_vnc_close_connection_timeout(RemminaProtocolWidge
close(gpdata->vnc_event_pipe[0]);
close(gpdata->vnc_event_pipe[1]);
#ifdef HAVE_PTHREAD