Logo Search packages:      
Sourcecode: vinagre version File versions

vinagre-tab.c

/*
 * vinagre-tab.c
 * This file is part of vinagre
 *
 * Copyright (C) 2007,2008 - 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/>.
 */
 
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
#include <glade/glade.h>
#include <gnome-keyring.h>
#include <vncdisplay.h>

#include "vinagre-notebook.h"
#include "vinagre-tab.h"
#include "vinagre-utils.h"
#include "vinagre-prefs.h"
#include "view/autoDrawer.h"

#define VINAGRE_TAB_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), VINAGRE_TYPE_TAB, VinagreTabPrivate))

struct _VinagreTabPrivate
{
  GtkWidget         *vnc;
  GtkWidget         *scroll;
  VinagreConnection *conn;
  VinagreNotebook   *nb;
  VinagreWindow     *window;
  gboolean           save_password;
  guint32            keyring_item_id;
  VinagreTabState    state;
  gchar             *clipboard_str;
  GtkWidget         *layout;
  GtkWidget         *toolbar;
  GtkWidget         *ro_button;
  GtkWidget         *scaling_button;
  gboolean           pointer_grab;
};

G_DEFINE_TYPE(VinagreTab, vinagre_tab, GTK_TYPE_VBOX)

/* Signals */
enum
{
  TAB_CONNECTED,
  TAB_DISCONNECTED,
  TAB_INITIALIZED,
  LAST_SIGNAL
};

/* Properties */
enum
{
  PROP_0,
  PROP_CONN,
  PROP_WINDOW,
};

static guint signals[LAST_SIGNAL] = { 0 };

static gboolean
vinagre_tab_window_state_cb (GtkWidget           *widget,
                       GdkEventWindowState *event,
                       VinagreTab          *tab)
{
  int vnc_w, vnc_h, screen_w, screen_h;
  GdkScreen *screen;
  GtkPolicyType h, v;

  if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
    return FALSE;

  vnc_w = vnc_display_get_width (VNC_DISPLAY (tab->priv->vnc));
  vnc_h = vnc_display_get_height (VNC_DISPLAY (tab->priv->vnc));

  screen = gtk_widget_get_screen (GTK_WIDGET (tab));
  screen_w = gdk_screen_get_width (screen);
  screen_h = gdk_screen_get_height (screen);

  if (vnc_w <= screen_w)
    h = GTK_POLICY_NEVER;
  else
    h = GTK_POLICY_AUTOMATIC;
  
  if (vnc_h <= screen_h)
    v = GTK_POLICY_NEVER;
  else
    v = GTK_POLICY_AUTOMATIC;

  if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
    {
      gtk_widget_show (tab->priv->toolbar);
      ViewAutoDrawer_SetActive (VIEW_AUTODRAWER (tab->priv->layout), TRUE);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tab->priv->scroll),
                              h, v);
    }
  else
    {
      gtk_widget_hide (tab->priv->toolbar);
      ViewAutoDrawer_SetActive (VIEW_AUTODRAWER (tab->priv->layout), FALSE);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tab->priv->scroll),
                              GTK_POLICY_AUTOMATIC,
                              GTK_POLICY_AUTOMATIC);
      vinagre_notebook_show_hide_tabs (tab->priv->nb);
    }

  return FALSE;
}

static void
vinagre_tab_get_property (GObject    *object,
                    guint       prop_id,
                    GValue     *value,
                    GParamSpec *pspec)
{
  VinagreTab *tab = VINAGRE_TAB (object);

  switch (prop_id)
    {
      case PROP_CONN:
        g_value_set_object (value, tab->priv->conn);
      break;
      case PROP_WINDOW:
        g_value_set_object (value, tab->priv->window);
      break;
      default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;                  
    }
}

static void
vinagre_tab_set_property (GObject      *object,
                    guint         prop_id,
                    const GValue *value,
                    GParamSpec   *pspec)
{
  VinagreTab *tab = VINAGRE_TAB (object);

  switch (prop_id)
    {
      case PROP_CONN:
        tab->priv->conn = g_value_get_object (value);
      g_object_set_data (G_OBJECT (tab->priv->conn), VINAGRE_TAB_KEY, tab);
        break;
      case PROP_WINDOW:
        tab->priv->window = g_value_get_object (value);
      g_signal_connect (tab->priv->window,
                    "window-state-event",
                    G_CALLBACK (vinagre_tab_window_state_cb),
                    tab);
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;                
    }
}

