diff --git a/ChangeLog b/ChangeLog index a3b05eaa6..8049adf8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,57 @@ +2004-08-12 Dan Williams + + * info-daemon/passphrase.glade + - Set window title to " " + + * panel-applet/Makefile.am + panel-applet/keyring.png + - Deliver to correct place + + * panel-applet/NMWirelessApplet.[ch] + - Add comments + - Remove applet->have_active_device as its no longer used + - (nmwa_load_theme): load keyring.png too + - (error_dialog): remove + - (show_warning_dialog): subsume functionality of error dialog too + - (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient + - (nmwa_handle_network_choice): add to deal with user clicking on an item from + the networks menu + - (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler + - (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup + and when we get broadcasts of changed wireless access points only, not when the + user clicks on the button to display the menu (too long of a wait) + - (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside + networks that are encrypted + - (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each + menu item with g_object_set_data() + + * panel-applet/NMWirelessAppletDbus.[ch] + - (nmwa_dbus_get_bool): add method to return boolean value from dbus message + - (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network) + - (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu + - (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards + - (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device + activation/deactivation signals and rebuild the menu when they happen + + * src/NetworkManager.c + - (main): use new nm_spawn_process() rather than system() + + * src/NetworkManagerDbus.c + - (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids + instead. Since we can now force best_aps to stick around, the AP structure to which + dev->options.wireless.best_ap points to won't necessarily be in the device's device list + if a scan has happened since the best_ap was frozen. Also add "setNetwork" method + to freeze the best_ap. + + * src/NetworkManagerDevice.[ch] + - (nm_device_activation_worker): Use new nm_spawn_process() call rather than system() + - (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update + the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's + ap list + + * src/NetworkManagerUtils.[ch] + - (nm_spawn_process): add replacement for system() usage + 2004-08-11 Dan Williams * panel-applet/NMWirelessApplet.[ch] diff --git a/info-daemon/passphrase.glade b/info-daemon/passphrase.glade index 273dd0cfb..4f4737af9 100644 --- a/info-daemon/passphrase.glade +++ b/info-daemon/passphrase.glade @@ -5,7 +5,7 @@ 6 - + GTK_WINDOW_TOPLEVEL GTK_WIN_POS_CENTER_ALWAYS False diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am index a5d97c548..50203ba29 100644 --- a/panel-applet/Makefile.am +++ b/panel-applet/Makefile.am @@ -53,6 +53,7 @@ pixmap_DATA = no-link-0.png \ connect-1.png \ connect-2.png \ connect-3.png \ + keyring.png \ $(NULL) CLEANFILES = $(server_in_files) $(server_DATA) *.bak *.gladep diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index 0e4858c71..3f19d4e61 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ static char * pixmap_names[] = "connect-3.png", }; +static char *glade_file; /* Represents an access point */ typedef struct @@ -71,12 +73,7 @@ typedef struct gboolean encrypted; } AccessPoint; -static GladeXML *xml = NULL; -static gchar *glade_file = NULL; - -static int nmwa_timeout_handler (NMWirelessApplet *applet); static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet); -static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet); static const BonoboUIVerb nmwa_context_menu_verbs [] = { @@ -105,6 +102,14 @@ static GType nmwa_get_type (void) return (type); } + +/* + * nmwa_draw + * + * Actually update the applet's pixmap so that our panel icon reflects + * the state of the applet + * + */ static void nmwa_draw (NMWirelessApplet *applet) { const char *label_text; @@ -117,6 +122,14 @@ static void nmwa_draw (NMWirelessApplet *applet) } } + +/* + * 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) { if (applet->nm_active) @@ -131,7 +144,6 @@ static void nmwa_update_state (NMWirelessApplet *applet) switch (type) { case (DEVICE_TYPE_WIRELESS_ETHERNET): - applet->have_active_device = TRUE; if (strcmp (status, "connected") == 0) applet->pix_state = PIX_SIGNAL_4; else if (strcmp (status, "connecting") == 0) @@ -146,29 +158,40 @@ static void nmwa_update_state (NMWirelessApplet *applet) case (DEVICE_TYPE_WIRED_ETHERNET): default: - applet->have_active_device = FALSE; applet->pix_state = PIX_BROKEN; break; } } else - { - applet->have_active_device = FALSE; applet->pix_state = PIX_BROKEN; - } if (active_device) dbus_free (active_device); if (status) dbus_free (status); } else - { - applet->have_active_device = FALSE; applet->pix_state = PIX_BROKEN; - } nmwa_draw (applet); } + +/* + * nmwa_timeout_handler + * + * Called regularly to update the applet's state and icon in the panel + * + */ +static int nmwa_timeout_handler (NMWirelessApplet *applet) +{ + /* Try to get a connection to dbus if we don't already have one */ + if (!applet->connection) + applet->connection = nmwa_dbus_init (applet); + + nmwa_update_state (applet); + + return (TRUE); +} + static void nmwa_start_timeout (NMWirelessApplet *applet) { applet->timeout_handler_id = g_timeout_add (CFG_UPDATE_INTERVAL * 1000, @@ -185,9 +208,10 @@ static void nmwa_cancel_timeout (NMWirelessApplet *applet) static void nmwa_load_theme (NMWirelessApplet *applet) { - char *pixmapdir; - char *pixmapname; - int i; + char *pixmapdir; + char *pixmapname; + int i; + GError *error = NULL; pixmapdir = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "NMWirelessApplet/", FALSE, NULL); @@ -200,22 +224,21 @@ static void nmwa_load_theme (NMWirelessApplet *applet) g_free (pixmapname); } + pixmapname = g_build_filename (G_DIR_SEPARATOR_S, pixmapdir, "keyring.png", NULL); + applet->key_pixbuf = gdk_pixbuf_new_from_file_at_size (pixmapname, 16, 16, &error); + g_free (pixmapname); + g_free (pixmapdir); } - -static int nmwa_timeout_handler (NMWirelessApplet *applet) -{ - /* Try to get a connection to dbus if we don't already have one */ - if (!applet->connection) - applet->connection = nmwa_dbus_init (applet); - nmwa_update_state (applet); - - return (TRUE); -} - -void show_error_dialog (gchar *mesg, ...) +/* + * show_warning_dialog + * + * pop up a warning or error dialog with certain text + * + */ +static void show_warning_dialog (gboolean error, gchar *mesg, ...) { GtkWidget *dialog; char *tmp; @@ -223,22 +246,8 @@ void show_error_dialog (gchar *mesg, ...) va_start (ap,mesg); tmp = g_strdup_vprintf (mesg,ap); - dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, mesg, NULL); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - g_free (tmp); - va_end (ap); -} - -void show_warning_dialog (gchar *mesg, ...) -{ - GtkWidget *dialog; - char *tmp; - va_list ap; - - va_start (ap,mesg); - tmp = g_strdup_vprintf (mesg,ap); - dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, mesg, NULL); + dialog = gtk_message_dialog_new (NULL, 0, error ? GTK_MESSAGE_ERROR : GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, mesg, NULL); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (tmp); @@ -246,6 +255,12 @@ void show_warning_dialog (gchar *mesg, ...) } +/* + * nmwa_about_cb + * + * Display our about dialog + * + */ static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet) { GdkPixbuf *pixbuf; @@ -290,12 +305,18 @@ static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet) } +/* + * nmwa_destroy + * + * Destroy the applet and clean up its data + * + */ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data) { int i; if (applet->menu) - gtk_widget_destroy (applet->menu); + nmwa_dispose_menu (applet); if (applet->timeout_handler_id > 0) { @@ -311,9 +332,18 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data) gtk_widget_destroy (applet->about_dialog); applet->about_dialog = NULL; } + + if (applet->gconf_client) + g_object_unref (G_OBJECT (applet->gconf_client)); } +/* + * nmwa_get_menu_pos + * + * When displaying the popup menu, figure out exactly where to put it on the screen + * + */ static void nmwa_get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) { NMWirelessApplet *applet = data; @@ -347,18 +377,65 @@ static void nmwa_get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_i } +/* + * nmwa_handle_network_choice + * + * Ask the user whether to add the network they have chosen to the trusted + * networks list, and then stuff the network into gconf in either the trusted + * or preferred networks list depending on their choice. This notifies + * NetworkInfoManager that the networks list has changed, and it notifies + * NetworkManager about those changes, triggering an AP switch. + */ +void nmwa_handle_network_choice (NMWirelessApplet *applet, char *network) +{ + + g_return_if_fail (applet != NULL); + g_return_if_fail (network != NULL); + +fprintf( stderr, "Forcing network '%s'\n", network); + nmwa_dbus_set_network (applet->connection, network); +} + + +/* + * nmwa_menu_item_activated + * + * Signal function called when user clicks on a menu item + * + */ +void nmwa_menu_item_activated (GtkMenuItem *item, gpointer user_data) +{ + NMWirelessApplet *applet = (NMWirelessApplet *)user_data; + char *network; + + g_return_if_fail (item != NULL); + g_return_if_fail (applet != NULL); + + if ((network = g_object_get_data (G_OBJECT (item), "network"))) + nmwa_handle_network_choice (applet, network); +} + + +/* + * nmwa_button_clicked + * + * Pop up the wireless networks menu in response to a click on the applet + * + */ static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet) { - if (applet->menu != NULL) - { - gtk_menu_popdown (GTK_MENU (applet->menu)); - g_object_unref(G_OBJECT(applet->menu)); - applet->menu = NULL; - } + if (applet->menu && GTK_WIDGET_VISIBLE (applet->menu)) + gtk_menu_popdown (GTK_MENU (applet->menu)); else { - applet->menu = nmwa_populate_menu (applet); - gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos, applet, 0, gtk_get_current_event_time()); + if (applet->nm_active) + { + if (!applet->menu) + applet->menu = nmwa_populate_menu (applet); + + gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos, + applet, 0, gtk_get_current_event_time()); + } } } @@ -370,18 +447,84 @@ static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet) * Given a network, add it to our networks menu. * */ -void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data) +void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, gboolean current, + gboolean encrypted) { - GtkWidget *menu = (GtkWidget *)user_data; GtkWidget *menu_item; + GtkWidget *label; + GtkWidget *hbox; - g_return_if_fail (network != NULL); + g_return_if_fail (text != NULL); g_return_if_fail (menu != NULL); +fprintf( stderr, "text = %s\n", text); + menu_item = gtk_menu_item_new (); + hbox = gtk_hbox_new (FALSE, 5); + gtk_container_add (GTK_CONTAINER (menu_item), hbox); + gtk_widget_show (hbox); + + label = gtk_label_new (text); + if (current) + { + char *markup = g_strdup_printf ("%s", text); + gtk_label_set_markup (GTK_LABEL (label), markup); + g_free (markup); + } + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2); + gtk_widget_show (label); + + if (encrypted) + { + GtkWidget *image; + + if ((image = gtk_image_new_from_pixbuf (applet->key_pixbuf))) + { + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2); + gtk_widget_show (image); + } + } + + g_object_set_data (G_OBJECT (menu_item), "network", g_strdup (tag)); + g_signal_connect(G_OBJECT (menu_item), "activate", G_CALLBACK(nmwa_menu_item_activated), applet); - menu_item = gtk_check_menu_item_new_with_label (network); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), current); - gtk_widget_show (menu_item); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); +} + + +/* + * 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 user_data) +{ + char *tag; + + g_return_if_fail (menu_item != 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); + } +} + + +/* + * nmwa_dispose_menu + * + * Destroy the menu and each of its items data tags + * + */ +void nmwa_dispose_menu (NMWirelessApplet *applet) +{ + g_return_if_fail (applet != NULL); + + /* Free the "network" data on each menu item */ + gtk_container_foreach (GTK_CONTAINER (applet->menu), nmwa_menu_item_data_free, NULL); + gtk_widget_destroy (applet->menu); } @@ -391,24 +534,27 @@ void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data) * Set up our networks menu from scratch * */ -static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet) +GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet) { GtkWidget *menu; - GtkWidget *menu_item; - int num_networks; - char **networks; - g_assert(applet->nm_active); + g_assert (applet->nm_active); g_return_if_fail (applet != NULL); menu = gtk_menu_new (); - - nmwa_dbus_add_networks_to_menu (applet->connection, menu); + nmwa_dbus_add_networks_to_menu (applet, menu); return (menu); } +/* + * mnwa_setup_widgets + * + * Intialize the applet's widgets and packing, create the initial + * menu of networks. + * + */ static void nmwa_setup_widgets (NMWirelessApplet *applet) { GtkRequisition req; @@ -467,7 +613,8 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet) applet->current_pixbuf = NULL; applet->about_dialog = NULL; - applet->menu = NULL; + if (applet->nm_active) + applet->menu = nmwa_populate_menu (applet); } static void change_size_cb(PanelApplet *pa, gint s, NMWirelessApplet *applet) @@ -517,17 +664,37 @@ static void change_background_cb(PanelApplet *a, PanelAppletBackgroundType type, gtk_rc_style_unref (rc_style); } + +/* + * nmwa_new + * + * Create the initial instance of our wireless applet + * + */ static GtkWidget * nmwa_new (NMWirelessApplet *applet) { panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR); gtk_widget_hide(GTK_WIDGET(applet)); + applet->gconf_client = gconf_client_get_default (); + if (!applet->gconf_client) + return (NULL); + +#if 0 + applet->net_dialog = glade_xml_new(GLADEDIR"/network_chocie.glade", NULL, NULL); + if (!applet->net_dialog) + { + fprintf (stderr, "Could not open the network dialog glade file!\n"); + g_object_unref (G_OBJECT (applet->gconf_client)); + return (NULL); + } +#endif + applet->pix_state = PIX_BROKEN; applet->connection = nmwa_dbus_init(applet); - applet->have_active_device = FALSE; applet->nm_active = nmwa_dbus_nm_is_running(applet->connection); - + nmwa_load_theme (applet); nmwa_setup_widgets (applet); diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index ccbcad2db..40bf6f6a9 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include typedef enum { @@ -48,7 +50,8 @@ typedef struct DBusConnection *connection; gboolean nm_active; - gboolean have_active_device; + GConfClient *gconf_client; + GladeXML *net_dialog; PixmapState pix_state; /* contains pointers into the images GList. @@ -56,6 +59,7 @@ typedef struct GdkPixbuf *pixmaps[PIX_NUMBER]; /* pointer to the current used file name */ GdkPixbuf *current_pixbuf; + GdkPixbuf *key_pixbuf; GtkWidget *pixmap; GtkWidget *button; @@ -67,11 +71,11 @@ typedef struct } NMWirelessApplet; -void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data); +void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, + gboolean current, gboolean encrypted); -void show_warning_dialog (gchar *mesg, ...); - -void show_warning_dialog (gchar *mesg, ...); +GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet); +void nmwa_dispose_menu (NMWirelessApplet *applet); #endif diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index 70d8c11f5..8c5a7d9a8 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -137,6 +137,54 @@ gint32 nmwa_dbus_get_int (DBusConnection *connection, const char *path, const ch } +/* + * nmwa_dbus_get_bool + * + */ +gboolean nmwa_dbus_get_bool (DBusConnection *connection, const char *path, const char *method) +{ + DBusMessage *message; + DBusMessage *reply; + DBusError error; + gboolean val; + + g_return_val_if_fail (connection != NULL, 0); + g_return_val_if_fail (path != NULL, 0); + g_return_val_if_fail (method != NULL, 0); + + if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method))) + { + fprintf (stderr, "nmwa_dbus_get_int(): Couldn't allocate the dbus message\n"); + return (0); + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "nmwa_dbus_get_int(): %s raised:\n %s\n\n", error.name, error.message); + dbus_message_unref (message); + return (0); + } + + if (reply == NULL) + { + fprintf( stderr, "nmwa_dbus_get_int(): dbus reply message was NULL\n" ); + dbus_message_unref (message); + return (0); + } + + dbus_error_init (&error); + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, &val, DBUS_TYPE_INVALID)) + val = FALSE; + + dbus_message_unref (reply); + dbus_message_unref (message); + + return (val); +} + + /* * nmwa_dbus_get_double * @@ -264,6 +312,32 @@ char * nmwa_dbus_get_active_device (DBusConnection *connection) } +/* + * nmwa_dbus_get_active_network + * + * Returns the object_path of the currently active network of the active device. + * + */ +char * nmwa_dbus_get_active_network (DBusConnection *connection, char *dev_path) +{ + char *network; + + if (!connection) + return (NULL); + + if ((network = nmwa_dbus_get_string (connection, dev_path, "getActiveNetwork"))) + { + if (strlen (network) < 1) + { + dbus_free (network); + network = NULL; + } + } + + return (network); +} + + /* * nmwa_dbus_get_device_type * @@ -311,61 +385,123 @@ char * nmwa_dbus_get_nm_status (DBusConnection *connection) * Query NetworkManager for networks and add any to the networks menu * */ -void nmwa_dbus_add_networks_to_menu (DBusConnection *connection, gpointer user_data) +void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu) { char *active_device; char *active_network; char **networks; int num_items = 0; + int i; - if (!connection) + g_return_if_fail (applet != NULL); + g_return_if_fail (applet->connection != NULL); + g_return_if_fail (menu != NULL); + + if (!applet->connection) { - nmwa_add_menu_item ("No wireless networks found...", FALSE, user_data); + nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE); return; } - if (!(active_device = nmwa_dbus_get_active_device (connection))) + if (!(active_device = nmwa_dbus_get_active_device (applet->connection))) { - nmwa_add_menu_item ("No network connection is present.", FALSE, user_data); + nmwa_add_menu_item (applet, menu, "No network connection is present.", NULL, FALSE, FALSE); return; } - switch (nmwa_dbus_get_device_type (connection, active_device)) + switch (nmwa_dbus_get_device_type (applet->connection, active_device)) { case (DEVICE_TYPE_WIRED_ETHERNET): - nmwa_add_menu_item ("A wired ethernet card is currently active.", FALSE, user_data); + nmwa_add_menu_item (applet, menu, "A wired ethernet card is currently active.", NULL, FALSE, FALSE); return; case (DEVICE_TYPE_WIRELESS_ETHERNET): break; default: - nmwa_add_menu_item ("Some other network device is currently active.", FALSE, user_data); + nmwa_add_menu_item (applet, menu, "Some other network device is currently active.", NULL, FALSE, FALSE); return; } + active_network = nmwa_dbus_get_active_network (applet->connection, active_device); + /* Get each of the networks in turn and add them to the menu */ - if ((networks = nmwa_dbus_get_string_array (connection, active_device, "getNetworks", &num_items))) + if (!(networks = nmwa_dbus_get_string_array (applet->connection, active_device, "getNetworks", &num_items))) { - if (strlen (networks[0]) == 0) - nmwa_add_menu_item ("No wireless networks found...", FALSE, user_data); - else - { - int i; - for (i = 0; i < num_items; i++) - { - char *name = nmwa_dbus_get_string (connection, networks[i], "getName"); - nmwa_add_menu_item (name, (strcmp (networks[i], active_network) == 0), user_data); - dbus_free (name); - } - } - dbus_free_string_array (networks); + dbus_free (active_device); + if (active_network) + dbus_free (active_network); + return; } + if (strlen (networks[0]) == 0) + { + nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE); + dbus_free (active_device); + if (active_network) + dbus_free (active_network); + return; + } + + for (i = 0; i < num_items; i++) + { + char *name = nmwa_dbus_get_string (applet->connection, networks[i], "getName"); + + if (name && strlen (name)) + { + gboolean found = FALSE; + int j; + + /* Only show one menu item per network. NetworkManager really passes back a list + * of access points, and there may be more than one that have the same ESSID. Filter + * them here. + */ + for (j = 0; j < i; j++) + if (found = (networks[j] && (strcmp (networks[i], networks[j]) == 0))) + break; + + if (!found) + { + gboolean active = active_network ? (strcmp (networks[i], active_network) == 0) : FALSE; + gboolean encrypted = nmwa_dbus_get_bool (applet->connection, networks[i], "getEncrypted"); + + fprintf( stderr, "Adding '%s' active (%d), enc (%d)\n", name, active, encrypted); + nmwa_add_menu_item (applet, menu, name, name, active, encrypted); + } + } + dbus_free (name); + } + + dbus_free_string_array (networks); + dbus_free (active_network); dbus_free (active_device); } +/* + * nmwa_dbus_set_network + * + * Tell NetworkManager to use a specific network that the user picked. + * + */ +void nmwa_dbus_set_network (DBusConnection *connection, char *network) +{ + DBusMessage *message; + + g_return_if_fail (connection != NULL); + g_return_if_fail (network != NULL); + + message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "setNetwork"); + if (message) + { + dbus_message_append_args (message, DBUS_TYPE_STRING, network, DBUS_TYPE_INVALID); + dbus_connection_send (connection, message, NULL); + } + else + fprintf (stderr, "nm_dbus_get_network_priority(): Couldn't allocate the dbus message\n"); +} + + /* * nmwa_dbus_nm_is_running * @@ -418,6 +554,19 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa && (strcmp (service, NM_DBUS_SERVICE) == 0)) applet->nm_active = FALSE; } + else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive") + || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive")) + { + if (applet->menu && !GTK_WIDGET_VISIBLE (applet->menu)) + { + nmwa_dispose_menu (applet); + applet->menu = nmwa_populate_menu (applet); + } + else if (!applet->menu) + applet->menu = nmwa_populate_menu (applet); + } else handled = FALSE; @@ -459,6 +608,13 @@ DBusConnection * nmwa_dbus_init (gpointer user_data) "sender='" DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "'", &error); + dbus_bus_add_match(connection, + "type='signal'," + "interface='" NM_DBUS_INTERFACE "'," + "path='" NM_DBUS_PATH "'," + "sender='" NM_DBUS_SERVICE "'", + &error); + return (connection); } diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h index ea290e485..eaf4e8909 100644 --- a/panel-applet/NMWirelessAppletDbus.h +++ b/panel-applet/NMWirelessAppletDbus.h @@ -24,6 +24,7 @@ #include #include +#include "NMWirelessApplet.h" /* Must match NetworkManager device types */ enum @@ -37,7 +38,7 @@ DBusConnection * nmwa_dbus_init (gpointer user_data); gboolean nmwa_dbus_nm_is_running (DBusConnection *connection); -void nmwa_dbus_add_networks_to_menu (DBusConnection *connection, gpointer user_data); +void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu); char * nmwa_dbus_get_active_device (DBusConnection *connection); @@ -45,4 +46,6 @@ int nmwa_dbus_get_device_type (DBusConnection *connection, char *path); char * nmwa_dbus_get_nm_status (DBusConnection *connection); +void nmwa_dbus_set_network (DBusConnection *connection, char *network); + #endif diff --git a/panel-applet/keyring.png b/panel-applet/keyring.png new file mode 100644 index 000000000..caade38ad Binary files /dev/null and b/panel-applet/keyring.png differ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 297107f17..89938486b 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -624,7 +624,7 @@ int main( int argc, char *argv[] ) /* We run dhclient when we need to, and we don't want any stray ones * lying around upon launch. */ - system ("killall dhclient"); + nm_spawn_process ("/usr/bin/killall dhclient"); /* Wheeee!!! */ loop = g_main_loop_new (NULL, FALSE); diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index 82eced5dd..43f57e467 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -440,6 +440,7 @@ void nm_ap_list_iter_free (NMAPListIter *iter) g_return_if_fail (iter != NULL); nm_ap_list_unlock (iter->list); + memset (iter, 0, sizeof (struct NMAPListIter)); g_free (iter); } diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 5c5da4b1c..987837ad5 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -1069,7 +1069,8 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, if ((ap = nm_device_ap_list_get_ap_by_essid (dev, nm_device_get_essid (dev)))) { - if ((ap == nm_device_get_best_ap (dev)) && (object_path = nm_device_get_path_for_ap (dev, ap))) + if ( (nm_null_safe_strcmp (nm_ap_get_essid (ap), nm_ap_get_essid (nm_device_get_best_ap (dev))) == 0) + && (object_path = nm_device_get_path_for_ap (dev, ap))) { dbus_message_append_args (reply_message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); g_free (object_path); @@ -1168,6 +1169,34 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, reply_message = nm_dbus_nm_get_devices (connection, message, data); else if (strcmp ("setKeyForNetwork", method) == 0) nm_dbus_set_user_key_for_network (connection, message, data); + else if (strcmp ("setNetwork", method) == 0) + { + if (data->active_device && nm_device_is_wireless (data->active_device)) + { + char *network; + DBusError error; + + dbus_error_init (&error); + if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID)) + { + NMAccessPoint *ap; + + if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (data->active_device), network))) + { +fprintf (stderr, "Forcing AP '%s'\n", nm_ap_get_essid (ap)); + nm_device_freeze_best_ap (data->active_device); + nm_device_set_best_ap (data->active_device, ap); + nm_data_set_state_modified (data, TRUE); + } + dbus_free (network); + } + } + else + reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadDevice", + "A network can only be set when a wireless device is active."); + + handled = TRUE; + } else if (strcmp ("status", method) == 0) { reply_message = dbus_message_new_method_return (message); diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 4717af1f7..493c6c56a 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -890,13 +890,13 @@ static gboolean nm_device_activate_wireless (NMDevice *dev) */ static gpointer nm_device_activation_worker (gpointer user_data) { + NMDevice *dev = (NMDevice *)user_data; unsigned char buf[500]; - unsigned char *iface; unsigned char hostname[100] = "\0"; int host_err; int dhclient_err; + char *iface; FILE *pidfile; - NMDevice *dev = (NMDevice *)user_data; g_return_val_if_fail (dev != NULL, NULL); g_return_val_if_fail (dev->app_data != NULL, NULL); @@ -965,8 +965,7 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n } /* Kill the old default route */ - snprintf (buf, 500, "/sbin/ip route del default"); - system (buf); + nm_spawn_process ("/sbin/ip route del default"); /* Find and kill the previous dhclient process for this interface */ iface = nm_device_get_iface (dev); @@ -985,7 +984,7 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n n_pid = atoi (s_pid); if (n_pid > 0) - kill (n_pid, 9); + kill (n_pid, SIGTERM); } /* If we don't have a "best" ap, don't try to get a DHCP address or restart the name service cache */ @@ -996,14 +995,10 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n /* Unfortunately, dhclient can take a long time to get a dhcp address * (for example, bad WEP key so it can't actually talk to the AP). - * We are essentially blocked until it returns. - * FIXME: fork() NetworkManager to do the dhclient stuff, and if our - * state changes during the dhclient stuff, we can kill() the - * forked process running dhclient. */ snprintf (buf, 500, "/sbin/dhclient -1 -q -lf /var/lib/dhcp/dhclient-%s.leases -pf /var/run/dhclient-%s.pid -cf /etc/dhclient-%s.conf %s\n", iface, iface, iface, iface); - dhclient_err = system (buf); + dhclient_err = nm_spawn_process (buf); /* Set the hostname back to what it was before so that X11 doesn't * puke when the hostname changes, and so users can actually launch stuff. @@ -1011,15 +1006,6 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n if (host_err >= 0) sethostname (hostname, strlen (hostname)); - /* If we were told to quit activation, stop the thread and return */ - if (dev->quit_activation) - { -fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_device_get_iface (dev)); - dev->just_activated = FALSE; - nm_device_unref (dev); - return (NULL); - } - if (dhclient_err != 0) { /* Interfaces cannot be down if they are the active interface, @@ -1036,9 +1022,17 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_ nm_device_bring_up (dev); } + /* If we were told to quit activation, stop the thread and return */ + if (dev->quit_activation) + { +fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_device_get_iface (dev)); + dev->just_activated = FALSE; + nm_device_unref (dev); + return (NULL); + } + /* Restart the nameservice caching daemon to make apps aware of new DNS servers */ - snprintf (buf, 500, "/sbin/service nscd restart"); - system (buf); + nm_spawn_process ("/sbin/service nscd restart"); } /* If we were told to quit activation, stop the thread and return */ @@ -1135,11 +1129,11 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) { /* Remove routing table entries */ snprintf (buf, 500, "/sbin/ip route flush dev %s", iface); - system (buf); + nm_spawn_process (buf); /* Remove ip address */ snprintf (buf, 500, "/sbin/ip address flush dev %s", iface); - system (buf); + nm_spawn_process (buf); dev->ip4_address = 0; @@ -1316,6 +1310,38 @@ void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap) } +/* + * Freeze/unfreeze best ap + * + * If the user explicitly picks a network to associate with, we don't + * change the active network until it goes out of range. + * + */ +void nm_device_freeze_best_ap (NMDevice *dev) +{ + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); + + dev->options.wireless.freeze_best_ap = TRUE; +} + +void nm_device_unfreeze_best_ap (NMDevice *dev) +{ + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); + + dev->options.wireless.freeze_best_ap = FALSE; +} + +gboolean nm_device_get_best_ap_frozen (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); + + return (dev->options.wireless.freeze_best_ap); +} + + /* * nm_device_get_path_for_ap * @@ -1377,7 +1403,33 @@ void nm_device_update_best_ap (NMDevice *dev) if (!(ap_list = nm_device_ap_list_get (dev))) return; - /* Check the trusted list first */ + /* Iterate over the device's ap list to make sure the current + * "best" ap is still in the device's ap list (so that if its + * not, we can "unfreeze" the best ap if its been frozen already). + * If it is, we don't change the best ap here. + */ + if (nm_device_get_best_ap_frozen (dev)) + { + g_mutex_lock (dev->options.wireless.best_ap_mutex); + best_ap = nm_device_get_best_ap (dev); + + /* If its in the device's ap list still, don't change the + * best ap, since its frozen. + */ + if ( best_ap + && !nm_ap_list_get_ap_by_essid (dev->app_data->invalid_ap_list, nm_ap_get_essid (best_ap)) + && nm_device_ap_list_get_ap_by_essid (dev, nm_ap_get_essid (best_ap))) + { + g_mutex_unlock (dev->options.wireless.best_ap_mutex); + return; + } + + /* Otherwise, its gone away and we don't care about it anymore */ + nm_device_unfreeze_best_ap (dev); + g_mutex_unlock (dev->options.wireless.best_ap_mutex); + } + + /* Check the trusted list then */ if (!(iter = nm_ap_list_iter_new (ap_list))) return; while ((ap = nm_ap_list_iter_next (iter))) diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index f4d497e2a..6e09840b2 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -75,6 +75,9 @@ NMAccessPoint *nm_device_get_best_ap (NMDevice *dev); void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap); void nm_device_update_best_ap (NMDevice *dev); gboolean nm_device_need_ap_switch (NMDevice *dev); +void nm_device_freeze_best_ap (NMDevice *dev); +void nm_device_unfreeze_best_ap (NMDevice *dev); +gboolean nm_device_get_best_ap_frozen (NMDevice *dev); char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap); diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 018ee6200..d8acdf407 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -172,3 +172,30 @@ void nm_dispose_scan_results (wireless_scan *result_list) } } + +/* + * nm_spawn_process + * + * Wrap g_spawn_sync in a usable manner + * + */ +int nm_spawn_process (char *args) +{ + gint num_args; + char **argv; + int exit_status; + + g_return_val_if_fail (args != NULL, -1); + + if (g_shell_parse_argv (args, &num_args, &argv, NULL)) + { + if (g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, NULL)) + { + g_strfreev (argv); + return (exit_status); + } + g_strfreev (argv); + } + + return (-1); +} diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 946af2ff2..48508c969 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -48,4 +48,6 @@ gboolean nm_ethernet_address_is_valid (struct ether_addr *test_addr); void nm_dispose_scan_results (wireless_scan *result_list); +int nm_spawn_process (char *args); + #endif