~skypce/indicator-session/indicator-session

« back to all changes in this revision

Viewing changes to src/session-service.c

  • Committer: Bazaar Package Importer
  • Author(s): Evgeni Golov
  • Date: 2011-04-03 14:16:17 UTC
  • mfrom: (13.1.31 natty)
  • Revision ID: james.westby@ubuntu.com-20110403141617-wvacgrixp44tw6i4
Tags: 0.2.15-1
* Merge from Ubuntu.
  Closes: #620671
* Standards-Version: 3.9.1
* Improve package descriptions.
* Update debian/copyright to DEP5 rev173.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
Authors:
8
8
    Ted Gould <ted@canonical.com>
9
9
    Christoph Korn <c_korn@gmx.de>
 
10
    Cody Russell <crussell@canonical.com>
10
11
 
11
12
This program is free software: you can redistribute it and/or modify it 
12
13
under the terms of the GNU General Public License version 3, as published 
23
24
 
24
25
#include <config.h>
25
26
 
 
27
#include <unistd.h>
 
28
 
26
29
#include <glib/gi18n.h>
 
30
#include <gio/gio.h>
 
31
#include <gio/gdesktopappinfo.h>
27
32
 
28
33
#include <dbus/dbus-glib.h>
29
34
#include <dbus/dbus-glib-bindings.h>
30
35
 
31
36
#include <libdbusmenu-glib/server.h>
32
37
#include <libdbusmenu-glib/menuitem.h>
 
38
#include <libdbusmenu-glib/client.h>
 
39
#include <libdbusmenu-gtk/menuitem.h>
 
40
 
 
41
#include <libindicator/indicator-service.h>
33
42
 
34
43
#include "dbus-shared-names.h"
35
 
 
36
 
#include "gtk-dialog/gconf-helper.h"
37
 
 
 
44
#include "dbusmenu-shared.h"
 
45
 
 
46
#include "gconf-helper.h"
 
47
 
 
48
#include "session-dbus.h"
 
49
#include "users-service-dbus.h"
38
50
#include "lock-helper.h"
39
 
 
40
 
#define DKP_ADDRESS    "org.freedesktop.DeviceKit.Power"
41
 
#define DKP_OBJECT     "/org/freedesktop/DeviceKit/Power"
42
 
#define DKP_INTERFACE  "org.freedesktop.DeviceKit.Power"
 
51
#include "upower-client.h"
 
52
 
 
53
#define UP_ADDRESS    "org.freedesktop.UPower"
 
54
#define UP_OBJECT     "/org/freedesktop/UPower"
 
55
#define UP_INTERFACE  "org.freedesktop.UPower"
 
56
 
 
57
#define EXTRA_LAUNCHER_DIR "/usr/share/indicators/session/applications"
 
58
 
 
59
#define GUEST_SESSION_LAUNCHER  "/usr/share/gdm/guest-session/guest-session-launch"
 
60
 
 
61
#define LOCKDOWN_DIR              "/desktop/gnome/lockdown"
 
62
#define LOCKDOWN_KEY_USER         LOCKDOWN_DIR "/disable_user_switching"
 
63
#define LOCKDOWN_KEY_SCREENSAVER  LOCKDOWN_DIR "/disable_lock_screen"
 
64
 
 
65
#define KEYBINDING_DIR            "/apps/gnome_settings_daemon/keybindings"
 
66
#define KEY_LOCK_SCREEN           KEYBINDING_DIR "/screensaver"
 
67
 
 
68
typedef struct _ActivateData ActivateData;
 
69
struct _ActivateData
 
70
{
 
71
  UsersServiceDbus *service;
 
72
  UserData *user;
 
73
};
 
74
 
 
75
static DBusGConnection   *system_bus = NULL;
 
76
static DBusGProxy        *gdm_proxy = NULL;
 
77
static UsersServiceDbus  *dbus_interface = NULL;
 
78
static SessionDbus       *session_dbus = NULL;
 
79
 
 
80
static DbusmenuMenuitem  *lock_menuitem = NULL;
 
81
static DbusmenuMenuitem  *switch_menuitem = NULL;
43
82
 
44
83
static DbusmenuMenuitem * root_menuitem = NULL;
45
84
static GMainLoop * mainloop = NULL;
46
 
static DBusGProxy * dkp_main_proxy = NULL;
47
 
static DBusGProxy * dkp_prop_proxy = NULL;
 
85
static DBusGProxy * up_main_proxy = NULL;
 
86
static DBusGProxy * up_prop_proxy = NULL;
48
87
 
49
88
static DBusGProxyCall * suspend_call = NULL;
50
89
static DBusGProxyCall * hibernate_call = NULL;
55
94
static DbusmenuMenuitem * restart_mi = NULL;
56
95
static DbusmenuMenuitem * shutdown_mi = NULL;
57
96
 
 
97
static gboolean can_hibernate = TRUE;
 
