~ubuntu-branches/ubuntu/oneiric/indicator-session/oneiric-proposed

« back to all changes in this revision

Viewing changes to src/device-menu-mgr.c

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2011-07-22 13:41:08 UTC
  • mfrom: (1.1.31 upstream)
  • Revision ID: james.westby@ubuntu.com-20110722134108-8qgaow6jiocdlpga
Tags: 0.3.0-0ubuntu1
* New upstream release.
  - fixed bug where the user menu wouldn't open in unity (LP: #812728)
  - Include apt, settings and device menus
* debian/rules
  - Updated gtk configure args

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright 2011 Canonical Ltd.
 
3
 
 
4
Authors:
 
5
    Conor Curran <conor.curran@canonical.com>
 
6
 
 
7
This program is free software: you can redistribute it and/or modify it 
 
8
under the terms of the GNU General Public License version 3, as published 
 
9
by the Free Software Foundation.
 
10
 
 
11
This program is distributed in the hope that it will be useful, but 
 
12
WITHOUT ANY WARRANTY; without even the implied warranties of 
 
13
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
14
PURPOSE.  See the GNU General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License along 
 
17
with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include <libdbusmenu-glib/client.h>
 
21
#include <libdbusmenu-gtk3/menuitem.h>
 
22
 
 
23
#include "device-menu-mgr.h"
 
24
#include "gconf-helper.h"
 
25
#include "dbus-shared-names.h"
 
26
#include "dbusmenu-shared.h"
 
27
#include "lock-helper.h"
 
28
#include "upower-client.h"
 
29
#include "apt-watcher.h"
 
30
 
 
31
 
 
32
#define UP_ADDRESS    "org.freedesktop.UPower"
 
33
#define UP_OBJECT     "/org/freedesktop/UPower"
 
34
#define UP_INTERFACE  "org.freedesktop.UPower"
 
35
 
 
36
#define EXTRA_LAUNCHER_DIR "/usr/share/indicators/session/applications"
 
37
 
 
38
struct _DeviceMenuMgr
 
39
{
 
40
        GObject parent_instance;
 
41
  DbusmenuMenuitem* root_item;
 
42
  SessionDbus* session_dbus_interface;  
 
43
  AptWatcher* apt_watcher;                              
 
44
};
 
45
 
 
46
static GConfClient       *gconf_client  = NULL;
 
47
static DbusmenuMenuitem  *lock_menuitem = NULL;
 
48
static DbusmenuMenuitem  *system_settings_menuitem = NULL;
 
49
static DbusmenuMenuitem  *display_settings_menuitem = NULL;
 
50
static DbusmenuMenuitem  *bluetooth_settings_menuitem = NULL;
 
51
static DbusmenuMenuitem  *login_settings_menuitem = NULL;
 
52
static DbusmenuMenuitem  *software_updates_menuitem = NULL;
 
53
static DbusmenuMenuitem  *printers_menuitem = NULL;
 
54
static DbusmenuMenuitem  *scanners_menuitem = NULL;
 
55
static DbusmenuMenuitem  *webcam_menuitem = NULL;
 
56
 
 
57
static DBusGProxyCall * suspend_call = NULL;
 
58
static DBusGProxyCall * hibernate_call = NULL;
 
59
 
 
60
static DbusmenuMenuitem * hibernate_mi = NULL;
 
61
static DbusmenuMenuitem * suspend_mi = NULL;
 
62
static DbusmenuMenuitem * logout_mi = NULL;
 
63
static DbusmenuMenuitem * restart_mi = NULL;
 
64
static DbusmenuMenuitem * shutdown_mi = NULL;
 
65
 
 
66
static gboolean can_hibernate = TRUE;
 
67
static gboolean can_suspend = TRUE;
 
68
static gboolean allow_hibernate = TRUE;
 
69
static gboolean allow_suspend = TRUE;
 
70
 
 
71
static DBusGProxy * up_main_proxy = NULL;
 
72
static DBusGProxy * up_prop_proxy = NULL;
 
73
 
 
74
static void device_menu_mgr_ensure_gconf_client (DeviceMenuMgr* self);
 
75
static void setup_restart_watch (DeviceMenuMgr* self);
 
76
static void setup_up (DeviceMenuMgr* self);
 
77
static void device_menu_mgr_rebuild_items (DeviceMenuMgr *self);
 