static void
vinagre_tab_finalize (GObject *object)
{
  VinagreTab *tab = VINAGRE_TAB (object);

  g_signal_handlers_disconnect_by_func (tab->priv->window,
                              vinagre_tab_window_state_cb,
                              tab);
  g_object_unref (tab->priv->conn);
  tab->priv->conn = NULL;

  g_free (tab->priv->clipboard_str);
  tab->priv->clipboard_str = NULL;

  G_OBJECT_CLASS (vinagre_tab_parent_class)->finalize (object);
}

static void 
vinagre_tab_class_init (VinagreTabClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->finalize = vinagre_tab_finalize;
  object_class->get_property = vinagre_tab_get_property;
  object_class->set_property = vinagre_tab_set_property;

  g_object_class_install_property (object_class,
                           PROP_CONN,
                           g_param_spec_object ("conn",
                                          "Connection",
                                          "The connection",
                                          VINAGRE_TYPE_CONNECTION,
                                          G_PARAM_READWRITE |
                                          G_PARAM_CONSTRUCT_ONLY |
                                          G_PARAM_STATIC_NAME |
                                          G_PARAM_STATIC_NICK |
                                          G_PARAM_STATIC_BLURB));
  g_object_class_install_property (object_class,
                           PROP_WINDOW,
                           g_param_spec_object ("window",
                                          "Window",
                                          "The VinagreWindow",
                                          VINAGRE_TYPE_WINDOW,
                                          G_PARAM_READWRITE |
                                          G_PARAM_CONSTRUCT_ONLY |
                                          G_PARAM_STATIC_NAME |
                                          G_PARAM_STATIC_NICK |
                                          G_PARAM_STATIC_BLURB));

  signals[TAB_CONNECTED] =
            g_signal_new ("tab-connected",
                        G_OBJECT_CLASS_TYPE (object_class),
                        G_SIGNAL_RUN_FIRST,
                        G_STRUCT_OFFSET (VinagreTabClass, tab_connected),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__VOID,
                        G_TYPE_NONE,
                        0);

  signals[TAB_DISCONNECTED] =
            g_signal_new ("tab-disconnected",
                        G_OBJECT_CLASS_TYPE (object_class),
                        G_SIGNAL_RUN_FIRST,
                        G_STRUCT_OFFSET (VinagreTabClass, tab_disconnected),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__VOID,
                        G_TYPE_NONE,
                        0);

  signals[TAB_INITIALIZED] =
            g_signal_new ("tab-initialized",
                        G_OBJECT_CLASS_TYPE (object_class),
                        G_SIGNAL_RUN_FIRST,
                        G_STRUCT_OFFSET (VinagreTabClass, tab_initialized),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__VOID,
                        G_TYPE_NONE,
                        0);

  g_type_class_add_private (object_class, sizeof (VinagreTabPrivate));
}

static void
open_vnc (VinagreTab *tab)
{
  gchar *port;
  gboolean scaling, view_only, fullscreen;

  port = g_strdup_printf ("%d", vinagre_connection_get_port (tab->priv->conn));

  g_object_get (tab->priv->conn,
            "view-only", &view_only,
            "scaling", &scaling,
            "fullscreen", &fullscreen,
            NULL);

  vinagre_tab_set_scaling (tab, scaling);
  vinagre_tab_set_readonly (tab, view_only);
  vnc_display_set_pointer_local (VNC_DISPLAY(tab->priv->vnc), TRUE);
  vnc_display_set_keyboard_grab (VNC_DISPLAY(tab->priv->vnc), TRUE);
  vnc_display_set_pointer_grab (VNC_DISPLAY(tab->priv->vnc), TRUE);

  if (vnc_display_open_host (VNC_DISPLAY(tab->priv->vnc), vinagre_connection_get_host (tab->priv->conn), port))
    {
      gtk_widget_grab_focus (tab->priv->vnc);

      if (fullscreen)
      vinagre_window_toggle_fullscreen (tab->priv->window);
    }
  else
    {
      vinagre_utils_show_error (_("Error connecting to host."), NULL);
    }

  g_free (port);
}

