/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* NetworkManager Wireless Applet -- Display wireless access points and allow user control * * Dan Williams * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * This applet used the GNOME Wireless Applet as a skeleton to build from. * * GNOME Wireless Applet Authors: * Eskil Heyn Olsen * Bastien Nocera (Gnome2 port) * * (C) Copyright 2004-2005 Red Hat, Inc. * (C) Copyright 2001, 2002 Free Software Foundation */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #if !GTK_CHECK_VERSION(2,6,0) #include #endif #include #include #include "applet.h" #include "applet-compat.h" #include "applet-dbus.h" #include "applet-dbus-devices.h" #include "applet-dbus-vpn.h" #include "applet-dbus-info.h" #include "other-network-dialog.h" #include "passphrase-dialog.h" #include "menu-items.h" #include "vpn-password-dialog.h" #include "vpn-connection.h" #include "nm-utils.h" #include "dbus-method-dispatcher.h" /* Compat for GTK 2.4 and lower... */ #if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6) #define GTK_STOCK_MEDIA_PAUSE GTK_STOCK_STOP #define GTK_STOCK_MEDIA_PLAY GTK_STOCK_REFRESH #define GTK_STOCK_ABOUT GTK_STOCK_DIALOG_INFO #define GTK_STOCK_INFO GTK_STOCK_DIALOG_INFO #endif /* Compat for GTK 2.6 */ #if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION == 6) #define GTK_STOCK_INFO GTK_STOCK_DIALOG_INFO #endif static GObject * nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props); static gboolean nmwa_icons_init (NMWirelessApplet *applet); static void nmwa_icons_free (NMWirelessApplet *applet); static void nmwa_about_cb (NMWirelessApplet *applet); static void nmwa_context_menu_update (NMWirelessApplet *applet); static GtkWidget * nmwa_get_instance (NMWirelessApplet *applet); static void nmwa_update_state (NMWirelessApplet *applet); G_DEFINE_TYPE(NMWirelessApplet, nmwa, EGG_TYPE_TRAY_ICON) /* * nm_null_safe_strcmp * * Doesn't freaking segfault if s1/s2 are NULL * */ int nm_null_safe_strcmp (const char *s1, const char *s2) { if (!s1 && !s2) return 0; if (!s1 && s2) return -1; if (s1 && !s2) return 1; return (strcmp (s1, s2)); } /* * nmwa_get_first_active_device * * Return the first device marked as "active". * */ NetworkDevice * nmwa_get_first_active_device (GSList *dev_list) { GSList * elt; for (elt = dev_list; elt; elt = g_slist_next (elt)) { NetworkDevice *dev = (NetworkDevice *)(elt->data); if (network_device_get_active (dev)) return dev; } return NULL; } static void nmwa_init (NMWirelessApplet *applet) { applet->animation_id = 0; applet->animation_step = 0; glade_gnome_init (); if (!nmwa_icons_init (applet)) return; /* gtk_window_set_default_icon_from_file (ICONDIR"/NMWirelessApplet/wireless-applet.png", NULL); */ gtk_widget_show (nmwa_get_instance (applet)); } static void nmwa_class_init (NMWirelessAppletClass *klass) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); gobject_class->constructor = nmwa_constructor; } static GObject *nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props) { GObject *obj; NMWirelessApplet *applet; NMWirelessAppletClass *klass; klass = NM_WIRELESS_APPLET_CLASS (g_type_class_peek (type)); obj = G_OBJECT_CLASS (nmwa_parent_class)->constructor (type, n_props, construct_props); applet = NM_WIRELESS_APPLET (obj); return obj; } static GtkWidget * get_label (GtkWidget *info_dialog, GladeXML *xml, const char *name) { GtkWidget *label; if (xml != NULL) { label = glade_xml_get_widget (xml, name); g_object_set_data (G_OBJECT (info_dialog), name, label); } else label = g_object_get_data (G_OBJECT (info_dialog), name); return label; } static void nmwa_show_socket_err (GtkWidget *info_dialog, const char *err) { GtkWidget *error_dialog; char *msg; msg = g_strdup_printf ("%s\n\n%s", _("Error displaying connection information: "), err); error_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (info_dialog), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, msg); g_free (msg); gtk_window_present (GTK_WINDOW (error_dialog)); g_signal_connect_swapped (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), error_dialog); } static gboolean nmwa_update_info (NMWirelessApplet *applet) { GtkWidget *info_dialog; char *addr = NULL, *broadcast = NULL, *primary_dns = NULL, *secondary_dns = NULL; char *mac = NULL, *iface_and_type = NULL, *route = NULL, *mask = NULL; GtkWidget *label; const char *iface = NULL; NetworkDevice *dev; info_dialog = glade_xml_get_widget (applet->info_dialog_xml, "info_dialog"); if (!info_dialog) { char *err = g_strdup (_("Could not find some required resources (the glade file)!")); nmwa_show_socket_err (info_dialog, err); g_free (err); return FALSE; } if ((dev = nmwa_get_first_active_device (applet->device_list))) iface = network_device_get_iface (dev); if (!dev || !iface) { char *err = g_strdup (_("No active connections!")); nmwa_show_socket_err (info_dialog, err); g_free (err); return FALSE; } mac = (char*) network_device_get_address (dev); broadcast = (char*) network_device_get_broadcast (dev); addr = (char*) network_device_get_ip4_address (dev); mask = (char*) network_device_get_netmask (dev); route = (char*) network_device_get_route (dev); primary_dns = (char*) network_device_get_primary_dns (dev); secondary_dns = (char*) network_device_get_secondary_dns (dev); if (network_device_is_wired (dev)) iface_and_type = g_strdup_printf (_("Wired Ethernet (%s)"), iface); else iface_and_type = g_strdup_printf (_("Wireless Ethernet (%s)"), iface); label = get_label (info_dialog, applet->info_dialog_xml, "label-interface"); gtk_label_set_text (GTK_LABEL (label), iface_and_type); label = get_label (info_dialog, applet->info_dialog_xml, "label-ip-address"); gtk_label_set_text (GTK_LABEL (label), addr); label = get_label (info_dialog, applet->info_dialog_xml, "label-broadcast-address"); gtk_label_set_text (GTK_LABEL (label), broadcast); label = get_label (info_dialog, applet->info_dialog_xml, "label-subnet-mask"); gtk_label_set_text (GTK_LABEL (label), mask); label = get_label (info_dialog, applet->info_dialog_xml, "label-default-route"); gtk_label_set_text (GTK_LABEL (label), route); label = get_label (info_dialog, applet->info_dialog_xml, "label-primary-dns"); gtk_label_set_text (GTK_LABEL (label), primary_dns); label = get_label (info_dialog, applet->info_dialog_xml, "label-secondary-dns"); gtk_label_set_text (GTK_LABEL (label), secondary_dns); label = get_label (info_dialog, applet->info_dialog_xml, "label-hardware-address"); gtk_label_set_text (GTK_LABEL (label), mac); g_free (iface_and_type); return TRUE; } static void nmwa_show_info_cb (GtkMenuItem *mi, NMWirelessApplet *applet) { GtkWidget *info_dialog; info_dialog = glade_xml_get_widget (applet->info_dialog_xml, "info_dialog"); if (nmwa_update_info (applet)) { gtk_window_present (GTK_WINDOW (info_dialog)); g_signal_connect_swapped (info_dialog, "response", G_CALLBACK (gtk_widget_hide), info_dialog); } } static void about_dialog_activate_link_cb (GtkAboutDialog *about, const gchar *link, gpointer data) { gnome_url_show (link, NULL); } static void nmwa_about_cb (NMWirelessApplet *applet) { static const gchar *authors[] = { "The Red Hat Desktop Team, including:\n", "Christopher Aillon ", "Jonathan Blandford ", "John Palmieri ", "Ray Strode ", "Colin Walters ", "Dan Williams ", "David Zeuthen ", "\nAnd others, including:\n", "Bill Moss ", "Tom Parker", "j@bootlab.org", "Peter Jones ", "Robert Love ", NULL }; static const gchar *artists[] = { "Diana Fong ", NULL }; static const gchar *documenters[] = { NULL }; #if !GTK_CHECK_VERSION(2,6,0) GdkPixbuf *pixbuf; char *file; GtkWidget *about_dialog; /* GTK 2.4 and earlier, have to use libgnome for about dialog */ file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "gnome-networktool.png", FALSE, NULL); pixbuf = gdk_pixbuf_new_from_file (file, NULL); g_free (file); about_dialog = gnome_about_new (_("NetworkManager Applet"), VERSION, _("Copyright \xc2\xa9 2004-2005 Red Hat, Inc."), _("Notification area applet for managing your network devices and connections."), authors, documenters, _("translator-credits"), pixbuf); g_object_unref (pixbuf); gtk_window_set_screen (GTK_WINDOW (about_dialog), gtk_widget_get_screen (GTK_WIDGET (applet))); g_signal_connect (about_dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &about_dialog); gtk_widget_show (about_dialog); #else static gboolean been_here = FALSE; if (!been_here) { been_here = TRUE; gtk_about_dialog_set_url_hook (about_dialog_activate_link_cb, NULL, NULL); } /* GTK 2.6 and later code */ gtk_show_about_dialog (NULL, "name", _("NetworkManager Applet"), "version", VERSION, "copyright", _("Copyright \xc2\xa9 2004-2005 Red Hat, Inc."), "comments", _("Notification area applet for managing your network devices and connections."), "website", "http://www.gnome.org/projects/NetworkManager/", "authors", authors, "artists", artists, "documenters", documenters, "translator-credits", _("translator-credits"), "logo-icon-name", GTK_STOCK_NETWORK, NULL); #endif } typedef struct DialogCBData { char *msg; char *title; } DialogCBData; static void free_dialog_cb_data (DialogCBData *data) { g_return_if_fail (data != NULL); g_free (data->msg); g_free (data->title); memset (data, 0, sizeof (DialogCBData)); g_free (data); } static void vpn_failure_dialog_close_cb (GtkWidget *dialog, gpointer user_data) { DialogCBData *data; if ((data = g_object_get_data (G_OBJECT (dialog), "data"))) { g_object_set_data (G_OBJECT (dialog), "data", NULL); free_dialog_cb_data (data); } gtk_widget_destroy (dialog); } /* * nmwa_show_vpn_failure_dialog * * Present the VPN failure dialog. * */ static gboolean nmwa_show_vpn_failure_dialog (DialogCBData *cb_data) { GtkWidget *dialog; guint32 timestamp; g_return_val_if_fail (cb_data != NULL, FALSE); g_return_val_if_fail (cb_data->msg != NULL, FALSE); g_return_val_if_fail (cb_data->title != NULL, FALSE); dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cb_data->msg, NULL); gtk_window_set_title (GTK_WINDOW (dialog), cb_data->title); g_signal_connect (dialog, "response", G_CALLBACK (vpn_failure_dialog_close_cb), NULL); g_signal_connect (dialog, "close", G_CALLBACK (vpn_failure_dialog_close_cb), NULL); g_object_set_data (G_OBJECT (dialog), "data", cb_data); gtk_widget_show_all (dialog); /* Bash focus-stealing prevention in the face */ timestamp = gdk_x11_get_server_time (dialog->window); gdk_x11_window_set_user_time (dialog->window, timestamp); return FALSE; } /* * nmwa_schedule_vpn_failure_dialog * * Schedule display of the VPN Failure dialog. * */ void nmwa_schedule_vpn_failure_dialog (NMWirelessApplet *applet, const char *member, const char *vpn_name, const char *error_msg) { DialogCBData *cb_data = NULL; gchar *error_head = NULL; gchar *error_desc = NULL; gchar *error_data = NULL; g_return_if_fail (applet != NULL); g_return_if_fail (member != NULL); g_return_if_fail (vpn_name != NULL); g_return_if_fail (error_msg != NULL); cb_data = g_malloc0 (sizeof (DialogCBData)); cb_data->title = g_strdup (_("VPN Error")); if (!strcmp (member, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED)) { error_head = g_strdup (_("VPN Login Failure")); error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a login failure."), vpn_name); } else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED)) { error_head = g_strdup (_("VPN Start Failure")); error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a failure launching the VPN program."), vpn_name); } else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED)) { error_head = g_strdup (_("VPN Connect Failure")); error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a connection error."), vpn_name); } else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD)) { error_head = g_strdup (_("VPN Configuration Error")); error_desc = g_strdup_printf (_("The VPN connection '%s' was not correctly configured."), vpn_name); } else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD)) { error_head = g_strdup (_("VPN Connect Failure")); error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' because the VPN server did not return an adequate network configuration."), vpn_name); } else { free_dialog_cb_data (cb_data); return; } error_data = g_strdup_printf (_("The VPN service said: \"%s\""), error_msg); cb_data->msg = g_strdup_printf ("%s\n\n" "%s\n\n%s", error_head, error_desc, error_data); g_free (error_head); g_free (error_desc); g_free (error_data); g_idle_add ((GSourceFunc) nmwa_show_vpn_failure_dialog, cb_data); } static void vpn_login_banner_dialog_close_cb (GtkWidget *dialog, gpointer user_data) { char *message; if ((message = g_object_get_data (G_OBJECT (dialog), "message"))) { g_object_set_data (G_OBJECT (dialog), "message", NULL); g_free (message); } gtk_widget_destroy (dialog); } /* * nmwa_show_vpn_login_banner_dialog * * Present the VPN login banner dialog. * */ static gboolean nmwa_show_vpn_login_banner_dialog (char *message) { GtkWidget *dialog; guint32 timestamp; g_return_val_if_fail (message != NULL, FALSE); dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, message, NULL); g_signal_connect (dialog, "response", G_CALLBACK (vpn_login_banner_dialog_close_cb), NULL); g_signal_connect (dialog, "close", G_CALLBACK (vpn_login_banner_dialog_close_cb), NULL); g_object_set_data (G_OBJECT (dialog), "message", message); gtk_widget_show_all (dialog); /* Bash focus-stealing prevention in the face */ timestamp = gdk_x11_get_server_time (dialog->window); gdk_x11_window_set_user_time (dialog->window, timestamp); return FALSE; } /* * nmwa_schedule_vpn_login_banner_dialog * * Schedule display of the VPN Login Banner dialog. * */ void nmwa_schedule_vpn_login_banner_dialog (NMWirelessApplet *applet, const char *vpn_name, const char *banner) { char *msg; char *msg2; g_return_if_fail (applet != NULL); g_return_if_fail (vpn_name != NULL); g_return_if_fail (banner != NULL); msg2 = g_strdup_printf (_("VPN connection '%s' said:"), vpn_name); msg = g_strdup_printf ("%s\n\n%s\n\n\"%s\"", _("VPN Login Message"), msg2, banner); g_free (msg2); g_idle_add ((GSourceFunc) nmwa_show_vpn_login_banner_dialog, msg); } /* * nmwa_driver_notify_get_ignored_list * * Return list of devices for which we are supposed to ignore driver * notifications for from GConf. * */ static GSList *nmwa_driver_notify_get_ignored_list (NMWirelessApplet *applet) { char *key; GConfValue *value; GSList *mac_list = NULL; g_return_val_if_fail (applet != NULL, NULL); g_return_val_if_fail (applet->gconf_client != NULL, NULL); /* Get current list of access point MAC addresses for this AP from GConf */ key = g_strdup_printf ("%s/non_notify_cards", GCONF_PATH_PREFS); value = gconf_client_get (applet->gconf_client, key, NULL); if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING)) mac_list = gconf_client_get_list (applet->gconf_client, key, GCONF_VALUE_STRING, NULL); if (value) gconf_value_free (value); g_free (key); return (mac_list); } /* * nmwa_driver_notify_is_device_ignored * * Look in GConf and determine whether or not we are supposed to * ignore driver notifications for a particular device. * */ static gboolean nmwa_driver_notify_is_device_ignored (NMWirelessApplet *applet, NetworkDevice *dev) { gboolean found = FALSE; GSList * mac_list = NULL; GSList * elt; const char * dev_addr; g_return_val_if_fail (applet != NULL, TRUE); g_return_val_if_fail (applet->gconf_client != NULL, TRUE); g_return_val_if_fail (dev != NULL, TRUE); dev_addr = network_device_get_address (dev); g_return_val_if_fail (dev_addr != NULL, TRUE); g_return_val_if_fail (strlen (dev_addr) > 0, TRUE); mac_list = nmwa_driver_notify_get_ignored_list (applet); /* Ensure that the MAC isn't already in the list */ for (elt = mac_list; elt; elt = g_slist_next (elt)) { if (elt->data && !strcmp (dev_addr, elt->data)) { found = TRUE; break; } } /* Free the list, since gconf_client_set_list deep-copies it */ g_slist_foreach (mac_list, (GFunc)g_free, NULL); g_slist_free (mac_list); return found; } /* * nmwa_driver_notify_ignore_device * * Add a device's MAC address to the list of ones that we ignore * in GConf. Stores user's pref for "Don't remind me". * */ static void nmwa_driver_notify_ignore_device (NMWirelessApplet *applet, NetworkDevice *dev) { gboolean found = FALSE; GSList * new_mac_list = NULL; GSList * elt; const char * dev_addr; g_return_if_fail (applet != NULL); g_return_if_fail (applet->gconf_client != NULL); g_return_if_fail (dev != NULL); dev_addr = network_device_get_address (dev); g_return_if_fail (dev_addr != NULL); g_return_if_fail (strlen (dev_addr) > 0); new_mac_list = nmwa_driver_notify_get_ignored_list (applet); /* Ensure that the MAC isn't already in the list */ for (elt = new_mac_list; elt; elt = g_slist_next (elt)) { if (elt->data && !strcmp (dev_addr, elt->data)) { found = TRUE; break; } } /* Add the new MAC address to the end of the list */ if (!found) { char *key = g_strdup_printf ("%s/non_notify_cards", GCONF_PATH_PREFS); new_mac_list = g_slist_append (new_mac_list, g_strdup (dev_addr)); gconf_client_set_list (applet->gconf_client, key, GCONF_VALUE_STRING, new_mac_list, NULL); g_free (key); } /* Free the list, since gconf_client_set_list deep-copies it */ g_slist_foreach (new_mac_list, (GFunc)g_free, NULL); g_slist_free (new_mac_list); } static gboolean nmwa_driver_notify_dialog_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { gtk_widget_destroy (widget); return FALSE; } static gboolean nmwa_driver_notify_dialog_destroy_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data); NetworkDevice *dev; g_return_val_if_fail (cb_data != NULL, FALSE); g_return_val_if_fail (cb_data->xml != NULL, FALSE); dev = cb_data->dev; g_return_val_if_fail (dev != NULL, FALSE); network_device_unref (dev); g_object_unref (cb_data->xml); g_free (cb_data); return FALSE; } static gboolean nmwa_driver_notify_ok_cb (GtkButton *button, gpointer user_data) { DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data); NetworkDevice *dev; NMWirelessApplet *applet; GtkWidget *dialog; GtkWidget *checkbox; g_return_val_if_fail (cb_data != NULL, FALSE); g_return_val_if_fail (cb_data->xml != NULL, FALSE); dev = cb_data->dev; g_return_val_if_fail (dev != NULL, FALSE); applet = cb_data->applet; g_return_val_if_fail (applet != NULL, FALSE); checkbox = glade_xml_get_widget (cb_data->xml, "dont_remind_checkbox"); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox))) nmwa_driver_notify_ignore_device (applet, dev); dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog"); gtk_widget_destroy (dialog); return FALSE; } /* * nmwa_driver_notify * * Notify the user if there's some problem with the driver * of a specific network device. * */ gboolean nmwa_driver_notify (gpointer user_data) { DriverNotifyCBData * cb_data = (DriverNotifyCBData *)(user_data); NetworkDevice * dev; NMWirelessApplet * applet; GtkWidget * dialog; GtkLabel * label; char * label_text = NULL; char * temp = NULL; GtkButton * button; guint32 timestamp; g_return_val_if_fail (cb_data != NULL, FALSE); dev = cb_data->dev; g_return_val_if_fail (dev != NULL, FALSE); if (!(applet = cb_data->applet) || !applet->glade_file) goto out; /* If the user has already requested that we ignore notifications for * this device, don't do anything. */ if (nmwa_driver_notify_is_device_ignored (applet, dev)) goto out; if (!(cb_data->xml = glade_xml_new (applet->glade_file, "driver_sucks_dialog", NULL))) { nmwa_schedule_warning_dialog (applet, _("The NetworkManager Applet could not find some required resources (the glade file was not found).")); goto out; } dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog"); g_signal_connect (G_OBJECT (dialog), "destroy-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_destroy_cb), cb_data); g_signal_connect (G_OBJECT (dialog), "delete-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_delete_cb), cb_data); label = GTK_LABEL (glade_xml_get_widget (cb_data->xml, "driver_sucks_label")); if (network_device_is_wireless (dev) && !(network_device_get_capabilities (dev) & NM_DEVICE_CAP_WIRELESS_SCAN)) { temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."), network_device_get_desc (dev), network_device_get_iface (dev)); label_text = g_strdup_printf (gtk_label_get_label (label), temp); g_free (temp); } if (network_device_is_wired (dev) && !(network_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT)) { temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."), network_device_get_desc (dev), network_device_get_iface (dev)); label_text = g_strdup_printf (gtk_label_get_label (label), temp); g_free (temp); } if (label_text) gtk_label_set_markup (label, label_text); button = GTK_BUTTON (glade_xml_get_widget (cb_data->xml, "ok_button")); g_signal_connect (G_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (nmwa_driver_notify_ok_cb), cb_data); gtk_widget_show_all (GTK_WIDGET (dialog)); /* Bash focus-stealing prevention in the face */ timestamp = gdk_x11_get_server_time (dialog->window); gdk_x11_window_set_user_time (dialog->window, timestamp); out: network_device_unref (cb_data->dev); return (FALSE); } /* * nmwa_get_first_active_vpn_connection * * Return the first active VPN connection, if any. * */ VPNConnection *nmwa_get_first_active_vpn_connection (NMWirelessApplet *applet) { VPNConnection * vpn; NMVPNActStage vpn_state; GSList * elt; for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt)) { vpn = (VPNConnection*) elt->data; vpn_state = nmwa_vpn_connection_get_stage (vpn); if (vpn_state == NM_VPN_ACT_STAGE_ACTIVATED) return vpn; } return NULL; } static VPNConnection *nmwa_get_first_activating_vpn_connection (NMWirelessApplet *applet) { VPNConnection * vpn; GSList * elt; for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt)) { vpn = (VPNConnection*) elt->data; if (nmwa_vpn_connection_is_activating (vpn)) return vpn; } return NULL; } static void nmwa_set_icon (NMWirelessApplet *applet, GdkPixbuf *link_icon, GdkPixbuf *vpn_icon) { GdkPixbuf *composite; VPNConnection *vpn; g_return_if_fail (applet != NULL); g_return_if_fail (link_icon != NULL); composite = gdk_pixbuf_copy (link_icon); vpn = nmwa_get_first_active_vpn_connection (applet); if (!vpn) vpn = nmwa_get_first_activating_vpn_connection (applet); if (vpn && vpn_icon) gdk_pixbuf_composite (vpn_icon, composite, 0, 0, gdk_pixbuf_get_width (vpn_icon), gdk_pixbuf_get_height (vpn_icon), 0, 0, 1.0, 1.0, GDK_INTERP_NEAREST, 255); out: gtk_image_set_from_pixbuf (GTK_IMAGE (applet->pixmap), composite); g_object_unref (composite); } static GdkPixbuf *nmwa_get_connected_icon (NMWirelessApplet *applet, NetworkDevice *dev) { int strength = 0; GdkPixbuf *pixbuf = NULL; g_return_val_if_fail (applet != NULL, NULL); g_return_val_if_fail (dev != NULL, NULL); if (network_device_is_wireless (dev)) { if (applet->is_adhoc) pixbuf = applet->adhoc_icon; else { strength = CLAMP ((int)network_device_get_strength (dev), 0, 100); if (strength > 80) pixbuf = applet->wireless_100_icon; else if (strength > 55) pixbuf = applet->wireless_75_icon; else if (strength > 30) pixbuf = applet->wireless_50_icon; else if (strength > 5) pixbuf = applet->wireless_25_icon; else pixbuf = applet->wireless_00_icon; } } else pixbuf = applet->wired_icon; return pixbuf; } static GdkPixbuf * nmwa_act_stage_to_pixbuf (NMWirelessApplet *applet, NetworkDevice *dev, WirelessNetwork *net, char **tip) { const char *essid; const char *iface; gint connecting_stage = -1; GdkPixbuf *pixbuf = NULL; g_return_val_if_fail (applet != NULL, NULL); g_return_val_if_fail (dev != NULL, NULL); g_return_val_if_fail (tip != NULL, NULL); iface = network_device_get_iface (dev); essid = net ? wireless_network_get_essid (net) : NULL; switch (network_device_get_act_stage (dev)) { case NM_ACT_STAGE_DEVICE_PREPARE: { if (network_device_is_wired (dev)) *tip = g_strdup_printf (_("Preparing device %s for the wired network..."), iface); else if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Preparing device %s for the wireless network '%s'..."), iface, essid); connecting_stage = 0; break; } case NM_ACT_STAGE_DEVICE_CONFIG: { if (network_device_is_wired (dev)) *tip = g_strdup_printf (_("Configuring device %s for the wired network..."), iface); else if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Attempting to join the wireless network '%s'..."), essid); connecting_stage = 0; break; } case NM_ACT_STAGE_NEED_USER_KEY: { if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Waiting for Network Key for the wireless network '%s'..."), essid); connecting_stage = 0; break; } case NM_ACT_STAGE_IP_CONFIG_START: { if (network_device_is_wired (dev)) *tip = g_strdup_printf (_("Requesting a network address from the wired network...")); else if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Requesting a network address from the wireless network '%s'..."), essid); connecting_stage = 1; break; } case NM_ACT_STAGE_IP_CONFIG_GET: { if (network_device_is_wired (dev)) *tip = g_strdup_printf (_("Requesting a network address from the wired network...")); else if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Requesting a network address from the wireless network '%s'..."), essid); connecting_stage = 2; break; } case NM_ACT_STAGE_IP_CONFIG_COMMIT: { if (network_device_is_wired (dev)) *tip = g_strdup_printf (_("Finishing connection to the wired network...")); else if (network_device_is_wireless (dev)) *tip = g_strdup_printf (_("Finishing connection to the wireless network '%s'..."), essid); connecting_stage = 2; break; } default: case NM_ACT_STAGE_ACTIVATED: case NM_ACT_STAGE_FAILED: case NM_ACT_STAGE_CANCELLED: case NM_ACT_STAGE_UNKNOWN: break; } if (connecting_stage >= 0 && connecting_stage < NUM_CONNECTING_STAGES) { if (applet->animation_step >= NUM_CONNECTING_FRAMES) applet->animation_step = 0; pixbuf = applet->network_connecting_icons[connecting_stage][applet->animation_step]; } return pixbuf; } /* * animation_timeout * * Jump to the next frame of the applets icon if the icon * is supposed to be animated. * */ static gboolean animation_timeout (NMWirelessApplet *applet) { NetworkDevice *act_dev; GdkPixbuf *pixbuf; g_return_val_if_fail (applet != NULL, FALSE); if (!applet->nm_running) { applet->animation_step = 0; applet->animation_id = 0; return FALSE; } act_dev = nmwa_get_first_active_device (applet->device_list); if (!act_dev) { applet->animation_step = 0; applet->animation_id = 0; return FALSE; } if (applet->nm_state == NM_STATE_CONNECTING) { if (act_dev) { char *tip = NULL; pixbuf = nmwa_act_stage_to_pixbuf (applet, act_dev, NULL, &tip); g_free (tip); if (pixbuf) nmwa_set_icon (applet, pixbuf, NULL); } applet->animation_step ++; } else if (nmwa_get_first_activating_vpn_connection (applet) != NULL) { pixbuf = nmwa_get_connected_icon (applet, act_dev); if (applet->animation_step >= NUM_VPN_CONNECTING_FRAMES) applet->animation_step = 0; nmwa_set_icon (applet, pixbuf, applet->vpn_connecting_icons[applet->animation_step]); applet->animation_step ++; } else { applet->animation_step = 0; nmwa_update_state (applet); return FALSE; } return TRUE; } /* * nmwa_update_state * * Figure out what the currently active device is from NetworkManager, its type, * and what our icon on the panel should look like for each type. * */ static void nmwa_update_state (NMWirelessApplet *applet) { gboolean show_applet = TRUE; gboolean need_animation = FALSE; GdkPixbuf * pixbuf = NULL; gint strength = -1; char * tip = NULL; char * vpntip = NULL; WirelessNetwork * active_network = NULL; NetworkDevice * act_dev = NULL; VPNConnection *vpn; act_dev = nmwa_get_first_active_device (applet->device_list); if (act_dev && network_device_is_wireless (act_dev)) { active_network = network_device_get_active_wireless_network (act_dev); strength = CLAMP ((int)network_device_get_strength (act_dev), 0, 100); } if (!applet->nm_running) { show_applet = FALSE; tip = g_strdup (_("NetworkManager is not running")); goto done; } if (!act_dev) applet->nm_state = NM_STATE_DISCONNECTED; switch (applet->nm_state) { case NM_STATE_ASLEEP: case NM_STATE_DISCONNECTED: pixbuf = applet->no_connection_icon; tip = g_strdup (_("No network connection")); break; case NM_STATE_CONNECTED: if (network_device_is_wired (act_dev)) tip = g_strdup (_("Wired network connection")); else if (network_device_is_wireless (act_dev)) { if (applet->is_adhoc) tip = g_strdup (_("Connected to an Ad-Hoc wireless network")); else tip = g_strdup_printf (_("Wireless network connection to '%s' (%d%%)"), active_network ? wireless_network_get_essid (active_network) : "(unknown)", strength); } pixbuf = nmwa_get_connected_icon (applet, act_dev); break; case NM_STATE_CONNECTING: { pixbuf = nmwa_act_stage_to_pixbuf (applet, act_dev, active_network, &tip); need_animation = TRUE; } break; default: break; } vpn = nmwa_get_first_active_vpn_connection (applet); if (vpn != NULL) { vpntip = g_strdup_printf (_("VPN connection to '%s'"), nmwa_vpn_connection_get_name (vpn)); } else { vpn = nmwa_get_first_activating_vpn_connection (applet); if (vpn != NULL) { need_animation = TRUE; vpntip = g_strdup_printf (_("VPN connecting to '%s'"), nmwa_vpn_connection_get_name (vpn)); } } if (vpntip) { char *newtip; newtip = g_strconcat (tip, "\n", vpntip, NULL); g_free (vpntip); g_free (tip); tip = newtip; } done: if (!applet->tooltips) applet->tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (applet->tooltips, applet->event_box, tip, NULL); g_free (tip); applet->animation_step = 0; if (need_animation && applet->animation_id == 0) applet->animation_id = g_timeout_add (100, (GSourceFunc) animation_timeout, applet); else if (!need_animation) { if (applet->animation_id) { g_source_remove (applet->animation_id); applet->animation_id = 0; } if (pixbuf) nmwa_set_icon (applet, pixbuf, applet->vpn_lock_icon); else show_applet = FALSE; } /* determine if we should hide the notification icon */ if (show_applet) gtk_widget_show (GTK_WIDGET (applet)); else gtk_widget_hide (GTK_WIDGET (applet)); } /* * nmwa_redraw_timeout * * Called regularly to update the applet's state and icon in the panel * */ static int nmwa_redraw_timeout (NMWirelessApplet *applet) { if (!applet->animation_id) nmwa_update_state (applet); return TRUE; } /* * show_warning_dialog * * pop up a warning or error dialog with certain text * */ static gboolean show_warning_dialog (char *mesg) { GtkWidget * dialog; guint32 timestamp; dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, mesg, NULL); gtk_widget_realize (dialog); /* Bash focus-stealing prevention in the face */ timestamp = gdk_x11_get_server_time (dialog->window); gdk_x11_window_set_user_time (dialog->window, timestamp); gtk_window_present (GTK_WINDOW (dialog)); g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); g_free (mesg); return FALSE; } /* * nmwa_schedule_warning_dialog * * Run a warning dialog in the main event loop. * */ void nmwa_schedule_warning_dialog (NMWirelessApplet *applet, const char *msg) { char *lcl_msg; g_return_if_fail (applet != NULL); g_return_if_fail (msg != NULL); lcl_msg = g_strdup (msg); g_idle_add ((GSourceFunc) show_warning_dialog, lcl_msg); } /* * nmwa_get_device_for_nm_device * * Searches the device list for a device that matches the * NetworkManager ID given. * */ NetworkDevice *nmwa_get_device_for_nm_path (GSList *dev_list, const char *nm_path) { NetworkDevice *found_dev = NULL; GSList *elt; g_return_val_if_fail (nm_path != NULL, NULL); g_return_val_if_fail (strlen (nm_path), NULL); for (elt = dev_list; elt; elt = g_slist_next (elt)) { NetworkDevice *dev = (NetworkDevice *)(elt->data); if (dev && (strcmp (network_device_get_nm_path (dev), nm_path) == 0)) { found_dev = dev; break; } } return (found_dev); } /* * nmwa_menu_item_activate * * Signal function called when user clicks on a menu item * */ static void nmwa_menu_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; NetworkDevice *dev = NULL; WirelessNetwork *net = NULL; char *tag; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); if (!(tag = g_object_get_data (G_OBJECT (item), "device"))) return; if ((dev = nmwa_get_device_for_nm_path (applet->device_list, tag))) network_device_ref (dev); if (!dev) return; if ((tag = g_object_get_data (G_OBJECT (item), "network"))) net = network_device_get_wireless_network_by_essid (dev, tag); nmwa_dbus_set_device (applet->connection, dev, net ? wireless_network_get_essid (net) : NULL, NULL); network_device_unref (dev); nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_vpn_item_activate * * Signal function called when user clicks on a VPN menu item * */ static void nmwa_menu_vpn_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; char *tag; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); if ((tag = g_object_get_data (G_OBJECT (item), "vpn"))) { VPNConnection *vpn = (VPNConnection *)tag; const char *name = nmwa_vpn_connection_get_name (vpn); GSList *passwords; VPNConnection *active_vpn = nmwa_get_first_active_vpn_connection (applet); if (vpn != active_vpn) { char *gconf_key; char *escaped_name; gboolean last_attempt_success; gboolean reprompt; escaped_name = gconf_escape_key (name, strlen (name)); gconf_key = g_strdup_printf ("%s/%s/last_attempt_success", GCONF_PATH_VPN_CONNECTIONS, escaped_name); last_attempt_success = gconf_client_get_bool (applet->gconf_client, gconf_key, NULL); g_free (gconf_key); g_free (escaped_name); reprompt = ! last_attempt_success; /* it's obvious, but.. */ if ((passwords = nmwa_vpn_request_password (applet, name, nmwa_vpn_connection_get_service (vpn), reprompt)) != NULL) { nmwa_dbus_vpn_activate_connection (applet->connection, name, passwords); g_slist_foreach (passwords, (GFunc)g_free, NULL); g_slist_free (passwords); } } } nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_connect_item_activate * * Signal function called when user clicks on a dialup menu item * */ static void nmwa_menu_dialup_connect_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *) user_data; const char *dialup; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); dialup = g_object_get_data (G_OBJECT (item), "dialup"); if (!dialup) return; nmwa_dbus_dialup_activate_connection (applet, dialup); nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_dialup_hangup_activate * * Signal function called when user clicks on a dialup menu item * */ static void nmwa_menu_dialup_disconnect_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *) user_data; const char *dialup; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); dialup = g_object_get_data (G_OBJECT (item), "dialup"); if (!dialup) return; nmwa_dbus_dialup_deactivate_connection (applet, dialup); nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_configure_vpn_item_activate * * Signal function called when user clicks "Configure VPN..." * */ static void nmwa_menu_configure_vpn_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; const char *argv[] = { BINDIR "/nm-vpn-properties", NULL}; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); g_spawn_async (NULL, (gchar **) argv, NULL, 0, NULL, NULL, NULL, NULL); nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_disconnect_vpn_item_activate * * Signal function called when user clicks "Disconnect VPN..." * */ static void nmwa_menu_disconnect_vpn_item_activate (GtkMenuItem *item, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; g_return_if_fail (item != NULL); g_return_if_fail (applet != NULL); nmwa_dbus_vpn_deactivate_connection (applet->connection); nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_menu_add_separator_item * */ static void nmwa_menu_add_separator_item (GtkWidget *menu) { GtkWidget *menu_item; menu_item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); } /* * nmwa_menu_add_text_item * * Add a non-clickable text item to a menu * */ static void nmwa_menu_add_text_item (GtkWidget *menu, char *text) { GtkWidget *menu_item; g_return_if_fail (text != NULL); g_return_if_fail (menu != NULL); menu_item = gtk_menu_item_new_with_label (text); gtk_widget_set_sensitive (menu_item, FALSE); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); } /* * nmwa_menu_add_device_item * * Add a network device to the menu * */ static void nmwa_menu_add_device_item (GtkWidget *menu, NetworkDevice *device, gint n_devices, NMWirelessApplet *applet) { g_return_if_fail (menu != NULL); g_return_if_fail (device != NULL); g_return_if_fail (applet != NULL); switch (network_device_get_type (device)) { case DEVICE_TYPE_802_3_ETHERNET: { NMWiredMenuItem *item = wired_menu_item_new (); GtkCheckMenuItem *gtk_item = wired_menu_item_get_check_item (item); wired_menu_item_update (item, device, n_devices); if (network_device_get_active (device)) gtk_check_menu_item_set_active (gtk_item, TRUE); gtk_check_menu_item_set_draw_as_radio (gtk_item, TRUE); g_object_set_data (G_OBJECT (gtk_item), "device", g_strdup (network_device_get_nm_path (device))); g_object_set_data (G_OBJECT (gtk_item), "nm-item-data", item); g_signal_connect(G_OBJECT (gtk_item), "activate", G_CALLBACK (nmwa_menu_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (gtk_item)); gtk_widget_show (GTK_WIDGET (gtk_item)); break; } case DEVICE_TYPE_802_11_WIRELESS: { NMWirelessMenuItem *item; GtkMenuItem *gtk_item; if (!applet->wireless_enabled) break; item = wireless_menu_item_new (); gtk_item = wireless_menu_item_get_item (item); wireless_menu_item_update (item, device, n_devices); g_object_set_data (G_OBJECT (gtk_item), "device", g_strdup (network_device_get_nm_path (device))); g_object_set_data (G_OBJECT (gtk_item), "nm-item-data", item); g_signal_connect(G_OBJECT (gtk_item), "activate", G_CALLBACK (nmwa_menu_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (gtk_item)); gtk_widget_show (GTK_WIDGET (gtk_item)); break; } default: break; } } static void custom_essid_item_selected (GtkWidget *menu_item, NMWirelessApplet *applet) { nmwa_other_network_dialog_run (applet, FALSE); } static void nmwa_menu_add_custom_essid_item (GtkWidget *menu, NMWirelessApplet *applet) { GtkWidget *menu_item; GtkWidget *label; menu_item = gtk_menu_item_new (); label = gtk_label_new_with_mnemonic (_("_Connect to Other Wireless Network...")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (menu_item), label); gtk_widget_show_all (menu_item); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); g_signal_connect (menu_item, "activate", G_CALLBACK (custom_essid_item_selected), applet); } static void new_network_item_selected (GtkWidget *menu_item, NMWirelessApplet *applet) { nmwa_other_network_dialog_run (applet, TRUE); } static void nmwa_menu_add_create_network_item (GtkWidget *menu, NMWirelessApplet *applet) { GtkWidget *menu_item; GtkWidget *label; menu_item = gtk_menu_item_new (); label = gtk_label_new_with_mnemonic (_("Create _New Wireless Network...")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (menu_item), label); gtk_widget_show_all (menu_item); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); g_signal_connect (menu_item, "activate", G_CALLBACK (new_network_item_selected), applet); } typedef struct AddNetworksCB { NMWirelessApplet * applet; gboolean has_encrypted; GtkWidget * menu; } AddNetworksCB; /* * nmwa_add_networks_helper * */ static void nmwa_add_networks_helper (NetworkDevice *dev, WirelessNetwork *net, gpointer user_data) { AddNetworksCB * cb_data = (AddNetworksCB *)user_data; NMNetworkMenuItem * item; GtkCheckMenuItem * gtk_item; g_return_if_fail (dev != NULL); g_return_if_fail (net != NULL); g_return_if_fail (cb_data != NULL); g_return_if_fail (cb_data->menu != NULL); g_return_if_fail (cb_data->applet != NULL); item = network_menu_item_new (cb_data->applet->encryption_size_group); gtk_item = network_menu_item_get_check_item (item); gtk_menu_shell_append (GTK_MENU_SHELL (cb_data->menu), GTK_WIDGET (gtk_item)); if (network_device_get_active (dev) && wireless_network_get_active (net)) gtk_check_menu_item_set_active (gtk_item, TRUE); network_menu_item_update (item, net, cb_data->has_encrypted); g_object_set_data (G_OBJECT (gtk_item), "network", g_strdup (wireless_network_get_essid (net))); g_object_set_data (G_OBJECT (gtk_item), "device", g_strdup (network_device_get_nm_path (dev))); g_object_set_data (G_OBJECT (gtk_item), "nm-item-data", item); g_signal_connect (G_OBJECT (gtk_item), "activate", G_CALLBACK (nmwa_menu_item_activate), cb_data->applet); gtk_widget_show (GTK_WIDGET (gtk_item)); } /* * nmwa_has_encrypted_networks_helper * */ static void nmwa_has_encrypted_networks_helper (NetworkDevice *dev, WirelessNetwork *net, gpointer user_data) { gboolean *has_encrypted = user_data; int capabilities; g_return_if_fail (dev != NULL); g_return_if_fail (net != NULL); g_return_if_fail (has_encrypted != NULL); capabilities = wireless_network_get_capabilities (net); if ( (capabilities & NM_802_11_CAP_PROTO_WEP) || (capabilities & NM_802_11_CAP_PROTO_WPA) || (capabilities & NM_802_11_CAP_PROTO_WPA2)) *has_encrypted = TRUE; } /* * nmwa_menu_device_add_networks * */ static void nmwa_menu_device_add_networks (GtkWidget *menu, NetworkDevice *dev, NMWirelessApplet *applet) { gboolean has_encrypted = FALSE; AddNetworksCB * add_networks_cb = NULL; g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); g_return_if_fail (dev != NULL); if (!network_device_is_wireless (dev) || !applet->wireless_enabled) return; /* Check for any security */ network_device_foreach_wireless_network (dev, nmwa_has_encrypted_networks_helper, &has_encrypted); add_networks_cb = g_malloc0 (sizeof (AddNetworksCB)); add_networks_cb->applet = applet; add_networks_cb->has_encrypted = has_encrypted; add_networks_cb->menu = menu; /* Add all networks in our network list to the menu */ network_device_foreach_wireless_network (dev, nmwa_add_networks_helper, add_networks_cb); g_free (add_networks_cb); } /* * nmwa_menu_add_devices * */ static void nmwa_menu_add_vpn_menu (GtkWidget *menu, NMWirelessApplet *applet) { GtkMenuItem *item; GtkMenu *vpn_menu; GtkMenuItem *other_item; GSList *elt; VPNConnection *active_vpn; g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_VPN Connections"))); vpn_menu = GTK_MENU (gtk_menu_new ()); active_vpn = nmwa_get_first_active_vpn_connection (applet); for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt)) { GtkCheckMenuItem *vpn_item; VPNConnection *vpn = elt->data; const char *vpn_name = nmwa_vpn_connection_get_name (vpn); vpn_item = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (vpn_name)); /* temporarily do this until we support multiple VPN connections */ gtk_check_menu_item_set_draw_as_radio (vpn_item, TRUE); nmwa_vpn_connection_ref (vpn); g_object_set_data (G_OBJECT (vpn_item), "vpn", vpn); if (active_vpn && active_vpn == vpn) gtk_check_menu_item_set_active (vpn_item, TRUE); if (applet->nm_state != NM_STATE_CONNECTED) gtk_widget_set_sensitive (GTK_WIDGET (vpn_item), FALSE); g_signal_connect (G_OBJECT (vpn_item), "activate", G_CALLBACK (nmwa_menu_vpn_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (vpn_item)); } /* Draw a seperator, but only if we have VPN connections above it */ if (applet->vpn_connections) { other_item = GTK_MENU_ITEM (gtk_separator_menu_item_new ()); gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (other_item)); } other_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Configure VPN..."))); g_signal_connect (G_OBJECT (other_item), "activate", G_CALLBACK (nmwa_menu_configure_vpn_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (other_item)); other_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Disconnect VPN..."))); g_signal_connect (G_OBJECT (other_item), "activate", G_CALLBACK (nmwa_menu_disconnect_vpn_item_activate), applet); if (!active_vpn) gtk_widget_set_sensitive (GTK_WIDGET (other_item), FALSE); gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (other_item)); gtk_menu_item_set_submenu (item, GTK_WIDGET (vpn_menu)); gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (item)); gtk_widget_show_all (GTK_WIDGET (item)); } static void nmwa_menu_add_dialup_menu (GtkWidget *menu, NMWirelessApplet *applet) { GtkMenuItem *item; GtkMenu *dialup_menu; GtkWidget *hangup_item; GSList *elt; g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Dial Up Connections"))); dialup_menu = GTK_MENU (gtk_menu_new ()); for (elt = applet->dialup_list; elt; elt = g_slist_next (elt)) { GtkMenuItem *connect_item, *disconnect_item; char *name = elt->data; const char *label; /* FIXME: We should save and then check the state of the devices and show Connect _or_ Disconnect for each item */ label = g_strdup_printf (_("Connect to %s..."), name); connect_item = GTK_MENU_ITEM (gtk_menu_item_new_with_label (label)); g_object_set_data (G_OBJECT (connect_item), "dialup", name); g_signal_connect (G_OBJECT (connect_item), "activate", G_CALLBACK (nmwa_menu_dialup_connect_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (dialup_menu), GTK_WIDGET (connect_item)); label = g_strdup_printf (_("Disconnect from %s..."), name); disconnect_item = GTK_MENU_ITEM (gtk_menu_item_new_with_label (label)); g_object_set_data (G_OBJECT (disconnect_item), "dialup", name); g_signal_connect (G_OBJECT (disconnect_item), "activate", G_CALLBACK (nmwa_menu_dialup_disconnect_item_activate), applet); gtk_menu_shell_append (GTK_MENU_SHELL (dialup_menu), GTK_WIDGET (disconnect_item)); } gtk_menu_item_set_submenu (item, GTK_WIDGET (dialup_menu)); gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (item)); gtk_widget_show_all (GTK_WIDGET (item)); } /** Returns TRUE if, and only if, we have VPN support installed * * Algorithm: just check whether any files exist in the directory * /etc/NetworkManager/VPN */ static gboolean is_vpn_available (void) { GDir *dir; gboolean result; result = FALSE; if ((dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL)) != NULL) { if (g_dir_read_name (dir) != NULL) result = TRUE; g_dir_close (dir); } return result; } /* * nmwa_menu_add_devices * */ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet) { GSList *element; gint n_wireless_interfaces = 0; gint n_wired_interfaces = 0; gboolean vpn_available, dialup_available; g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); if (! applet->device_list) { nmwa_menu_add_text_item (menu, _("No network devices have been found")); return; } for (element = applet->device_list; element; element = element->next) { NetworkDevice *dev = (NetworkDevice *)(element->data); g_assert (dev); /* Ignore unsupported devices */ if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) continue; switch (network_device_get_type (dev)) { case DEVICE_TYPE_802_11_WIRELESS: n_wireless_interfaces++; break; case DEVICE_TYPE_802_3_ETHERNET: n_wired_interfaces++; break; default: break; } } /* Add all devices in our device list to the menu */ for (element = applet->device_list; element; element = element->next) { NetworkDevice *dev = (NetworkDevice *)(element->data); if (dev) { gint n_devices = 0; /* Ignore unsupported devices */ if (!(network_device_get_capabilities (dev) & NM_DEVICE_CAP_NM_SUPPORTED)) continue; switch (network_device_get_type (dev)) { case DEVICE_TYPE_802_3_ETHERNET: n_devices = n_wired_interfaces; break; case DEVICE_TYPE_802_11_WIRELESS: n_devices = n_wireless_interfaces; break; default: break; } if (n_devices >= 0) { nmwa_menu_add_device_item (menu, dev, n_devices, applet); nmwa_menu_device_add_networks (menu, dev, applet); } } } /* Add the VPN and Dial Up menus and their associated seperator */ vpn_available = is_vpn_available (); dialup_available = !! applet->dialup_list; if (vpn_available || dialup_available) { nmwa_menu_add_separator_item (menu); if (vpn_available) nmwa_menu_add_vpn_menu (menu, applet); if (dialup_available) nmwa_menu_add_dialup_menu (menu, applet); } if (n_wireless_interfaces > 0 && applet->wireless_enabled) { /* Add the "Other wireless network..." entry */ nmwa_menu_add_separator_item (menu); nmwa_menu_add_custom_essid_item (menu, applet); nmwa_menu_add_create_network_item (menu, applet); } } static void nmwa_set_wireless_enabled_cb (GtkWidget *widget, NMWirelessApplet *applet) { gboolean state; g_return_if_fail (applet != NULL); state = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)); if (applet->wireless_enabled != state) nmwa_dbus_enable_wireless (applet, state); } /* * nmwa_menu_item_data_free * * Frees the "network" data tag on a menu item we've created * */ static void nmwa_menu_item_data_free (GtkWidget *menu_item, gpointer data) { char *tag; GtkMenu *menu; g_return_if_fail (menu_item != NULL); g_return_if_fail (data != NULL); if ((tag = g_object_get_data (G_OBJECT (menu_item), "network"))) { g_object_set_data (G_OBJECT (menu_item), "network", NULL); g_free (tag); } if ((tag = g_object_get_data (G_OBJECT (menu_item), "nm-item-data"))) { g_object_set_data (G_OBJECT (menu_item), "nm-item-data", NULL); g_free (tag); } if ((tag = g_object_get_data (G_OBJECT (menu_item), "device"))) { g_object_set_data (G_OBJECT (menu_item), "device", NULL); g_free (tag); } if ((tag = g_object_get_data (G_OBJECT (menu_item), "vpn"))) { g_object_set_data (G_OBJECT (menu_item), "vpn", NULL); nmwa_vpn_connection_unref ((VPNConnection *)tag); } if ((tag = g_object_get_data (G_OBJECT (menu_item), "disconnect"))) { g_object_set_data (G_OBJECT (menu_item), "disconnect", NULL); g_free (tag); } if ((menu = GTK_MENU (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item))))) gtk_container_foreach (GTK_CONTAINER (menu), nmwa_menu_item_data_free, menu); gtk_widget_destroy (menu_item); } /* * nmwa_dispose_menu_items * * Destroy the menu and each of its items data tags * */ static void nmwa_dropdown_menu_clear (GtkWidget *menu) { g_return_if_fail (menu != NULL); /* Free the "network" data on each menu item, and destroy the item */ gtk_container_foreach (GTK_CONTAINER (menu), nmwa_menu_item_data_free, menu); } /* * nmwa_dropdown_menu_populate * * Set up our networks menu from scratch * */ static void nmwa_dropdown_menu_populate (GtkWidget *menu, NMWirelessApplet *applet) { g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); if (!applet->nm_running) nmwa_menu_add_text_item (menu, _("NetworkManager is not running...")); else nmwa_menu_add_devices (menu, applet); } /* * nmwa_dropdown_menu_show_cb * * Pop up the wireless networks menu * */ static void nmwa_dropdown_menu_show_cb (GtkWidget *menu, NMWirelessApplet *applet) { g_return_if_fail (menu != NULL); g_return_if_fail (applet != NULL); if (!applet->tooltips) applet->tooltips = gtk_tooltips_new (); gtk_tooltips_set_tip (applet->tooltips, applet->event_box, NULL, NULL); if (applet->dropdown_menu && (menu == applet->dropdown_menu)) { nmwa_dropdown_menu_clear (applet->dropdown_menu); nmwa_dropdown_menu_populate (applet->dropdown_menu, applet); gtk_widget_show_all (applet->dropdown_menu); } nmi_dbus_signal_user_interface_activated (applet->connection); } /* * nmwa_dropdown_menu_create * * Create the applet's dropdown menu * */ static GtkWidget *nmwa_dropdown_menu_create (GtkMenuItem *parent, NMWirelessApplet *applet) { GtkWidget *menu; g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (applet != NULL, NULL); menu = gtk_menu_new (); gtk_container_set_border_width (GTK_CONTAINER (menu), 0); gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), menu); g_signal_connect (menu, "show", G_CALLBACK (nmwa_dropdown_menu_show_cb), applet); return menu; } /* * nmwa_context_menu_update * */ static void nmwa_context_menu_update (NMWirelessApplet *applet) { GSList *element; gboolean have_wireless = FALSE; NetworkDevice *dev; const char *iface = NULL; g_return_if_fail (applet != NULL); g_return_if_fail (applet->stop_wireless_item != NULL); g_return_if_fail (applet->info_menu_item != NULL); if ((dev = nmwa_get_first_active_device (applet->device_list))) iface = network_device_get_iface (dev); if (!dev || !iface) gtk_widget_set_sensitive (applet->info_menu_item, FALSE); else gtk_widget_set_sensitive (applet->info_menu_item, TRUE); for (element = applet->device_list; element; element = element->next) { dev = (NetworkDevice *)(element->data); g_assert (dev); if (network_device_get_type (dev) == DEVICE_TYPE_802_11_WIRELESS) { have_wireless = TRUE; break; } } if (have_wireless) gtk_widget_show_all (applet->stop_wireless_item); else gtk_widget_hide (applet->stop_wireless_item); } /* * nmwa_enable_wireless_set_active * * Set the 'Enable Wireless' menu item state to match the daemon's last DBUS * message. We cannot just do this at menu creation time because the DBUS * message might not have been sent yet or in case the daemon state changes * out from under us. */ void nmwa_enable_wireless_set_active (NMWirelessApplet *applet) { gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->stop_wireless_item), applet->wireless_enabled); } /* * nmwa_context_menu_create * * Generate the contextual popup menu. * */ static GtkWidget *nmwa_context_menu_create (NMWirelessApplet *applet) { GtkWidget *menu; GtkWidget *menu_item; GtkWidget *image; g_return_val_if_fail (applet != NULL, NULL); menu = gtk_menu_new (); /* 'Enable Wireless' item */ applet->stop_wireless_item = gtk_check_menu_item_new_with_mnemonic (_("Enable _Wireless")); nmwa_enable_wireless_set_active (applet); g_signal_connect (G_OBJECT (applet->stop_wireless_item), "toggled", G_CALLBACK (nmwa_set_wireless_enabled_cb), applet); gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->stop_wireless_item); /* 'Connection Information' item */ applet->info_menu_item = gtk_image_menu_item_new_with_mnemonic (_("Connection _Information")); g_signal_connect (G_OBJECT (applet->info_menu_item), "activate", G_CALLBACK (nmwa_show_info_cb), applet); image = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->info_menu_item), image); gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->info_menu_item); /* Separator */ nmwa_menu_add_separator_item (menu); #if 0 /* FIXME: Implement the help callback, nmwa_help_cb()! */ /* Help item */ menu_item = gtk_image_menu_item_new_with_mnemonic (_("_Help")); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (nmwa_help_cb), applet); image = gtk_image_new_from_stock (GTK_STOCK_HELP, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE); #endif /* About item */ menu_item = gtk_image_menu_item_new_with_mnemonic (_("_About")); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (nmwa_about_cb), applet); image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show_all (menu); return menu; } /* * nmwa_theme_change_cb * * Destroy the popdown menu when the theme changes * */ static void nmwa_theme_change_cb (NMWirelessApplet *applet) { g_return_if_fail (applet != NULL); if (applet->dropdown_menu) nmwa_dropdown_menu_clear (applet->dropdown_menu); if (applet->top_menu_item) { gtk_menu_item_remove_submenu (GTK_MENU_ITEM (applet->top_menu_item)); applet->dropdown_menu = nmwa_dropdown_menu_create (GTK_MENU_ITEM (applet->top_menu_item), applet); } } /* * nmwa_toplevel_menu_button_press_cb * * Handle right-clicks for the context popup menu * */ static gboolean nmwa_toplevel_menu_button_press_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { NMWirelessApplet *applet = (NMWirelessApplet *)user_data; g_return_val_if_fail (applet != NULL, FALSE); if (event->button != 1) g_signal_stop_emission_by_name (widget, "button_press_event"); if (event->button == 3) { nmwa_context_menu_update (applet); gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL, NULL, applet, event->button, event->time); return (TRUE); } return (FALSE); } /* * nmwa_setup_widgets * * Intialize the applet's widgets and packing, create the initial * menu of networks. * */ static void nmwa_setup_widgets (NMWirelessApplet *applet) { GtkWidget *menu_bar; /* Event box for tooltips */ applet->event_box = gtk_event_box_new (); gtk_container_set_border_width (GTK_CONTAINER (applet->event_box), 0); menu_bar = gtk_menu_bar_new (); applet->top_menu_item = gtk_menu_item_new(); gtk_widget_set_name (applet->top_menu_item, "ToplevelMenu"); gtk_container_set_border_width (GTK_CONTAINER (applet->top_menu_item), 0); g_signal_connect (applet->top_menu_item, "button_press_event", G_CALLBACK (nmwa_toplevel_menu_button_press_cb), applet); applet->dropdown_menu = nmwa_dropdown_menu_create (GTK_MENU_ITEM (applet->top_menu_item), applet); applet->pixmap = gtk_image_new (); applet->icon_box = gtk_hbox_new (FALSE, 3); gtk_container_set_border_width (GTK_CONTAINER (applet->icon_box), 0); /* Set up the widget structure and show the applet */ gtk_container_add (GTK_CONTAINER (applet->icon_box), applet->pixmap); gtk_container_add (GTK_CONTAINER (applet->top_menu_item), applet->icon_box); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), applet->top_menu_item); gtk_container_add (GTK_CONTAINER (applet->event_box), menu_bar); gtk_container_add (GTK_CONTAINER (applet), applet->event_box); gtk_widget_show_all (GTK_WIDGET (applet)); applet->context_menu = nmwa_context_menu_create (applet); applet->encryption_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); } /* * nmwa_gconf_info_notify_callback * * Callback from gconf when wireless key/values have changed. * */ static void nmwa_gconf_info_notify_callback (GConfClient *client, guint connection_id, GConfEntry *entry, gpointer user_data) { NMWirelessApplet * applet = (NMWirelessApplet *)user_data; const char * key = NULL; g_return_if_fail (client != NULL); g_return_if_fail (entry != NULL); g_return_if_fail (applet != NULL); if ((key = gconf_entry_get_key (entry))) { int net_path_len = strlen (GCONF_PATH_WIRELESS_NETWORKS) + 1; if (strncmp (GCONF_PATH_WIRELESS_NETWORKS"/", key, net_path_len) == 0) { char *network = g_strdup ((key + net_path_len)); char *slash_pos; char *unescaped_network; /* If its a key under the network name, zero out the slash so we * are left with only the network name. */ unescaped_network = gconf_unescape_key (network, strlen (network)); if ((slash_pos = strchr (unescaped_network, '/'))) *slash_pos = '\0'; nmi_dbus_signal_update_network (applet->connection, unescaped_network, NETWORK_TYPE_ALLOWED); g_free (unescaped_network); g_free (network); } } } /* * nmwa_gconf_vpn_connections_notify_callback * * Callback from gconf when VPN connection values have changed. * */ static void nmwa_gconf_vpn_connections_notify_callback (GConfClient *client, guint connection_id, GConfEntry *entry, gpointer user_data) { NMWirelessApplet * applet = (NMWirelessApplet *)user_data; const char * key = NULL; /*g_debug ("Entering nmwa_gconf_vpn_connections_notify_callback, key='%s'", gconf_entry_get_key (entry));*/ g_return_if_fail (client != NULL); g_return_if_fail (entry != NULL); g_return_if_fail (applet != NULL); if ((key = gconf_entry_get_key (entry))) { int path_len = strlen (GCONF_PATH_VPN_CONNECTIONS) + 1; if (strncmp (GCONF_PATH_VPN_CONNECTIONS"/", key, path_len) == 0) { char *name = g_strdup ((key + path_len)); char *slash_pos; char *unescaped_name; char *name_path; GConfValue *value; /* If its a key under the the VPN name, zero out the slash so we * are left with only the VPN name. */ if ((slash_pos = strchr (name, '/'))) *slash_pos = '\0'; unescaped_name = gconf_unescape_key (name, strlen (name)); /* Check here if the name entry is gone so we can remove the conn from the UI */ name_path = g_strdup_printf ("%s/%s/name", GCONF_PATH_VPN_CONNECTIONS, name); gconf_client_clear_cache (client); value = gconf_client_get (client, name_path, NULL); if (value == NULL) { /*g_debug ("removing '%s' from UI", name_path);*/ nmwa_dbus_vpn_remove_one_vpn_connection (applet, unescaped_name); } else { gconf_value_free (value); } g_free (name_path); nmi_dbus_signal_update_vpn_connection (applet->connection, unescaped_name); g_free (unescaped_name); g_free (name); } } } /* * nmwa_destroy * * Destroy the applet and clean up its data * */ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data) { if (applet->dropdown_menu) nmwa_dropdown_menu_clear (applet->dropdown_menu); if (applet->top_menu_item) gtk_menu_item_remove_submenu (GTK_MENU_ITEM (applet->top_menu_item)); nmwa_icons_free (applet); nmi_passphrase_dialog_destroy (applet); if (applet->redraw_timeout_id > 0) { gtk_timeout_remove (applet->redraw_timeout_id); applet->redraw_timeout_id = 0; } if (applet->gconf_client) g_object_unref (G_OBJECT (applet->gconf_client)); nmwa_free_data_model (applet); g_free (applet->glade_file); gconf_client_notify_remove (applet->gconf_client, applet->gconf_prefs_notify_id); gconf_client_notify_remove (applet->gconf_client, applet->gconf_vpn_notify_id); g_object_unref (G_OBJECT (applet->gconf_client)); dbus_method_dispatcher_unref (applet->nmi_methods); exit (EXIT_SUCCESS); } /* * nmwa_get_instance * * Create the initial instance of our wireless applet * */ static GtkWidget * nmwa_get_instance (NMWirelessApplet *applet) { gtk_widget_hide (GTK_WIDGET (applet)); applet->nm_running = FALSE; applet->device_list = NULL; applet->vpn_connections = NULL; applet->dialup_list = NULL; applet->nm_state = NM_STATE_DISCONNECTED; applet->tooltips = NULL; applet->passphrase_dialog = NULL; applet->glade_file = g_build_filename (GLADEDIR, "wireless-applet.glade", NULL); if (!applet->glade_file || !g_file_test (applet->glade_file, G_FILE_TEST_IS_REGULAR)) { nmwa_schedule_warning_dialog (applet, _("The NetworkManager Applet could not find some required resources (the glade file was not found).")); g_free (applet->glade_file); applet->glade_file = NULL; return NULL; } applet->info_dialog_xml = glade_xml_new (applet->glade_file, "info_dialog", NULL); applet->gconf_client = gconf_client_get_default (); if (!applet->gconf_client) return NULL; gconf_client_add_dir (applet->gconf_client, GCONF_PATH_WIRELESS, GCONF_CLIENT_PRELOAD_NONE, NULL); applet->gconf_prefs_notify_id = gconf_client_notify_add (applet->gconf_client, GCONF_PATH_WIRELESS, nmwa_gconf_info_notify_callback, applet, NULL, NULL); gconf_client_add_dir (applet->gconf_client, GCONF_PATH_VPN_CONNECTIONS, GCONF_CLIENT_PRELOAD_NONE, NULL); applet->gconf_vpn_notify_id = gconf_client_notify_add (applet->gconf_client, GCONF_PATH_VPN_CONNECTIONS, nmwa_gconf_vpn_connections_notify_callback, applet, NULL, NULL); /* Convert old-format stored network entries to the new format. * Must be RUN BEFORE DBUS INITIALIZATION since we have to do * synchronous calls against gnome-keyring. */ nma_compat_convert_oldformat_entries (applet->gconf_client); nmwa_dbus_init_helper (applet); /* Load pixmaps and create applet widgets */ nmwa_setup_widgets (applet); g_signal_connect (applet, "destroy", G_CALLBACK (nmwa_destroy), NULL); g_signal_connect (applet, "style-set", G_CALLBACK (nmwa_theme_change_cb), NULL); /* Start redraw timeout */ applet->redraw_timeout_id = g_timeout_add (1000, (GtkFunction) nmwa_redraw_timeout, applet); return GTK_WIDGET (applet); } static void nmwa_icons_free (NMWirelessApplet *applet) { gint i,j; g_object_unref (applet->no_connection_icon); g_object_unref (applet->wired_icon); g_object_unref (applet->adhoc_icon); g_object_unref (applet->vpn_lock_icon); g_object_unref (applet->wireless_00_icon); g_object_unref (applet->wireless_25_icon); g_object_unref (applet->wireless_50_icon); g_object_unref (applet->wireless_75_icon); g_object_unref (applet->wireless_100_icon); for (i = 0; i < NUM_CONNECTING_STAGES; i++) for (j = 0; j < NUM_CONNECTING_FRAMES; j++) g_object_unref (applet->network_connecting_icons[i][j]); for (i = 0; i < NUM_VPN_CONNECTING_FRAMES; i++) g_object_unref (applet->vpn_connecting_icons[i]); } #define ICON_LOAD(x, y) \ { \ GError *err = NULL; \ x = gtk_icon_theme_load_icon (icon_theme, y, icon_size, 0, &err); \ if (x == NULL) { \ success = FALSE; \ g_warning ("Icon %s missing: %s", y, err->message); \ g_error_free (err); \ goto out; \ } \ } static gboolean nmwa_icons_load_from_disk (NMWirelessApplet *applet, GtkIconTheme *icon_theme) { char * name; int i, j; gboolean success = FALSE; /* Assume icons are square */ gint icon_size = 22; ICON_LOAD(applet->no_connection_icon, "nm-no-connection"); ICON_LOAD(applet->wired_icon, "nm-device-wired"); ICON_LOAD(applet->adhoc_icon, "nm-adhoc"); ICON_LOAD(applet->vpn_lock_icon, "nm-vpn-lock"); ICON_LOAD(applet->wireless_00_icon, "nm-signal-00"); ICON_LOAD(applet->wireless_25_icon, "nm-signal-25"); ICON_LOAD(applet->wireless_50_icon, "nm-signal-50"); ICON_LOAD(applet->wireless_75_icon, "nm-signal-75"); ICON_LOAD(applet->wireless_100_icon, "nm-signal-100"); for (i = 0; i < NUM_CONNECTING_STAGES; i++) { for (j = 0; j < NUM_CONNECTING_FRAMES; j++) { name = g_strdup_printf ("nm-stage%02d-connecting%02d", i+1, j+1); ICON_LOAD(applet->network_connecting_icons[i][j], name); g_free (name); } } for (i = 0; i < NUM_VPN_CONNECTING_FRAMES; i++) { name = g_strdup_printf ("nm-vpn-connecting%02d", i+1); ICON_LOAD(applet->vpn_connecting_icons[i], name); g_free (name); } success = TRUE; out: if (!success) { char *msg = g_strdup(_("The NetworkManager applet could not find some required resources. It cannot continue.\n")); show_warning_dialog (msg); nmwa_icons_free (applet); } return success; } static void nmwa_icon_theme_changed (GtkIconTheme *icon_theme, NMWirelessApplet *applet) { nmwa_icons_free (applet); nmwa_icons_load_from_disk (applet, icon_theme); /* FIXME: force redraw */ } static gboolean nmwa_icons_init (NMWirelessApplet *applet) { GtkIconTheme *icon_theme; const gchar *style = " \ style \"MenuBar\" \ { \ GtkMenuBar::shadow_type = GTK_SHADOW_NONE \ GtkMenuBar::internal-padding = 0 \ } \ style \"MenuItem\" \ { \ xthickness=0 \ ythickness=0 \ } \ class \"GtkMenuBar\" style \"MenuBar\"\ widget \"*ToplevelMenu*\" style \"MenuItem\"\ "; /* FIXME: Do we need to worry about other screens? */ gtk_rc_parse_string (style); icon_theme = gtk_icon_theme_get_default (); if (!nmwa_icons_load_from_disk (applet, icon_theme)) return FALSE; g_signal_connect (icon_theme, "changed", G_CALLBACK (nmwa_icon_theme_changed), applet); return TRUE; } NMWirelessApplet *nmwa_new () { return g_object_new (NM_TYPE_WIRELESS_APPLET, "title", "NetworkManager", NULL); }