[network-manager-netbook] Fix the status icon (again).
- From: Tambet Ingo <tambeti src gnome org>
- To: svn-commits-list gnome org
- Subject: [network-manager-netbook] Fix the status icon (again).
- Date: Tue, 28 Jul 2009 14:06:06 +0000 (UTC)
commit eca2bb21b4e1a4da40cb4250ca9cc8a017b872e2
Author: Tambet Ingo <tambet gmail com>
Date: Tue Jul 28 09:11:08 2009 +0300
Fix the status icon (again).
2nd rewrite.
src/nmn-status-icon.c | 513 ++++++++++++++++++++++++++-----------------------
1 files changed, 272 insertions(+), 241 deletions(-)
---
diff --git a/src/nmn-status-icon.c b/src/nmn-status-icon.c
index 34046ed..8003996 100644
--- a/src/nmn-status-icon.c
+++ b/src/nmn-status-icon.c
@@ -1,5 +1,6 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#include <string.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <nm-device-ethernet.h>
@@ -10,18 +11,6 @@
#include "nmn-status-icon.h"
#include "nmn-icon-cache.h"
-typedef enum {
- STATUS_IMAGE_NO_NETWORK,
- STATUS_IMAGE_ETHERNET,
- STATUS_IMAGE_WWAN,
- STATUS_IMAGE_WIFI_00,
- STATUS_IMAGE_WIFI_25,
- STATUS_IMAGE_WIFI_50,
- STATUS_IMAGE_WIFI_75,
- STATUS_IMAGE_WIFI_100,
- STATUS_IMAGE_ACTIVATING,
-} StatusImage;
-
#define ACTIVATION_STEPS 6
G_DEFINE_TYPE (NmnStatusIcon, nmn_status_icon, GTK_TYPE_STATUS_ICON)
@@ -29,92 +18,46 @@ G_DEFINE_TYPE (NmnStatusIcon, nmn_status_icon, GTK_TYPE_STATUS_ICON)
#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NMN_TYPE_STATUS_ICON, NmnStatusIconPrivate))
typedef struct {
+ NmnStatusIcon *icon;
+ void (*destroy) (gpointer);
+} NmnIconHandler;
+
+typedef struct {
NMClient *client;
- StatusImage current_image;
+ char *current_image;
gboolean active;
- guint activation_step;
- NMActiveConnection *default_ac;
- gulong ac_state_changed_id;
-
- guint activation_animation_id;
- guint activation_animation_index;
+ GSList *ac_list;
+ NmnIconHandler *ac_icon_handler;
} NmnStatusIconPrivate;
-static StatusImage get_active_wifi_icon (NmnStatusIcon *self, NMDeviceWifi *device);
-
-static char *
-get_icon_filename (StatusImage image,
- guint activation_step,
- gboolean active)
+GtkStatusIcon *
+nmn_status_icon_new (void)
{
- GString *str;
-
- str = g_string_sized_new (32);
-
- switch (image) {
- case STATUS_IMAGE_NO_NETWORK:
- g_string_append (str, "nm-no-connection");
- break;
- case STATUS_IMAGE_ETHERNET:
- g_string_append (str, "nm-device-wired");
- break;
- case STATUS_IMAGE_WWAN:
- g_string_append (str, "nm-device-wwan");
- break;
- case STATUS_IMAGE_WIFI_00:
- g_string_append (str, "nm-signal-00");
- break;
- case STATUS_IMAGE_WIFI_25:
- g_string_append (str, "nm-signal-25");
- break;
- case STATUS_IMAGE_WIFI_50:
- g_string_append (str, "nm-signal-50");
- break;
- case STATUS_IMAGE_WIFI_75:
- g_string_append (str, "nm-signal-75");
- break;
- case STATUS_IMAGE_WIFI_100:
- g_string_append (str, "nm-signal-100");
- break;
- case STATUS_IMAGE_ACTIVATING:
- g_string_append_printf (str, "nm-progress-working-%02d", activation_step);
- break;
- }
-
- g_string_append (str, active ? "-active" : "-normal");
-
- return g_string_free (str, FALSE);
+ return GTK_STATUS_ICON (g_object_new (NMN_TYPE_STATUS_ICON, NULL));
}
static void
-update_icon (NmnStatusIcon *self, StatusImage image)
+update_icon (NmnStatusIcon *self, const char *image)
{
NmnStatusIconPrivate *priv = GET_PRIVATE (self);
- char *filename;
+ char *real_image;
GdkPixbuf *pixbuf;
- filename = get_icon_filename (image, priv->activation_step, priv->active);
- pixbuf = nmn_icon_cache_get (filename);
- g_free (filename);
+ real_image = g_strconcat (image, priv->active ? "-active" : "-normal", NULL);
+ pixbuf = nmn_icon_cache_get (real_image);
+ g_free (real_image);
if (pixbuf) {
- GtkStatusIcon *s = GTK_STATUS_ICON (self);
-
- priv->current_image = image;
- if (!(gtk_status_icon_get_storage_type (s) == GTK_IMAGE_PIXBUF &&
- gtk_status_icon_get_pixbuf (s) == pixbuf))
+ if (priv->current_image == NULL || strcmp (priv->current_image, image)) {
+ g_free (priv->current_image);
+ priv->current_image = g_strdup (image);
+ }
- gtk_status_icon_set_from_pixbuf (s, pixbuf);
+ gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (self), pixbuf);
}
}
-GtkStatusIcon *
-nmn_status_icon_new (void)
-{
- return GTK_STATUS_ICON (g_object_new (NMN_TYPE_STATUS_ICON, NULL));
-}
-
void
nmn_status_icon_set_active (NmnStatusIcon *self,
gboolean active)
@@ -130,223 +73,287 @@ nmn_status_icon_set_active (NmnStatusIcon *self,
}
}
-static StatusImage
-get_active_ap_icon (NmnStatusIcon *self, NMAccessPoint *ap)
+static void
+icon_handler_destroy (NmnIconHandler *handler)
{
- StatusImage icon;
- guint32 strength;
-
- strength = nm_access_point_get_strength (ap);
- strength = CLAMP (strength, 0, 100);
+ g_return_if_fail (handler != NULL);
- if (strength > 80)
- icon = STATUS_IMAGE_WIFI_100;
- else if (strength > 55)
- icon = STATUS_IMAGE_WIFI_75;
- else if (strength > 30)
- icon = STATUS_IMAGE_WIFI_50;
- else if (strength > 5)
- icon = STATUS_IMAGE_WIFI_25;
+ if (handler->destroy)
+ handler->destroy (handler);
else
- icon = STATUS_IMAGE_WIFI_00;
-
- return icon;
+ g_warning ("Missing destroy method");
}
+/* Pending activation animation handler */
+
+typedef struct {
+ NmnIconHandler parent;
+ guint step;
+ guint animation_id;
+ guint animation_index;
+} NmnPendingActivationHandler;
+
static void
-ap_strength_changed (NMAccessPoint *ap, GParamSpec *pspec, gpointer user_data)
+icon_handler_pending_activation_destroy (gpointer data)
{
- NmnStatusIcon *self = NMN_STATUS_ICON (user_data);
+ NmnPendingActivationHandler *handler = (NmnPendingActivationHandler *) data;
+
+ g_source_remove (handler->animation_id);
+ g_free (handler);
+}
+
+static gboolean
+activation_animation (gpointer data)
+{
+ NmnPendingActivationHandler *handler = (NmnPendingActivationHandler *) data;
+ char *image;
+
+ if (++handler->step > ACTIVATION_STEPS)
+ handler->step = 1;
+
+ image = g_strdup_printf ("nm-progress-working-%02d", handler->step);
+ update_icon (handler->parent.icon, image);
+ g_free (image);
+
+ return TRUE;
+}
+
+static NmnIconHandler *
+icon_handler_pending_activation_new (NmnStatusIcon *icon)
+{
+ NmnPendingActivationHandler *handler;
+
+ handler = g_new0 (NmnPendingActivationHandler, 1);
+ handler->parent.icon = icon;
+ handler->parent.destroy = icon_handler_pending_activation_destroy;
+
+ handler->animation_id = g_timeout_add (200, activation_animation, handler);
+ activation_animation (handler);
+
+ return (NmnIconHandler *) handler;
+}
+
+
+/* Ethernet handler */
+
+static NmnIconHandler *
+icon_handler_ethernet_new (NmnStatusIcon *icon)
+{
+ NmnIconHandler *handler;
- update_icon (self, get_active_ap_icon (self, ap));
+ handler = g_new0 (NmnIconHandler, 1);
+ handler->destroy = g_free;
+ update_icon (icon, "nm-device-wired");
+
+ return handler;
}
+
+/* Wifi handler */
+
typedef struct {
- NmnStatusIcon *status_icon;
- NMDeviceWifi *device;
+ NmnIconHandler parent;
+
+ NMDevice *device;
+ gulong active_ap_id;
+
NMAccessPoint *ap;
gulong ap_strength_id;
- gulong active_ap_id;
-} WifiIconInfo;
+} NmnWifiHandler;
static void
-wifi_icon_info_destroy (gpointer data,
- GClosure *closure)
+icon_handler_wifi_destroy (gpointer data)
{
- WifiIconInfo *info = (WifiIconInfo *) data;
+ NmnWifiHandler *handler = (NmnWifiHandler *) data;
+
+ g_signal_handler_disconnect (handler->device, handler->active_ap_id);
+
+ if (handler->ap_strength_id)
+ g_signal_handler_disconnect (handler->ap, handler->ap_strength_id);
- g_object_unref (info->ap);
- g_slice_free (WifiIconInfo, data);
+ g_free (handler);
}
static void
-device_active_ap_changed (NMDeviceWifi *device, GParamSpec *pspec, gpointer user_data)
+ap_strength_changed (NMAccessPoint *ap, GParamSpec *pspec, gpointer user_data)
{
- WifiIconInfo *info = (WifiIconInfo *) user_data;
- NmnStatusIcon *self = info->status_icon;
+ NmnIconHandler *handler = (NmnIconHandler *) user_data;
+ const char *image;
+ guint32 strength;
- /* First, remove the old signal handlers */
- g_signal_handler_disconnect (info->device, info->active_ap_id);
- g_signal_handler_disconnect (info->ap, info->ap_strength_id);
+ /* Hack: libnm-glib emits this signal sometimes with AP == NULL.
+ Should fix that instead */
+ strength = ap ? nm_access_point_get_strength (ap) : 0;
+ strength = CLAMP (strength, 0, 100);
- /* If the device is still active, it means we've roamed to another AP,
- set up new signal handlers and update the icon */
- if (nm_device_get_state (NM_DEVICE (device)) == NM_DEVICE_STATE_ACTIVATED)
- update_icon (self, get_active_wifi_icon (self, device));
-}
+ if (strength > 80)
+ image = "nm-signal-100";
+ else if (strength > 55)
+ image = "nm-signal-75";
+ else if (strength > 30)
+ image = "nm-signal-50";
+ else if (strength > 5)
+ image = "nm-signal-25";
+ else
+ image = "nm-signal-00";
-static StatusImage
-get_active_wifi_icon (NmnStatusIcon *self, NMDeviceWifi *device)
-{
- NMAccessPoint *ap;
- StatusImage icon;
-
- ap = nm_device_wifi_get_active_access_point (device);
- if (ap) {
- WifiIconInfo *info;
-
- info = g_slice_new0 (WifiIconInfo);
- info->status_icon = self;
- info->device = device;
- info->ap = g_object_ref (ap);
-
- info->active_ap_id = g_signal_connect_data (device,
- "notify::" NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,
- G_CALLBACK (device_active_ap_changed),
- info,
- wifi_icon_info_destroy,
- 0);
-
- info->ap_strength_id = g_signal_connect (ap,
- "notify::" NM_ACCESS_POINT_STRENGTH,
- G_CALLBACK (ap_strength_changed),
- self);
-
- icon = get_active_ap_icon (self, ap);
- } else
- icon = STATUS_IMAGE_WIFI_00;
-
- return icon;
+ update_icon (handler->icon, image);
}
-static StatusImage
-get_active_device_icon (NmnStatusIcon *self, NMDevice *device)
+static void
+active_ap_changed (NMDeviceWifi *device, GParamSpec *pspec, gpointer user_data)
{
- StatusImage icon;
-
- if (NM_IS_DEVICE_ETHERNET (device))
- icon = STATUS_IMAGE_ETHERNET;
- else if (NM_IS_DEVICE_WIFI (device))
- icon = get_active_wifi_icon (self, NM_DEVICE_WIFI (device));
- else if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device))
- icon = STATUS_IMAGE_WWAN;
- else {
- g_warning ("Unhandled device type: '%s'", G_OBJECT_TYPE_NAME (device));
- icon = STATUS_IMAGE_NO_NETWORK;
+ NmnWifiHandler *handler = (NmnWifiHandler *) user_data;
+
+ if (handler->ap_strength_id) {
+ g_signal_handler_disconnect (handler->ap, handler->ap_strength_id);
+
+ handler->ap = NULL;
+ handler->ap_strength_id = 0;
}
- return icon;
+ handler->ap = nm_device_wifi_get_active_access_point (device);
+ if (handler->ap) {
+ handler->ap_strength_id = g_signal_connect (handler->ap, "notify::" NM_ACCESS_POINT_STRENGTH,
+ G_CALLBACK (ap_strength_changed), handler);
+ }
+
+ ap_strength_changed (handler->ap, NULL, handler);
}
-static gboolean
-activation_animation (gpointer data)
+static NmnIconHandler *
+icon_handler_wifi_new (NmnStatusIcon *icon, NMActiveConnection *ac)
{
- NmnStatusIcon *self = NMN_STATUS_ICON (data);
- NmnStatusIconPrivate *priv = GET_PRIVATE (self);
+ const GPtrArray *active_devices;
+ NMDevice *device;
+ NmnWifiHandler *handler;
- if (++priv->activation_step > ACTIVATION_STEPS)
- priv->activation_step = 1;
+ active_devices = nm_active_connection_get_devices (ac);
+ if (!active_devices)
+ return NULL;
- update_icon (self, STATUS_IMAGE_ACTIVATING);
+ device = NM_DEVICE (g_ptr_array_index (active_devices, 0));
- return TRUE;
+ handler = g_new0 (NmnWifiHandler, 1);
+ handler->parent.icon = icon;
+ handler->parent.destroy = icon_handler_wifi_destroy;
+
+ handler->device = device;
+ handler->active_ap_id = g_signal_connect (device, "notify::" NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,
+ G_CALLBACK (active_ap_changed),
+ handler);
+
+ active_ap_changed (NM_DEVICE_WIFI (device), NULL, handler);
+
+ return (NmnIconHandler *) handler;
}
-/***********************************************************************************/
-static void
-ac_state_changed (NMActiveConnection *ac,
- GParamSpec *pspec,
- gpointer user_data)
+/* 3G handler */
+
+static NmnIconHandler *
+icon_handler_3g_new (NmnStatusIcon *icon)
{
- NmnStatusIcon *self = NMN_STATUS_ICON (user_data);
- NmnStatusIconPrivate *priv = GET_PRIVATE (self);
- const GPtrArray *active_devices;
- NMDevice *device = NULL;
- StatusImage icon;
- NMActiveConnectionState state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-
- /* Cancel any ongoing activation animantion */
- if (priv->activation_animation_id) {
- g_source_remove (priv->activation_animation_id);
- priv->activation_animation_id = 0;
- priv->activation_animation_index = 0;
- }
+ NmnIconHandler *handler;
+
+ handler = g_new0 (NmnIconHandler, 1);
+ handler->destroy = g_free;
+ update_icon (icon, "nm-device-wwan");
+
+ return handler;
+}
+
+
+/* Handler creator */
+
+static NmnIconHandler *
+icon_handler_create (NmnStatusIcon *self, NMActiveConnection *ac)
+{
+ NmnIconHandler *handler = NULL;
+ NMActiveConnectionState state;
+
+ state = nm_active_connection_get_state (ac);
+
+ if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
+ handler = icon_handler_pending_activation_new (self);
+ else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ const GPtrArray *active_devices;
+ NMDevice *device = NULL;
- if (ac) {
active_devices = nm_active_connection_get_devices (ac);
- if (active_devices) {
+ if (active_devices)
device = NM_DEVICE (g_ptr_array_index (active_devices, 0));
- state = nm_active_connection_get_state (ac);
- }
- }
- switch (state) {
- case NM_ACTIVE_CONNECTION_STATE_UNKNOWN:
- icon = STATUS_IMAGE_NO_NETWORK;;
- break;
- case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
- priv->activation_animation_id = g_timeout_add (200, activation_animation, self);
- activation_animation (self);
- return;
- break;
- case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
- icon = get_active_device_icon (self, device);
- break;
+ if (NM_IS_DEVICE_ETHERNET (device))
+ handler = icon_handler_ethernet_new (self);
+ else if (NM_IS_DEVICE_WIFI (device))
+ handler = icon_handler_wifi_new (self, ac);
+ else if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device))
+ handler = icon_handler_3g_new (self);
+ else
+ g_warning ("Unhandled device type: '%s'", G_OBJECT_TYPE_NAME (device));
}
- update_icon (self, icon);
+ return handler;
}
+typedef struct {
+ NMActiveConnection *ac;
+ gulong signal_id;
+} AcListItem;
+
static void
update_best_ac (NmnStatusIcon *self)
{
NmnStatusIconPrivate *priv = GET_PRIVATE (self);
- const GPtrArray *acs;
+ GSList *iter;
NMActiveConnection *best_ac = NULL;
- int i;
- if (nm_client_get_manager_running (priv->client))
- acs = nm_client_get_active_connections (priv->client);
- else
- acs = NULL;
+ for (iter = priv->ac_list; iter; iter = iter->next) {
+ AcListItem *item = (AcListItem *) iter->data;
- for (i = 0; acs && i < acs->len; i++) {
- NMActiveConnection *ac = g_ptr_array_index (acs, i);
-
- if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_UNKNOWN)
+ if (nm_active_connection_get_state (item->ac) == NM_ACTIVE_CONNECTION_STATE_UNKNOWN)
continue;
if (!best_ac ||
- nm_active_connection_get_state (ac) > nm_active_connection_get_state (best_ac) ||
- nm_active_connection_get_default (ac) == TRUE)
- best_ac = ac;
+ nm_active_connection_get_state (item->ac) > nm_active_connection_get_state (best_ac) ||
+ nm_active_connection_get_default (item->ac) == TRUE)
+ best_ac = item->ac;
}
- if (priv->default_ac && priv->default_ac != best_ac) {
- g_signal_handler_disconnect (priv->default_ac, priv->ac_state_changed_id);
- g_object_unref (priv->default_ac);
- priv->default_ac = NULL;
+ if (priv->ac_icon_handler) {
+ icon_handler_destroy (priv->ac_icon_handler);
+ priv->ac_icon_handler = NULL;
}
- if (best_ac) {
- priv->default_ac = best_ac;
- priv->default_ac = g_object_ref (best_ac);
- priv->ac_state_changed_id = g_signal_connect (best_ac, "notify",
- G_CALLBACK (ac_state_changed), self);
- }
+ if (best_ac)
+ priv->ac_icon_handler = icon_handler_create (self, best_ac);
+
+ if (!priv->ac_icon_handler)
+ update_icon (self, "nm-no-connection");
+}
+
+static void
+ac_state_changed (NMActiveConnection *ac,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ update_best_ac (NMN_STATUS_ICON (user_data));
+}
+
+static void
+ac_list_destroy (NmnStatusIcon *self)
+{
+ NmnStatusIconPrivate *priv = GET_PRIVATE (self);
+
+ while (priv->ac_list) {
+ AcListItem *item = (AcListItem *) priv->ac_list->data;
- ac_state_changed (best_ac, NULL, self);
+ g_signal_handler_disconnect (item->ac, item->signal_id);
+ g_object_unref (item->ac);
+ g_free (item);
+ priv->ac_list = g_slist_delete_link (priv->ac_list, priv->ac_list);
+ }
}
static void
@@ -354,7 +361,31 @@ active_connections_changed (NMClient *client,
GParamSpec *pspec,
gpointer user_data)
{
- update_best_ac (NMN_STATUS_ICON (user_data));
+ NmnStatusIcon *self = NMN_STATUS_ICON (user_data);
+ NmnStatusIconPrivate *priv = GET_PRIVATE (self);
+ const GPtrArray *ac_list;
+ int i;
+
+ /* First, disconnect all previous handlers */
+ ac_list_destroy (self);
+
+ /* add signal handlers for each AC */
+ if (nm_client_get_manager_running (client))
+ ac_list = nm_client_get_active_connections (client);
+ else
+ ac_list = NULL;
+
+ for (i = 0; ac_list && i < ac_list->len; i++) {
+ NMActiveConnection *ac = (NMActiveConnection *) g_ptr_array_index (ac_list, i);
+ AcListItem *item;
+
+ item = g_new (AcListItem, 1);
+ item->ac = g_object_ref (ac);
+ item->signal_id = g_signal_connect (ac, "notify", G_CALLBACK (ac_state_changed), self);
+ priv->ac_list = g_slist_prepend (priv->ac_list, item);
+ }
+
+ update_best_ac (self);
}
void
@@ -373,7 +404,7 @@ nmn_status_icon_set_client (NmnStatusIcon *self,
G_CALLBACK (active_connections_changed),
self);
- update_best_ac (self);
+ active_connections_changed (client, NULL, self);
}
/*****************************************************************************/
@@ -381,7 +412,7 @@ nmn_status_icon_set_client (NmnStatusIcon *self,
static gboolean
set_initial_icon (gpointer data)
{
- update_icon (NMN_STATUS_ICON (data), STATUS_IMAGE_NO_NETWORK);
+ update_icon (NMN_STATUS_ICON (data), "nm-no-connection");
return FALSE;
}
@@ -397,10 +428,10 @@ finalize (GObject *object)
{
NmnStatusIconPrivate *priv = GET_PRIVATE (object);
- if (priv->activation_animation_id) {
- g_source_remove (priv->activation_animation_id);
- priv->activation_animation_id = 0;
- }
+ if (priv->ac_icon_handler)
+ icon_handler_destroy (priv->ac_icon_handler);
+
+ ac_list_destroy (NMN_STATUS_ICON (object));
if (priv->client)
g_object_unref (priv->client);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]