98
static gboolean can_suspend = TRUE;
 
99
static gboolean allow_hibernate = TRUE;
 
100
static gboolean allow_suspend = TRUE;
 
101
 
 
102
static GConfClient * gconf_client = NULL;
 
103
 
 
104
static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
 
105
 
 
106
static void
 
107
lockdown_changed (GConfClient *client,
 
108
                  guint        cnxd_id,
 
109
                  GConfEntry  *entry,
 
110
                  gpointer     user_data)
 
111
{
 
112
        GConfValue  *value = gconf_entry_get_value (entry);
 
113
        const gchar *key   = gconf_entry_get_key (entry);
 
114
 
 
115
        if (value == NULL || key == NULL) {
 
116
                return;
 
117
        }
 
118
 
 
119
        if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
 
120
                rebuild_items(root_menuitem, dbus_interface);
 
121
        }
 
122
 
 
123
        return;
 
124
}
 
125
 
 
126
static void
 
127
keybinding_changed (GConfClient *client,
 
128
                    guint        cnxd_id,
 
129
                    GConfEntry  *entry,
 
130
                    gpointer     user_data)
 
131
{
 
132
        GConfValue  *value = gconf_entry_get_value (entry);
 
133
        const gchar *key   = gconf_entry_get_key (entry);
 
134
 
 
135
        if (value == NULL || key == NULL) {
 
136
                return;
 
137
        }
 
138
 
 
139
        if (g_strcmp0 (key, KEY_LOCK_SCREEN) == 0) {
 
140
                g_debug("Keybinding changed to: %s", gconf_value_get_string(value));
 
141
                if (lock_menuitem != NULL) {
 
142
                        dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, gconf_value_get_string(value));
 
143
                }
 
144
        }
 
145
 
 
146
        return;
 
147
}
 
148
 
 
149
/* Ensures that we have a GConf client and if we build one
 
150
   set up the signal handler. */
 
151
static void
 
152
ensure_gconf_client (void)
 
153
{
 
154
        if (!gconf_client) {
 
155
                gconf_client = gconf_client_get_default ();
 
156
 
 
157
                gconf_client_add_dir(gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 
158
                gconf_client_notify_add(gconf_client, LOCKDOWN_DIR, lockdown_changed, NULL, NULL, NULL);
 
159
 
 
160
                gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 
161
                gconf_client_notify_add(gconf_client, KEYBINDING_DIR, keybinding_changed, NULL, NULL, NULL);
 
162
        }
 
163
        return;
 
164
}
 
165
 
 
166
/* Check to see if the lockdown key is protecting from
 
167
   locking the screen.  If not, lock it. */
 
168
static void
 
169
lock_if_possible (void) {
 
170
        ensure_gconf_client ();
 
171
 
 
172
        if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
 
173
                lock_screen(NULL, 0, NULL);
 
174
        }
 
175
 
 
176
        return;
 
177
}
 
178
 
58
179
/* A return from the command to sleep the system.  Make sure
59
180
   that we unthrottle the screensaver. */
60
181
static void
67
188
/* Let's put this machine to sleep, with some info on how
68
189
   it should sleep.  */
69
190
static void
70
 
sleep (DbusmenuMenuitem * mi, gpointer userdata)
 