78
static void lock_if_possible (DeviceMenuMgr* self);
 
79
static void machine_sleep_with_context (DeviceMenuMgr* self,
 
80
                                        gchar* type);
 
81
static void show_system_settings_with_context (DbusmenuMenuitem * mi,
 
82
                                               guint timestamp,
 
83
                                               gchar * type);                                               
 
84
                                        
 
85
static void
 
86
machine_sleep_from_hibernate (DbusmenuMenuitem * mi,
 
87
                              guint timestamp,
 
88
                              gpointer userdata);
 
89
static void
 
90
machine_sleep_from_suspend (DbusmenuMenuitem * mi,
 
91
                            guint timestamp,
 
92
                            gpointer userdata);
 
93
 
 
94
G_DEFINE_TYPE (DeviceMenuMgr, device_menu_mgr, G_TYPE_OBJECT);
 
95
 
 
96
static void
 
97
device_menu_mgr_init (DeviceMenuMgr *self)
 
98
{
 
99
  self->apt_watcher = NULL;
 
100
  self->root_item = dbusmenu_menuitem_new ();  
 
101
  setup_restart_watch(self);
 
102
        setup_up(self);  
 
103
        g_idle_add(lock_screen_setup, NULL);  
 
104
}
 
105
 
 
106
static void
 
107
device_menu_mgr_finalize (GObject *object)
 
108
{
 
109
        G_OBJECT_CLASS (device_menu_mgr_parent_class)->finalize (object);
 
110
}
 
111
 
 
112
// TODO refactor into one helper method for both menu mgrs.
 
113
static void
 
114
device_menu_mgr_class_init (DeviceMenuMgrClass *klass)
 
115
{
 
116
        GObjectClass* object_class = G_OBJECT_CLASS (klass);
 
117
        object_class->finalize = device_menu_mgr_finalize;
 
118
}
 
119
 
 
120
// TODO
 
121
// Is this needed anymore
 
122
static void
 
123
lockdown_changed (GConfClient *client,
 
124
                  guint        cnxd_id,
 
125
                  GConfEntry  *entry,
 
126
                  gpointer     user_data)
 
127
{
 
128
  DeviceMenuMgr* self = DEVICE_MENU_MGR (user_data);
 
129
        GConfValue  *value = gconf_entry_get_value (entry);
 
130
        const gchar *key   = gconf_entry_get_key (entry);
 
131
 
 
132
        if (value == NULL || key == NULL) {
 
133
                return;
 
134
        }
 
135
 
 
136
        if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 ||
 
137
      g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
 
138
                device_menu_mgr_rebuild_items(self);
 
139
        }
 
140
 
 
141
        return;
 
142
}
 
143
 
 
144
static void
 
145
keybinding_changed (GConfClient *client,
 
146
                    guint        cnxd_id,
 
147
                    GConfEntry  *entry,
 
148
                    gpointer     user_data)
 
149
{
 
150
        GConfValue  *value = gconf_entry_get_value (entry);
 
151
        const gchar *key   = gconf_entry_get_key (entry);
 
152
 
 
153
        if (value == NULL || key == NULL) {
 
154
                return;
 
155
        }
 
156
 
 
157
        if (g_strcmp0 (key, KEY_LOCK_SCREEN) == 0) {
 
158
                g_debug("Keybinding changed to: %s", gconf_value_get_string(value));
 
159
                if (lock_menuitem != NULL) {
 
160
                        dbusmenu_menuitem_property_set_shortcut_string (lock_menuitem,
 
161
                                                      gconf_value_get_string(value));
 
162
                }
 
163
        }
 
164
        return;
 
165
}
 
166
 
 
167
/* Check to see if the lockdown key is protecting from
 
168
   locking the screen.  If not, lock it. */
 
169
static void
 
170
lock_if_possible (DeviceMenuMgr* self) {
 
171
        device_menu_mgr_ensure_gconf_client (self);
 
172
 
 
173
        if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
 
174
                lock_screen (NULL, 0, NULL);
 
175
        }
 
176
        return;
 
177
}
 
178
 
 
179
/* A return from the command to sleep the system.  Make sure
 
180
   that we unthrottle the screensaver. */
 
181
static void
 
182
sleep_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data)
 
183
{
 
184
        screensaver_unthrottle();
 
185
        return;
 
186
}
 
