55
94
static DbusmenuMenuitem * restart_mi = NULL;
56
95
static DbusmenuMenuitem * shutdown_mi = NULL;
97
static gboolean can_hibernate = TRUE;
98
static gboolean can_suspend = TRUE;
99
static gboolean allow_hibernate = TRUE;
100
static gboolean allow_suspend = TRUE;
102
static GConfClient * gconf_client = NULL;
104
static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
107
lockdown_changed (GConfClient *client,
112
GConfValue *value = gconf_entry_get_value (entry);
113
const gchar *key = gconf_entry_get_key (entry);
115
if (value == NULL || key == NULL) {
119
if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
120
rebuild_items(root_menuitem, dbus_interface);
127
keybinding_changed (GConfClient *client,
132
GConfValue *value = gconf_entry_get_value (entry);
133
const gchar *key = gconf_entry_get_key (entry);
135
if (value == NULL || key == NULL) {
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));
149
/* Ensures that we have a GConf client and if we build one
150
set up the signal handler. */
152
ensure_gconf_client (void)
155
gconf_client = gconf_client_get_default ();
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);
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);
166
/* Check to see if the lockdown key is protecting from
167
locking the screen. If not, lock it. */
169
lock_if_possible (void) {
170
ensure_gconf_client ();
172
if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
173
lock_screen(NULL, 0, NULL);
58
179
/* A return from the command to sleep the system. Make sure
59
180
that we unthrottle the screensaver. */
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. */
306
allowed_cb (DBusGProxy *proxy, gboolean OUT_allowed, GError *error, gpointer userdata)
309
g_warning("Unable to get information on what is allowed from UPower: %s", error->message);
313
gboolean * can_do = (gboolean *)userdata;
315
if (OUT_allowed != *can_do) {
316
*can_do = OUT_allowed;
317
rebuild_items (root_menuitem, dbus_interface);
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
182
326
DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
183
327
g_return_if_fail(bus != NULL);
185
if (dkp_main_proxy == NULL) {
186
dkp_main_proxy = dbus_g_proxy_new_for_name(bus,
329
if (up_main_proxy == NULL) {
330
up_main_proxy = dbus_g_proxy_new_for_name(bus,
191
g_return_if_fail(dkp_main_proxy != NULL);
335
g_return_if_fail(up_main_proxy != NULL);
193
if (dkp_prop_proxy == NULL) {
194
dkp_prop_proxy = dbus_g_proxy_new_for_name(bus,
337
if (up_prop_proxy == NULL) {
338
up_prop_proxy = dbus_g_proxy_new_for_name(bus,
197
341
DBUS_INTERFACE_PROPERTIES);
342
/* Connect to changed signal */
343
dbus_g_proxy_add_signal(up_main_proxy,
347
dbus_g_proxy_connect_signal(up_main_proxy,
349
G_CALLBACK(up_changed_cb),
199
g_return_if_fail(dkp_prop_proxy != NULL);
201
/* Connect to changed signal */
202
dbus_g_proxy_add_signal(dkp_main_proxy,
206
dbus_g_proxy_connect_signal(dkp_main_proxy,
208
G_CALLBACK(dpk_changed_cb),
353
g_return_if_fail(up_prop_proxy != NULL);
212
356
/* Force an original "changed" event */
213
dpk_changed_cb(dkp_main_proxy, NULL);
357
up_changed_cb(up_main_proxy, NULL);
359
/* Check to see if these are getting blocked by PolicyKit */
360
org_freedesktop_UPower_suspend_allowed_async(up_main_proxy,
363
org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy,
242
/* This function creates all of the menuitems that the service
243
provides in the UI. It also connects them to the callbacks. */
245
create_items (DbusmenuMenuitem * root) {
394
/* Checks to see if we should show the guest suession item */
396
check_guest_session (void)
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. */
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! */
412
/* Called when someone clicks on the guest session item. */
414
activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
416
GError * error = NULL;
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))) {
424
g_warning("Unable to activate guest session, falling back to command line activation.");
427
if (!g_spawn_command_line_async(GUEST_SESSION_LAUNCHER " --no-lock", &error)) {
428
g_warning("Unable to start guest session: %s", error->message);
435
/* Checks to see if we can create sessions and get a proxy
436
to the display manager (GDM) */
438
check_new_session (void)
440
if (system_bus == NULL) {
441
system_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
444
if (system_bus == NULL) {
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");
455
if (gdm_proxy == NULL) {
462
/* Starts a new generic session */
464
activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
466
GError * error = NULL;
470
if (!g_spawn_command_line_async("gdmflexiserver --startnew", &error)) {
471
g_warning("Unable to start new session: %s", error->message);
478
/* Activates a session for a particular user. */
480
activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
482
UserData *user = (UserData *)user_data;
483
UsersServiceDbus *service = user->service;
487
users_service_dbus_activate_user_session (service, user);
490
/* Comparison function to look into the UserData struct
491
to compare by using the username value */
493
compare_users_by_username (const gchar *a,
496
UserData *user1 = (UserData *)a;
497
UserData *user2 = (UserData *)b;
499
gint retval = g_strcmp0 (user1->real_name, user2->real_name);
501
/* If they're the same, they're both in conflict. */
503
user1->real_name_conflict = TRUE;
504
user2->real_name_conflict = TRUE;
510
/* Take a desktop file and execute it */
512
desktop_activate_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
514
GAppInfo * appinfo = G_APP_INFO(data);
515
g_return_if_fail(appinfo != NULL);
516
g_app_info_launch(appinfo, NULL, NULL, NULL);
520
/* Look at the GAppInfo structures and sort based on
521
the application names */
523
sort_app_infos (gconstpointer a, gconstpointer b)
525
GAppInfo * appa = G_APP_INFO(a);
526
GAppInfo * appb = G_APP_INFO(b);
528
const gchar * namea = NULL;
529
const gchar * nameb = NULL;
532
namea = g_app_info_get_name(appa);
536
nameb = g_app_info_get_name(appb);
539
return g_strcmp0(namea, nameb);
542
/* Builds up the menu for us */
544
rebuild_items (DbusmenuMenuitem *root,
545
UsersServiceDbus *service)
547
DbusmenuMenuitem *mi = NULL;
548
DbusmenuMenuitem * guest_mi = NULL;
551
gboolean can_activate;
552
gboolean can_lockscreen;
555
/* Make sure we have a valid GConf client, and build one
557
ensure_gconf_client ();
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);
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);
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"));
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);
580
g_debug("Unable to get lock screen shortcut.");
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);
587
/* Set to NULL just incase we don't end up building one */
588
users_service_dbus_set_guest_item(service, NULL);
590
/* Build all of the user switching items */
591
if (can_activate == TRUE)
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);
599
if (check_guest_session ())
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);
610
if (check_new_session ())
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);
620
GList * users = NULL;
621
users = users_service_dbus_get_user_list (service);
622
guint user_count = g_list_length(users);
624
if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
625
users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
628
for (u = users; u != NULL; u = g_list_next (u)) {
630
user->service = service;
632
if (user->uid == getuid()) {
633
/* Hide me from the list */
637
if (g_strcmp0(user->user_name, "guest") == 0) {
638
/* Check to see if the guest has sessions and so therefore should
640
if (user->sessions != NULL) {
641
dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, TRUE);
643
/* If we're showing user accounts, keep going through the list */
644
if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
647
/* If not, we can stop here */
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);
659
dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
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://"));
665
dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
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);
676
/* If there were a bunch of items before us, we need a
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);
684
/* Start going through the session based items. */
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"));
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"));
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");
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");
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");
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"));
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"));
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");
290
736
update_menu_entries(restart_shutdown_logout_mi);
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;
744
/* Find all the desktop files we want to use */
746
const gchar *extra_launcher_file;
748
extra_launcher_file = g_dir_read_name (extra_launchers_dir);
749
if (extra_launcher_file == NULL)
751
if (!g_str_has_suffix (extra_launcher_file, ".desktop"))
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));
758
launchers = g_list_prepend(launchers, appinfo);
760
g_dir_close(extra_launchers_dir);
762
/* Sort the desktop files based on their names */
763
launchers = g_list_sort(launchers, sort_app_infos);
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);
771
/* Make sure we have a separator */
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);
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);
786
/* Put into the menu */
787
dbusmenu_menuitem_child_append(root, desktop_mi);
790
g_list_free(launchers);
796
/* Signal called when a user is added. It updates the count and
799
user_change (UsersServiceDbus *service,
803
DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data;
804
rebuild_items (root, service);
808
/* When the service interface starts to shutdown, we
811
service_shutdown (IndicatorService * service, gpointer user_data)
813
if (mainloop != NULL) {
814
g_debug("Service shutdown");
815
g_main_loop_quit(mainloop);
820
/* When the directory changes we need to figure out how our menu
823
restart_dir_changed (void)
825
gboolean restart_required = g_file_test("/var/run/reboot-required", G_FILE_TEST_EXISTS);
827
if (restart_required) {
828
if (supress_confirmations()) {
829
dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update"));
831
dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update\342\200\246"));
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);
838
if (supress_confirmations()) {
839
dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
841
dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
843
dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON);
844
if (session_dbus != NULL) {
845
session_dbus_set_name(session_dbus, ICON_DEFAULT);
852
/* Buids a file watcher for the directory so that when it
853
changes we can check to see if our reboot-required is
856
setup_restart_watch (void)
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);
863
restart_dir_changed();