191
machine_sleep (DbusmenuMenuitem * mi, guint timestamp, gpointer userdata)
71
192
{
72
193
        gchar * type = (gchar *)userdata;
73
194
 
74
 
        if (dkp_main_proxy == NULL) {
75
 
                g_warning("Can not %s as no DeviceKit Power Proxy", type);
 
195
        if (up_main_proxy == NULL) {
 
196
                g_warning("Can not %s as no upower proxy", type);
76
197
        }
77
198
 
78
199
        screensaver_throttle(type);
79
 
        lock_screen(NULL, NULL);
 
200
        lock_if_possible();
80
201
 
81
 
        dbus_g_proxy_begin_call(dkp_main_proxy,
 
202
        dbus_g_proxy_begin_call(up_main_proxy,
82
203
                                type,
83
204
                                sleep_response,
84
205
                                NULL,
104
225
        }
105
226
        g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
106
227
 
107
 
        if (suspend_mi != NULL) {
108
 
                dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, g_value_get_boolean(&candoit) ? "true" : "false");
 
228
        gboolean local_can_suspend = g_value_get_boolean(&candoit);
 
229
        if (local_can_suspend != can_suspend) {
 
230
                can_suspend = local_can_suspend;
 
231
                rebuild_items(root_menuitem, dbus_interface);
109
232
        }
110
233
 
111
234
        return;
127
250
        }
128
251
        g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
129
252
 
130
 
        if (suspend_mi != NULL) {
131
 
                dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, g_value_get_boolean(&candoit) ? "true" : "false");
 
253
        gboolean local_can_hibernate = g_value_get_boolean(&candoit);
 
254
        if (local_can_hibernate != can_hibernate) {
 
255
                can_hibernate = local_can_hibernate;
 
256
                rebuild_items(root_menuitem, dbus_interface);
132
257
        }
133
258
 
134
259
        return;
137
262
/* A signal that we need to recheck to ensure we can still
138
263
   hibernate and/or suspend */
139
264
static void
140
 
dpk_changed_cb (DBusGProxy * proxy, gpointer user_data)
 
265
up_changed_cb (DBusGProxy * proxy, gpointer user_data)
141
266
{
142
267
        /* Start Async call to see if we can hibernate */
143
268
        if (suspend_call == NULL) {
144
 
                suspend_call = dbus_g_proxy_begin_call(dkp_prop_proxy,
 
269
                suspend_call = dbus_g_proxy_begin_call(up_prop_proxy,
145
270
                                                       "Get",
146
271
                                                       suspend_prop_cb,
147
272
                                                       NULL,
148
273
                                                       NULL,
149
274
                                                       G_TYPE_STRING,
150
 
                                                       DKP_INTERFACE,
 
275
                                                       UP_INTERFACE,
151
276
                                                       G_TYPE_STRING,
152
 
                                                       "can-suspend",
 
277
                                                       "CanSuspend",
153
278
                                                       G_TYPE_INVALID,
154
279
                                                       G_TYPE_VALUE,
155
280
                                                       G_TYPE_INVALID);
157
282
 
158
283
        /* Start Async call to see if we can suspend */
159
284
        if (hibernate_call == NULL) {
160
 
                hibernate_call = dbus_g_proxy_begin_call(dkp_prop_proxy,
 
285
                hibernate_call = dbus_g_proxy_begin_call(up_prop_proxy,
161
286
                                                         "Get",
162
287
                                                         hibernate_prop_cb,
163
288
                                                         NULL,
164
289
                                                         NULL,
165
290
                                                         G_TYPE_STRING,
166
 
                                                         DKP_INTERFACE,
 
291
                                                         UP_INTERFACE,
167
292
                                                         G_TYPE_STRING,
168
 
                                                         "can-hibernate",
 
293
                                                         "CanHibernate",
169
294
                                                         G_TYPE_INVALID,
170
295
                                                         G_TYPE_VALUE,
171
296
                                                         G_TYPE_INVALID);
174
299
        return;
175
300
}
176
301
 
 
302
/* Handle the callback from the allow functions to check and
 
303
   see if we're changing the value, and if so, rebuilding the
 
304
   menus based on that info. */
 
305
static void
 
306
allowed_cb (DBusGProxy *proxy, gboolean OUT_allowed, GError *error, gpointer userdata)
 
307
{
 
308
        if (error != NULL) {
 
309
                g_warning("Unable to get information on what is allowed from UPower: %s", error->message);
 
310
                return;
 
311
        }
 
312
 
 
313
        gboolean * can_do = (gboolean *)userdata;
 
314
 
 
315
        if (OUT_allowed != *can_do) {
 
316
                *can_do = OUT_allowed;
 
317
                rebuild_items (root_menuitem, dbus_interface);
 
318
        }
 
319
}
 
320
 
177
321
/* This function goes through and sets up what we need for
178
322
   DKp checking.  We're even setting up the calls for the props
179
323
   we need */
180
324
static void
181
 
setup_dkp (void) {
 
325
setup_up (void) {
182
326
        DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
183
327
        g_return_if_fail(bus != NULL);
184
328
 
185
 
        if (dkp_main_proxy == NULL) {
186
 
                dkp_main_proxy = dbus_g_proxy_new_for_name(bus,
187
 
                                                           DKP_ADDRESS,
188
 
                                                           DKP_OBJECT,
189
 
                                                           DKP_INTERFACE);
 
329
        if (up_main_proxy == NULL) {
 
330
                up_main_proxy = dbus_g_proxy_new_for_name(bus,
 
331
                                                           UP_ADDRESS,
 
332
                                                           UP_OBJECT,
 
333
                                                           UP_INTERFACE);
190
334
        }
191
 
        g_return_if_fail(dkp_main_proxy != NULL);
 
335
        g_return_if_fail(up_main_proxy != NULL);
192
336
 
193
 
        if (dkp_prop_proxy == NULL) {
194
 
                dkp_prop_proxy = dbus_g_proxy_new_for_name(bus,
195
 
                                                           DKP_ADDRESS,
196
 
                                                           DKP_OBJECT,
 
337
        if (up_prop_proxy == NULL) {
 
338
                up_prop_proxy = dbus_g_proxy_new_for_name(bus,
 
339
                                                           UP_ADDRESS,
 
340
                                                           UP_OBJECT,
197
341
                                                           DBUS_INTERFACE_PROPERTIES);
 
342
                /* Connect to changed signal */
 
343
                dbus_g_proxy_add_signal(up_main_proxy,
 
344
                                        "Changed",
 
345
                                        G_TYPE_INVALID);
 
346
 
 
347
                dbus_g_proxy_connect_signal(up_main_proxy,
 
348
                                            "Changed",
 
349
                                            G_CALLBACK(up_changed_cb),
 
350
                                            NULL,
 
351
                                            NULL);
198
352
        }
199
 
        g_return_if_fail(dkp_prop_proxy != NULL);
200
 
 
201
 
        /* Connect to changed signal */
202
 
        dbus_g_proxy_add_signal(dkp_main_proxy,
203
 
                                "Changed",
204
 
                                G_TYPE_INVALID);
205
 
 
206
 
        dbus_g_proxy_connect_signal(dkp_main_proxy,
207
 
                                    "Changed",
208
 
                                    G_CALLBACK(dpk_changed_cb),
209
 
                                    NULL,
210
 
                                    NULL);
 
353
        g_return_if_fail(up_prop_proxy != NULL);
 
354
 
211
355
 
212
356
        /* Force an original "changed" event */
213
 
        dpk_changed_cb(dkp_main_proxy, NULL);
 
357
        up_changed_cb(up_main_proxy, NULL);
 
358
 
 
359
        /* Check to see if these are getting blocked by PolicyKit */
 
360
        org_freedesktop_UPower_suspend_allowed_async(up_main_proxy,
 
361
                                                     allowed_cb,
 
362
                                                     &allow_suspend);
 
363
        org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy,
 
364
                                                       allowed_cb,
 
365
                                                       &allow_hibernate);
214
366
 
215
367
        return;
216
368
}
220
372
   but it seems that in the future it should figure out
221
373
   what's going on and something better. */
222
374
static void
223
 
show_dialog (DbusmenuMenuitem * mi, gchar * type)
 
375
show_dialog (DbusmenuMenuitem * mi, guint timestamp, gchar * type)
224
376
{
225
377
        gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL);
226
378
        gchar * dialog_line = g_strdup_printf("%s --%s", helper, type);
239
391
        return;
240
392
}
241
393
 
242
 
/* This function creates all of the menuitems that the service
243
 
   provides in the UI.  It also connects them to the callbacks. */
244
 
static void
245
 
create_items (DbusmenuMenuitem * root) {
 
394
/* Checks to see if we should show the guest suession item */
 
395
static gboolean
 
396
check_guest_session (void)
 
397
{
 
398
        if (geteuid() < 500) {
 
399
                /* System users shouldn't have guest account shown.  Mosly
 
400
                   this would be the case of the guest user itself. */
 
401
                return FALSE;
 
402
        }
 
403
        if (!g_file_test(GUEST_SESSION_LAUNCHER, G_FILE_TEST_IS_EXECUTABLE)) {
 
404
                /* It doesn't appear that the Guest session stuff is
 
405
                   installed.  So let's not use it then! */
 
406
                return FALSE;
 
407
        }
 
408
 
 
409
        return TRUE;
 
410
}
 
411
 
 
412
/* Called when someone clicks on the guest session item. */
 
413
static void
 
414
activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
 
415
{
 
416
        GError * error = NULL;
 
417
 
 
418
        lock_if_possible();
 
419
 
 
420
        if (dbusmenu_menuitem_property_get_bool(mi, USER_ITEM_PROP_LOGGED_IN)) {
 
421
                if (users_service_dbus_activate_guest_session(USERS_SERVICE_DBUS(user_data))) {
 
422
                        return;
 
423
                }
 
424
                g_warning("Unable to activate guest session, falling back to command line activation.");
 
425
        }
 
426
 
 
427
        if (!g_spawn_command_line_async(GUEST_SESSION_LAUNCHER " --no-lock", &error)) {
 
428
                g_warning("Unable to start guest session: %s", error->message);
 
429
                g_error_free(error);
 
430
        }
 
431
 
 
432
        return;
 
433
}
 
434
 
 
435
/* Checks to see if we can create sessions and get a proxy
 
436
   to the display manager (GDM) */
 
437
static gboolean
 
438
check_new_session (void)
 
439
{
 
440
        if (system_bus == NULL) {
 
441
                system_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
 
442
        }
 
443
 
 
444
        if (system_bus == NULL) {
 
445
                return FALSE;
 
446
        }
 
447
 
 
448
        if (gdm_proxy == NULL) {
 
449
                gdm_proxy = dbus_g_proxy_new_for_name(system_bus,
 
450
                                                      "org.gnome.DisplayManager",
 
451
                                                      "/org/gnome/DisplayManager/LocalDisplayFactory",
 
452
                                                      "org.gnome.DisplayManager.LocalDisplayFactory");
 
453
        }
 
454
 
 
455
        if (gdm_proxy == NULL) {
 
456
                return FALSE;
 
457
        }
 
458
 
 
459
        return TRUE;
 
460
}
 
461
 
 
462
/* Starts a new generic session */
 
463
static void
 
464
activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
 
465
{
 
466
        GError * error = NULL;
 
467
 
 
468
        lock_if_possible();
 
469
 
 
470
        if (!g_spawn_command_line_async("gdmflexiserver --startnew", &error)) {
 
471
                g_warning("Unable to start new session: %s", error->message);
 
472
                g_error_free(error);
 
473
        }
 
474
 
 
475
        return;
 
476
}
 
477
 
 
478
/* Activates a session for a particular user. */
 
479
static void
 
480
activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
 
481
{
 
482
  UserData *user = (UserData *)user_data;
 
483
  UsersServiceDbus *service = user->service;
 
484
 
 
485
  lock_if_possible();
 
486
 
 
487
  users_service_dbus_activate_user_session (service, user);
 
488
}
 
489
 
 
490
/* Comparison function to look into the UserData struct
 
491
   to compare by using the username value */
 
492
static gint
 
493
compare_users_by_username (const gchar *a,
 
494
                           const gchar *b)
 
495
{
 
496
  UserData *user1 = (UserData *)a;
 
497
  UserData *user2 = (UserData *)b;
 
498
 
 
499
  gint retval = g_strcmp0 (user1->real_name, user2->real_name);
 
500
 
 
501
  /* If they're the same, they're both in conflict. */
 
502
  if (retval == 0) {
 
503
    user1->real_name_conflict = TRUE;
 
504
    user2->real_name_conflict = TRUE;
 
505
  }
 
506
 
 
507
  return retval;
 
508
}
 
509
 
 
510
/* Take a desktop file and execute it */
 
511
static void
 
512
desktop_activate_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
 
513
{
 
514
        GAppInfo * appinfo = G_APP_INFO(data);
 
515
        g_return_if_fail(appinfo != NULL);
 
516
        g_app_info_launch(appinfo, NULL, NULL, NULL);
 
517
        return;
 
518
}
 
519
 
 
520
/* Look at the GAppInfo structures and sort based on
 
521
   the application names */
 
522
static gint
 
523
sort_app_infos (gconstpointer a, gconstpointer b)
 
524
{
 
525
        GAppInfo * appa = G_APP_INFO(a);
 
526
        GAppInfo * appb = G_APP_INFO(b);
 
527
 
 
528
        const gchar * namea = NULL;
 
529
        const gchar * nameb = NULL;
 
530
 
 
531
        if (appa != NULL) {
 
532
                namea = g_app_info_get_name(appa);
 
533
        }
 
534
 
 
535
        if (appb != NULL) {
 
536
                nameb = g_app_info_get_name(appb);
 
537
        }
 
538
 
 
539
        return g_strcmp0(namea, nameb);
 
540
}
 
541
 
 
542
/* Builds up the menu for us */
 
543
static void
 
544
rebuild_items (DbusmenuMenuitem *root,
 
545
               UsersServiceDbus *service)
 
546
{
 
547
  DbusmenuMenuitem *mi = NULL;
 
548
  DbusmenuMenuitem * guest_mi = NULL;
 
549
  GList *u;
 
550
  UserData *user;
 
551
  gboolean can_activate;
 
552
  gboolean can_lockscreen;
 
553
  GList *children;
 
554
 
 
555
  /* Make sure we have a valid GConf client, and build one
 
556
     if needed */
 
557
  ensure_gconf_client ();
 
558
 
 
559
  /* Check to see which menu items we're allowed to have */
 
560
  can_activate = users_service_dbus_can_activate_session (service) &&
 
561
      !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL);
 
562
  can_lockscreen = !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL);
 
563
 
 
564
  /* Remove the old menu items if that makes sense */
 
565
  children = dbusmenu_menuitem_take_children (root);
 
566
  g_list_foreach (children, (GFunc)g_object_unref, NULL);
 
567
  g_list_free (children);
 
568
 
 
569
  /* Lock screen item */
 
570
  if (can_lockscreen) {
 
571
        lock_menuitem = dbusmenu_menuitem_new();
 
572
        dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
 
573
 
 
574
        gchar * shortcut = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL);
 
575
        if (shortcut != NULL) {
 
576
                g_debug("Lock screen shortcut: %s", shortcut);
 
577
                dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, shortcut);
 
578
                g_free(shortcut);
 
579
        } else {
 
580
                g_debug("Unable to get lock screen shortcut.");
 
581
        }
 
582
 
 
583
        g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
 
584
        dbusmenu_menuitem_child_append(root, lock_menuitem);
 
585
  }
 
586
 
 
587
  /* Set to NULL just incase we don't end up building one */
 
588
  users_service_dbus_set_guest_item(service, NULL);
 
589
 
 
590
  /* Build all of the user switching items */
 
591
  if (can_activate == TRUE)
 
592
    {
 
593
                if (can_lockscreen) {
 
594
                        DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
 
595
                        dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
 
596
                        dbusmenu_menuitem_child_append(root, separator1);
 
597
                }
 
598
 
 
599
      if (check_guest_session ())
 
600
        {
 
601
          guest_mi = dbusmenu_menuitem_new ();
 
602
                  dbusmenu_menuitem_property_set (guest_mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
 
603
          dbusmenu_menuitem_property_set (guest_mi, USER_ITEM_PROP_NAME, _("Guest Session"));
 
604
          dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, FALSE);
 
605
          dbusmenu_menuitem_child_append (root, guest_mi);
 
606
          g_signal_connect (G_OBJECT (guest_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), service);
 
607
          users_service_dbus_set_guest_item(service, guest_mi);
 
608
        }
 
609
 
 
610
      if (check_new_session ())
 
611
        {
 
612
 
 
613
          switch_menuitem = dbusmenu_menuitem_new ();
 
614
                  dbusmenu_menuitem_property_set (switch_menuitem, DBUSMENU_MENUITEM_PROP_TYPE, MENU_SWITCH_TYPE);
 
615
                  dbusmenu_menuitem_property_set (switch_menuitem, MENU_SWITCH_USER, g_get_user_name());
 
616
          dbusmenu_menuitem_child_append (root, switch_menuitem);
 
617
          g_signal_connect (G_OBJECT (switch_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), NULL);
 
618
        }
 
619
 
 
620
                GList * users = NULL;
 
621
                users = users_service_dbus_get_user_list (service);
 
622
                guint user_count = g_list_length(users);
 
623
 
 
624
                if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
 
625
                        users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
 
626
                }
 
627
 
 
628
                for (u = users; u != NULL; u = g_list_next (u)) {
 
629
                        user = u->data;
 
630
                        user->service = service;
 
631
 
 
632
                        if (user->uid == getuid()) {
 
633
                                /* Hide me from the list */
 
634
                                continue;
 
635
                        }
 
636
 
 
637
                        if (g_strcmp0(user->user_name, "guest") == 0) {
 
638
                                /* Check to see if the guest has sessions and so therefore should
 
639
                                   get a check mark. */
 
640
                                if (user->sessions != NULL) {
 
641
                                        dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, TRUE);
 
642
                                }
 
643
                                /* If we're showing user accounts, keep going through the list */
 
644
                                if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
 
645
                                        continue;
 
646
                                }
 
647
                                /* If not, we can stop here */
 
648
                                break;
 
649
                        }
 
650
 
 
651
                        if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
 
652
                                mi = dbusmenu_menuitem_new ();
 
653
                                dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
 
654
                                if (user->real_name_conflict) {
 
655
                                        gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name);
 
656
                                        dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname);
 
657
                                        g_free(conflictedname);
 
658
                                } else {
 
659
                                        dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
 
660
                                }
 
661
                                dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, user->sessions != NULL);
 
662
                                if (user->icon_url != NULL && user->icon_url[0] != '\0' && g_str_has_prefix(user->icon_url, "file://")) {
 
663
                                        dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_url + strlen("file://"));
 
664
                                } else {
 
665
                                        dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
 
666
                                }
 
667
                                dbusmenu_menuitem_child_append (root, mi);
 
668
                                g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_user_session), user);
 