187
 
 
188
static void
 
189
machine_sleep_from_suspend (DbusmenuMenuitem * mi,
 
190
                            guint timestamp,
 
191
                            gpointer userdata)
 
192
{
 
193
  DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata);
 
194
  machine_sleep_with_context (self, "Suspend");
 
195
}
 
196
 
 
197
static void
 
198
machine_sleep_from_hibernate (DbusmenuMenuitem * mi,
 
199
                              guint timestamp,
 
200
                              gpointer userdata)
 
201
{
 
202
  DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata);
 
203
  machine_sleep_with_context (self, "Hibernate");
 
204
}
 
205
 
 
206
/* Let's put this machine to sleep, with some info on how
 
207
   it should sleep.  */
 
208
static void
 
209
machine_sleep_with_context (DeviceMenuMgr* self, gchar* type)
 
210
{
 
211
        if (up_main_proxy == NULL) {
 
212
                g_warning("Can not %s as no upower proxy", type);
 
213
        }
 
214
 
 
215
        screensaver_throttle(type);
 
216
        lock_if_possible (self);
 
217
 
 
218
        dbus_g_proxy_begin_call(up_main_proxy,
 
219
                                type,
 
220
                                sleep_response,
 
221
                                NULL,
 
222
                                NULL,
 
223
                                G_TYPE_INVALID);
 
224
 
 
225
        return;
 
226
}
 
227
 
 
228
/* A response to getting the suspend property */
 
229
static void
 
230
suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
 
231
{
 
232
        suspend_call = NULL;
 
233
  DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata);
 
234
  
 
235
        GValue candoit = {0};
 
236
        GError * error = NULL;
 
237
        dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
 
238
        if (error != NULL) {
 
239
                g_warning("Unable to check suspend: %s", error->message);
 
240
                g_error_free(error);
 
241
                return;
 
242
        }
 
243
        g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
 
244
 
 
245
        gboolean local_can_suspend = g_value_get_boolean(&candoit);
 
246
        if (local_can_suspend != can_suspend) {
 
247
                can_suspend = local_can_suspend;
 
248
    // TODO figure out what needs updating on the menu
 
249
    // And add or remove it but just don't rebuild the whole menu
 
250
    // a waste
 
251
                device_menu_mgr_rebuild_items(self);
 
252
        }
 
253
        return;
 
254
}
 
255
 
 
256
/* Response to getting the hibernate property */
 
257
static void
 
258
hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
 
259
{
 
260
        hibernate_call = NULL;
 
261
  DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata);
 
262
 
 
263
        GValue candoit = {0};
 
264
        GError * error = NULL;
 
265
        dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID);
 
266
        if (error != NULL) {
 
267
                g_warning("Unable to check hibernate: %s", error->message);
 
268
                g_error_free(error);
 
269
                return;
 
270
        }
 
271
        g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
 
272
 
 
273
        gboolean local_can_hibernate = g_value_get_boolean(&candoit);
 
274
        if (local_can_hibernate != can_hibernate) {
 
275
                can_hibernate = local_can_hibernate;
 
276
                device_menu_mgr_rebuild_items(self);
 
277
        }
 
278
}
 
279
 
 
280
/* A signal that we need to recheck to ensure we can still
 
281
   hibernate and/or suspend */
 
282
static void
 
283
up_changed_cb (DBusGProxy * proxy, gpointer user_data)
 
284
{
 
285
        /* Start Async call to see if we can hibernate */
 
286
        if (suspend_call == NULL) {
 
287
                suspend_call = dbus_g_proxy_begin_call(up_prop_proxy,
 
288
                                                       "Get",
 
289
                                                       suspend_prop_cb,
 
290
                                                       user_data,
 
291
                                                       NULL,
 
292
                                                       G_TYPE_STRING,
 
293
                                                       UP_INTERFACE,
 
294
                                                       G_TYPE_STRING,
 
295
                                                       "CanSuspend",
 
296
                                                       G_TYPE_INVALID,
 
297
                                                       G_TYPE_VALUE,
 
298
                                                       G_TYPE_INVALID);
 
299
        }
 
300
 
 
301
        /* Start Async call to see if we can suspend */
 
302
        if (hibernate_call == NULL) {
 
303
                hibernate_call = dbus_g_proxy_begin_call(up_prop_proxy,
 
304
                                                         "Get",
 
305
                                                         hibernate_prop_cb,
 
306
                                                         user_data,
 
307
                                                         NULL,
 
308
                                                         G_TYPE_STRING,
 
309
                                                         UP_INTERFACE,
 
310
                                                         G_TYPE_STRING,
 
311
                                                         "CanHibernate",
 
312
                                                         G_TYPE_INVALID,
 
313
                                                         G_TYPE_VALUE,
 
314
                                                         G_TYPE_INVALID);
 
315
        }
 
316
}
 