static void
vnc_connected_cb (VncDisplay *vnc, VinagreTab *tab)
{
  /* Emits the signal saying that we have connected to the machine */
  g_signal_emit (G_OBJECT (tab),
             signals[TAB_CONNECTED],
             0);
}

static void
vnc_disconnected_cb (VncDisplay *vnc, VinagreTab *tab)
{
  /* Emits the signal saying that we have disconnected from the machine */
  g_signal_emit (G_OBJECT (tab),
             signals[TAB_DISCONNECTED],
             0);
}

static void
vnc_auth_failed_cb (VncDisplay *vnc, const gchar *msg, VinagreTab *tab)
{
  GString *message;
  gchar   *name;

  message = g_string_new (NULL);
  name = vinagre_connection_get_best_name (vinagre_tab_get_conn (tab));

  g_string_printf (message, _("Authentication to host \"%s\" has failed"),
               name);
  if (msg)
      g_string_append_printf (message, " (%s)", msg);
  g_string_append_printf (message, ".");

  vinagre_utils_show_error (message->str, GTK_WINDOW (tab->priv->window));
  g_string_free (message, TRUE);
  g_free (name);

  if (tab->priv->keyring_item_id > 0)
    {
      gnome_keyring_item_delete_sync (NULL, tab->priv->keyring_item_id);
      tab->priv->keyring_item_id = 0;
    }

  vinagre_notebook_remove_tab (tab->priv->nb, tab);
}

static void
vnc_auth_unsupported_cb (VncDisplay *vnc, guint auth_type, VinagreTab *tab)
{
  GString *message;
  gchar   *name;

  message = g_string_new (NULL);
  name = vinagre_connection_get_best_name (vinagre_tab_get_conn (tab));

  g_string_printf (message, _("Authentication method to host \"%s\" is unsupported. (%u)"),
               name,
               auth_type);

  vinagre_utils_show_error (message->str, GTK_WINDOW (tab->priv->window));
  g_string_free (message, TRUE);
  g_free (name);

  vinagre_notebook_remove_tab (tab->priv->nb, tab);
}

/* text was actually requested */
static void
copy_cb (GtkClipboard     *clipboard,
         GtkSelectionData *data,
       guint             info,
       VinagreTab       *tab)
{
  gtk_selection_data_set_text (data, tab->priv->clipboard_str, -1);
}

static void
vnc_server_cut_text_cb (VncDisplay *vnc, const gchar *text, VinagreTab *tab)
{
  GtkClipboard *cb;
  gsize a, b;
  GtkTargetEntry targets[] = {
                        {"UTF8_STRING", 0, 0},
                        {"COMPOUND_TEXT", 0, 0},
                        {"TEXT", 0, 0},
                        {"STRING", 0, 0},
                       };

  if (!text)
    return;

  g_free (tab->priv->clipboard_str);
  tab->priv->clipboard_str = g_convert (text, -1, "utf-8", "iso8859-1", &a, &b, NULL);

  if (tab->priv->clipboard_str)
    {
      cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);

      gtk_clipboard_set_with_owner (cb,
                            targets,
                            G_N_ELEMENTS(targets),
                            (GtkClipboardGetFunc) copy_cb,
                            NULL,
                            G_OBJECT (tab));
    }
}

static void
vinagre_tab_add_recent_used (VinagreTab *tab)
{
  GtkRecentManager *manager;
  GtkRecentData    *data;
  GString          *uri;

  static gchar *groups[2] = {
            "vinagre",
            NULL
      };

  manager = gtk_recent_manager_get_default ();
  data = g_slice_new (GtkRecentData);

  uri = g_string_new (NULL);
  g_string_printf (uri, "vnc://%s:%d",
                   vinagre_connection_get_host (tab->priv->conn),
                   vinagre_connection_get_port (tab->priv->conn));

  data->display_name = vinagre_connection_get_best_name (tab->priv->conn);
  data->description = NULL;
  data->mime_type = g_strdup ("application/x-remote-connection");
  data->app_name = (gchar *) g_get_application_name ();
  data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
  data->groups = groups;
  data->is_private = FALSE;

  if (!gtk_recent_manager_add_full (manager, uri->str, data))
    vinagre_utils_show_error (_("Error saving recent connection."),
                        GTK_WINDOW (tab->priv->window));

  g_string_free (uri, TRUE);
  g_free (data->app_exec);
  g_free (data->mime_type);
  g_free (data->display_name);
  g_slice_free (GtkRecentData, data);
}

