2
Tracks the various indicators to know when they come on and off
3
the bus for searching their menus.
5
Copyright 2011 Canonical Ltd.
8
Ted Gould <ted@canonical.com>
10
This program is free software: you can redistribute it and/or modify it
11
under the terms of the GNU General Public License version 3, as published
12
by the Free Software Foundation.
14
This program is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranties of
16
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17
PURPOSE. See the GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License along
20
with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include "indicator-tracker.h"
29
#include <glib/gi18n.h>
32
typedef struct _SystemIndicator SystemIndicator;
33
struct _SystemIndicator {
35
gchar * dbus_menu_path;
36
gchar * indicator_name;
37
gchar * user_visible_name;
40
SystemIndicator system_indicators[] = {
41
{dbus_name: "com.canonical.indicator.datetime", dbus_menu_path: "/com/canonical/indicator/datetime/menu", indicator_name: "indicator-datetime", user_visible_name: N_("Date") },
42
{dbus_name: "com.canonical.indicator.session", dbus_menu_path: "/com/canonical/indicator/session/menu", indicator_name: "indicator-session-device", user_visible_name: N_("Device") },
43
{dbus_name: "com.canonical.indicator.session", dbus_menu_path: "/com/canonical/indicator/user/menu", indicator_name: "indicator-session-user", user_visible_name: N_("User") },
44
{dbus_name: "com.canonical.indicators.sound", dbus_menu_path: "/com/canonical/indicators/sound/menu", indicator_name: "indicator-sound", user_visible_name: N_("Sound") },
45
{dbus_name: "com.canonical.indicator.messages", dbus_menu_path: "/com/canonical/indicator/messages/menu", indicator_name: "indicator-messages", user_visible_name: N_("Messages") }
48
struct _IndicatorTrackerPrivate {
50
guint watches[G_N_ELEMENTS(system_indicators)];
53
#define INDICATOR_TRACKER_GET_PRIVATE(o) \
54
(G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_TRACKER_TYPE, IndicatorTrackerPrivate))
56
static void indicator_tracker_class_init (IndicatorTrackerClass *klass);
57
static void indicator_tracker_init (IndicatorTracker *self);
58
static void indicator_tracker_dispose (GObject *object);
59
static void indicator_tracker_finalize (GObject *object);
60
static void system_watch_appeared (GDBusConnection * connection, const gchar * name, const gchar * name_owner, gpointer user_data);
61
static void system_watch_vanished (GDBusConnection * connection, const gchar * name, gpointer user_data);
63
G_DEFINE_TYPE (IndicatorTracker, indicator_tracker, G_TYPE_OBJECT);
66
indicator_tracker_class_init (IndicatorTrackerClass *klass)
68
GObjectClass *object_class = G_OBJECT_CLASS (klass);
70
g_type_class_add_private (klass, sizeof (IndicatorTrackerPrivate));
72
object_class->dispose = indicator_tracker_dispose;
73
object_class->finalize = indicator_tracker_finalize;
79
indicator_tracker_init (IndicatorTracker *self)
81
self->priv = INDICATOR_TRACKER_GET_PRIVATE(self);
82
self->priv->indicators = NULL;
84
self->priv->indicators = g_array_new(FALSE, TRUE, sizeof(IndicatorTrackerIndicator));
87
for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
88
self->priv->watches[indicator_cnt] = g_bus_watch_name(G_BUS_TYPE_SESSION,
89
system_indicators[indicator_cnt].dbus_name,
90
G_BUS_NAME_WATCHER_FLAGS_NONE,
91
system_watch_appeared, /* acquired */
92
system_watch_vanished, /* vanished */
94
NULL); /* free func */
101
indicator_tracker_dispose (GObject *object)
103
IndicatorTracker * self = INDICATOR_TRACKER(object);
106
for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
107
if (self->priv->watches[indicator_cnt] != 0) {
108
g_bus_unwatch_name(self->priv->watches[indicator_cnt]);
109
self->priv->watches[indicator_cnt] = 0;
114
G_OBJECT_CLASS (indicator_tracker_parent_class)->dispose (object);
119
indicator_tracker_finalize (GObject *object)
122
G_OBJECT_CLASS (indicator_tracker_parent_class)->finalize (object);
127
indicator_tracker_new (void)
129
return INDICATOR_TRACKER(g_object_new(INDICATOR_TRACKER_TYPE, NULL));
133
indicator_tracker_get_indicators (IndicatorTracker * tracker)
135
g_return_val_if_fail(IS_INDICATOR_TRACKER(tracker), NULL);
136
return tracker->priv->indicators;
139
/* Function watches names on Dbus to find out when the system indicators
140
go on and off the bus. This makes it so that we can handle them properly
141
at the higher levels in the system. If a system indicator gets added to
142
the list it gets put the indicator structure. */
144
system_watch_appeared (GDBusConnection * connection, const gchar * name, const gchar * name_owner, gpointer user_data)
146
g_return_if_fail(IS_INDICATOR_TRACKER(user_data));
147
g_return_if_fail(name_owner != NULL);
148
g_return_if_fail(name_owner[0] != '\0');
149
IndicatorTracker * self = INDICATOR_TRACKER(user_data);
151
/* Check all the system indicators because there might be more than
152
one menu/indicator on a well known name */
154
for (indicator_cnt = 0; indicator_cnt < G_N_ELEMENTS(system_indicators); indicator_cnt++) {
155
SystemIndicator * sys_indicator = &system_indicators[indicator_cnt];
157
if (g_strcmp0(sys_indicator->dbus_name, name) != 0) {
161
/* Check to see if we already have this system indicator in the
162
list of indicators */
164
for (i = 0; i < self->priv->indicators->len; i++) {
165
IndicatorTrackerIndicator * indicator = &g_array_index(self->priv->indicators, IndicatorTrackerIndicator, i);
167
if (g_strcmp0(sys_indicator->dbus_name, indicator->dbus_name_wellknown) != 0) {
171
if (g_strcmp0(sys_indicator->dbus_menu_path, indicator->dbus_object) != 0) {
175
/* If both of them match, we need to break */
179
/* We found it in the list so we broke out eary */
180
if (i != self->priv->indicators->len) {
184
g_debug("Adding an indicator for '%s' at owner '%s'", name, name_owner);
185
/* Okay, we need to build one for this system indicator */
186
IndicatorTrackerIndicator final_indicator = {
187
name: g_strdup(sys_indicator->indicator_name),
188
dbus_name: g_strdup(name_owner),
189
dbus_name_wellknown: g_strdup(sys_indicator->dbus_name),
190
dbus_object: g_strdup(sys_indicator->dbus_menu_path),
191
prefix: g_strdup(_(sys_indicator->user_visible_name))
194
g_array_append_val(self->priv->indicators, final_indicator);
200
/* When the names drop off of DBus we need to check to see if that
201
means any indicators getting lost as well. If so, remove them from
202
the indicator list. */
204
system_watch_vanished (GDBusConnection * connection, const gchar * name, gpointer user_data)
206
g_return_if_fail(IS_INDICATOR_TRACKER(user_data));
207
IndicatorTracker * self = INDICATOR_TRACKER(user_data);
209
/* See if any of our indicators know this name */
211
for (i = 0; i < self->priv->indicators->len; i++) {
212
IndicatorTrackerIndicator * indicator = &g_array_index(self->priv->indicators, IndicatorTrackerIndicator, i);
215
if (g_strcmp0(indicator->dbus_name_wellknown, name) != 0) {
219
g_free(indicator->name);
220
g_free(indicator->dbus_name);
221
g_free(indicator->dbus_name_wellknown);
222
g_free(indicator->dbus_object);
223
g_free(indicator->prefix);
225
g_array_remove_index_fast(self->priv->indicators, i);
226
/* Oh, this is confusing. Basically becasue we shorten the array
227
we need to check the one that replaced the entry we deleted
228
so we have to look in this same slot again. */