From 9fa4a67aa52cd401903ce2868a5b9914378c25c7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 25 Oct 2006 03:57:41 +0000 Subject: [PATCH] 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() git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2084 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 46 +++++++++++ gnome/applet/applet-dbus.c | 163 ++++++++++++++++++++++--------------- gnome/applet/applet-dbus.h | 1 + gnome/applet/applet.c | 44 ++++++++-- gnome/applet/applet.h | 3 + 5 files changed, 184 insertions(+), 73 deletions(-) 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);