static void
vinagre_tab_save_password (VinagreTab *tab)
{
  GnomeKeyringResult result;

  if (!tab->priv->save_password)
    return;

  result = gnome_keyring_set_network_password_sync (
                NULL,           /* default keyring */
                NULL,           /* user            */
                NULL,           /* domain          */
                vinagre_connection_get_host (tab->priv->conn),   /* server          */
                NULL,           /* object          */
                "rfb",          /* protocol        */
                "vnc-password", /* authtype        */
                vinagre_connection_get_port (tab->priv->conn),           /* port            */
                vinagre_connection_get_password (tab->priv->conn),       /* password        */
                &tab->priv->keyring_item_id);

  if (result != GNOME_KEYRING_RESULT_OK)
    vinagre_utils_show_error (_("Error saving the password on the keyring."),
                        GTK_WINDOW (tab->priv->window));

  tab->priv->save_password = FALSE;
}

static gchar *
vinagre_tab_find_password (VinagreTab *tab)
{
  GnomeKeyringNetworkPasswordData *found_item;
  GnomeKeyringResult               result;
  GList                           *matches;
  gchar                           *password;
  
  matches = NULL;

  result = gnome_keyring_find_network_password_sync (
                NULL,           /* user     */
            NULL,           /* domain   */
            vinagre_connection_get_host (tab->priv->conn),   /* server   */
            NULL,           /* object   */
            "rfb",          /* protocol */
            "vnc-password", /* authtype */
            vinagre_connection_get_port (tab->priv->conn),           /* port     */
            &matches);

  if (result != GNOME_KEYRING_RESULT_OK || matches == NULL || matches->data == NULL)
    return NULL;

  found_item = (GnomeKeyringNetworkPasswordData *) matches->data;

  password = g_strdup (found_item->password);
  tab->priv->keyring_item_id = found_item->item_id;

  gnome_keyring_network_password_list_free (matches);

  return password;
}

static void
vnc_initialized_cb (VncDisplay *vnc, VinagreTab *tab)
{
  GtkLabel *label;
  gchar    *name;

  vinagre_connection_set_desktop_name (tab->priv->conn,
                               vnc_display_get_name (VNC_DISPLAY (tab->priv->vnc)));

  name = vinagre_connection_get_best_name (tab->priv->conn);
  label = g_object_get_data (G_OBJECT (tab), "label");
  g_return_if_fail (label != NULL);
  gtk_label_set_label (label, name);
  g_free (name);

  vinagre_window_set_title (tab->priv->window);
  vinagre_tab_save_password (tab);
  vinagre_tab_add_recent_used (tab);

  tab->priv->state = VINAGRE_TAB_STATE_CONNECTED;
  vinagre_window_update_machine_menu_sensitivity (tab->priv->window);

  /* Emits the signal saying that we have connected to the machine */
  g_signal_emit (G_OBJECT (tab),
             signals[TAB_INITIALIZED],
             0);
}

static gchar *
ask_password(VinagreTab *tab)
{
  GladeXML   *xml;
  const char *glade_file;
  GtkWidget  *password_dialog, *password_entry, *host_label, *save_password_check;
  gchar      *password = NULL, *name;
  int         result;

  glade_file = vinagre_utils_get_glade_filename ();
  xml = glade_xml_new (glade_file, NULL, NULL);

  password_dialog = glade_xml_get_widget (xml, "password_required_dialog");
  gtk_window_set_transient_for (GTK_WINDOW(password_dialog), GTK_WINDOW(tab->priv->window));

  host_label = glade_xml_get_widget (xml, "host_label");
  name = vinagre_connection_get_best_name (tab->priv->conn);
  gtk_label_set_text (GTK_LABEL (host_label), name);
  g_free (name);

  result = gtk_dialog_run (GTK_DIALOG (password_dialog));
  if (result == -5)
    {
      password_entry = glade_xml_get_widget (xml, "password_entry");
      password = g_strdup (gtk_entry_get_text (GTK_ENTRY (password_entry)));

      save_password_check = glade_xml_get_widget (xml, "save_password_check");
      tab->priv->save_password = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (save_password_check));
    }

  gtk_widget_destroy (GTK_WIDGET (password_dialog));
  g_object_unref (xml);

  return password;
}