317
/* Handle the callback from the allow functions to check and
 
318
   see if we're changing the value, and if so, rebuilding the
 
319
   menus based on that info. */
 
320
static void
 
321
allowed_suspend_cb (DBusGProxy *proxy,
 
322
                    gboolean OUT_allowed,
 
323
                    GError *error,
 
324
                    gpointer userdata)
 
325
{
 
326
        if (error != NULL) {
 
327
                g_warning("Unable to get information on what is allowed from UPower: %s",
 
328
               error->message);
 
329
                return;
 
330
        }
 
331
  
 
332
        if (OUT_allowed != allow_suspend) {
 
333
    allow_suspend = OUT_allowed;
 
334
    device_menu_mgr_rebuild_items(DEVICE_MENU_MGR (userdata));
 
335
  }
 
336
}
 
337
 
 
338
/* Handle the callback from the allow functions to check and
 
339
   see if we're changing the value, and if so, rebuilding the
 
340
   menus based on that info. */
 
341
static void
 
342
allowed_hibernate_cb (DBusGProxy *proxy,
 
343
                      gboolean OUT_allowed,
 
344
                      GError *error,
 
345
                      gpointer userdata)
 
346
{
 
347
        if (error != NULL) {
 
348
                g_warning("Unable to get information on what is allowed from UPower: %s",
 
349
               error->message);
 
350
                return;
 
351
        }
 
352
  
 
353
        if (OUT_allowed != allow_hibernate) {
 
354
    allow_hibernate = OUT_allowed;
 
355
    device_menu_mgr_rebuild_items(DEVICE_MENU_MGR (userdata));
 
356
  }
 
357
}
 
358
 
 
359
/* This function goes through and sets up what we need for
 
360
   DKp checking.  We're even setting up the calls for the props
 
361
   we need */
 
362
static void
 
363
setup_up (DeviceMenuMgr* self) {
 
364
        DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
 
365
        g_return_if_fail(bus != NULL);
 
366
 
 
367
        if (up_main_proxy == NULL) {
 
368
                up_main_proxy = dbus_g_proxy_new_for_name(bus,
 
369
                                                           UP_ADDRESS,
 
370
                                                           UP_OBJECT,
 
371
                                                           UP_INTERFACE);
 
372
        }
 
373
        g_return_if_fail(up_main_proxy != NULL);
 
374
 
 
375
        if (up_prop_proxy == NULL) {
 
376
                up_prop_proxy = dbus_g_proxy_new_for_name(bus,
 
377
                                              UP_ADDRESS,
 
378
                                              UP_OBJECT,
 
379
                                              DBUS_INTERFACE_PROPERTIES);
 
380
                /* Connect to changed signal */
 
381
                dbus_g_proxy_add_signal(up_main_proxy,
 
382
                                        "Changed",
 
383
                                        G_TYPE_INVALID);
 
384
 
 
385
                dbus_g_proxy_connect_signal(up_main_proxy,
 
386
                                            "Changed",
 
387
                                            G_CALLBACK(up_changed_cb),
 
388
                                            self,
 
389
                                            NULL);
 
390
        }
 
391
        g_return_if_fail(up_prop_proxy != NULL);
 
392
 
 
393
 
 
394
        /* Force an original "changed" event */
 
395
        up_changed_cb(up_main_proxy, self);
 
396
 
 
397
        /* Check to see if these are getting blocked by PolicyKit */
 
398
        org_freedesktop_UPower_suspend_allowed_async(up_main_proxy,
 
399
                                                     allowed_suspend_cb,
 
400
                                                     self);
 
401
        org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy,
 
402
                                                       allowed_hibernate_cb,
 
403
                                                       self);
 
404
 
 
405
        return;
 
406
}
 