669
                                user->menuitem = mi;
 
670
                        }
 
671
                }
 
672
 
 
673
                g_list_free(users);
 
674
        }
 
675
 
 
676
        /* If there were a bunch of items before us, we need a
 
677
           separator. */
 
678
        if (can_lockscreen || can_activate) {
 
679
                DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
 
680
                dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
 
681
                dbusmenu_menuitem_child_append(root, separator);
 
682
        }
 
683
 
 
684
        /* Start going through the session based items. */
 
685
 
246
686
        logout_mi = dbusmenu_menuitem_new();
247
687
        if (supress_confirmations()) {
248
688
                dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out"));
249
689
        } else {
250
 
                dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out..."));
 
690
                dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out\342\200\246"));
251
691
        }
 
692
        dbusmenu_menuitem_property_set_bool(logout_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_logout());
252
693
        dbusmenu_menuitem_child_append(root, logout_mi);
253
694
        g_signal_connect(G_OBJECT(logout_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "logout");
254
695
 
255
 
        suspend_mi = dbusmenu_menuitem_new();
256
 
        dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, "false");
257
 
        dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Suspend"));
258
 
        dbusmenu_menuitem_child_append(root, suspend_mi);
259
 
        g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Suspend");
 
696
        if (can_suspend && allow_suspend) {
 
697
                suspend_mi = dbusmenu_menuitem_new();
 
698
                dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Suspend"));
 
699
                dbusmenu_menuitem_child_append(root, suspend_mi);
 
700
                g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
 
701
        }