static void
vnc_authentication_cb (VncDisplay *vnc, GValueArray *credList, VinagreTab *tab)
{
  gchar *password;
  int i;

  if (credList == NULL)
    return;

  for (i = 0; i < credList->n_values; i++) {
    switch (g_value_get_enum (&credList->values[i]))
      {
        case VNC_DISPLAY_CREDENTIAL_PASSWORD:
          password = vinagre_tab_find_password (tab);
          if (!password)
            {
              password = ask_password (tab);
              if (!password) {
                vinagre_notebook_remove_tab (tab->priv->nb, tab);
                return;
              }
            }

          vinagre_connection_set_password (tab->priv->conn, password);
          vnc_display_set_credential (vnc, VNC_DISPLAY_CREDENTIAL_PASSWORD, password);

          g_free (password);
          break;

        case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
          vnc_display_set_credential (vnc, VNC_DISPLAY_CREDENTIAL_CLIENTNAME, "vinagre");
          break;
      }
  }
}

static void
vnc_pointer_grab_cb (VncDisplay *vnc, VinagreTab *tab)
{
  tab->priv->pointer_grab = TRUE;
  vinagre_window_set_title (tab->priv->window);
}

static void
vnc_pointer_ungrab_cb (VncDisplay *vnc, VinagreTab *tab)
{
  tab->priv->pointer_grab = FALSE;
  vinagre_window_set_title (tab->priv->window);
}

static void vnc_bell_cb (VncDisplay *vnc, VinagreTab *tab)
{
  gdk_window_beep (GTK_WIDGET (tab->priv->window)->window);
}

static gboolean
vnc_key_event ( GtkWidget   *widget G_GNUC_UNUSED,
            GdkEventKey *key G_GNUC_UNUSED,
            gpointer     data G_GNUC_UNUSED)
{
  return TRUE;
}

static gboolean
vnc_scroll_event (GtkWidget *widget G_GNUC_UNUSED,
              GdkEventScroll *scroll G_GNUC_UNUSED,
              gpointer data G_GNUC_UNUSED)
{
  return TRUE;
}

static void
close_button_clicked (GtkToolButton *button,
                  VinagreTab    *tab)
{
  vinagre_notebook_remove_tab (tab->priv->nb, tab);
}

static void
fullscreen_button_clicked (GtkToolButton *button,
                     VinagreTab    *tab)
{
  vinagre_window_toggle_fullscreen (tab->priv->window);
}

static void
screenshot_button_clicked (GtkToolButton *button,
                     VinagreTab    *tab)
{
  vinagre_tab_take_screenshot (tab);
}

static void
cad_button_clicked (GtkToolButton *button,
                     VinagreTab    *tab)
{
  vinagre_tab_send_ctrlaltdel (tab);
}

static void
ro_button_clicked (GtkToggleToolButton *button,
               VinagreTab          *tab)
{
  GtkAction *action;

  vinagre_tab_set_readonly (tab, gtk_toggle_tool_button_get_active (button));

  action = gtk_action_group_get_action (vinagre_window_get_connected_action (tab->priv->window), "ViewReadOnly");
  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
                        vinagre_tab_get_readonly (tab));
}

static void
scaling_button_clicked (GtkToggleToolButton *button,
                  VinagreTab          *tab)
{
  GtkAction *action;

  if (!vinagre_tab_set_scaling (tab, gtk_toggle_tool_button_get_active (button)))
    gtk_toggle_tool_button_set_active (button, FALSE);

  action = gtk_action_group_get_action (vinagre_window_get_connected_action (tab->priv->window), "ViewScaling");
  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
                        vinagre_tab_get_scaling (tab));
}