407
 
 
408
/* This is the function to show a dialog on actions that
 
409
   can destroy data.  Currently it just calls the GTK version
 
410
   but it seems that in the future it should figure out
 
411
   what's going on and something better. */
 
412
static void
 
413
show_dialog (DbusmenuMenuitem * mi, guint timestamp, gchar * type)
 
414
{
 
415
 
 
416
        gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL);
 
417
        gchar * dialog_line = g_strdup_printf("%s --%s", helper, type);
 
418
        g_free(helper);
 
419
 
 
420
        g_debug("Showing dialog '%s'", dialog_line);
 
421
 
 
422
        GError * error = NULL;
 
423
        if (!g_spawn_command_line_async(dialog_line, &error)) {
 
424
                g_warning("Unable to show dialog: %s", error->message);
 
425
                g_error_free(error);
 
426
        }
 
427
        g_free(dialog_line);  
 
428
}
 
429
 
 
430
static void
 
431
show_session_properties (DbusmenuMenuitem * mi,
 
432
                         guint timestamp,
 
433
                         gchar * type)
 
434
{
 
435
  GError * error = NULL;
 
436
  if (!g_spawn_command_line_async("gnome-session-properties", &error))
 
437
  {
 
438
    g_warning("Unable to show dialog: %s", error->message);
 
439
    g_error_free(error);
 
440
  }  
 
441
}                                   
 
442
 
 
443
static void
 
444
show_system_settings_with_context (DbusmenuMenuitem * mi,
 
445
                                   guint timestamp,
 
446
                                   gchar * type)
 
447
{
 
448
        gchar * control_centre_command = g_strdup_printf("%s %s",
 
449
                                                   "gnome-control-center",
 
450
                                                    type);
 
451
 
 
452
        g_debug("Command centre exec call '%s'", control_centre_command);
 
453
 
 
454
  GError * error = NULL;
 
455
  if (!g_spawn_command_line_async(control_centre_command, &error))
 
456
  {
 
457
    g_warning("Unable to show dialog: %s", error->message);
 
458
    g_error_free(error);
 
459
  }
 
460
        g_free(control_centre_command);
 
461
}
 
462
 
 
463
static void
 
464
device_menu_mgr_build_static_items (DeviceMenuMgr* self)
 
