Skip to content

Commit

Permalink
Fixes for issue #744
Browse files Browse the repository at this point in the history
  • Loading branch information
giox069 committed Jan 31, 2016
1 parent 24cdef4 commit b606256
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 53 deletions.
14 changes: 11 additions & 3 deletions remmina-plugins/rdp/rdp_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 6 additions & 8 deletions remmina-plugins/rdp/rdp_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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;
}

Expand Down
80 changes: 54 additions & 26 deletions remmina/src/remmina_connection_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ struct _RemminaConnectionHolder

gboolean hostkey_activated;
gboolean hostkey_used;

gboolean preventCnnwinDestroyOnLastPageRemoval;
};

enum
Expand Down Expand Up @@ -264,13 +266,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));
}

Expand Down Expand Up @@ -305,15 +307,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);
Expand All @@ -327,17 +349,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;
}

Expand Down Expand Up @@ -384,6 +400,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)
Expand Down Expand Up @@ -1517,7 +1534,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)
Expand Down Expand Up @@ -2502,12 +2519,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*
Expand Down Expand Up @@ -3066,7 +3087,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)
{
Expand Down Expand Up @@ -3218,6 +3239,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;

Expand All @@ -3237,6 +3270,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))
{
Expand All @@ -3247,12 +3281,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(
Expand Down
7 changes: 5 additions & 2 deletions remmina/src/remmina_exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
3 changes: 3 additions & 0 deletions remmina/src/remmina_masterthread_exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions remmina/src/remmina_masterthread_exec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
{
Expand Down
31 changes: 18 additions & 13 deletions remmina/src/remmina_protocol_widget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 14 additions & 1 deletion remmina/src/remmina_widget_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit b606256

Please sign in to comment.