Commit 165b6ad3 authored by Giovanni Panozzo's avatar Giovanni Panozzo

Fixes for issue #744

parent 24cdef41
......@@ -216,7 +216,7 @@ void remmina_rdp_event_update_rect(RemminaProtocolWidget* gp, gint x, gint y, gi
gtk_widget_queue_draw_area(rfi->drawing_area, x, y, w, h);
}
static gboolean remmina_rdp_event_update_scale_factor(RemminaProtocolWidget* gp)
static void remmina_rdp_event_update_scale_factor(RemminaProtocolWidget* gp)
{
TRACE_CALL("remmina_rdp_event_update_scale_factor");
GtkAllocation a;
......@@ -260,8 +260,14 @@ static gboolean remmina_rdp_event_update_scale_factor(RemminaProtocolWidget* gp)
if ((gpwidth > 1) && (gpheight > 1))
gtk_widget_queue_draw_area(GTK_WIDGET(gp), 0, 0, gpwidth, gpheight);
rfi->scale_handler = 0;
}
static gboolean remmina_rdp_event_update_scale_factor_async(RemminaProtocolWidget* gp)
{
TRACE_CALL("remmina_rdp_event_update_scale_factor_async");
rfContext* rfi = GET_PLUGIN_DATA(gp);
rfi->scale_handler = 0;
remmina_rdp_event_update_scale_factor(gp);
return FALSE;
}
......@@ -301,7 +307,7 @@ static gboolean remmina_rdp_event_on_configure(GtkWidget* widget, GdkEventConfig
if (rfi->scale_handler)
g_source_remove(rfi->scale_handler);
rfi->scale_handler = g_timeout_add(300, (GSourceFunc) remmina_rdp_event_update_scale_factor, gp);
rfi->scale_handler = g_timeout_add(300, (GSourceFunc) remmina_rdp_event_update_scale_factor_async, gp);
return FALSE;
}
......@@ -743,6 +749,8 @@ static void remmina_rdp_event_connected(RemminaProtocolWidget* gp, RemminaPlugin
TRACE_CALL("remmina_rdp_event_connected");
rfContext* rfi = GET_PLUGIN_DATA(gp);
remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect");
gtk_widget_realize(rfi->drawing_area);
remmina_rdp_event_create_cairo_surface(rfi);
......
......@@ -359,8 +359,6 @@ static BOOL remmina_rdp_post_connect(freerdp* instance)
freerdp_channels_post_connect(instance->context->channels, instance);
rfi->connected = True;
remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect");
ui = g_new0(RemminaPluginRdpUiObject, 1);
ui->type = REMMINA_RDP_UI_CONNECTED;
rf_queue_ui(gp, ui);
......@@ -475,8 +473,6 @@ static void remmina_rdp_main_loop(RemminaProtocolWidget* gp)
gchar buf[100];
rfContext* rfi = GET_PLUGIN_DATA(gp);
while (!freerdp_shall_disconnect(rfi->instance))
{
nCount = freerdp_get_event_handles(rfi->instance->context, &handles[0], 64);
......@@ -960,7 +956,9 @@ static gpointer remmina_rdp_main_thread(gpointer data)
remmina_rdp_main(gp);
rfi->thread = 0;
IDLE_ADD((GSourceFunc) remmina_plugin_service->protocol_plugin_close_connection, gp);
/* Signal main thread that we closed the connection. But wait 200ms, because we may
* have outstaiding events to process in the meanwhile */
g_timeout_add(200, ((GSourceFunc) remmina_plugin_service->protocol_plugin_close_connection), gp);
return NULL;
}
......@@ -1034,9 +1032,6 @@ static gboolean remmina_rdp_close_connection(RemminaProtocolWidget* gp)
}
remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect");
if (instance)
{
if ( rfi->connected ) {
......@@ -1089,6 +1084,9 @@ static gboolean remmina_rdp_close_connection(RemminaProtocolWidget* gp)
/* Remove instance->context from gp object data to avoid double free */
g_object_steal_data(G_OBJECT(gp), "plugin-data");
/* Now let remmina to complete its disconnection tasks */
remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect");
return FALSE;
}
......
......@@ -139,6 +139,7 @@ struct _RemminaConnectionHolder
gboolean hostkey_activated;
gboolean hostkey_used;
};
enum
......@@ -264,13 +265,13 @@ static void remmina_connection_window_class_init(RemminaConnectionWindowClass* k
}
static void remmina_connection_holder_disconnect(RemminaConnectionHolder* cnnhld)
static void remmina_connection_holder_disconnect_current_page(RemminaConnectionHolder* cnnhld)
{
TRACE_CALL("remmina_connection_holder_disconnect");
TRACE_CALL("remmina_connection_holder_disconnect_current_page");
DECLARE_CNNOBJ
/* Notify the RemminaProtocolWidget to disconnect, but not to close the window here.
The window will be destroyed in RemminaProtocolWidget "disconnect" signal */
/* Disconnects the connection which is currently in view in the notebook */
remmina_protocol_widget_close_connection(REMMINA_PROTOCOL_WIDGET(cnnobj->proto));
}
......@@ -305,15 +306,35 @@ static void remmina_connection_holder_keyboard_grab(RemminaConnectionHolder* cnn
}
}
static void remmina_connection_window_close_all_connections(RemminaConnectionWindow* cnnwin)
{
RemminaConnectionWindowPriv* priv = cnnwin->priv;
GtkNotebook* notebook = GTK_NOTEBOOK(priv->notebook);
GtkWidget* w;
RemminaConnectionObject* cnnobj;
gint i, n;
if (GTK_IS_WIDGET(notebook))
{
n = gtk_notebook_get_n_pages(notebook);
for (i = n - 1; i >= 0; i--)
{
w = gtk_notebook_get_nth_page(notebook, i);
cnnobj = (RemminaConnectionObject*) g_object_get_data(G_OBJECT(w), "cnnobj");
/* Do close the connection on this tab */
remmina_protocol_widget_close_connection(REMMINA_PROTOCOL_WIDGET(cnnobj->proto));
}
}
}
static gboolean remmina_connection_window_delete_event(GtkWidget* widget, GdkEvent* event, gpointer data)
{
TRACE_CALL("remmina_connection_window_delete_event");
RemminaConnectionHolder* cnnhld = (RemminaConnectionHolder*) data;
RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv;
RemminaConnectionObject* cnnobj;
GtkNotebook* notebook = GTK_NOTEBOOK(priv->notebook);
GtkWidget* dialog;
GtkWidget* w;
gint i, n;
n = gtk_notebook_get_n_pages(notebook);
......@@ -327,17 +348,11 @@ static gboolean remmina_connection_window_delete_event(GtkWidget* widget, GdkEve
if (i != GTK_RESPONSE_YES)
return TRUE;
}
/* Just in case the connection already closed by the server before clicking yes */
if (GTK_IS_WIDGET(notebook))
{
n = gtk_notebook_get_n_pages(notebook);
for (i = n - 1; i >= 0; i--)
{
w = gtk_notebook_get_nth_page(notebook, i);
cnnobj = (RemminaConnectionObject*) g_object_get_data(G_OBJECT(w), "cnnobj");
remmina_protocol_widget_close_connection(REMMINA_PROTOCOL_WIDGET(cnnobj->proto));
}
}
remmina_connection_window_close_all_connections(cnnhld->cnnwin);
gtk_widget_destroy(GTK_WIDGET(cnnhld->cnnwin));
cnnhld->cnnwin = NULL;
return TRUE;
}
......@@ -384,6 +399,7 @@ static void remmina_connection_window_destroy(GtkWidget* widget, RemminaConnecti
cnnhld->cnnwin->priv = NULL;
cnnhld->cnnwin = NULL;
}
}
gboolean remmina_connection_window_notify_widget_toolbar_placement(GtkWidget *widget, gpointer data)
......@@ -1517,7 +1533,7 @@ static void remmina_connection_holder_toolbar_minimize(GtkWidget* widget, Remmin
static void remmina_connection_holder_toolbar_disconnect(GtkWidget* widget, RemminaConnectionHolder* cnnhld)
{
TRACE_CALL("remmina_connection_holder_toolbar_disconnect");
remmina_connection_holder_disconnect(cnnhld);
remmina_connection_holder_disconnect_current_page(cnnhld);
}
static void remmina_connection_holder_toolbar_grab(GtkWidget* widget, RemminaConnectionHolder* cnnhld)
......@@ -2502,12 +2518,16 @@ static void remmina_connection_holder_on_page_removed(GtkNotebook* notebook, Gtk
RemminaConnectionHolder* cnnhld)
{
TRACE_CALL("remmina_connection_holder_on_page_removed");
if (!cnnhld->cnnwin)
return;
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook)) <= 0)
{
gtk_widget_destroy(GTK_WIDGET(cnnhld->cnnwin));
cnnhld->cnnwin = NULL;
g_free(cnnhld);
}
}
GtkNotebook*
......@@ -3066,7 +3086,7 @@ static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp
}
else if (keyval == remmina_pref.shortcutkey_disconnect)
{
remmina_connection_holder_disconnect(cnnhld);
remmina_connection_holder_disconnect_current_page(cnnhld);
}
else if (keyval == remmina_pref.shortcutkey_toolbar)
{
......@@ -3218,6 +3238,18 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R
TRACE_CALL("remmina_connection_object_on_disconnect");
RemminaConnectionHolder* cnnhld = cnnobj->cnnhld;
GtkWidget* dialog;
GtkWidget* pparent;
/* Detach the protocol widget from the notebook now, or we risk that a
* window delete will destroy cnnobj->proto before we complete disconnection.
*/
pparent = gtk_widget_get_parent(cnnobj->proto);
if (pparent != NULL)
{
g_object_ref(cnnobj->proto);
gtk_container_remove(GTK_CONTAINER(pparent), cnnobj->proto);
}
cnnobj->connected = FALSE;
......@@ -3237,6 +3269,7 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R
}
}
remmina_file_free(cnnobj->remmina_file);
cnnobj->remmina_file = NULL;
if (remmina_protocol_widget_has_error(gp))
{
......@@ -3247,12 +3280,6 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R
remmina_widget_pool_register(dialog);
}
if (cnnobj->window)
{
gtk_widget_destroy(cnnobj->window);
cnnobj->window = NULL;
}
if (cnnhld && cnnhld->cnnwin && cnnobj->scrolled_container)
{
gtk_notebook_remove_page(
......
......@@ -53,14 +53,17 @@
static gboolean cb_closewidget(GtkWidget *widget, gpointer data)
{
gtk_widget_destroy(widget);
TRACE_CALL("cb_closewidget");
/* The correct way to close a remmina_connection_window is to send
* it a "delete-event" signal. Simply destroying it will not close
* all network connections */
g_signal_emit_by_name(G_OBJECT(widget), "delete-event", NULL);
return TRUE;
}
void remmina_exec_exitremmina()
{
TRACE_CALL("remmina_exec_exitremmina");
int n;
/* Destroy all widgets, main window included */
......
......@@ -99,6 +99,9 @@ static gboolean remmina_masterthread_exec_callback(RemminaMTExecData *d)
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_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,
......
......@@ -49,6 +49,7 @@ typedef struct remmina_masterthread_exec_data
FUNC_DIALOG_CERT, FUNC_DIALOG_CERTCHANGED, FUNC_DIALOG_AUTHX509,
FUNC_FTP_CLIENT_UPDATE_TASK, FUNC_FTP_CLIENT_GET_WAITING_TASK,
FUNC_SFTP_CLIENT_CONFIRM_RESUME,
FUNC_PROTOCOLWIDGET_EMIT_SIGNAL,
FUNC_VTE_TERMINAL_SET_ENCODING_AND_PTY
} func;
......@@ -133,6 +134,11 @@ typedef struct remmina_masterthread_exec_data
RemminaFTPClient *client;
RemminaFTPTask* retval;
} ftp_client_get_waiting_task;
struct
{
RemminaProtocolWidget* gp;
const gchar* signal_name;
} protocolwidget_emit_signal;
#if defined (HAVE_LIBSSH) && defined (HAVE_LIBVTE)
struct
{
......
......@@ -149,8 +149,11 @@ static void remmina_protocol_widget_destroy(RemminaProtocolWidget* gp, gpointer
TRACE_CALL("remmina_protocol_widget_destroy");
remmina_protocol_widget_hide_init_dialog(gp);
g_free(gp->priv->features);
gp->priv->features = NULL;
g_free(gp->priv->error_message);
gp->priv->error_message = NULL;
g_free(gp->priv);
gp->priv = NULL;
}
static void remmina_protocol_widget_connect(RemminaProtocolWidget* gp, gpointer data)
......@@ -427,23 +430,25 @@ void remmina_protocol_widget_send_keystrokes(RemminaProtocolWidget* gp, GtkMenuI
return;
}
static gboolean remmina_protocol_widget_emit_signal_timeout(gpointer user_data)
{
TRACE_CALL("remmina_protocol_widget_emit_signal_timeout");
RemminaProtocolWidgetSignalData* data = (RemminaProtocolWidgetSignalData*) user_data;
g_signal_emit_by_name(G_OBJECT(data->gp), data->signal_name);
g_free(data);
return FALSE;
}
void remmina_protocol_widget_emit_signal(RemminaProtocolWidget* gp, const gchar* signal_name)
{
TRACE_CALL("remmina_protocol_widget_emit_signal");
RemminaProtocolWidgetSignalData* data;
data = g_new(RemminaProtocolWidgetSignalData, 1);
data->gp = gp;
data->signal_name = signal_name;
TIMEOUT_ADD(0, remmina_protocol_widget_emit_signal_timeout, data);
if ( !remmina_masterthread_exec_is_main_thread() )
{
/* Allow the execution of this function from a non main thread */
RemminaMTExecData *d;
d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) );
d->func = FUNC_PROTOCOLWIDGET_EMIT_SIGNAL;
d->p.protocolwidget_emit_signal.signal_name = signal_name;
d->p.protocolwidget_emit_signal.gp = gp;
remmina_masterthread_exec_and_wait(d);
g_free(d);
return;
}
g_signal_emit_by_name(G_OBJECT(gp), signal_name);
}
const RemminaProtocolFeature* remmina_protocol_widget_get_features(RemminaProtocolWidget* gp)
......
......@@ -124,16 +124,29 @@ gint remmina_widget_pool_foreach(RemminaWidgetPoolForEachFunc callback, gpointer
GtkWidget *widget;
gint i;
gint n = 0;
GPtrArray *wpcpy = NULL;
if (remmina_widget_pool == NULL)
return 0;
/* Make a copy of remmina_widget_pool, so we can survive when callback()
* remove an element from remmina_widget_pool */
wpcpy = g_ptr_array_sized_new(remmina_widget_pool->len);
for (i = 0; i < remmina_widget_pool->len; i++)
g_ptr_array_add(wpcpy, g_ptr_array_index(remmina_widget_pool, i));
/* Scan the remmina_widget_pool and call callbac() on every element */
for (i = 0; i < wpcpy->len; i++)
{
widget = GTK_WIDGET(g_ptr_array_index(remmina_widget_pool, i));
widget = GTK_WIDGET(g_ptr_array_index(wpcpy, i));
if (callback(widget, data))
n++;
}
/* Free the copy */
g_ptr_array_unref(wpcpy);
return n;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment