~unity8-desktop-session-team/indicator-session/indicator-session-using-upstart

« back to all changes in this revision

Viewing changes to src/indicator-session.c

  • Committer: Charles Kerr
  • Date: 2012-08-22 06:31:53 UTC
  • Revision ID: charles.kerr@canonical.com-20120822063153-ezwmbzyfr0waf99i
Tags: 12.10.1
12.10.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
A small wrapper utility to load indicators and put them as menu items
 
3
into the gnome-panel using its applet interface.
 
4
 
 
5
Copyright 2009 Canonical Ltd.
 
6
 
 
7
Authors:
 
8
    Ted Gould <ted@canonical.com>
 
9
    Conor Curran <conor.curran@canonical.com>
 
10
 
 
11
This program is free software: you can redistribute it and/or modify it
 
12
under the terms of the GNU General Public License version 3, as published
 
13
by the Free Software Foundation.
 
14
 
 
15
This program is distributed in the hope that it will be useful, but
 
16
WITHOUT ANY WARRANTY; without even the implied warranties of
 
17
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
18
PURPOSE.  See the GNU General Public License for more details.
 
19
 
 
20
You should have received a copy of the GNU General Public License along
 
21
with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include "config.h"
 
26
#endif
 
27
 
 
28
#include <glib.h>
 
29
#include <glib-object.h>
 
30
#include <glib/gi18n-lib.h>
 
31
#include <gtk/gtk.h>
 
32
#include <gio/gio.h>
 
33
 
 
34
#include <libdbusmenu-gtk/menu.h>
 
35
 
 
36
#include <libindicator/indicator.h>
 
37
#include <libindicator/indicator-object.h>
 
38
#include <libindicator/indicator-service-manager.h>
 
39
 
 
40
#include "shared-names.h"
 
41
#include "user-widget.h"
 
42
 
 
43
#define INDICATOR_SESSION_TYPE            (indicator_session_get_type ())
 
44
#define INDICATOR_SESSION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession))
 
45
#define INDICATOR_SESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SESSION_TYPE, IndicatorSessionClass))
 
46
#define IS_INDICATOR_SESSION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SESSION_TYPE))
 
47
#define IS_INDICATOR_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SESSION_TYPE))
 
48
#define INDICATOR_SESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SESSION_TYPE, IndicatorSessionClass))
 
49
 
 
50
typedef struct _IndicatorSession      IndicatorSession;
 
51
typedef struct _IndicatorSessionClass IndicatorSessionClass;
 
52
 
 
53
struct _IndicatorSessionClass
 
54
{
 
55
  IndicatorObjectClass parent_class;
 
56
};
 
57
 
 
58
struct _IndicatorSession
 
59
{
 
60
  IndicatorObject parent;
 
61
  IndicatorServiceManager * service;
 
62
  IndicatorObjectEntry entry;
 
63
  GCancellable * service_proxy_cancel;
 
64
  GDBusProxy * service_proxy;
 
65
  GSettings * settings;
 
66
};
 
67
 
 
68
static gboolean greeter_mode;
 
69
 
 
70
GType indicator_session_get_type (void);
 
71
 
 
72
/* Indicator stuff */
 
73
INDICATOR_SET_VERSION
 
74
INDICATOR_SET_TYPE(INDICATOR_SESSION_TYPE)
 
75
 
 
76
/* Prototypes */
 
77
static gboolean new_user_item (DbusmenuMenuitem * newitem,
 
78
                               DbusmenuMenuitem * parent,
 
79
                               DbusmenuClient * client,
 
80
                               gpointer user_data);
 
81
static gboolean build_restart_item (DbusmenuMenuitem * newitem,
 
82
                                    DbusmenuMenuitem * parent,
 
83
                                    DbusmenuClient * client,
 
84
                                    gpointer user_data);
 
85
static void indicator_session_update_users_label (IndicatorSession* self,
 
86
                                                  const gchar* name);
 
87
static void service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data);
 
88
static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
 
89
static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
 
90
static void user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data);
 
91
 
 
92
static void indicator_session_class_init (IndicatorSessionClass *klass);
 
93
static void indicator_session_init       (IndicatorSession *self);
 
94
static void indicator_session_dispose    (GObject *object);
 
95
static void indicator_session_finalize   (GObject *object);
 
