[hotssh] Add API to request pty size, use it
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hotssh] Add API to request pty size, use it
- Date: Thu, 10 Oct 2013 23:28:26 +0000 (UTC)
commit 25f66c9ea130913260d93bea3f2c3de8cfb43705
Author: Colin Walters <walters verbum org>
Date: Thu Oct 10 19:13:24 2013 -0400
Add API to request pty size, use it
libgssh/gssh-channel-private.h | 13 +++++++-
libgssh/gssh-channel.c | 65 ++++++++++++++++++++++++++++++++++++++-
libgssh/gssh-channel.h | 11 +++++++
libgssh/gssh-connection.c | 2 +-
src/hotssh-win.c | 60 ++++++++++++++++++++++++++++++++++++-
5 files changed, 145 insertions(+), 6 deletions(-)
---
diff --git a/libgssh/gssh-channel-private.h b/libgssh/gssh-channel-private.h
index 6f9d7dd..2b861c1 100644
--- a/libgssh/gssh-channel-private.h
+++ b/libgssh/gssh-channel-private.h
@@ -30,7 +30,12 @@ struct _GSshChannel
GIOStream parent;
GSshConnection *connection;
+ gboolean have_pty;
LIBSSH2_CHANNEL *libsshchannel;
+
+ GTask *pty_size_task;
+ guint pty_width;
+ guint pty_height;
GSshChannelInputStream *input_stream;
GSshChannelOutputStream *output_stream;
@@ -41,5 +46,9 @@ struct _GSshChannelClass
GIOStreamClass parent_class;
};
-GSshChannel *_gssh_channel_new (GSshConnection *connection,
- LIBSSH2_CHANNEL *libsshchannel);
+GSshChannel *_gssh_channel_new (GSshConnection *connection,
+ gboolean have_pty,
+ LIBSSH2_CHANNEL *libsshchannel);
+
+
+void _gssh_channel_iteration (GSshChannel *self);
diff --git a/libgssh/gssh-channel.c b/libgssh/gssh-channel.c
index a212809..f2c92ae 100644
--- a/libgssh/gssh-channel.c
+++ b/libgssh/gssh-channel.c
@@ -86,6 +86,65 @@ gssh_channel_close_finish (GIOStream *stream,
return G_IO_STREAM_CLASS (gssh_channel_parent_class)->close_finish (stream, result, error);
}
+void
+_gssh_channel_iteration (GSshChannel *self)
+{
+ int rc;
+ GError *local_error = NULL;
+
+ if (self->pty_size_task)
+ {
+ GTask *orig_pty_size_task = self->pty_size_task;
+ rc = libssh2_channel_request_pty_size (self->libsshchannel,
+ self->pty_width, self->pty_height);
+ if (rc == LIBSSH2_ERROR_EAGAIN)
+ ;
+ else
+ {
+ self->pty_size_task = NULL;
+ if (rc < 0)
+ {
+ _gssh_set_error_from_libssh2 (&local_error, "Failed to set pty size",
+ self->connection->session);
+ g_task_return_error (orig_pty_size_task, local_error);
+ }
+ else
+ {
+ g_assert (rc == 0);
+ g_task_return_boolean (orig_pty_size_task, TRUE);
+ }
+ g_object_unref (orig_pty_size_task);
+ }
+ }
+}
+
+void
+gssh_channel_request_pty_size_async (GSshChannel *self,
+ guint width,
+ guint height,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (self->have_pty);
+ g_return_if_fail (self->pty_size_task == NULL);
+
+ self->pty_size_task = g_task_new (self, cancellable, callback, user_data);
+ self->pty_width = width;
+ self->pty_height = height;
+
+ _gssh_channel_iteration (self);
+}
+
+gboolean
+gssh_channel_request_pty_size_finish (GSshChannel *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
static void
gssh_channel_init (GSshChannel *self)
{
@@ -114,14 +173,16 @@ gssh_channel_class_init (GSshChannelClass *class)
}
GSshChannel *
-_gssh_channel_new (GSshConnection *connection,
- LIBSSH2_CHANNEL *libsshchannel)
+_gssh_channel_new (GSshConnection *connection,
+ gboolean have_pty,
+ LIBSSH2_CHANNEL *libsshchannel)
{
GSshChannel *self = (GSshChannel*)g_object_new (GSSH_TYPE_CHANNEL, NULL);
/* We don't hold a ref; if the connection goes away, it will ensure
* this pointer is zeroed.
*/
self->connection = connection;
+ self->have_pty = have_pty;
self->libsshchannel = libsshchannel;
return self;
}
diff --git a/libgssh/gssh-channel.h b/libgssh/gssh-channel.h
index 9575b69..33d4a29 100644
--- a/libgssh/gssh-channel.h
+++ b/libgssh/gssh-channel.h
@@ -28,3 +28,14 @@
typedef struct _GSshChannelClass GSshChannelClass;
GType gssh_channel_get_type (void);
+
+void gssh_channel_request_pty_size_async (GSshChannel *self,
+ guint width,
+ guint height,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gssh_channel_request_pty_size_finish (GSshChannel *self,
+ GAsyncResult *res,
+ GError **error);
diff --git a/libgssh/gssh-connection.c b/libgssh/gssh-connection.c
index 21d55a8..8a5cd27 100644
--- a/libgssh/gssh-connection.c
+++ b/libgssh/gssh-connection.c
@@ -297,7 +297,7 @@ process_channels (GSshConnection *self,
g_assert (rc == 0);
- new_channel = _gssh_channel_new (self, data->libssh2channel);
+ new_channel = _gssh_channel_new (self, TRUE, data->libssh2channel);
g_hash_table_insert (self->channels, new_channel, new_channel);
g_task_return_pointer (task, new_channel, g_object_unref);
diff --git a/src/hotssh-win.c b/src/hotssh-win.c
index 7f1c338..c8a33c3 100644
--- a/src/hotssh-win.c
+++ b/src/hotssh-win.c
@@ -1,6 +1,6 @@
#include "hotssh-app.h"
#include "hotssh-win.h"
-#include "gssh-connection.h"
+#include "gssh.h"
#include "libgsystem.h"
@@ -52,6 +52,8 @@ struct _HotSshWindowPrivate
GSshConnection *connection;
GSshChannel *channel;
+ gboolean need_pty_size_request;
+ gboolean sent_pty_size_request;
gboolean have_outstanding_write;
gboolean have_outstanding_auth;
GQueue write_queue;
@@ -424,6 +426,61 @@ on_connect_cancel (GtkButton *button,
}
static void
+send_pty_size_request (HotSshWindow *self);
+
+static void
+on_pty_size_complete (GObject *src,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ HotSshWindow *self = user_data;
+ HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
+ GError *local_error = NULL;
+
+ g_debug ("pty size request complete");
+ priv->sent_pty_size_request = FALSE;
+
+ if (!gssh_channel_request_pty_size_finish (priv->channel, result, &local_error))
+ goto out;
+
+ if (priv->need_pty_size_request)
+ send_pty_size_request (self);
+
+ out:
+ if (local_error)
+ page_transition_take_error (self, local_error);
+}
+
+static void
+send_pty_size_request (HotSshWindow *self)
+{
+ HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
+ guint width = vte_terminal_get_column_count ((VteTerminal*)priv->terminal);
+ guint height = vte_terminal_get_row_count ((VteTerminal*)priv->terminal);
+
+ priv->need_pty_size_request = FALSE;
+ priv->sent_pty_size_request = TRUE;
+ gssh_channel_request_pty_size_async (priv->channel, width, height,
+ priv->cancellable, on_pty_size_complete, self);
+}
+
+static void
+on_terminal_size_allocate (GtkWidget *widget,
+ GdkRectangle *allocation,
+ gpointer user_data)
+{
+ HotSshWindow *self = user_data;
+ HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
+
+ if (priv->channel)
+ {
+ priv->need_pty_size_request = TRUE;
+ if (!priv->sent_pty_size_request)
+ send_pty_size_request (self);
+ }
+}
+
+static void
hotssh_window_init (HotSshWindow *self)
{
HotSshWindowPrivate *priv = hotssh_window_get_instance_private (self);
@@ -438,6 +495,7 @@ hotssh_window_init (HotSshWindow *self)
g_signal_connect_swapped (priv->password_submit, "clicked", G_CALLBACK (submit_password), self);
priv->terminal = vte_terminal_new ();
+ g_signal_connect ((GObject*)priv->terminal, "size-allocate", G_CALLBACK (on_terminal_size_allocate), self);
g_signal_connect ((GObject*)priv->terminal, "commit", G_CALLBACK (on_terminal_commit), self);
gtk_box_pack_start ((GtkBox*)priv->terminal_box, (GtkWidget*)priv->terminal, TRUE, TRUE, 0);
gtk_widget_show_all (priv->terminal_box);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]