static void
setup_layout (VinagreTab *tab)
{
  GtkWidget  *button;

  tab->priv->toolbar = gtk_toolbar_new ();
  GTK_WIDGET_SET_FLAGS (tab->priv->toolbar, GTK_NO_SHOW_ALL);

  gtk_toolbar_set_tooltips (GTK_TOOLBAR (tab->priv->toolbar), TRUE);
  gtk_toolbar_set_style (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOLBAR_BOTH_HORIZ);

  /* Leave fullscreen */
  button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_LEAVE_FULLSCREEN));
  gtk_widget_show (GTK_WIDGET (button));
  gtk_tool_item_set_is_important (GTK_TOOL_ITEM (button), TRUE);
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);
  g_signal_connect (button, "clicked", G_CALLBACK (fullscreen_button_clicked), tab);

  /* Close connection */
  button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE));
  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (button), _("Close connection"));
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);
  g_signal_connect (button, "clicked", G_CALLBACK (close_button_clicked), tab);

  /* Space */
  button = GTK_WIDGET (gtk_separator_tool_item_new ());
  gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (button), FALSE);
  gtk_tool_item_set_expand (GTK_TOOL_ITEM (button), TRUE);
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);

  /* Scaling */
  button = GTK_WIDGET (gtk_toggle_tool_button_new ());
  gtk_tool_button_set_label (GTK_TOOL_BUTTON (button), _("Scaling"));
  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (button), _("Scaling"));
  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (button), "zoom-fit-best");
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);
  g_signal_connect (button, "toggled", G_CALLBACK (scaling_button_clicked), tab);
  tab->priv->scaling_button = button;

  /* Read only */
  button = GTK_WIDGET (gtk_toggle_tool_button_new ());
  gtk_tool_button_set_label (GTK_TOOL_BUTTON (button), _("Read only"));
  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (button), _("Read only"));
  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (button), "emblem-readonly");
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);
  g_signal_connect (button, "toggled", G_CALLBACK (ro_button_clicked), tab);
  tab->priv->ro_button = button;

  /* Screenshot */
  button = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (button), "applets-screenshooter");
  gtk_tool_button_set_label (GTK_TOOL_BUTTON (button), _("Take screenshot"));
  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (button), _("Take screenshot"));
  g_signal_connect (button, "clicked", G_CALLBACK (screenshot_button_clicked), tab);
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);

  /* Send Ctrl-alt-del */
  button = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (button), "preferences-desktop-keyboard-shortcuts");
  gtk_tool_button_set_label (GTK_TOOL_BUTTON (button), _("Send Ctrl-Alt-Del"));
  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (button), _("Send Ctrl-Alt-Del"));
  g_signal_connect (button, "clicked", G_CALLBACK (cad_button_clicked), tab);
  gtk_widget_show (GTK_WIDGET (button));
  gtk_toolbar_insert (GTK_TOOLBAR (tab->priv->toolbar), GTK_TOOL_ITEM (button), 0);

  tab->priv->layout = ViewAutoDrawer_New ();
  ViewAutoDrawer_SetActive (VIEW_AUTODRAWER (tab->priv->layout), FALSE);
  ViewOvBox_SetOver (VIEW_OV_BOX (tab->priv->layout), tab->priv->toolbar);
  ViewOvBox_SetUnder (VIEW_OV_BOX (tab->priv->layout), tab->priv->scroll);
}