96
static GList* indicator_session_get_entries (IndicatorObject* obj);
 
97
static guint indicator_session_get_location (IndicatorObject * io,
 
98
                                             IndicatorObjectEntry * entry);
 
99
 
 
100
G_DEFINE_TYPE (IndicatorSession, indicator_session, INDICATOR_OBJECT_TYPE);
 
101
 
 
102
static void
 
103
indicator_session_class_init (IndicatorSessionClass *klass)
 
104
{
 
105
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
106
 
 
107
        object_class->dispose = indicator_session_dispose;
 
108
        object_class->finalize = indicator_session_finalize;
 
109
 
 
110
        IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
 
111
        io_class->get_entries = indicator_session_get_entries;
 
112
        io_class->get_location = indicator_session_get_location;
 
113
        return;
 
114
}
 
115
 
 
116
static void
 
117
indicator_session_init (IndicatorSession *self)
 
118
{
 
119
  const gchar * icon_name;
 
120
 
 
121
  self->settings = g_settings_new ("com.canonical.indicator.session");
 
122
 
 
123
  /* Now let's fire these guys up. */
 
124
  self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME,
 
125
                                                        INDICATOR_SESSION_DBUS_VERSION);
 
126
  g_signal_connect (G_OBJECT(self->service),
 
127
                    INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
 
128
                    G_CALLBACK(service_connection_cb), self);
 
129
 
 
130
  greeter_mode = !g_strcmp0(g_getenv("INDICATOR_GREETER_MODE"), "1");
 
131
 
 
132
  self->entry.name_hint = PACKAGE;
 
133
  self->entry.accessible_desc = _("Session Menu");
 
134
  self->entry.label = GTK_LABEL (gtk_label_new ("User Name"));
 
135
  icon_name = greeter_mode ? GREETER_ICON_DEFAULT : ICON_DEFAULT;
 
136
  self->entry.image = GTK_IMAGE (gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON));
 
137
  self->entry.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME,
 
138
                                                    INDICATOR_SESSION_DBUS_OBJECT));
 
139
  g_settings_bind (self->settings, "show-real-name-on-panel",
 
140
                   self->entry.label, "visible",
 
141
                   G_SETTINGS_BIND_GET);
 
142
 
 
143
  gtk_widget_show (GTK_WIDGET(self->entry.menu));
 
144
  gtk_widget_show (GTK_WIDGET(self->entry.image));
 
145
  g_object_ref_sink (self->entry.menu);
 
146
  g_object_ref_sink (self->entry.image);
 
147
 
 
148
  // set up the handlers
 
149
  DbusmenuClient * menu_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->entry.menu)));
 
150
  dbusmenu_client_add_type_handler (menu_client,
 
151
                                    USER_ITEM_TYPE,
 
152
                                    new_user_item);
 
153
  dbusmenu_client_add_type_handler (menu_client,
 
154
                                    RESTART_ITEM_TYPE,
 
155
                                    build_restart_item);
 
156
  dbusmenu_gtkclient_set_accel_group (DBUSMENU_GTKCLIENT(menu_client),
 
157
                                      gtk_accel_group_new());
 
158
}
 
159
 
 
160
static void
 
161
indicator_session_dispose (GObject *object)
 
162
{
 
163
  IndicatorSession * self = INDICATOR_SESSION(object);
 
164
 
 
165
  g_clear_object (&self->settings);
 
166
  g_clear_object (&self->service);
 
167
  g_clear_object (&self->service_proxy);
 
168
 
 
169
  if (self->service_proxy_cancel != NULL)
 
170
    {
 
171
      g_cancellable_cancel(self->service_proxy_cancel);
 
172
      g_clear_object (&self->service_proxy_cancel);
 
173
    }
 
174
 
 
175
  g_clear_object (&self->entry.menu);
 
176
 
 
177
  G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object);
 
178
}
 
179
 
 
180
static void
 
181
indicator_session_finalize (GObject *object)
 
182
{
 
183
 
 
184
        G_OBJECT_CLASS (indicator_session_parent_class)->finalize (object);
 
185
        return;
 
186
}
 
187
 
 
188
static GList*
 
189
indicator_session_get_entries (IndicatorObject* obj)
 
