Commit 736a2272 authored by llyzs's avatar llyzs Committed by llyzs

Some more tricks to make the SSH shell terminal resizing work correctly

git-svn-id: https://remmina.svn.sourceforge.net/svnroot/remmina/trunk@52 b6cfa94a-2857-405c-b0d6-536ef9fc39e1
parent 794c0f9e
......@@ -60,6 +60,9 @@
/*************************** SSH Base *********************************/
#define LOCK_SSH(ssh) pthread_mutex_lock (&REMMINA_SSH (ssh)->ssh_mutex);
#define UNLOCK_SSH(ssh) pthread_mutex_unlock (&REMMINA_SSH (ssh)->ssh_mutex);
static const gchar *common_identities[] = {
".ssh/id_rsa",
".ssh/id_dsa",
......@@ -754,7 +757,7 @@ remmina_ssh_tunnel_main_thread (gpointer data)
if (channel)
{
pthread_mutex_lock (&REMMINA_SSH (tunnel)->ssh_mutex);
LOCK_SSH (tunnel)
sock = remmina_public_open_xdisplay (tunnel->localdisplay);
if (sock >= 0)
......@@ -769,7 +772,7 @@ remmina_ssh_tunnel_main_thread (gpointer data)
}
channel = NULL;
pthread_mutex_unlock (&REMMINA_SSH (tunnel)->ssh_mutex);
UNLOCK_SSH (tunnel)
}
}
......@@ -885,12 +888,12 @@ remmina_ssh_tunnel_main_thread (gpointer data)
}
}
pthread_mutex_lock (&REMMINA_SSH (tunnel)->ssh_mutex);
LOCK_SSH (tunnel)
tunnel->thread = 0;
remmina_ssh_tunnel_close_all_channels (tunnel);
pthread_mutex_unlock (&REMMINA_SSH (tunnel)->ssh_mutex);
UNLOCK_SSH (tunnel)
return NULL;
}
......@@ -998,7 +1001,7 @@ remmina_ssh_tunnel_terminated (RemminaSSHTunnel* tunnel)
void
remmina_ssh_tunnel_free (RemminaSSHTunnel* tunnel)
{
pthread_mutex_lock (&REMMINA_SSH (tunnel)->ssh_mutex);
LOCK_SSH (tunnel)
if (tunnel->thread != 0)
{
......@@ -1019,7 +1022,7 @@ remmina_ssh_tunnel_free (RemminaSSHTunnel* tunnel)
}
remmina_ssh_tunnel_close_all_channels (tunnel);
pthread_mutex_unlock (&REMMINA_SSH (tunnel)->ssh_mutex);
UNLOCK_SSH (tunnel)
g_free (tunnel->buffer);
g_free (tunnel->channels_out);
......@@ -1132,9 +1135,12 @@ remmina_ssh_shell_thread (gpointer data)
gint len;
gint i, ret;
LOCK_SSH (shell)
if ((channel = channel_new (REMMINA_SSH (shell)->session)) == NULL ||
channel_open_session (channel))
{
UNLOCK_SSH (shell)
remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to open channel : %s");
if (channel) channel_free (channel);
shell->thread = 0;
......@@ -1144,6 +1150,7 @@ remmina_ssh_shell_thread (gpointer data)
channel_request_pty (channel);
if (channel_request_shell(channel))
{
UNLOCK_SSH (shell)
remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to request shell : %s");
channel_close (channel);
channel_free (channel);
......@@ -1151,6 +1158,10 @@ remmina_ssh_shell_thread (gpointer data)
return NULL;
}
shell->channel = channel;
UNLOCK_SSH (shell)
buf_len = 1000;
buf = g_malloc (buf_len + 1);
......@@ -1173,11 +1184,15 @@ remmina_ssh_shell_thread (gpointer data)
{
len = read (shell->master, buf, buf_len);
if (len <= 0) break;
LOCK_SSH (shell)
channel_write (channel, buf, len);
UNLOCK_SSH (shell)
}
for (i = 0; i < 2; i++)
{
LOCK_SSH (shell)
len = channel_poll (channel, i);
UNLOCK_SSH (shell)
if (len == SSH_ERROR || len == SSH_EOF)
{
shell->closed = TRUE;
......@@ -1189,7 +1204,9 @@ remmina_ssh_shell_thread (gpointer data)
buf_len = len;
buf = (gchar*) g_realloc (buf, buf_len + 1);
}
LOCK_SSH (shell)
len = channel_read_nonblocking (channel, buf, len, i);
UNLOCK_SSH (shell)
if (len <= 0)
{
shell->closed = TRUE;
......@@ -1204,8 +1221,12 @@ remmina_ssh_shell_thread (gpointer data)
}
}
LOCK_SSH (shell)
shell->channel = NULL;
channel_close (channel);
channel_free (channel);
UNLOCK_SSH (shell)
g_free (buf);
shell->thread = 0;
......@@ -1245,6 +1266,17 @@ remmina_ssh_shell_open (RemminaSSHShell *shell, RemminaSSHExitFunc exit_callback
return TRUE;
}
void
remmina_ssh_shell_set_size (RemminaSSHShell *shell, gint columns, gint rows)
{
LOCK_SSH (shell)
if (shell->channel)
{
channel_change_pty_size (shell->channel, columns, rows);
}
UNLOCK_SSH (shell)
}
void
remmina_ssh_shell_free (RemminaSSHShell *shell)
{
......
......@@ -186,6 +186,7 @@ typedef struct _RemminaSSHShell
gint master;
gint slave;
pthread_t thread;
ssh_channel channel;
gboolean closed;
RemminaSSHExitFunc exit_callback;
gpointer user_data;
......@@ -200,6 +201,9 @@ RemminaSSHShell* remmina_ssh_shell_new_from_ssh (RemminaSSH *ssh);
/* open the SSH Shell, assuming the session already authenticated */
gboolean remmina_ssh_shell_open (RemminaSSHShell *shell, RemminaSSHExitFunc exit_callback, gpointer data);
/* Change the SSH Shell terminal size */
void remmina_ssh_shell_set_size (RemminaSSHShell *shell, gint columns, gint rows);
/* Free the SFTP session */
void remmina_ssh_shell_free (RemminaSSHShell *shell);
......
......@@ -31,6 +31,56 @@
#include "remminaprotocolwidget.h"
#include "remminasshplugin.h"
/***** A VTE-Terminal subclass to override the size_request behavior *****/
#define REMMINA_TYPE_VTE (remmina_vte_get_type ())
#define REMMINA_VTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), REMMINA_TYPE_VTE, RemminaVte))
#define REMMINA_VTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), REMMINA_TYPE_VTE, RemminaVteClass))
#define REMMINA_IS_VTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), REMMINA_TYPE_VTE))
#define REMMINA_IS_VTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), REMMINA_TYPE_VTE))
#define REMMINA_VTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REMMINA_TYPE_VTE, RemminaVteClass))
typedef struct _RemminaVte
{
VteTerminal vte;
} RemminaVte;
typedef struct _RemminaVteClass
{
VteTerminalClass parent_class;
} RemminaVteClass;
GType remmina_vte_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (RemminaVte, remmina_vte, VTE_TYPE_TERMINAL)
static void
remmina_vte_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
requisition->width = -1;
requisition->height = -1;
}
static void
remmina_vte_class_init (RemminaVteClass *klass)
{
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->size_request = remmina_vte_size_request;
}
static void
remmina_vte_init (RemminaVte *vte)
{
}
static GtkWidget*
remmina_vte_new (void)
{
return GTK_WIDGET (g_object_new (REMMINA_TYPE_VTE, NULL));
}
/***** The SSH plugin implementation *****/
typedef struct _RemminaPluginSshData
{
RemminaSSHShell *shell;
......@@ -138,10 +188,22 @@ remmina_plugin_ssh_on_focus_in (GtkWidget *widget, GdkEventFocus *event, Remmina
return TRUE;
}
static void
remmina_plugin_ssh_on_resize_window (VteTerminal *vte, guint x, guint y, RemminaProtocolWidget *gp)
static gboolean
remmina_plugin_ssh_on_size_allocate (GtkWidget *widget, GtkAllocation *alloc, RemminaProtocolWidget *gp)
{
g_print ("%i x %i\n", x, y);
RemminaPluginSshData *gpdata;
gint cols, rows;
if (!GTK_WIDGET_MAPPED (widget)) return FALSE;
gpdata = (RemminaPluginSshData*) g_object_get_data (G_OBJECT (gp), "plugin-data");
cols = vte_terminal_get_column_count (VTE_TERMINAL (widget));
rows = vte_terminal_get_row_count (VTE_TERMINAL (widget));
remmina_ssh_shell_set_size (gpdata->shell, cols, rows);
return FALSE;
}
static void
......@@ -160,13 +222,13 @@ remmina_plugin_ssh_init (RemminaProtocolWidget *gp)
gtk_container_add (GTK_CONTAINER (gp), hbox);
g_signal_connect (G_OBJECT (hbox), "focus-in-event", G_CALLBACK (remmina_plugin_ssh_on_focus_in), gp);
vte = vte_terminal_new ();
vte = remmina_vte_new ();
gtk_widget_show (vte);
vte_terminal_set_size (VTE_TERMINAL (vte), 80, 25);
vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL (vte), TRUE);
gtk_box_pack_start (GTK_BOX (hbox), vte, TRUE, TRUE, 0);
g_signal_connect (G_OBJECT (vte), "resize-window", G_CALLBACK (remmina_plugin_ssh_on_resize_window), gp);
gpdata->vte = vte;
g_signal_connect (G_OBJECT (vte), "size-allocate", G_CALLBACK (remmina_plugin_ssh_on_size_allocate), gp);
vscrollbar = gtk_vscrollbar_new (vte_terminal_get_adjustment (VTE_TERMINAL (vte)));
gtk_widget_show (vscrollbar);
......
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