465
{
 
466
  // Static Setting items
 
467
  system_settings_menuitem  = dbusmenu_menuitem_new();
 
468
  dbusmenu_menuitem_property_set (system_settings_menuitem,
 
469
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
470
                                  _("System Settings..."));
 
471
  g_signal_connect (G_OBJECT(system_settings_menuitem),
 
472
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
473
                    G_CALLBACK(show_system_settings_with_context), "");
 
474
  dbusmenu_menuitem_child_add_position(self->root_item,
 
475
                                       system_settings_menuitem,
 
476
                                       0);
 
477
  
 
478
  display_settings_menuitem = dbusmenu_menuitem_new();
 
479
  dbusmenu_menuitem_property_set (display_settings_menuitem,
 
480
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
481
                                  _("Displays..."));
 
482
  g_signal_connect (G_OBJECT(display_settings_menuitem),
 
483
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
484
                    G_CALLBACK(show_system_settings_with_context), "display");
 
485
  dbusmenu_menuitem_child_add_position(self->root_item,
 
486
                                       display_settings_menuitem,
 
487
                                       1);
 
488
  bluetooth_settings_menuitem = dbusmenu_menuitem_new();
 
489
  dbusmenu_menuitem_property_set (bluetooth_settings_menuitem,
 
490
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
491
                                  _("Bluetooth..."));
 
492
  g_signal_connect (G_OBJECT(bluetooth_settings_menuitem),
 
493
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
494
                    G_CALLBACK(show_system_settings_with_context), "bluetooth");
 
495
  dbusmenu_menuitem_child_add_position(self->root_item,
 
496
                                       bluetooth_settings_menuitem,
 
497
                                       2);
 
498
 
 
499
  login_settings_menuitem = dbusmenu_menuitem_new();
 
500
  dbusmenu_menuitem_property_set (login_settings_menuitem,
 
501
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
502
                                  _("Startup Applications..."));
 
503
  g_signal_connect (G_OBJECT(login_settings_menuitem),
 
504
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
505
                    G_CALLBACK(show_session_properties),
 
506
                    "login");
 
507
  dbusmenu_menuitem_child_add_position(self->root_item,
 
508
                                       login_settings_menuitem,                                  
 
509
                                       3);
 
510
  software_updates_menuitem = dbusmenu_menuitem_new();
 
511
  dbusmenu_menuitem_property_set (software_updates_menuitem,
 
512
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
513
                                  _("Software Up to Date"));
 
514
  dbusmenu_menuitem_child_add_position(self->root_item,
 
515
                                       software_updates_menuitem,
 
516
                                       4);
 
517
 
 
518
  DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
 
519
  dbusmenu_menuitem_property_set (separator1,
 
520
                                  DBUSMENU_MENUITEM_PROP_TYPE,
 
521
                                  DBUSMENU_CLIENT_TYPES_SEPARATOR);
 
522
  dbusmenu_menuitem_child_add_position (self->root_item, separator1, 5);
 
523
 
 
524
  // Devices control
 
525
  DbusmenuMenuitem * device_heading = dbusmenu_menuitem_new();
 
526
  dbusmenu_menuitem_property_set (device_heading,
 
527
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
528
                                  _("Attached Devices"));
 
529
  dbusmenu_menuitem_property_set_bool (device_heading,
 
530
                                       DBUSMENU_MENUITEM_PROP_ENABLED,
 
531
                                       FALSE);
 
532
  dbusmenu_menuitem_child_add_position (self->root_item,
 
533
                                        device_heading,
 
534
                                        6);
 
535
 
 
536
  printers_menuitem = dbusmenu_menuitem_new();
 
537
  dbusmenu_menuitem_property_set (printers_menuitem,
 
538
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
539
                                  _("Printers"));
 
540
  g_signal_connect (G_OBJECT(printers_menuitem),
 
541
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
542
                    G_CALLBACK(show_system_settings_with_context),
 
543
                    "printers");
 
544
  dbusmenu_menuitem_child_add_position(self->root_item,
 
545
                                       printers_menuitem,
 
546
                                       7);
 
547
  scanners_menuitem = dbusmenu_menuitem_new();
 
548
  dbusmenu_menuitem_property_set (scanners_menuitem,
 
549
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
550
                                  _("HP Scanners"));
 
551
  g_signal_connect (G_OBJECT(scanners_menuitem),
 
552
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
553
                    G_CALLBACK(show_system_settings_with_context),
 
554
                    "scanners");
 
555
  dbusmenu_menuitem_child_add_position (self->root_item,
 
556
                                        scanners_menuitem,
 
557
                                        8);
 
558
 //tmp
 
559
  dbusmenu_menuitem_property_set_bool (scanners_menuitem,
 
560
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
561
                                       FALSE);
 
562
                                        
 
563
  webcam_menuitem = dbusmenu_menuitem_new();
 
564
  dbusmenu_menuitem_property_set (webcam_menuitem,
 
565
                                  DBUSMENU_MENUITEM_PROP_LABEL,
 
566
                                  _("HP Webcam"));
 
567
  g_signal_connect (G_OBJECT(webcam_menuitem),
 
568
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
569
                    G_CALLBACK(show_system_settings_with_context),
 
570
                    "HP Webcam");
 
571
  dbusmenu_menuitem_child_add_position (self->root_item,
 
572
                                        webcam_menuitem,
 
573
                                        10);
 
574
 //tmp
 
575
  dbusmenu_menuitem_property_set_bool (webcam_menuitem,
 
576
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
577
                                       FALSE);
 
578
                                        
 
579
  DbusmenuMenuitem * separator3 = dbusmenu_menuitem_new();
 
580
  dbusmenu_menuitem_property_set (separator3,
 
581
                                  DBUSMENU_MENUITEM_PROP_TYPE,
 
582
                                  DBUSMENU_CLIENT_TYPES_SEPARATOR);
 
583
  dbusmenu_menuitem_child_add_position (self->root_item, separator3, 11);
 
584
                                        
 
585
  // Session control  
 
586
  gboolean can_lockscreen;
 
587
 
 
588
  /* Make sure we have a valid GConf client, and build one
 
589
     if needed */
 
590
  device_menu_mgr_ensure_gconf_client (self);
 
591
  can_lockscreen = !gconf_client_get_bool ( gconf_client,
 
592
                                            LOCKDOWN_KEY_SCREENSAVER,
 
593
                                            NULL);
 
594
  /* Lock screen item */
 
595
  if (can_lockscreen) {
 
596
    lock_menuitem = dbusmenu_menuitem_new();
 
597
    dbusmenu_menuitem_property_set (lock_menuitem,
 
598
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
599
                                    _("Lock Screen"));
 
600
 
 
601
    gchar * shortcut = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL);
 
602
    if (shortcut != NULL) {
 
603
      g_debug("Lock screen shortcut: %s", shortcut);
 
604
      dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, shortcut);
 
605
      g_free(shortcut);
 
606
    }
 