260
702
 
261
 
        hibernate_mi = dbusmenu_menuitem_new();
262
 
        dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, "false");
263
 
        dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
264
 
        dbusmenu_menuitem_child_append(root, hibernate_mi);
265
 
        g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Hibernate");
 
703
        if (can_hibernate && allow_hibernate) {
 
704
                hibernate_mi = dbusmenu_menuitem_new();
 
705
                dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
 
706
                dbusmenu_menuitem_child_append(root, hibernate_mi);
 
707
                g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Hibernate");
 
708
        }
266
709
 
267
710
        restart_mi = dbusmenu_menuitem_new();
 
711
        dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_TYPE, RESTART_ITEM_TYPE);
268
712
        if (supress_confirmations()) {
269
 
                dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart"));
 
713
                dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
270
714
        } else {
271
 
                dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart..."));
 
715
                dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
272
716
        }
 
717
        dbusmenu_menuitem_property_set_bool(restart_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_restart());
273
718
        dbusmenu_menuitem_child_append(root, restart_mi);
274
719
        g_signal_connect(G_OBJECT(restart_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "restart");
275
720
 
277
722
        if (supress_confirmations()) {
278
723
                dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down"));
279
724
        } else {
280
 
                dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down..."));
 
725
                dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down\342\200\246"));
281
726
        }
 
727
        dbusmenu_menuitem_property_set_bool(shutdown_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_shutdown());
282
728
        dbusmenu_menuitem_child_append(root, shutdown_mi);
283
729
        g_signal_connect(G_OBJECT(shutdown_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "shutdown");
284
730
 
289
735
 
290
736
        update_menu_entries(restart_shutdown_logout_mi);
291
737
 
 
738
        /* now add extra launchers */
 
739
        GDir *extra_launchers_dir;
 
740
        extra_launchers_dir = g_dir_open (EXTRA_LAUNCHER_DIR, 0, NULL);
 
741
        if (extra_launchers_dir != NULL) {
 
742
                GList * launchers = NULL;
 
743
 
 
744
                /* Find all the desktop files we want to use */
 
745
                for (;;) {
 
746
                        const gchar *extra_launcher_file;
 
747
 
 
748
                        extra_launcher_file = g_dir_read_name (extra_launchers_dir);
 
749
                        if (extra_launcher_file == NULL)
 
750
                                break;
 
751
                        if (!g_str_has_suffix (extra_launcher_file, ".desktop"))
 
752
                                continue;
 
753
 
 
754
                        gchar *full_path = g_build_filename (EXTRA_LAUNCHER_DIR, extra_launcher_file, NULL);
 
755
                        GAppInfo * appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename (full_path));
 
756
                        g_free (full_path);
 
757
 
 
758
                        launchers = g_list_prepend(launchers, appinfo);
 
759
                }
 
760
                g_dir_close(extra_launchers_dir);
 
761
 
 
762
                /* Sort the desktop files based on their names */
 
763
                launchers = g_list_sort(launchers, sort_app_infos);
 
764
 
 
765
                /* Turn each one into a separate menu item */
 
766
                GList * launcher = NULL;
 
767
                gboolean sepadded = FALSE;
 
768
                for (launcher = launchers; launcher != NULL; launcher = g_list_next(launcher)) {
 
769
                        GAppInfo * appinfo = G_APP_INFO(launcher->data);
 
770
 
 
771
                        /* Make sure we have a separator */
 
772
                        if (!sepadded) {
 
773
                                DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
 
774
                                dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
 
775
                                dbusmenu_menuitem_child_append(root, separator);
 
776
                                g_object_unref(separator);
 
777
                                sepadded = TRUE;
 
778
                        }
 
779
 
 
780
                        /* Build the item */
 
781
                        DbusmenuMenuitem * desktop_mi = dbusmenu_menuitem_new();
 
782
                        dbusmenu_menuitem_property_set(desktop_mi, DBUSMENU_MENUITEM_PROP_LABEL, g_app_info_get_name(appinfo));
 
783
                        g_signal_connect(G_OBJECT(desktop_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(desktop_activate_cb), appinfo);
 
784
                        g_object_weak_ref(G_OBJECT(desktop_mi), (GWeakNotify)g_object_unref, appinfo);
 
785
 
 
786
                        /* Put into the menu */
 
787
                        dbusmenu_menuitem_child_append(root, desktop_mi);
 
788
                }
 
789
 
 
790
                g_list_free(launchers);
 
791
        }
 
792
 
 
793
        return;
 
794
}
 
795
 
 
796
/* Signal called when a user is added.  It updates the count and
 
797
   rebuilds the menu */
 
798
static void
 
799
user_change (UsersServiceDbus *service,
 
800
             gint64            user,
 
801
             gpointer          user_data)
 
802
{
 
803
        DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data;
 
804
        rebuild_items (root, service);
 
805
        return;
 
806
}
 
807
 
 
808
/* When the service interface starts to shutdown, we
 
809
   should follow it. */
 
810
void
 
811
service_shutdown (IndicatorService * service, gpointer user_data)
 
812
{
 
813
        if (mainloop != NULL) {
 
814
                g_debug("Service shutdown");
 
815
                g_main_loop_quit(mainloop);
 
816
        }
 
817
        return;
 
818
}
 
819
 
 
820
/* When the directory changes we need to figure out how our menu
 
821
   item should look. */
 
822
static void
 
823
restart_dir_changed (void)
 
824
{
 
825
        gboolean restart_required = g_file_test("/var/run/reboot-required", G_FILE_TEST_EXISTS);
 
826
 
 
827
        if (restart_required) {
 
828
                if (supress_confirmations()) {
 
829
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update"));
 
830
                } else {
 
831
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update\342\200\246"));
 
832
                }
 
833
                dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_ICON, "system-restart-panel");
 
834
                if (session_dbus != NULL) {
 
835
                        session_dbus_set_name(session_dbus, ICON_RESTART);
 
836
                }
 
837
        } else {        
 
838
                if (supress_confirmations()) {
 
839
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
 
840
                } else {
 
841
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
 
842
                }
 
843
                dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON);
 
844
                if (session_dbus != NULL) {
 
845
                        session_dbus_set_name(session_dbus, ICON_DEFAULT);
 
846
                }
 
847
        }
 
