[vinagre] Added VNC listen mode. Closes #578717.
- From: Jonh Wendell <jwendell src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [vinagre] Added VNC listen mode. Closes #578717.
- Date: Tue, 29 Sep 2009 18:50:49 +0000 (UTC)
commit 755cbe72145c3e0e95a139748bf3d059bde78831
Author: Jonh Wendell <jwendell gnome org>
Date: Tue Sep 29 15:50:07 2009 -0300
Added VNC listen mode. Closes #578717.
plugins/vnc/Makefile.am | 11 +-
plugins/vnc/vinagre-vnc-listener-dialog.c | 252 +++++++++++++++++++++++++++
plugins/vnc/vinagre-vnc-listener-dialog.h | 34 ++++
plugins/vnc/vinagre-vnc-listener.c | 265 +++++++++++++++++++++++++++++
plugins/vnc/vinagre-vnc-listener.h | 62 +++++++
plugins/vnc/vinagre-vnc-plugin.c | 108 ++++++++++++-
plugins/vnc/vnc.ui | 258 ++++++++++++++++++++++++++++
7 files changed, 984 insertions(+), 6 deletions(-)
---
diff --git a/plugins/vnc/Makefile.am b/plugins/vnc/Makefile.am
index 682c0f0..3b2927c 100644
--- a/plugins/vnc/Makefile.am
+++ b/plugins/vnc/Makefile.am
@@ -12,13 +12,15 @@ plugin_LTLIBRARIES = libvnc.la
libvnc_la_SOURCES = \
vinagre-vnc-plugin.h vinagre-vnc-plugin.c \
vinagre-vnc-connection.h vinagre-vnc-connection.c \
- vinagre-vnc-tab.h vinagre-vnc-tab.c
+ vinagre-vnc-tab.h vinagre-vnc-tab.c \
+ vinagre-vnc-listener.h vinagre-vnc-listener.c \
+ vinagre-vnc-listener-dialog.h vinagre-vnc-listener-dialog.c
libvnc_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libvnc_la_LIBADD = $(VNC_LIBS)
-#uidir = $(VINAGRE_PLUGINS_DATA_DIR)/vnc
-#ui_DATA = vnc.ui
+uidir = $(VINAGRE_PLUGINS_DATA_DIR)/vnc
+ui_DATA = vnc.ui
plugin_in_files = vnc.vinagre-plugin.desktop.in
@@ -26,8 +28,7 @@ vnc.vinagre-plugin: vnc.vinagre-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $
plugin_DATA = $(plugin_in_files:.vinagre-plugin.desktop.in=.vinagre-plugin)
-#EXTRA_DIST = $(ui_DATA) $(plugin_in_files)
-EXTRA_DIST = $(plugin_in_files)
+EXTRA_DIST = $(ui_DATA) $(plugin_in_files)
CLEANFILES = $(plugin_DATA)
DISTCLEANFILES = $(plugin_DATA)
diff --git a/plugins/vnc/vinagre-vnc-listener-dialog.c b/plugins/vnc/vinagre-vnc-listener-dialog.c
new file mode 100644
index 0000000..15f4eb5
--- /dev/null
+++ b/plugins/vnc/vinagre-vnc-listener-dialog.c
@@ -0,0 +1,252 @@
+/*
+ * vinagre-vnc-listener-dialog.c
+ * This file is part of vinagre
+ *
+ * Copyright (C) 2009 Jonh Wendell <wendell bani com br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <vinagre/vinagre-utils.h>
+#include <vinagre/vinagre-prefs.h>
+#include "vinagre-vnc-listener-dialog.h"
+#include "vinagre-vnc-listener.h"
+
+typedef struct
+{
+ GtkBuilder *xml;
+ GtkWidget *dialog;
+ GtkWidget *enable_reverse_check;
+ GtkWidget *always_enabled_check;
+ GtkWidget *port_label;
+ GtkWidget *connectivity_exp;
+ GtkTextBuffer *ip_buffer;
+} VncListenDialog;
+
+static void
+setup_ip_buffer (VncListenDialog *dialog)
+{
+ char buf[INET6_ADDRSTRLEN], *dup;
+ struct ifaddrs *myaddrs, *ifa;
+ void *sin;
+ GArray *ipv4, *ipv6;
+ GString *str;
+ int i;
+
+ ipv4 = g_array_new (FALSE, TRUE, sizeof (char *));
+ ipv6 = g_array_new (FALSE, TRUE, sizeof (char *));
+ str = g_string_new (NULL);
+
+ getifaddrs (&myaddrs);
+ for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0 || strncmp (ifa->ifa_name, "lo", 2) == 0)
+ continue;
+
+ switch (ifa->ifa_addr->sa_family)
+ {
+ case AF_INET:
+ sin = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
+ inet_ntop (AF_INET, sin, buf, INET6_ADDRSTRLEN);
+ dup = g_strdup (buf);
+ g_array_append_val (ipv4, dup);
+ break;
+
+ case AF_INET6:
+ sin = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ inet_ntop (AF_INET6, sin, buf, INET6_ADDRSTRLEN);
+ dup = g_strdup (buf);
+ g_array_append_val (ipv6, dup);
+ break;
+ default: continue;
+ }
+ }
+
+ if (ipv4->len > 0)
+ {
+ if (ipv6->len > 0)
+ g_string_append (str, _("IPv4:"));
+
+ for (i = 0; i < ipv4->len; i++)
+ {
+ dup = g_array_index (ipv4, char *, i);
+ g_string_append_printf (str, "\n%s", dup);
+ g_free (dup);
+ }
+ }
+ if (ipv6->len > 0)
+ {
+ if (ipv4->len > 0)
+ g_string_append (str, _("\n\nIPv6:"));
+
+ for (i = 0; i < ipv6->len; i++)
+ {
+ dup = g_array_index (ipv6, char *, i);
+ g_string_append_printf (str, "\n%s", g_array_index (ipv6, char *, i));
+ g_free (dup);
+ }
+ }
+
+ gtk_text_buffer_set_text (dialog->ip_buffer, str->str, -1);
+
+ freeifaddrs (myaddrs);
+ g_array_free (ipv4, TRUE);
+ g_array_free (ipv6, TRUE);
+ g_string_free (str, TRUE);
+}
+
+static void
+dialog_destroy (GtkObject *obj,
+ VncListenDialog *dialog)
+{
+ g_object_unref (dialog->xml);
+ g_slice_free (VncListenDialog, dialog);
+}
+
+static void
+dialog_response_handler (GtkDialog *widget,
+ gint res_id,
+ VncListenDialog *dialog)
+{
+ switch (res_id)
+ {
+ case GTK_RESPONSE_HELP:
+ // TODO: display the help
+ break;
+
+ default:
+ gtk_widget_destroy (dialog->dialog);
+ break;
+ }
+}
+
+static void
+update_ui_sensitivity (VncListenDialog *dialog)
+{
+ gboolean listening;
+ gchar *str;
+ VinagreVncListener *listener = vinagre_vnc_listener_get_default ();
+
+ listening = vinagre_vnc_listener_is_listening (listener);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->enable_reverse_check),
+ listening);
+ gtk_widget_set_sensitive (dialog->always_enabled_check, listening);
+ gtk_widget_set_sensitive (dialog->connectivity_exp, listening);
+
+ if (listening)
+ {
+ str = g_strdup_printf (_("On the port %d"), vinagre_vnc_listener_get_port (listener));
+ gtk_label_set_label (GTK_LABEL (dialog->port_label), str);
+ g_free (str);
+ }
+ else
+ {
+ gtk_expander_set_expanded (GTK_EXPANDER (dialog->connectivity_exp), FALSE);
+ }
+}
+
+static void
+enable_reverse_toggled_cb (GtkToggleButton *button, VncListenDialog *dialog)
+{
+ VinagreVncListener *listener = vinagre_vnc_listener_get_default ();
+
+ if (gtk_toggle_button_get_active (button))
+ vinagre_vnc_listener_start (listener);
+ else
+ vinagre_vnc_listener_stop (listener);
+
+ update_ui_sensitivity (dialog);
+}
+
+static void
+always_enabled_toggled_cb (GtkToggleButton *button, VncListenDialog *dialog)
+{
+ g_object_set (vinagre_prefs_get_default (),
+ "always-enable-listening", gtk_toggle_button_get_active (button),
+ NULL);
+}
+
+void
+vinagre_vnc_listener_dialog_show (VinagreWindow *parent, VinagrePlugin *plugin)
+{
+ VncListenDialog *dialog;
+ GtkBuilder *xml;
+ gboolean always;
+
+ xml = vinagre_utils_get_builder (plugin, "vnc.ui");
+ if (!xml)
+ return;
+
+ dialog = g_slice_new (VncListenDialog);
+ dialog->xml = xml;
+
+ dialog->dialog = GTK_WIDGET (gtk_builder_get_object (xml, "listener_dialog"));
+ g_assert (dialog->dialog != NULL);
+
+ dialog->ip_buffer = GTK_TEXT_BUFFER (gtk_builder_get_object (xml, "ip_textbuffer"));
+ g_assert (dialog->ip_buffer != NULL);
+ setup_ip_buffer (dialog);
+
+ dialog->enable_reverse_check = GTK_WIDGET (gtk_builder_get_object (xml, "enable_reverse_check"));
+ g_assert (dialog->enable_reverse_check != NULL);
+ g_signal_connect (dialog->enable_reverse_check,
+ "toggled",
+ G_CALLBACK (enable_reverse_toggled_cb),
+ dialog);
+
+ dialog->always_enabled_check = GTK_WIDGET (gtk_builder_get_object (xml, "always_enabled_check"));
+ g_assert (dialog->always_enabled_check != NULL);
+ g_object_get (vinagre_prefs_get_default (),
+ "always-enable-listening", &always,
+ NULL);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->always_enabled_check),
+ always);
+ g_signal_connect (dialog->always_enabled_check,
+ "toggled",
+ G_CALLBACK (always_enabled_toggled_cb),
+ dialog);
+
+ dialog->connectivity_exp = GTK_WIDGET (gtk_builder_get_object (xml, "connectivity_exp"));
+ g_assert (dialog->connectivity_exp != NULL);
+
+ dialog->port_label = GTK_WIDGET (gtk_builder_get_object (xml, "port_label"));
+ g_assert (dialog->port_label != NULL);
+
+ update_ui_sensitivity (dialog);
+
+ g_signal_connect (dialog->dialog,
+ "destroy",
+ G_CALLBACK (dialog_destroy),
+ dialog);
+
+ g_signal_connect (dialog->dialog,
+ "response",
+ G_CALLBACK (dialog_response_handler),
+ dialog);
+
+ if (GTK_IS_WINDOW (parent))
+ gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent));
+
+ gtk_widget_show_all (dialog->dialog);
+}
+
+/* vim: set ts=8: */
diff --git a/plugins/vnc/vinagre-vnc-listener-dialog.h b/plugins/vnc/vinagre-vnc-listener-dialog.h
new file mode 100644
index 0000000..8c6a8d2
--- /dev/null
+++ b/plugins/vnc/vinagre-vnc-listener-dialog.h
@@ -0,0 +1,34 @@
+/*
+ * vinagre-vnc-listener-dialog.h
+ * This file is part of vinagre
+ *
+ * Copyright (C) 2009 Jonh Wendell <wendell bani com br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VINAGRE_VNC_LISTENER_DIALOG_H__
+#define __VINAGRE_VNC_LISTENER_DIALOG_H__
+
+#include <vinagre/vinagre-window.h>
+#include <vinagre/vinagre-plugin.h>
+
+G_BEGIN_DECLS
+
+void vinagre_vnc_listener_dialog_show (VinagreWindow *parent, VinagrePlugin *plugin);
+
+G_END_DECLS
+
+#endif /* __VINAGRE_VNC_LISTENER_DIALOG_H__ */
+/* vim: set ts=8: */
diff --git a/plugins/vnc/vinagre-vnc-listener.c b/plugins/vnc/vinagre-vnc-listener.c
new file mode 100644
index 0000000..b7c301e
--- /dev/null
+++ b/plugins/vnc/vinagre-vnc-listener.c
@@ -0,0 +1,265 @@
+/*
+ * vinagre-vnc-listener.c
+ * This file is part of vinagre
+ *
+ * Copyright (C) 2009 - Jonh Wendell <wendell bani com br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <vinagre/vinagre-commands.h>
+#include <vinagre/vinagre-app.h>
+#include "vinagre-vnc-listener.h"
+#include "vinagre-vnc-connection.h"
+
+struct _VinagreVncListenerPrivate
+{
+ int server_sock;
+ GIOChannel *io;
+ gboolean listening;
+ guint io_uid;
+ gint port;
+};
+
+enum
+{
+ PROP_0,
+ PROP_LISTENING,
+ PROP_PORT
+};
+
+static VinagreVncListener *listener_singleton = NULL;
+
+#define VINAGRE_VNC_LISTENER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VINAGRE_TYPE_VNC_LISTENER, VinagreVncListenerPrivate))
+G_DEFINE_TYPE (VinagreVncListener, vinagre_vnc_listener, G_TYPE_OBJECT);
+
+static void
+vinagre_vnc_listener_init (VinagreVncListener *listener)
+{
+ listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener, VINAGRE_TYPE_VNC_LISTENER, VinagreVncListenerPrivate);
+
+ listener->priv->io = NULL;
+ listener->priv->server_sock = 0;
+ listener->priv->listening = FALSE;
+ listener->priv->io_uid = 0;
+ listener->priv->port = 0;
+}
+
+static void
+vinagre_vnc_listener_dispose (GObject *object)
+{
+ VinagreVncListener *listener = VINAGRE_VNC_LISTENER (object);
+
+ vinagre_vnc_listener_stop (listener);
+
+ G_OBJECT_CLASS (vinagre_vnc_listener_parent_class)->dispose (object);
+}
+
+static void
+vinagre_vnc_listener_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ VinagreVncListener *listener;
+
+ g_return_if_fail (VINAGRE_IS_VNC_LISTENER (object));
+
+ listener = VINAGRE_VNC_LISTENER (object);
+
+ switch (prop_id)
+ {
+ case PROP_LISTENING:
+ g_value_set_boolean (value, listener->priv->listening);
+ break;
+
+ case PROP_PORT:
+ g_value_set_int (value, vinagre_vnc_listener_get_port (listener));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+vinagre_vnc_listener_class_init (VinagreVncListenerClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (VinagreVncListenerPrivate));
+
+ object_class->dispose = vinagre_vnc_listener_dispose;
+ object_class->get_property = vinagre_vnc_listener_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_LISTENING,
+ g_param_spec_boolean ("listening",
+ "Listening",
+ "If we are listening for incoming (reverse) VNC connections",
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (object_class,
+ PROP_PORT,
+ g_param_spec_int ("port",
+ "Port",
+ "TCP port in which we are listening for reverse connections",
+ 5500,
+ 5600,
+ 5500,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB));
+
+}
+
+VinagreVncListener *
+vinagre_vnc_listener_get_default (void)
+{
+ if (G_UNLIKELY (!listener_singleton))
+ listener_singleton = VINAGRE_VNC_LISTENER (g_object_new (VINAGRE_TYPE_VNC_LISTENER, NULL));
+
+ return listener_singleton;
+}
+
+static gboolean
+incoming (GIOChannel *source, GIOCondition condition, VinagreVncListener *listener)
+{
+ VinagreConnection *conn;
+ VinagreWindow *window;
+ int cl_sock;
+ struct sockaddr_in6 client_addr;
+ char client_name[INET6_ADDRSTRLEN];
+ socklen_t client_addr_len = sizeof (client_addr);
+
+ cl_sock = accept (listener->priv->server_sock, (struct sockaddr *) &client_addr, &client_addr_len);
+ if (cl_sock < 0)
+ g_error ("accept() failed");
+
+ window = vinagre_app_get_active_window (vinagre_app_get_default ());
+ if (!window)
+ {
+ g_warning (_("Incoming VNC connection arrived but there is none active window"));
+ return TRUE;
+ }
+
+ conn = vinagre_vnc_connection_new ();
+ vinagre_vnc_connection_set_fd (VINAGRE_VNC_CONNECTION (conn), cl_sock);
+
+ if (inet_ntop (AF_INET6, &client_addr.sin6_addr.s6_addr, client_name, sizeof (client_name)) != NULL)
+ vinagre_connection_set_host (conn, client_name);
+ vinagre_connection_set_port (conn, ntohs (client_addr.sin6_port));
+
+ vinagre_cmd_direct_connect (conn, window);
+
+ return TRUE;
+}
+
+void
+vinagre_vnc_listener_start (VinagreVncListener *listener)
+{
+ struct sockaddr_in6 server_addr;
+ int port;
+
+ g_return_if_fail (VINAGRE_IS_VNC_LISTENER (listener));
+
+ if (listener->priv->listening)
+ return;
+
+ listener->priv->server_sock = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ if (listener->priv->server_sock < 0)
+ g_error ("socket() failed");
+
+ memset (&server_addr, 0, sizeof (server_addr));
+ server_addr.sin6_family = AF_INET6;
+ server_addr.sin6_addr = in6addr_any;
+
+ for (port=5500; port<=5600; port++)
+ {
+ server_addr.sin6_port = htons (port);
+
+ if (bind (listener->priv->server_sock, (struct sockaddr *) &server_addr, sizeof (server_addr)) == 0)
+ break;
+ }
+ if (port>5600)
+ g_error ("bind() failed");
+
+ if (listen (listener->priv->server_sock, 5) < 0)
+ g_error ("listen() failed");
+
+ listener->priv->io = g_io_channel_unix_new (listener->priv->server_sock);
+ listener->priv->io_uid = g_io_add_watch (listener->priv->io, G_IO_IN, (GIOFunc)incoming, listener);
+
+ listener->priv->port = port;
+ listener->priv->listening = TRUE;
+ g_object_notify (G_OBJECT (listener), "listening");
+}
+
+void
+vinagre_vnc_listener_stop (VinagreVncListener *listener)
+{
+ g_return_if_fail (VINAGRE_IS_VNC_LISTENER (listener));
+
+ if (!listener->priv->listening)
+ return;
+
+ if (listener->priv->io)
+ {
+ g_source_remove (listener->priv->io_uid);
+ g_io_channel_unref (listener->priv->io);
+ listener->priv->io = NULL;
+ }
+
+ if (listener->priv->server_sock > 0)
+ {
+ close (listener->priv->server_sock);
+ listener->priv->server_sock = 0;
+ }
+
+ listener->priv->listening = FALSE;
+ g_object_notify (G_OBJECT (listener), "listening");
+}
+
+gboolean
+vinagre_vnc_listener_is_listening (VinagreVncListener *listener)
+{
+ g_return_val_if_fail (VINAGRE_IS_VNC_LISTENER (listener), FALSE);
+
+ return listener->priv->listening;
+}
+
+gint
+vinagre_vnc_listener_get_port (VinagreVncListener *listener)
+{
+ g_return_val_if_fail (VINAGRE_IS_VNC_LISTENER (listener), 0);
+
+ return listener->priv->listening ? listener->priv->port : 0;
+}
+
+/* vim: set ts=8: */
diff --git a/plugins/vnc/vinagre-vnc-listener.h b/plugins/vnc/vinagre-vnc-listener.h
new file mode 100644
index 0000000..f68c4b0
--- /dev/null
+++ b/plugins/vnc/vinagre-vnc-listener.h
@@ -0,0 +1,62 @@
+/*
+ * vinagre-vnc-listener.h
+ * This file is part of vinagre
+ *
+ * Copyright (C) 2009 - Jonh Wendell <wendell bani com br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VINAGRE_VNC_LISTENER_H__
+#define __VINAGRE_VNC_LISTENER_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define VINAGRE_TYPE_VNC_LISTENER (vinagre_vnc_listener_get_type ())
+#define VINAGRE_VNC_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VINAGRE_TYPE_VNC_LISTENER, VinagreVncListener))
+#define VINAGRE_VNC_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VINAGRE_TYPE_VNC_LISTENER, VinagreVncListenerClass))
+#define VINAGRE_IS_VNC_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VINAGRE_TYPE_VNC_LISTENER))
+#define VINAGRE_IS_VNC_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VINAGRE_TYPE_VNC_LISTENER))
+#define VINAGRE_VNC_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VINAGRE_TYPE_VNC_LISTENER, VinagreVncListenerClass))
+
+typedef struct _VinagreVncListenerClass VinagreVncListenerClass;
+typedef struct _VinagreVncListener VinagreVncListener;
+typedef struct _VinagreVncListenerPrivate VinagreVncListenerPrivate;
+
+struct _VinagreVncListenerClass
+{
+ GObjectClass parent_class;
+};
+
+struct _VinagreVncListener
+{
+ GObject parent_instance;
+ VinagreVncListenerPrivate *priv;
+};
+
+
+GType vinagre_vnc_listener_get_type (void) G_GNUC_CONST;
+
+VinagreVncListener* vinagre_vnc_listener_get_default (void);
+void vinagre_vnc_listener_start (VinagreVncListener *listener);
+void vinagre_vnc_listener_stop (VinagreVncListener *listener);
+gboolean vinagre_vnc_listener_is_listening (VinagreVncListener *listener);
+gint vinagre_vnc_listener_get_port (VinagreVncListener *listener);
+
+G_END_DECLS
+
+#endif /* __VINAGRE_VNC_LISTENER_H__ */
+/* vim: set ts=8: */
diff --git a/plugins/vnc/vinagre-vnc-plugin.c b/plugins/vnc/vinagre-vnc-plugin.c
index 2a3c156..16646d8 100644
--- a/plugins/vnc/vinagre-vnc-plugin.c
+++ b/plugins/vnc/vinagre-vnc-plugin.c
@@ -28,28 +28,134 @@
#include <vncdisplay.h>
#include <vinagre/vinagre-debug.h>
-#include <vinagre/vinagre-utils.h>
+#include <vinagre/vinagre-prefs.h>
#include "vinagre-vnc-plugin.h"
#include "vinagre-vnc-connection.h"
#include "vinagre-vnc-tab.h"
+#include "vinagre-vnc-listener-dialog.h"
+#include "vinagre-vnc-listener.h"
#define VINAGRE_VNC_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), VINAGRE_TYPE_VNC_PLUGIN, VinagreVncPluginPrivate))
+#define WINDOW_DATA_KEY "VinagreVNCPluginWindowData"
VINAGRE_PLUGIN_REGISTER_TYPE(VinagreVncPlugin, vinagre_vnc_plugin)
+typedef struct
+{
+ GtkActionGroup *ui_action_group;
+ guint ui_id;
+} WindowData;
+
+typedef struct
+{
+ VinagrePlugin *plugin;
+ VinagreWindow *window;
+} ActionData;
+
+static void
+free_window_data (WindowData *data)
+{
+ g_return_if_fail (data != NULL);
+
+ g_object_unref (data->ui_action_group);
+ g_slice_free (WindowData, data);
+}
+
+static void
+free_action_data (ActionData *data)
+{
+ g_return_if_fail (data != NULL);
+
+ g_slice_free (ActionData, data);
+}
+
+static void
+listening_cb (GtkAction *action, ActionData *action_data)
+{
+ vinagre_vnc_listener_dialog_show (action_data->window, action_data->plugin);
+}
+
+static GtkActionEntry action_entries[] =
+{
+ { "VNCListener",
+ NULL,
+ N_("_Reverse Connections..."),
+ NULL,
+ N_("Configure incoming VNC connections"),
+ G_CALLBACK (listening_cb)
+ }
+};
+
static void
impl_activate (VinagrePlugin *plugin,
VinagreWindow *window)
{
+ GtkActionGroup *action_group;
+ GtkUIManager *manager;
+ WindowData *data;
+ ActionData *action_data;
+ gboolean always;
+
vinagre_debug_message (DEBUG_PLUGINS, "VinagreVncPlugin Activate");
+
+ data = g_slice_new (WindowData);
+ action_data = g_slice_new (ActionData);
+ action_data->window = window;
+ action_data->plugin = plugin;
+
+ action_group = vinagre_window_get_always_sensitive_action (window);
+ manager = vinagre_window_get_ui_manager (window);
+
+ data->ui_action_group = gtk_action_group_new ("VinagreVNCPluginActions");
+ gtk_action_group_set_translation_domain (data->ui_action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions_full (data->ui_action_group,
+ action_entries,
+ G_N_ELEMENTS (action_entries),
+ action_data,
+ (GDestroyNotify) free_action_data);
+ gtk_ui_manager_insert_action_group (manager,
+ data->ui_action_group,
+ -1);
+
+ data->ui_id = gtk_ui_manager_new_merge_id (manager);
+ gtk_ui_manager_add_ui (manager,
+ data->ui_id,
+ "/MenuBar/MachineMenu/MachineOps_1",
+ "VNCListener",
+ "VNCListener",
+ GTK_UI_MANAGER_AUTO,
+ TRUE);
+
+ g_object_set_data_full (G_OBJECT (window),
+ WINDOW_DATA_KEY,
+ data,
+ (GDestroyNotify) free_window_data);
+
+ g_object_get (vinagre_prefs_get_default (),
+ "always-enable-listening", &always,
+ NULL);
+ if (always)
+ vinagre_vnc_listener_start (vinagre_vnc_listener_get_default ());
}
static void
impl_deactivate (VinagrePlugin *plugin,
VinagreWindow *window)
{
+ GtkUIManager *manager;
+ WindowData *data;
+
vinagre_debug_message (DEBUG_PLUGINS, "VinagreVncPlugin Deactivate");
+
+ manager = vinagre_window_get_ui_manager (window);
+ data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ gtk_ui_manager_remove_ui (manager, data->ui_id);
+ gtk_ui_manager_remove_action_group (manager, data->ui_action_group);
+
+ g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL);
}
static void
diff --git a/plugins/vnc/vnc.ui b/plugins/vnc/vnc.ui
new file mode 100644
index 0000000..31a3dab
--- /dev/null
+++ b/plugins/vnc/vnc.ui
@@ -0,0 +1,258 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkDialog" id="listener_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Reverse Connections</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="xpad">6</property>
+ <property name="stock">gtk-dialog-info</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">By activating reverse connections you can access machines that are behind a firewall. The remote side is supposed to initiate the connection with you. For further information, checkout the help.</property>
+ <property name="wrap">True</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkCheckButton" id="enable_reverse_check">
+ <property name="label" translatable="yes">_Enable Reverse Connections</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="always_enabled_check">
+ <property name="label" translatable="yes">_Always Enabled</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label"> </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="connectivity_exp">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkTextView" id="ip_textview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="pixels_above_lines">3</property>
+ <property name="pixels_below_lines">3</property>
+ <property name="editable">False</property>
+ <property name="buffer">ip_textbuffer</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">This machine is reachable through the following IP address(es):</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="port_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label">label</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ <attribute name="scale" value="1,000000"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Connectivity</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-11">button1</action-widget>
+ <action-widget response="0">button2</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkTextBuffer" id="ip_textbuffer"/>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]