607
    else {
 
608
      g_debug("Unable to get lock screen shortcut.");
 
609
    }
 
610
 
 
611
    g_signal_connect (G_OBJECT(lock_menuitem),
 
612
                      DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
613
                      G_CALLBACK(lock_screen), NULL);
 
614
    dbusmenu_menuitem_child_append(self->root_item, lock_menuitem);
 
615
  } 
 
616
   
 
617
        logout_mi = dbusmenu_menuitem_new();
 
618
 
 
619
        if (supress_confirmations()) {
 
620
                dbusmenu_menuitem_property_set (logout_mi,
 
621
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
622
                                    _("Log Out"));
 
623
        }
 
624
  else {
 
625
                dbusmenu_menuitem_property_set (logout_mi,
 
626
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
627
                                    _("Log Out\342\200\246"));
 
628
        }
 
629
        dbusmenu_menuitem_property_set_bool (logout_mi,
 
630
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
631
                                       show_logout());
 
632
        dbusmenu_menuitem_child_append(self->root_item, logout_mi);
 
633
        g_signal_connect( G_OBJECT(logout_mi),
 
634
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
635
                    G_CALLBACK(show_dialog), "logout");
 
636
 
 
637
        if (can_suspend && allow_suspend) {
 
638
                suspend_mi = dbusmenu_menuitem_new();
 
639
                dbusmenu_menuitem_property_set (suspend_mi,
 
640
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
641
                                    _("Suspend"));
 
642
                dbusmenu_menuitem_child_append (self->root_item, suspend_mi);
 
643
                g_signal_connect( G_OBJECT(suspend_mi),
 
644
                      DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
645
                      G_CALLBACK(machine_sleep_from_suspend),
 
646
                      self);
 
647
        }
 
648
 
 
649
        if (can_hibernate && allow_hibernate) {
 
650
                hibernate_mi = dbusmenu_menuitem_new();
 
651
                dbusmenu_menuitem_property_set (hibernate_mi,
 
652
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
653
                                    _("Hibernate"));
 
654
                dbusmenu_menuitem_child_append(self->root_item, hibernate_mi);
 
655
                g_signal_connect (G_OBJECT(hibernate_mi),
 
656
                      DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
657
                      G_CALLBACK(machine_sleep_from_hibernate), self);
 
658
        }
 
659
  
 
660
        shutdown_mi = dbusmenu_menuitem_new();
 
661
 
 
662
        if (supress_confirmations()) {
 
663
                dbusmenu_menuitem_property_set (shutdown_mi,
 
664
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
665
                                    _("Shut Down"));
 
666
        }
 
667
  else {
 
668
                dbusmenu_menuitem_property_set (shutdown_mi,
 
669
                                    DBUSMENU_MENUITEM_PROP_LABEL,
 
670
                                    _("Shut Down\342\200\246"));
 
671
        }
 
672
        dbusmenu_menuitem_property_set_bool (shutdown_mi,
 
673
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
674
                                       show_shutdown());
 
675
        dbusmenu_menuitem_child_append (self->root_item, shutdown_mi);
 
676
        g_signal_connect (G_OBJECT(shutdown_mi),
 
677
                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
678
                    G_CALLBACK(show_dialog), "shutdown");
 
679
 
 
680
        RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1);
 
681
        restart_shutdown_logout_mi->logout_mi = logout_mi;
 
682
        restart_shutdown_logout_mi->shutdown_mi = shutdown_mi;
 
683
 
 
684
        update_menu_entries(restart_shutdown_logout_mi);                    
 
685
}
 
686
 
 
687
 
 
688
static void
 
689
device_menu_mgr_rebuild_items (DeviceMenuMgr* self)
 