848
 
 
849
        return;
 
850
}
 
851
 
 
852
/* Buids a file watcher for the directory so that when it
 
853
   changes we can check to see if our reboot-required is
 
854
   there. */
 
855
static void
 
856
setup_restart_watch (void)
 
857
{
 
858
        GFile * filedir = g_file_new_for_path("/var/run");
 
859
        GFileMonitor * filemon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
 
860
        if (filemon != NULL) {
 
861
                g_signal_connect(G_OBJECT(filemon), "changed", G_CALLBACK(restart_dir_changed), NULL);
 
862
        }
 
863
        restart_dir_changed();
292
864
        return;
293
865
}
294
866
 
305
877
        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
306
878
        textdomain (GETTEXT_PACKAGE);
307
879
 
308
 
    DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
309
 
    DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
310
 
    GError * error = NULL;
311
 
    guint nameret = 0;
312
 
 
313
 
    if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_SESSION_DBUS_NAME, 0, &nameret, &error)) {
314
 
        g_error("Unable to call to request name");
315
 
        return 1;
316
 
    }   
317
 
 
318
 
    if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
319
 
        g_error("Unable to get name");
320
 
        return 1;
321
 
    }   
 
880
        IndicatorService * service = indicator_service_new_version(INDICATOR_SESSION_DBUS_NAME,
 
881
                                                                   INDICATOR_SESSION_DBUS_VERSION);
 
882
        g_signal_connect(G_OBJECT(service),
 
883
                         INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
 
884
                         G_CALLBACK(service_shutdown), NULL);
 
885
 
 
886
        session_dbus = session_dbus_new();
322
887
 
323
888
        g_idle_add(lock_screen_setup, NULL);
324
889
 
325
890
    root_menuitem = dbusmenu_menuitem_new();
326
891
        g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
327
892
 
328
 
        create_items(root_menuitem);
329
 
        setup_dkp();
 
893
    dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
 
894
 
 
895
    rebuild_items (root_menuitem, dbus_interface);
 
896
 
 
897
    g_signal_connect (G_OBJECT (dbus_interface),
 
898
                      "user-added",
 
899
                      G_CALLBACK (user_change),
 
900
                      root_menuitem);
 
901
    g_signal_connect (G_OBJECT (dbus_interface),
 
902
                      "user-removed",
 
903
                      G_CALLBACK (user_change),
 
904
                      root_menuitem);
 
905
 
 
906
        setup_restart_watch();
 
907
 
 
908
        setup_up();
330
909
 
331
910
    DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
332
911
    dbusmenu_server_set_root(server, root_menuitem);