190
{
 
191
  g_return_val_if_fail(IS_INDICATOR_SESSION(obj), NULL);
 
192
 
 
193
  IndicatorSession* self = INDICATOR_SESSION (obj);
 
194
  return g_list_append (NULL, &self->entry);
 
195
}
 
196
 
 
197
static guint
 
198
indicator_session_get_location (IndicatorObject * io,
 
199
                                IndicatorObjectEntry * entry)
 
200
{
 
201
  return 0;
 
202
}
 
203
 
 
204
/* callback for the service manager state of being */
 
205
static void
 
206
service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
 
207
{
 
208
        IndicatorSession * self = INDICATOR_SESSION (user_data);
 
209
 
 
210
        if (connected) {
 
211
    if (self->service_proxy != NULL){
 
212
      // Its a reconnect !
 
213
      // Fetch synchronisation data and return (proxy is still legit)
 
214
      g_dbus_proxy_call (self->service_proxy,
 
215
                         "GetUserRealName",
 
216
                         NULL,
 
217
                         G_DBUS_CALL_FLAGS_NONE,
 
218
                         -1,
 
219
                         NULL,
 
220
                         user_real_name_get_cb,
 
221
                         user_data);
 
222
      return;
 
223
    }
 
224
 
 
225
          self->service_proxy_cancel = g_cancellable_new();
 
226
          g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
 
227
                              G_DBUS_PROXY_FLAGS_NONE,
 
228
                              NULL,
 
229
                              INDICATOR_SESSION_DBUS_NAME,
 
230
                              INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
 
231
                              INDICATOR_SESSION_SERVICE_DBUS_IFACE,
 
232
                              self->service_proxy_cancel,
 
233
                              service_proxy_cb,
 
234
                              self);
 
235
  }
 
236
        return;
 
237
}
 
238
 
 
239
 
 
240
static void
 
241
service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
 
242
{
 
243
        GError * error = NULL;
 
244
 
 
245
        IndicatorSession * self = INDICATOR_SESSION(user_data);
 
246
        g_return_if_fail(self != NULL);
 
247
 
 
248
        GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
 
249
 
 
250
        g_clear_object (&self->service_proxy_cancel);
 
251
 
 
252
        if (error != NULL) {
 
253
                g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message);
 
254
                g_error_free(error);
 
255
                return;
 
256
        }
 
257
 
 
258
        /* Okay, we're good to grab the proxy at this point, we're
 
259
        sure that it's ours. */
 
260
        self->service_proxy = proxy;
 
261
 
 
262
        g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
 
263
 
 
264
  // Fetch the user's real name for the user entry label
 
265
  g_dbus_proxy_call (self->service_proxy,
 
266
                     "GetUserRealName",
 
267
                     NULL,
 
268
                     G_DBUS_CALL_FLAGS_NONE,
 
269
                     -1,
 
270
                     NULL,
 
271
                     user_real_name_get_cb,
 
272
                     user_data);
 
273
        return;
 
274
}
 
275
 
 
276
 
 
277
static gboolean
 
278
new_user_item (DbusmenuMenuitem * newitem,
 
279
               DbusmenuMenuitem * parent,
 
280
               DbusmenuClient   * client,
 
281
               gpointer           user_data)
 
282
{
 
283
  g_return_val_if_fail (DBUSMENU_IS_MENUITEM(newitem), FALSE);
 
284
  g_return_val_if_fail (DBUSMENU_IS_GTKCLIENT(client), FALSE);
 
285
 
 
286
  GtkWidget * user_item = user_widget_new (newitem);
 
287
 
 
288
  GtkMenuItem *user_widget = GTK_MENU_ITEM(user_item);
 
289
 
 
290
  dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
 
291
                                   newitem,
 
292
                                   user_widget,
 
293
                                   parent);
 
294
 
 
295
  g_debug ("%s (\"%s\")", __func__,
 
296
           dbusmenu_menuitem_property_get (newitem,
 
297
                                           USER_ITEM_PROP_NAME));
 
298
  gtk_widget_show_all (user_item);
 
299
 
 
300
  return TRUE;
 
301
}
 
302
 
 
303
 
 
304
static void
 
305
user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
 