static void
vinagre_tab_init (VinagreTab *tab)
{
  GtkWidget     *viewport;
  gboolean       shared;

  tab->priv = VINAGRE_TAB_GET_PRIVATE (tab);
  tab->priv->save_password = FALSE;
  tab->priv->keyring_item_id = 0;
  tab->priv->state = VINAGRE_TAB_STATE_INITIALIZING;
  tab->priv->clipboard_str = NULL;
  tab->priv->pointer_grab = FALSE;

  /* Create the scrolled window */
  tab->priv->scroll = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tab->priv->scroll),
                          GTK_POLICY_AUTOMATIC,
                          GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (tab->priv->scroll),
                               GTK_SHADOW_NONE);

  /* Create the vnc widget */
  tab->priv->vnc = vnc_display_new ();

  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (tab->priv->scroll),
                               tab->priv->vnc);
  viewport = gtk_bin_get_child (GTK_BIN (tab->priv->scroll));
  gtk_viewport_set_shadow_type(GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);

  g_object_get (vinagre_prefs_get_default (),
            "shared-flag", &shared,
            NULL);
  vnc_display_set_shared_flag (VNC_DISPLAY (tab->priv->vnc),
                         shared);

  g_signal_connect (tab->priv->vnc,
                "vnc-connected",
                G_CALLBACK (vnc_connected_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-initialized",
                G_CALLBACK (vnc_initialized_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-disconnected",
                G_CALLBACK (vnc_disconnected_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-auth-credential",
                G_CALLBACK (vnc_authentication_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-pointer-grab",
                G_CALLBACK (vnc_pointer_grab_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-pointer-ungrab",
                G_CALLBACK (vnc_pointer_ungrab_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-auth-failure",
                G_CALLBACK (vnc_auth_failed_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-auth-unsupported",
                G_CALLBACK (vnc_auth_unsupported_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-server-cut-text",
                G_CALLBACK (vnc_server_cut_text_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "vnc-bell",
                G_CALLBACK (vnc_bell_cb),
                tab);

  g_signal_connect (tab->priv->vnc,
                "key-press-event",
                G_CALLBACK (vnc_key_event),
                NULL);

  g_signal_connect (tab->priv->vnc,
                "key-release-event",
                G_CALLBACK (vnc_key_event),
                NULL);

  g_signal_connect (tab->priv->vnc,
                "scroll-event",
                G_CALLBACK (vnc_scroll_event),
                NULL);

  setup_layout (tab);

  gtk_box_pack_end (GTK_BOX(tab), tab->priv->layout, TRUE, TRUE, 0);
  gtk_widget_show_all (GTK_WIDGET (tab));
}

GtkWidget *
vinagre_tab_new (VinagreConnection *conn, VinagreWindow *window)
{
  VinagreTab *tab = g_object_new (VINAGRE_TYPE_TAB, 
                           "conn", conn,
                           "window", window,
                           NULL);
  open_vnc (tab);
  return GTK_WIDGET (tab);
}


gchar *
vinagre_tab_get_tooltips (VinagreTab *tab)
{
  gchar *tip;

  g_return_val_if_fail (VINAGRE_IS_TAB (tab), NULL);

  tip =  g_markup_printf_escaped (
                          "<b>%s</b> %s\n\n"
                          "<b>%s</b> %s\n"
                          "<b>%s</b> %d\n"
                          "<b>%s</b> %dx%d",
                          _("Desktop Name:"), vnc_display_get_name (VNC_DISPLAY (tab->priv->vnc)),
                          _("Host:"), vinagre_connection_get_host (tab->priv->conn),
                          _("Port:"), vinagre_connection_get_port (tab->priv->conn),
                          _("Dimensions:"), vnc_display_get_width (VNC_DISPLAY (tab->priv->vnc)), vnc_display_get_height (VNC_DISPLAY (tab->priv->vnc)));

  return tip;
}

VinagreConnection *
vinagre_tab_get_conn (VinagreTab *tab)
{
  g_return_val_if_fail (VINAGRE_IS_TAB (tab), NULL);

  return tab->priv->conn;
}

GtkWidget *
vinagre_tab_get_vnc (VinagreTab *tab)
{
  g_return_val_if_fail (VINAGRE_IS_TAB (tab), NULL);

  return tab->priv->vnc;
}

void
vinagre_tab_set_title (VinagreTab *tab,
                   const char *title)
{
  GtkLabel *label;

  g_return_if_fail (VINAGRE_IS_TAB (tab));

  label = GTK_LABEL (g_object_get_data (G_OBJECT (tab),  "label"));
  gtk_label_set_label (label, title);
}

void
vinagre_tab_set_notebook (VinagreTab      *tab,
                      VinagreNotebook *nb)
{
  g_return_if_fail (VINAGRE_IS_TAB (tab));
  g_return_if_fail (VINAGRE_IS_NOTEBOOK (nb));

  tab->priv->nb = nb;
}

VinagreNotebook *
vinagre_tab_get_notebook (VinagreTab *tab)
{
  g_return_val_if_fail (VINAGRE_IS_TAB (tab), NULL);

  return tab->priv->nb;
}

void
vinagre_tab_take_screenshot (VinagreTab *tab)
{
  GdkPixbuf     *pix;
  GtkWidget     *dialog;
  GString       *suggested_filename;
  gchar         *filename, *name;
  GtkFileFilter *filter;

  g_return_if_fail (VINAGRE_IS_TAB (tab));

  pix = vnc_display_get_pixbuf (VNC_DISPLAY (tab->priv->vnc));

  filename = NULL;
  name = vinagre_connection_get_best_name (tab->priv->conn);
  suggested_filename = g_string_new (NULL);
  g_string_printf (suggested_filename, _("Screenshot of %s"), name);
  g_string_append (suggested_filename, ".png");

  dialog = gtk_file_chooser_dialog_new (_("Save Screenshot"),
                              GTK_WINDOW (tab->priv->window),
                              GTK_FILE_CHOOSER_ACTION_SAVE,
                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                              GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                              NULL);
  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested_filename->str);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);

  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, _("Supported formats"));
  gtk_file_filter_add_pixbuf_formats (filter);
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);

  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
      gdk_pixbuf_save (pix, filename, "png", NULL, NULL);
      g_free (filename);
  }

  gtk_widget_destroy (dialog);
  gdk_pixbuf_unref (pix);
  g_string_free (suggested_filename, TRUE);
  g_free (name);
}

void
vinagre_tab_send_ctrlaltdel (VinagreTab *tab)
{
  guint keys[] = { GDK_Control_L, GDK_Alt_L, GDK_Delete };

  g_return_if_fail (VINAGRE_IS_TAB (tab));

  vnc_display_send_keys_ex (VNC_DISPLAY (tab->priv->vnc), keys, sizeof (keys) / sizeof (keys[0]), VNC_DISPLAY_KEY_EVENT_CLICK);
}

void
vinagre_tab_paste_text (VinagreTab *tab, const gchar *text)
{
  gchar *out;
  size_t a, b;
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  out = g_convert (text, -1, "iso8859-1", "utf-8", &a, &b, NULL);

  if (out)
    {
      vnc_display_client_cut_text (VNC_DISPLAY (tab->priv->vnc), out);
      g_free (out);
    }
}

gboolean
vinagre_tab_set_scaling (VinagreTab *tab, gboolean active) {
  g_return_val_if_fail (VINAGRE_IS_TAB (tab), FALSE);

  if (vnc_display_get_scaling (VNC_DISPLAY (tab->priv->vnc)) == active)
    return TRUE;

  if (active &&
      gdk_screen_is_composited (gtk_widget_get_screen (GTK_WIDGET (tab->priv->window))))
    {
      vinagre_utils_show_error (_("Scaling does not work properly on composited windows. Disable the visual effects and try again."),
                        GTK_WINDOW (tab->priv->window));
      return FALSE;
    }

  if (!vnc_display_set_scaling (VNC_DISPLAY (tab->priv->vnc), active))
    {
      vinagre_utils_show_error (_("Scaling is not supported on this installation.\n\nRead the README file (shipped with Vinagre) in order to know how to enable this feature."),
                        GTK_WINDOW (tab->priv->window));
      return FALSE;
    }

  gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (tab->priv->scaling_button),
                             active);

  return TRUE;
}

gboolean
vinagre_tab_get_scaling (VinagreTab *tab) {
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  return vnc_display_get_scaling (VNC_DISPLAY (tab->priv->vnc));
}

void
vinagre_tab_set_readonly (VinagreTab *tab, gboolean active) {
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  vnc_display_set_read_only (VNC_DISPLAY (tab->priv->vnc), active);
  gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (tab->priv->ro_button),
                             active);

}

gboolean
vinagre_tab_get_readonly (VinagreTab *tab) {
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  return vnc_display_get_read_only (VNC_DISPLAY (tab->priv->vnc));
}

VinagreTabState
vinagre_tab_get_state (VinagreTab *tab)
{
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  return tab->priv->state;
}

VinagreTab *
vinagre_tab_get_from_connection (VinagreConnection *conn)
{
  gpointer res;
      
  g_return_val_if_fail (VINAGRE_IS_CONNECTION (conn), NULL);
      
  res = g_object_get_data (G_OBJECT (conn), VINAGRE_TAB_KEY);
      
  return (res != NULL) ? VINAGRE_TAB (res) : NULL;
}

gboolean
vinagre_tab_is_pointer_grab (VinagreTab *tab) {
  g_return_if_fail (VINAGRE_IS_TAB (tab));

  return tab->priv->pointer_grab;
}

/* vim: set ts=8: */

Generated by  Doxygen 1.6.0   Back to index