diff --git a/ChangeLog b/ChangeLog index b9353fb1e8..096539d589 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2006-10-24 Dan Williams + + Reduce the number of times the Gnome applet wakes up, especially when + it's doing absolutely nothing and is hidden. Initial patch by + Chris Aillon. + + * gnome/applet/applet-dbus.c + - (nma_dbus_filter): when NM isn't around, or when it goes away, + kill the redraw timeout. When NM starts up, start the redraw + timeout. Also, if we get kicked off the bus for some reason, + start the reconnection timeout if one's not already running. + - (nma_dbus_init): better handling of error conditions, don't leak + a half-initialized dbus connection + - (nma_dbus_connection_watcher): consolidate places we reinitialize + the applet's data, just call nm_dbus_init_helper() + - (nma_start_dbus_connection_watch): new function, starts a periodic + timeout that calls nma_dbus_connection_watcher() + - (nma_dbus_init_helper): if we get a successful connection, kill the + reconnection timeout, and don't start the reconnection timeout + unconditionally anymore + + * gnome/applet/applet-dbus.h + - Expose nma_start_dbus_connection_watch() + + * gnome/applet/applet.c + - (nma_update_state): no longer static, called from applet-dbus.c for + immediate UI updates on certain events + - (nma_set_running): new function; take over setting applet->running, + when not running (ie, NM is not active), don't activate the redraw + timeout because we're not showing the applet anyway. When we are + running (ie, NM is active), and only when we're running, start the + redraw timeout. + - (nma_destroy): kill the redraw timeout by setting 'not running', and + kill any reconnection timeout + - (nma_get_instance): move one-off dbus initialization code here since + nm_dbus_init_helper() gets called more than once, possibly by the + reconnection timeout function too. And, when we start up, if we + can't get a connection to the bus, start the reconnection timeout. + But don't start the redraw timeout yet, only do that when we get + NM's state and find out if it's running or not. + + * gnome/applet/applet.h + - Add the reconnection GSource ID + - Add prototypes for nma_set_running() and the no-longer-static + nma_update_state() + 2006-10-24 Dan Williams * src/vpn-daemons/nm-dbus-vpnc.c diff --git a/gnome/applet/applet-dbus.c b/gnome/applet/applet-dbus.c index 06b0aa299a..f6307df61a 100644 --- a/gnome/applet/applet-dbus.c +++ b/gnome/applet/applet-dbus.c @@ -72,7 +72,9 @@ static DBusHandlerResult nma_dbus_filter (DBusConnection *connection, DBusMessag { dbus_connection_unref (applet->connection); applet->connection = NULL; - applet->nm_running = FALSE; + nma_set_running (applet, FALSE); + if (!applet->connection_timeout_id) + nma_start_dbus_connection_watch (applet); } else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { @@ -94,18 +96,25 @@ static DBusHandlerResult nma_dbus_filter (DBusConnection *connection, DBusMessag if (!old_owner_good && new_owner_good && !applet->nm_running) { /* NetworkManager started up */ - applet->nm_running = TRUE; + nma_set_running (applet, TRUE); nma_set_state (applet, NM_STATE_DISCONNECTED); + nma_dbus_update_nm_state (applet); nma_dbus_update_devices (applet); nma_dbus_update_dialup (applet); nma_dbus_vpn_update_vpn_connections (applet); + + /* Immediate redraw */ + nma_update_state (applet); } else if (old_owner_good && !new_owner_good) { - applet->nm_running = FALSE; nma_set_state (applet, NM_STATE_DISCONNECTED); + nma_set_running (applet, FALSE); nmi_passphrase_dialog_destroy (applet); + + /* One last redraw to capture new state before sleeping */ + nma_update_state (applet); } } } @@ -322,68 +331,94 @@ static DBusConnection * nma_dbus_init (NMApplet *applet) DBusError error; DBusObjectPathVTable vtable = { NULL, &nmi_dbus_info_message_handler, NULL, NULL, NULL, NULL }; int acquisition; + dbus_bool_t success = FALSE; g_return_val_if_fail (applet != NULL, NULL); dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (dbus_error_is_set (&error)) - { + if (dbus_error_is_set (&error)) { nm_warning ("%s raised:\n %s\n\n", error.name, error.message); - dbus_error_free (&error); - return NULL; + goto error; } dbus_error_init (&error); - acquisition = dbus_bus_request_name (connection, NMI_DBUS_SERVICE, DBUS_NAME_FLAG_REPLACE_EXISTING, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("nma_dbus_init() could not acquire its service. dbus_bus_acquire_service() says: '%s'", error.message); - dbus_error_free (&error); - return NULL; + acquisition = dbus_bus_request_name (connection, + NMI_DBUS_SERVICE, + DBUS_NAME_FLAG_REPLACE_EXISTING, + &error); + if (dbus_error_is_set (&error)) { + nm_warning ("could not acquire its service. dbus_bus_acquire_service()" + " says: '%s'", + error.message); + goto error; } if (acquisition == DBUS_REQUEST_NAME_REPLY_EXISTS) - return NULL; + goto error; - if (!dbus_connection_register_object_path (connection, NMI_DBUS_PATH, &vtable, applet)) - { - nm_warning ("nma_dbus_init() could not register a handler for NetworkManagerInfo. Not enough memory?"); - return NULL; + success = dbus_connection_register_object_path (connection, + NMI_DBUS_PATH, + &vtable, + applet); + if (!success) { + nm_warning ("could not register a messgae handler for the" + " NetworkManagerInfo service. Not enough memory?"); + goto error; } - if (!dbus_connection_add_filter (connection, nma_dbus_filter, applet, NULL)) - return NULL; + success = dbus_connection_add_filter (connection, nma_dbus_filter, applet, NULL); + if (!success) + goto error; dbus_connection_set_exit_on_disconnect (connection, FALSE); dbus_connection_setup_with_g_main (connection, NULL); + dbus_error_init (&error); dbus_bus_add_match(connection, "type='signal'," "interface='" DBUS_INTERFACE_DBUS "'," "sender='" DBUS_SERVICE_DBUS "'", &error); - if (dbus_error_is_set (&error)) - dbus_error_free (&error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not register signal handlers. '%s'", + error.message); + goto error; + } + dbus_error_init (&error); dbus_bus_add_match(connection, "type='signal'," "interface='" NM_DBUS_INTERFACE "'," "path='" NM_DBUS_PATH "'," "sender='" NM_DBUS_SERVICE "'", &error); - if (dbus_error_is_set (&error)) - dbus_error_free (&error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not register signal handlers. '%s'", + error.message); + goto error; + } + dbus_error_init (&error); dbus_bus_add_match(connection, "type='signal'," "interface='" NM_DBUS_INTERFACE_VPN "'," "path='" NM_DBUS_PATH_VPN "'," "sender='" NM_DBUS_SERVICE "'", &error); + if (dbus_error_is_set (&error)) { + nm_warning ("Could not register signal handlers. '%s'", + error.message); + goto error; + } + + return connection; + +error: if (dbus_error_is_set (&error)) dbus_error_free (&error); - - return (connection); + if (connection) + dbus_connection_unref (connection); + return NULL; } @@ -393,62 +428,62 @@ static DBusConnection * nma_dbus_init (NMApplet *applet) * Try to reconnect if we ever get disconnected from the bus * */ -static gboolean nma_dbus_connection_watcher (gpointer user_data) +static gboolean +nma_dbus_connection_watcher (gpointer user_data) { - NMApplet *applet = (NMApplet *)user_data; + NMApplet * applet = (NMApplet *)user_data; g_return_val_if_fail (applet != NULL, TRUE); - if (!applet->connection) - { - if ((applet->connection = nma_dbus_init (applet))) - { - applet->nm_running = nma_dbus_nm_is_running (applet->connection); - if (applet->nm_running) - { - nma_set_state (applet, NM_STATE_DISCONNECTED); - nma_dbus_update_nm_state (applet); - nma_dbus_update_devices (applet); - nma_dbus_update_dialup (applet); - nma_dbus_vpn_update_vpn_connections (applet); - } - } + nma_dbus_init_helper (applet); + if (applet->connection) { + applet->connection_timeout_id = 0; + return FALSE; /* Remove timeout */ } - return (TRUE); + return TRUE; +} + + +void +nma_start_dbus_connection_watch (NMApplet *applet) +{ + if (applet->connection_timeout_id) + g_source_remove (applet->connection_timeout_id); + + applet->connection_timeout_id = g_timeout_add (5000, + (GSourceFunc) nma_dbus_connection_watcher, + applet); } /* - * nma_dbus_worker + * nma_dbus_init_helper * - * Thread worker function that periodically grabs the NetworkManager state - * and updates our local applet state to reflect that. + * Set up the applet's NMI dbus methods and dbus connection * */ -void nma_dbus_init_helper (NMApplet *applet) +void +nma_dbus_init_helper (NMApplet *applet) { - GSource * timeout_source; - g_return_if_fail (applet != NULL); - dbus_g_thread_init (); - applet->connection = nma_dbus_init (applet); - applet->nmi_methods = nmi_dbus_nmi_methods_setup (); + if (applet->connection) { + if (applet->connection_timeout_id) { + g_source_remove (applet->connection_timeout_id); + applet->connection_timeout_id = 0; + } - timeout_source = g_timeout_source_new (2000); - g_source_set_callback (timeout_source, nma_dbus_connection_watcher, applet, NULL); - g_source_attach (timeout_source, NULL); + if (nma_dbus_nm_is_running (applet->connection)) { + nma_set_running (applet, TRUE); + nma_dbus_update_nm_state (applet); + nma_dbus_update_devices (applet); + nma_dbus_update_dialup (applet); + nma_dbus_vpn_update_vpn_connections (applet); - if (applet->connection && nma_dbus_nm_is_running (applet->connection)) - { - applet->nm_running = TRUE; - nma_dbus_update_nm_state (applet); - nma_dbus_update_devices (applet); - nma_dbus_update_dialup (applet); - nma_dbus_vpn_update_vpn_connections (applet); + /* Immediate redraw */ + nma_update_state (applet); + } } - - g_source_unref (timeout_source); } diff --git a/gnome/applet/applet-dbus.h b/gnome/applet/applet-dbus.h index 2a725ae7e5..81263bdcef 100644 --- a/gnome/applet/applet-dbus.h +++ b/gnome/applet/applet-dbus.h @@ -35,6 +35,7 @@ static inline gboolean message_is_error (DBusMessage *msg) } void nma_dbus_init_helper (NMApplet *applet); +void nma_start_dbus_connection_watch (NMApplet *applet); void nma_dbus_enable_wireless (NMApplet *applet, gboolean enabled); void nma_dbus_enable_networking (NMApplet *applet, gboolean enabled); void nma_free_gui_data_model (NMApplet *applet); diff --git a/gnome/applet/applet.c b/gnome/applet/applet.c index 8cfde56699..d33f5726af 100644 --- a/gnome/applet/applet.c +++ b/gnome/applet/applet.c @@ -80,7 +80,6 @@ static gboolean nma_icons_init (NMApplet *applet); static void nma_icons_free (NMApplet *applet); static void nma_context_menu_update (NMApplet *applet); static GtkWidget * nma_get_instance (NMApplet *applet); -static void nma_update_state (NMApplet *applet); static void nma_dropdown_menu_deactivate_cb (GtkWidget *menu, NMApplet *applet); static G_GNUC_NORETURN void nma_destroy (NMApplet *applet); static GType nma_get_type (void); /* for G_DEFINE_TYPE */ @@ -1050,7 +1049,7 @@ static gboolean animation_timeout (NMApplet *applet) * and what our icon on the panel should look like for each type. * */ -static void nma_update_state (NMApplet *applet) +void nma_update_state (NMApplet *applet) { gboolean show_applet = TRUE; gboolean need_animation = FALSE; @@ -2135,6 +2134,29 @@ static inline void nma_enable_networking_set_active (NMApplet *applet) } +/* + * nma_set_running + * + * Set whether NM is running to TRUE or FALSE. + * + */ +void nma_set_running (NMApplet *applet, gboolean running) +{ + if (running == applet->nm_running) + return; + + applet->nm_running = running; + + /* if NM became active, start drawing our icon, else stop drawing it */ + if (applet->nm_running && !applet->redraw_timeout_id) + applet->redraw_timeout_id = g_timeout_add (1000, (GSourceFunc) nma_redraw_timeout, applet); + else if (!applet->nm_running && applet->redraw_timeout_id) + { + g_source_remove (applet->redraw_timeout_id); + applet->redraw_timeout_id = 0; + } +} + /* * nma_set_state * @@ -2460,10 +2482,10 @@ static void G_GNUC_NORETURN nma_destroy (NMApplet *applet) } #endif - if (applet->redraw_timeout_id > 0) - { - gtk_timeout_remove (applet->redraw_timeout_id); - applet->redraw_timeout_id = 0; + nma_set_running (applet, FALSE); + if (applet->connection_timeout_id) { + g_source_remove (applet->connection_timeout_id); + applet->connection_timeout_id = 0; } if (applet->gconf_client) @@ -2500,6 +2522,8 @@ static GtkWidget * nma_get_instance (NMApplet *applet) applet->nm_state = NM_STATE_DISCONNECTED; applet->tooltips = NULL; applet->passphrase_dialog = NULL; + applet->connection_timeout_id = 0; + applet->redraw_timeout_id = 0; #ifdef ENABLE_NOTIFY applet->notification = NULL; #endif @@ -2533,7 +2557,12 @@ static GtkWidget * nma_get_instance (NMApplet *applet) */ nma_compat_convert_oldformat_entries (applet->gconf_client); + /* D-Bus init stuff */ + dbus_g_thread_init (); + applet->nmi_methods = nmi_dbus_nmi_methods_setup (); nma_dbus_init_helper (applet); + if (!applet->connection) + nma_start_dbus_connection_watch (applet); /* Load pixmaps and create applet widgets */ nma_setup_widgets (applet); @@ -2541,9 +2570,6 @@ static GtkWidget * nma_get_instance (NMApplet *applet) g_signal_connect (applet, "destroy", G_CALLBACK (nma_destroy), NULL); g_signal_connect (applet, "style-set", G_CALLBACK (nma_theme_change_cb), NULL); - /* Start redraw timeout */ - applet->redraw_timeout_id = g_timeout_add (1000, (GtkFunction) nma_redraw_timeout, applet); - return GTK_WIDGET (applet); } diff --git a/gnome/applet/applet.h b/gnome/applet/applet.h index 9661653b13..ccb9b8c131 100644 --- a/gnome/applet/applet.h +++ b/gnome/applet/applet.h @@ -81,6 +81,7 @@ typedef struct guint gconf_vpn_notify_id; char * glade_file; guint redraw_timeout_id; + guint connection_timeout_id; /* Data model elements */ gboolean is_adhoc; @@ -152,6 +153,8 @@ VPNConnection * nma_get_first_active_vpn_connection (NMApplet *applet); void nma_enable_wireless_set_active (NMApplet *applet); void nma_set_state (NMApplet *applet, NMState state); +void nma_set_running (NMApplet *applet, gboolean running); +void nma_update_state (NMApplet *applet); int nm_null_safe_strcmp (const char *s1, const char *s2);