306
{
 
307
  IndicatorSession * self = INDICATOR_SESSION(user_data);
 
308
 
 
309
  GError * error = NULL;
 
310
  GVariant * result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
 
311
 
 
312
  if (error != NULL)
 
313
    {
 
314
      g_warning ("Unable to complete real name dbus query: %s", error->message);
 
315
      g_clear_error (&error);
 
316
    }
 
317
  else
 
318
    {
 
319
      const gchar * username = NULL;
 
320
      g_variant_get (result, "(&s)", &username);
 
321
      indicator_session_update_users_label (self, username);
 
322
      g_variant_unref (result);
 
323
    }
 
324
}
 
325
 
 
326
/* Receives all signals from the service, routed to the appropriate functions */
 
327
static void
 
328
receive_signal (GDBusProxy * proxy,
 
329
                gchar      * sender_name,
 
330
                gchar      * signal_name,
 
331
                GVariant   * parameters,
 
332
                gpointer     user_data)
 
333
{
 
334
  IndicatorSession * self = INDICATOR_SESSION(user_data);
 
335
 
 
336
  if (!g_strcmp0(signal_name, "UserRealNameUpdated"))
 
337
    {
 
338
      const gchar * username = NULL;
 
339
      g_variant_get (parameters, "(&s)", &username);
 
340
      indicator_session_update_users_label (self, username);    
 
341
    }
 
342
  else if (!g_strcmp0(signal_name, "RestartRequired"))
 
343
    {
 
344
      const gchar * icon_name = greeter_mode ? GREETER_ICON_RESTART : ICON_RESTART;
 
345
      gtk_image_set_from_icon_name (GTK_IMAGE(self->entry.image), icon_name, GTK_ICON_SIZE_MENU);
 
346
      self->entry.accessible_desc = _("Device Menu (reboot required)");
 
347
      g_signal_emit (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, 0, &self->entry);
 
348
    }
 
349
}
 
350
 
 
351
 
 
352
 
 
353
 
 
354
static void
 
355
restart_property_change (DbusmenuMenuitem * item,
 
356
                         const gchar * property,
 
357
                         GVariant * variant,
 
358
                         gpointer user_data)
 
359
{
 
360
        DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
 
361
        GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(client, item);
 
362
 
 
363
        if (g_strcmp0(property, RESTART_ITEM_LABEL) == 0) {
 
364
                gtk_menu_item_set_label(gmi, g_variant_get_string(variant, NULL));
 
365
        } else if (g_strcmp0(property, RESTART_ITEM_ICON) == 0) {
 
366
                GtkWidget * image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(gmi));
 
367
 
 
368
                GIcon * gicon = g_themed_icon_new_with_default_fallbacks(g_variant_get_string(variant, NULL));
 
369
                if (image == NULL) {
 
370
                        image = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU);
 
371
                        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gmi), image);
 
372
                } else {
 
373
                        gtk_image_set_from_gicon(GTK_IMAGE(image), gicon, GTK_ICON_SIZE_MENU);
 
374
                }
 
375
                g_object_unref(G_OBJECT(gicon));
 
376
        }
 
377
        return;
 
378
}
 
379
 
 
380
static gboolean
 
381
build_restart_item (DbusmenuMenuitem * newitem,
 
382
                    DbusmenuMenuitem * parent,
 
383
                    DbusmenuClient * client,
 
384
                    gpointer user_data)
 
385
{
 
386
        GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new());
 
387
        if (gmi == NULL) {
 
388
                return FALSE;
 
389
        }
 
390
 
 
391
        dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
 
392
 
 
393
        g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(restart_property_change), client);
 
394
 
 
395
        GVariant * variant;
 
396
        variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_LABEL);
 
397
        if (variant != NULL) {
 
398
                restart_property_change(newitem, RESTART_ITEM_LABEL, variant, client);
 
399
        }
 
400
 
 
401
        variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_ICON);
 
402
        if (variant != NULL) {
 
403
                restart_property_change(newitem, RESTART_ITEM_ICON, variant, client);
 
404
        }
 
405
 
 
406
        return TRUE;
 
407
}
 
408
 
 
409
static void
 
410
indicator_session_update_users_label (IndicatorSession * self,
 
411
                                      const gchar      * name)
 
412
{
 
413
  gtk_label_set_text (self->entry.label, name ? name : "");
 
414
}