690
{
 
691
  dbusmenu_menuitem_property_set_bool (hibernate_mi,
 
692
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
693
                                       can_hibernate && allow_hibernate);
 
694
  dbusmenu_menuitem_property_set_bool (suspend_mi,
 
695
                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
 
696
                                       can_suspend && allow_suspend);
 
697
}                                       
 
698
 
 
699
/* When the directory changes we need to figure out how our menu
 
700
   item should look. */
 
701
static void
 
702
restart_dir_changed (gpointer userdata)
 
703
{
 
704
  DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata);
 
705
        gboolean restart_required = g_file_test("/var/run/reboot-required", G_FILE_TEST_EXISTS);
 
706
 
 
707
        if (restart_required) {
 
708
                if (supress_confirmations()) {
 
709
                        dbusmenu_menuitem_property_set (restart_mi,
 
710
                                      RESTART_ITEM_LABEL,
 
711
                                      _("Restart to Complete Update"));
 
712
                } else {
 
713
                        dbusmenu_menuitem_property_set (restart_mi,
 
714
                                      RESTART_ITEM_LABEL,
 
715
                                      _("Restart to Complete Update\342\200\246"));
 
716
                }
 
717
                dbusmenu_menuitem_property_set (restart_mi,
 
718
                                    RESTART_ITEM_ICON,
 
719
                                    "system-restart-panel");
 
720
                if (self->session_dbus_interface != NULL) {
 
721
                        session_dbus_set_name (self->session_dbus_interface, ICON_RESTART);
 
722
                }
 
723
        } else {        
 
724
                if (supress_confirmations()) {
 
725
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
 
726
                } else {
 
727
                        dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
 
728
                }
 
729
                dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON);
 
730
                if (self->session_dbus_interface != NULL) {
 
731
                        session_dbus_set_name(self->session_dbus_interface, ICON_DEFAULT);
 
732
                }
 
733
        }
 
734
        return;
 
735
}
 
736
 
 
737
/* Buids a file watcher for the directory so that when it
 
738
   changes we can check to see if our reboot-required is
 
739
   there. */
 
740
static void
 
741
setup_restart_watch (DeviceMenuMgr* self)
 
742
{
 
743
        GFile * filedir = g_file_new_for_path("/var/run");
 
744
        GFileMonitor * filemon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
 
745
        if (filemon != NULL) {
 
746
                g_signal_connect (G_OBJECT(filemon),
 
747
                      "changed",
 
748
                      G_CALLBACK(restart_dir_changed),
 
749
                      self);
 
750
        }
 
751
        restart_dir_changed(self);
 
752
        return;
 
753
}
 
754
 
 
755
/* Ensures that we have a GConf client and if we build one
 
756
   set up the signal handler. */
 
757
static void
 
758
device_menu_mgr_ensure_gconf_client (DeviceMenuMgr* self)
 
759
{
 
760
        if (!gconf_client) {
 
761
                gconf_client = gconf_client_get_default ();
 
762
 
 
763
                gconf_client_add_dir(gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 
764
                gconf_client_notify_add (gconf_client,
 
765
                             LOCKDOWN_DIR,
 
766
                             lockdown_changed,
 
767
                             self,
 
768
                             NULL,
 
769
                             NULL);
 
770
 
 
771
                gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 
772
                gconf_client_notify_add (gconf_client,
 
773
                             KEYBINDING_DIR,
 
774
                             keybinding_changed,
 
775
                             self,
 
776
                             NULL,
 
777
                             NULL);
 
778
        }
 
779
}
 
780
 
 
781
DbusmenuMenuitem*
 
782
device_mgr_get_root_item (DeviceMenuMgr* self)
 
783
{
 
784
  return self->root_item;
 
785
}
 
786
 
 
787
/*
 
788
 * Clean Entry Point 
 
789
 */
 
790
DeviceMenuMgr* device_menu_mgr_new (SessionDbus* session_dbus)
 
791
{
 
792
  DeviceMenuMgr* device_mgr = g_object_new (DEVICE_TYPE_MENU_MGR, NULL);
 
793
  device_mgr->session_dbus_interface = session_dbus;
 
794
  device_menu_mgr_build_static_items (device_mgr);   
 
795
  device_mgr->apt_watcher = apt_watcher_new (session_dbus,
 
796
                                             software_updates_menuitem);
 
797
  return device_mgr;
 
798
}