From 63b800e6036bc9d5096d8f7b7db42a814b8a2bed Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 17 Jun 2012 14:03:25 -0500 Subject: a step in merging the two menus: consolidate & clean up the code in session-menu-mgr --- src/Makefile.am | 4 +- src/gtk-logout-helper.c | 1 + src/lock-helper.c | 184 ------- src/lock-helper.h | 31 -- src/session-menu-mgr.c | 1259 ++++++++++++++++++++++++++--------------------- src/session-menu-mgr.h | 4 +- src/settings-helper.c | 133 +---- src/settings-helper.h | 24 - 8 files changed, 716 insertions(+), 924 deletions(-) delete mode 100644 src/lock-helper.c delete mode 100644 src/lock-helper.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 9391d86..24f2ee8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,8 +100,8 @@ dbus_upower_sources = \ $(dbus_upower_sources): upower.xml gdbus-codegen \ --interface-prefix org.freedesktop \ - --c-namespace IndicatorSession \ --generate-c-code dbus-upower \ + --c-namespace DBus \ $^ gen-%.xml.c: %.xml @@ -126,8 +126,6 @@ indicator_session_service_SOURCES = \ $(dbus_display_manager_sources) \ $(dbus_upower_sources) \ $(dbus_user_sources) \ - lock-helper.c \ - lock-helper.h \ session-service.c \ session-dbus.c \ session-dbus.h \ diff --git a/src/gtk-logout-helper.c b/src/gtk-logout-helper.c index 4f23ba2..360dd0f 100644 --- a/src/gtk-logout-helper.c +++ b/src/gtk-logout-helper.c @@ -24,6 +24,7 @@ with this program. If not, see . #include #include #include +#include /* textdomain(), bindtextdomain() */ #include #include #include "dialog.h" diff --git a/src/lock-helper.c b/src/lock-helper.c deleted file mode 100644 index 11bcbd1..0000000 --- a/src/lock-helper.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -A small helper for locking the screen. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#include -#include -#include "lock-helper.h" - -#define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver" -#define SCREENSAVER_LOCK_ENABLED_KEY "lock-enabled" - -static GDBusProxy * gss_proxy = NULL; - -static GMainLoop * gss_mainloop = NULL; - -static gboolean is_guest = FALSE; - -static GSettings * settings = NULL; - -void build_gss_proxy (void); - -/* This is our logic on whether the screen should be locked - or not. It effects everything else. */ -gboolean -will_lock_screen (void) -{ - if (is_guest) { - return FALSE; - } - - if (settings == NULL) { - settings = g_settings_new (SCREENSAVER_SCHEMA); - } - - return g_settings_get_boolean (settings, SCREENSAVER_LOCK_ENABLED_KEY); -} - -/* When the screensave goes active, - if we've got a mainloop running we should quit it. */ -static void -on_gss_signal (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - g_debug ("%s sender_name: %s", G_STRLOC, sender_name); - g_debug ("%s signal_name: %s", G_STRLOC, signal_name); - - if (!g_strcmp0 (signal_name, "ActiveChanged")) - { - gboolean active = FALSE; - g_variant_get_child (parameters, 0, "b", &active); - g_debug ("%s active: %i", G_STRLOC, active); - - if (active && gss_mainloop != NULL) - { - g_main_loop_quit(gss_mainloop); - } - } -} - -static gboolean -get_greeter_mode (void) -{ - const gchar *var; - var = g_getenv("INDICATOR_GREETER_MODE"); - return (g_strcmp0(var, "1") == 0); -} - -/* Build the gss proxy and set up its signals */ -void -build_gss_proxy (void) -{ - if (gss_proxy == NULL) { - if (get_greeter_mode ()) - return; /* Don't start/lock the screensaver from the login screen */ - - - GError * error = NULL; - gss_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.ScreenSaver", - "/", - "org.gnome.ScreenSaver", - NULL, - &error); - if (error != NULL) { - g_message ("Unable to get ScreenSaver proxy: %s", error->message); - g_error_free (error); - } - - g_return_if_fail (gss_proxy != NULL); - g_signal_connect (gss_proxy, "g-signal", G_CALLBACK(on_gss_signal), NULL); - } - - return; -} - -/* This is a timeout, we only want to wait for the screen to - lock for a little bit, but not forever. */ -static gboolean -activate_timeout (gpointer data) -{ - /* Clear the ID for the timeout */ - guint * address = (guint *)data; - *address = 0; - - /* Quit the mainloop */ - if (gss_mainloop != NULL) { - g_main_loop_quit(gss_mainloop); - } - - return FALSE; -} - -/* A fun little function to actually lock the screen. - If that's what you want, let's do it! */ -void -lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data) -{ - g_debug("Lock Screen"); - - build_gss_proxy(); - g_return_if_fail(gss_proxy != NULL); - - GError * error = NULL; - GVariant * ret = g_dbus_proxy_call_sync (gss_proxy, - "Lock", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - g_variant_unref (ret); - if (error != NULL) { - g_warning ("Unable to lock: %s", error->message); - g_error_free (error); - } - if (gss_mainloop == NULL) { - gss_mainloop = g_main_loop_new(NULL, FALSE); - } - - guint timer = g_timeout_add_seconds(1, activate_timeout, &timer); - - g_main_loop_run(gss_mainloop); - - if (timer != 0) { - g_source_remove(timer); - } - - return; -} - -/* Do what it takes to make the lock screen function work - and be happy. */ -gboolean -lock_screen_setup (gpointer data) -{ - if (!g_strcmp0(g_get_user_name(), "guest")) { - is_guest = TRUE; - } - - return FALSE; -} - diff --git a/src/lock-helper.h b/src/lock-helper.h deleted file mode 100644 index e2d5106..0000000 --- a/src/lock-helper.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -A small helper for locking the screen. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef LOCK_HELPER_H__ -#define LOCK_HELPER_H__ - -#include - -gboolean will_lock_screen (void); -void lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data); -gboolean lock_screen_setup (gpointer data); - -#endif /* LOCK_HELPER_H__ */ diff --git a/src/session-menu-mgr.c b/src/session-menu-mgr.c index 0fdaeb5..c6de0b1 100644 --- a/src/session-menu-mgr.c +++ b/src/session-menu-mgr.c @@ -3,6 +3,7 @@ Copyright 2011 Canonical Ltd. Authors: Conor Curran + Charles Kerr This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published @@ -19,126 +20,182 @@ with this program. If not, see . #include +#include +#include + #include -#include +#include #include #include #include "dbus-shared-names.h" #include "dbus-upower.h" -#include "lock-helper.h" #include "session-menu-mgr.h" -#include "settings-helper.h" #include "users-service-dbus.h" -#define UP_ADDRESS "org.freedesktop.UPower" -#define UP_OBJECT "/org/freedesktop/UPower" -#define UP_INTERFACE "org.freedesktop.UPower" +#define UPOWER_ADDRESS "org.freedesktop.UPower" +#define UPOWER_PATH "/org/freedesktop/UPower" + +#define CMD_HELP "yelp" +#define CMD_INFO "gnome-control-center info" +#define CMD_SYSTEM_SETTINGS "gnome-control-center" +#ifdef HAVE_GTKLOGOUTHELPER + #define CMD_LOGOUT LIBEXECDIR"/gtk-logout-helper --logout" + #define CMD_SHUTDOWN LIBEXECDIR"/gtk-logout-helper --shutdown" + #define CMD_RESTART LIBEXECDIR"/gtk-logout-helper --restart" +#else + #define CMD_LOGOUT "gnome-session-quit --logout" + #define CMD_SHUTDOWN "gnome-session-quit --power-off" + #define CMD_RESTART CMD_SHUTDOWN /* hmm, no gnome-session-quit --restart? */ +#endif -#define EXTRA_LAUNCHER_DIR "/usr/share/indicators/session/applications" +/** + * Which switch menuitem to show -- based on lockdown settings, + * greeter mode, number of users in the system, and so on. + * See get_switcher_mode() + */ +typedef enum +{ + SWITCHER_MODE_SCREENSAVER, + SWITCHER_MODE_LOCK, + SWITCHER_MODE_SWITCH, + SWITCHER_MODE_SWITCH_OR_LOCK +} +SwitcherMode; + +typedef struct +{ + SessionMenuMgr * mgr; + AccountsUser * user; +} +ActivateUserSessionData; struct _SessionMenuMgr { GObject parent_instance; + DbusmenuMenuitem * parent_mi; - SessionDbus* session_dbus_interface; + DbusmenuMenuitem * lock_mi; + DbusmenuMenuitem * lock_switch_mi; + DbusmenuMenuitem * guest_mi; + DbusmenuMenuitem * logout_mi; + DbusmenuMenuitem * suspend_mi; + DbusmenuMenuitem * hibernate_mi; + DbusmenuMenuitem * restart_mi; + DbusmenuMenuitem * shutdown_mi; - GSettings *lockdown_settings; - GSettings * keybinding_settings; + GSList * user_menuitems; + gint user_menuitem_index; - DbusmenuMenuitem * hibernate_mi; - DbusmenuMenuitem * suspend_mi; - DbusmenuMenuitem * lock_mi; + GSettings * lockdown_settings; + GSettings * indicator_settings; + GSettings * keybinding_settings; gboolean can_hibernate; gboolean can_suspend; gboolean allow_hibernate; gboolean allow_suspend; + gboolean greeter_mode; - IndicatorSessionUPower * upower_proxy; GCancellable * cancellable; - - UsersServiceDbus* users_dbus_interface; - DbusmenuMenuitem * guest_mi; - gboolean greeter_mode; + DBusUPower * upower_proxy; + SessionDbus * session_dbus; + UsersServiceDbus * users_dbus_facade; }; -static void setup_up (SessionMenuMgr* self); -static void session_menu_mgr_rebuild_items (SessionMenuMgr *self); -static void screensaver_keybinding_changed (GSettings*, const gchar*, gpointer); - -static void activate_new_session (DbusmenuMenuitem * mi, - guint timestamp, - gpointer user_data); -static void activate_user_session (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static void activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static gint compare_users_by_username (gconstpointer a, - gconstpointer b); -static void activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static void menu_mgr_rebuild_users (SessionMenuMgr *self); -static void on_user_list_changed (UsersServiceDbus *service, - SessionMenuMgr * umm); - -static void on_guest_logged_in_changed (UsersServiceDbus * users_dbus, - SessionMenuMgr * self); - -static void on_user_logged_in_changed (UsersServiceDbus * users_dbus, - AccountsUser * user, - SessionMenuMgr * self); -static gboolean is_this_guest_session (void); -static void activate_guest_session (DbusmenuMenuitem * mi, - guint timestamp, - gpointer user_data); - +static SwitcherMode get_switcher_mode (SessionMenuMgr *); +static void init_upower_proxy (SessionMenuMgr *); +static void update_screensaver_shortcut (SessionMenuMgr *); +static void update_user_menuitems (SessionMenuMgr *); +static void update_session_menuitems (SessionMenuMgr *); +static void update_confirmation_labels (SessionMenuMgr *); -G_DEFINE_TYPE (SessionMenuMgr, session_menu_mgr, G_TYPE_OBJECT); +static void action_func_lock (SessionMenuMgr *); +static void action_func_suspend (SessionMenuMgr *); +static void action_func_hibernate (SessionMenuMgr *); +static void action_func_switch_to_lockscreen (SessionMenuMgr *); +static void action_func_switch_to_greeter (SessionMenuMgr *); +static void action_func_switch_to_guest (SessionMenuMgr *); +static void action_func_switch_to_user (ActivateUserSessionData *); +static void action_func_spawn_async (const char * fmt, ...); -static void -session_menu_mgr_init (SessionMenuMgr *self) -{ - self->can_hibernate = TRUE; - self->can_suspend = TRUE; - self->allow_hibernate = TRUE; - self->allow_suspend = TRUE; +static gboolean is_this_guest_session (void); +static gboolean is_this_live_session (void); - self->lockdown_settings = g_settings_new (LOCKDOWN_SCHEMA); - g_signal_connect_swapped (self->lockdown_settings, "changed::" LOCKDOWN_KEY_USER, G_CALLBACK(session_menu_mgr_rebuild_items), self); - g_signal_connect_swapped (self->lockdown_settings, "changed::" LOCKDOWN_KEY_SCREENSAVER, G_CALLBACK(session_menu_mgr_rebuild_items), self); +static void on_guest_logged_in_changed (UsersServiceDbus *, + SessionMenuMgr *); - self->keybinding_settings = g_settings_new (KEYBINDING_SCHEMA); - g_signal_connect (self->keybinding_settings, "changed::" KEY_LOCK_SCREEN, G_CALLBACK(screensaver_keybinding_changed), self); +static void on_user_logged_in_changed (UsersServiceDbus *, + AccountsUser *, + SessionMenuMgr *); - setup_up(self); +/** +*** GObject init / dispose / finalize +**/ - /* users */ - self->users_dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); - g_signal_connect (self->users_dbus_interface, "user-list-changed", - G_CALLBACK (on_user_list_changed), self); - g_signal_connect (self->users_dbus_interface, "user-logged-in-changed", - G_CALLBACK(on_user_logged_in_changed), self); - g_signal_connect (self->users_dbus_interface, "guest-logged-in-changed", - G_CALLBACK(on_guest_logged_in_changed), self); +G_DEFINE_TYPE (SessionMenuMgr, session_menu_mgr, G_TYPE_OBJECT); - g_idle_add(lock_screen_setup, NULL); +static void +session_menu_mgr_init (SessionMenuMgr *mgr) +{ + mgr->can_hibernate = TRUE; + mgr->can_suspend = TRUE; + mgr->allow_hibernate = TRUE; + mgr->allow_suspend = TRUE; + + /* Lockdown settings */ + GSettings * s = g_settings_new ("org.gnome.desktop.lockdown"); + g_signal_connect_swapped (s, "changed", + G_CALLBACK(update_session_menuitems), mgr); + g_signal_connect_swapped (s, "changed::disable-lock-screen", + G_CALLBACK(update_user_menuitems), mgr); + g_signal_connect_swapped (s, "changed::disable-user-switching", + G_CALLBACK(update_user_menuitems), mgr); + mgr->lockdown_settings = s; + + /* Indicator settings */ + s = g_settings_new ("com.canonical.indicator.session"); + g_signal_connect_swapped (s, "changed::suppress-logout-restart-shutdown", + G_CALLBACK(update_confirmation_labels), mgr); + g_signal_connect (s, "changed", G_CALLBACK(update_session_menuitems), mgr); + mgr->indicator_settings = s; + + /* Keybinding settings */ + s = g_settings_new ("org.gnome.settings-daemon.plugins.media-keys"); + g_signal_connect_swapped (s, "changed::screensaver", + G_CALLBACK(update_screensaver_shortcut), mgr); + mgr->keybinding_settings = s; + + /* listen for users who appear or log in or log out */ + mgr->users_dbus_facade = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); + g_signal_connect_swapped (mgr->users_dbus_facade, "user-list-changed", + G_CALLBACK (update_user_menuitems), mgr); + g_signal_connect (mgr->users_dbus_facade, "user-logged-in-changed", + G_CALLBACK(on_user_logged_in_changed), mgr); + g_signal_connect (mgr->users_dbus_facade, "guest-logged-in-changed", + G_CALLBACK(on_guest_logged_in_changed), mgr); + + init_upower_proxy (mgr); } static void session_menu_mgr_dispose (GObject *object) { - SessionMenuMgr * self = SESSION_MENU_MGR (object); - g_clear_object (&self->lockdown_settings); - g_clear_object (&self->keybinding_settings); - g_clear_object (&self->upower_proxy); - g_clear_object (&self->cancellable); - g_clear_object (&self->users_dbus_interface); + SessionMenuMgr * mgr = SESSION_MENU_MGR (object); + + if (mgr->cancellable != NULL) + { + g_cancellable_cancel (mgr->cancellable); + g_clear_object (&mgr->cancellable); + } + + g_clear_object (&mgr->indicator_settings); + g_clear_object (&mgr->lockdown_settings); + g_clear_object (&mgr->keybinding_settings); + g_clear_object (&mgr->upower_proxy); + g_clear_object (&mgr->users_dbus_facade); G_OBJECT_CLASS (session_menu_mgr_parent_class)->finalize (object); } @@ -158,117 +215,68 @@ session_menu_mgr_class_init (SessionMenuMgrClass *klass) } /*** -**** +**** Menuitem Helpers ***/ -static void -update_screensaver_shortcut (DbusmenuMenuitem * menuitem, GSettings * settings) +static inline void +mi_set_label (DbusmenuMenuitem * mi, const char * str) { - if (menuitem != NULL) - { - gchar * val = g_settings_get_string (settings, KEY_LOCK_SCREEN); - g_debug ("Keybinding changed to: %s", val); - dbusmenu_menuitem_property_set_shortcut_string (menuitem, val); - g_free (val); - } + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, str); } -static void -screensaver_keybinding_changed (GSettings * settings, - const gchar * key G_GNUC_UNUSED, - gpointer userdata) +static inline void +mi_set_type (DbusmenuMenuitem * mi, const char * str) { - update_screensaver_shortcut (SESSION_MENU_MGR(userdata)->lock_mi, settings); + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, str); } - -static void -machine_sleep_from_suspend (DbusmenuMenuitem * mi G_GNUC_UNUSED, - guint timestamp G_GNUC_UNUSED, - gpointer userdata) +static inline void +mi_set_visible (DbusmenuMenuitem * mi, gboolean b) { - GError * error = NULL; - SessionMenuMgr * mgr = SESSION_MENU_MGR (userdata); - - indicator_session_upower_call_suspend_sync (mgr->upower_proxy, mgr->cancellable, &error); - if (error != NULL) - { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_clear_error (&error); - } + dbusmenu_menuitem_property_set_bool (mi, DBUSMENU_MENUITEM_PROP_VISIBLE, b); } -static void -machine_sleep_from_hibernate (DbusmenuMenuitem * mi G_GNUC_UNUSED, - guint timestamp G_GNUC_UNUSED, - gpointer userdata) +static inline void +mi_set_logged_in (DbusmenuMenuitem * mi, gboolean b) { - GError * error = NULL; - SessionMenuMgr * mgr = SESSION_MENU_MGR (userdata); - - indicator_session_upower_call_hibernate_sync (mgr->upower_proxy, mgr->cancellable, &error); - if (error != NULL) - { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_clear_error (&error); - } + dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, b); } -/*** -**** -***/ - -/* When allow-suspend changes, rebuild the menus */ -static void -allowed_suspend_cb (GObject * source, GAsyncResult * res, gpointer userdata) +static DbusmenuMenuitem* +mi_new_separator (void) { - gboolean allowed; - GError * error = NULL; - SessionMenuMgr * mgr = SESSION_MENU_MGR (userdata); - - indicator_session_upower_call_suspend_allowed_finish (mgr->upower_proxy, &allowed, res, &error); - if (error != NULL) - { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } - else if (mgr->allow_suspend != allowed) - { - mgr->allow_suspend = allowed; - session_menu_mgr_rebuild_items (mgr); - } + DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); + mi_set_type (mi, DBUSMENU_CLIENT_TYPES_SEPARATOR); + return mi; } -/* When allow-hibernate changes, rebuild the menus */ -static void -allowed_hibernate_cb (GObject * source, GAsyncResult * res, gpointer userdata) +static DbusmenuMenuitem* +mi_new (const char * label) { - gboolean allowed; - GError * error = NULL; - SessionMenuMgr * mgr = SESSION_MENU_MGR (userdata); - - indicator_session_upower_call_hibernate_allowed_finish (mgr->upower_proxy, &allowed, res, &error); - if (error != NULL) - { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } - else if (mgr->allow_hibernate != allowed) - { - mgr->allow_hibernate = allowed; - session_menu_mgr_rebuild_items (mgr); - } + DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); + mi_set_label (mi, label); + return mi; } +/*** +**** UPower Proxy: +**** +**** 1. While bootstrapping, we invoke the AllowSuspend and AllowHibernate +**** methods to find out whether or not those functions are allowed. +**** 2. While bootstrapping, we get the CanSuspend and CanHibernate properties +**** and also listen for property changes. +**** 3. These four values are used to set suspend and hibernate's visibility +**** +***/ static void -on_upower_properties_changed (IndicatorSessionUPower * upower_proxy, SessionMenuMgr * mgr) +on_upower_properties_changed (SessionMenuMgr * mgr) { gboolean b; gboolean refresh = FALSE; /* suspend */ - b = indicator_session_upower_get_can_suspend (upower_proxy); + b = dbus_upower_get_can_suspend (mgr->upower_proxy); if (mgr->can_suspend != b) { mgr->can_suspend = b; @@ -276,7 +284,7 @@ on_upower_properties_changed (IndicatorSessionUPower * upower_proxy, SessionMenu } /* hibernate */ - b = indicator_session_upower_get_can_hibernate (upower_proxy); + b = dbus_upower_get_can_hibernate (mgr->upower_proxy); if (mgr->can_hibernate != b) { mgr->can_hibernate = b; @@ -285,230 +293,185 @@ on_upower_properties_changed (IndicatorSessionUPower * upower_proxy, SessionMenu if (refresh) { - session_menu_mgr_rebuild_items (mgr); + update_session_menuitems (mgr); } } -/* This function goes through and sets up what we need for DKp checking. - We're even setting up the calls for the props we need */ static void -setup_up (SessionMenuMgr* self) +init_upower_proxy (SessionMenuMgr * mgr) { - self->cancellable = g_cancellable_new (); + mgr->cancellable = g_cancellable_new (); GError * error = NULL; - self->upower_proxy = indicator_session_upower_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - 0, - UP_ADDRESS, - UP_OBJECT, - NULL, - &error); + mgr->upower_proxy = dbus_upower_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + 0, + UPOWER_ADDRESS, + UPOWER_PATH, + NULL, + &error); if (error != NULL) { - g_warning ("Error creating cups notify handler: %s", error->message); - g_error_free (error); + g_warning ("Error creating upower proxy: %s", error->message); + g_clear_error (&error); } else { - /* Check to see if these are getting blocked by PolicyKit */ - indicator_session_upower_call_suspend_allowed (self->upower_proxy, self->cancellable, allowed_suspend_cb, self); - indicator_session_upower_call_hibernate_allowed (self->upower_proxy, self->cancellable, allowed_hibernate_cb, self); - - g_signal_connect (self->upower_proxy, "changed", G_CALLBACK(on_upower_properties_changed), self); - - /* trigger an initial "changed" event */ - on_upower_properties_changed (self->upower_proxy, self); - } - - -} - -static void -spawn_command_line_async (const char * fmt, ...) -{ - va_list marker; - va_start (marker, fmt); - gchar * cmd = g_strdup_vprintf (fmt, marker); - va_end (marker); - - GError * error = NULL; - if (!g_spawn_command_line_async (cmd, &error)) - { - g_warning ("Unable to show \"%s\": %s", cmd, error->message); + dbus_upower_call_suspend_allowed_sync (mgr->upower_proxy, + &mgr->allow_suspend, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + + dbus_upower_call_hibernate_allowed_sync (mgr->upower_proxy, + &mgr->allow_hibernate, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + + on_upower_properties_changed (mgr); + g_signal_connect_swapped (mgr->upower_proxy, "changed", + G_CALLBACK(on_upower_properties_changed), mgr); } - - g_clear_error (&error); - g_free (cmd); } +/*** +**** Admin Menuitems +***/ -/* This is the function to show a dialog on actions that - can destroy data. Currently it just calls the GTK version - but it seems that in the future it should figure out - what's going on and something better. */ -static void -show_dialog (DbusmenuMenuitem * mi, guint timestamp, gchar * type) -{ -#ifdef HAVE_GTKLOGOUTHELPER - gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL); -#else - gchar * helper = g_build_filename("gnome-session-quit", NULL); -#endif /* HAVE_GTKLOGOUTHELPER */ - spawn_command_line_async ("%s --%s", helper, type); - g_free (helper); -} +#define DEBUG_SHOW_ALL 1 static void -session_menu_mgr_build_static_items (SessionMenuMgr* self, gboolean greeter_mode) +build_admin_menuitems (SessionMenuMgr * mgr) { - const char * name; DbusmenuMenuitem * mi; - DbusmenuMenuitem * logout_mi = NULL; - DbusmenuMenuitem * shutdown_mi = NULL; - - /*** - **** Admin items - ***/ + const gboolean show_settings = DEBUG_SHOW_ALL || !mgr->greeter_mode; - name = _("About This Computer"); - mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append (self->parent_mi, mi); + mi = mi_new (_("About This Computer")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_INFO); + mi = mi_new (_("Ubuntu Help")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(spawn_command_line_async), "gnome-control-center info"); + G_CALLBACK(action_func_spawn_async), CMD_HELP); + + mi = mi_new_separator (); + mi_set_visible (mi, show_settings); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); - name = _("Ubuntu Help"); - mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append (self->parent_mi, mi); + mi = mi_new (_("System Settings\342\200\246")); + mi_set_visible (mi, show_settings); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(spawn_command_line_async), "yelp"); - - if (!greeter_mode) - { - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - - name = _("System Settings…"); - mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(spawn_command_line_async), "gnome-control-center"); - } + G_CALLBACK(action_func_spawn_async), + CMD_SYSTEM_SETTINGS); - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append (self->parent_mi, mi); + mi = mi_new_separator (); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); +} - /*** - **** Account-switching items - ***/ +/*** +**** Session Menuitems +***/ - /* TODO: FIXME */ +static void +update_session_menuitems (SessionMenuMgr * mgr) +{ + gboolean v; + GSettings * s = mgr->indicator_settings; - const gboolean can_lockscreen = !g_settings_get_boolean (self->lockdown_settings, LOCKDOWN_KEY_SCREENSAVER); - if (can_lockscreen) - { - name = _("Lock Screen"); - self->lock_mi = mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - update_screensaver_shortcut (mi, self->keybinding_settings); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - g_signal_connect (G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(lock_screen), NULL); - } + v = !mgr->greeter_mode + && !is_this_live_session() + && !g_settings_get_boolean (mgr->lockdown_settings, "disable-logout") + && !g_settings_get_boolean (s, "suppress-logout-menuitem"); + mi_set_visible (mgr->logout_mi, v); - /*** - **** Session Items - ***/ + v = mgr->can_suspend + && mgr->allow_suspend; + mi_set_visible (mgr->suspend_mi, v); - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append (self->parent_mi, mi); + v = mgr->can_hibernate + && mgr->allow_hibernate; + mi_set_visible (mgr->hibernate_mi, v); - if (!greeter_mode) - { - name = supress_confirmations() ? _("Log Out") : _("Log Out\342\200\246"); - logout_mi = mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_property_set_bool (mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_logout()); - dbusmenu_menuitem_child_append(self->parent_mi, mi); - g_signal_connect (G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_dialog), "logout"); - } + v = !g_settings_get_boolean (s, "suppress-restart-menuitem"); + mi_set_visible (mgr->restart_mi, v); - if (self->can_suspend && self->allow_suspend) - { - name = _("Suspend"); - self->suspend_mi = mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - g_signal_connect (G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep_from_suspend), self); - } + v = !g_settings_get_boolean (s, "suppress-shutdown-menuitem"); + mi_set_visible (mgr->shutdown_mi, v); +} - if (self->can_hibernate && self->allow_hibernate) - { - name = _("Hibernate"); - self->hibernate_mi = mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append(self->parent_mi, mi); - g_signal_connect (G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep_from_hibernate), self); - } +/* if confirmation is enabled, + add ellipsis to the labels of items whose actions need confirmation */ +static void +update_confirmation_labels (SessionMenuMgr * mgr) +{ + const gboolean confirm_needed = !g_settings_get_boolean ( + mgr->indicator_settings, + "suppress-logout-restart-shutdown"); - name = _("Restart"); - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - /* FIXME: not implemented */ - - name = supress_confirmations() ? _("Shut Down") : _("Shut Down\342\200\246"); - shutdown_mi = mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - dbusmenu_menuitem_property_set_bool (mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_shutdown()); - dbusmenu_menuitem_child_append (self->parent_mi, mi); - g_signal_connect (G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, -#ifdef HAVE_GTKLOGOUTHELPER - G_CALLBACK(show_dialog), "shutdown"); -#else - G_CALLBACK(show_dialog), "power-off"); -#endif /* HAVE_GTKLOGOUTHELPER */ + mi_set_label (mgr->logout_mi, confirm_needed ? _("Log Out\342\200\246") + : _("Log Out")); - RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1); - restart_shutdown_logout_mi->logout_mi = logout_mi; - restart_shutdown_logout_mi->shutdown_mi = shutdown_mi; + mi_set_label (mgr->shutdown_mi, confirm_needed ? _("Switch Off\342\200\246") + : _("Switch Off")); - update_menu_entries(restart_shutdown_logout_mi); + dbusmenu_menuitem_property_set (mgr->restart_mi, RESTART_ITEM_LABEL, + confirm_needed ? _("Restart\342\200\246") + : _("Restart")); } static void -session_menu_mgr_rebuild_items (SessionMenuMgr* self) +build_session_menuitems (SessionMenuMgr* mgr) { - dbusmenu_menuitem_property_set_bool (self->hibernate_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - self->can_hibernate && self->allow_hibernate); - dbusmenu_menuitem_property_set_bool (self->suspend_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - self->can_suspend && self->allow_suspend); -} + DbusmenuMenuitem * mi; -/*** -**** User Menu -***/ + mi = mi_new_separator (); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); -struct ActivateUserSessionData -{ - SessionMenuMgr * menu_mgr; - AccountsUser * user; -}; + mi = mgr->logout_mi = mi_new (_("Log Out\342\200\246")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_LOGOUT); -/*** -**** -***/ + mi = mgr->suspend_mi = mi_new ("Suspend"); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_suspend), mgr); + + mi = mgr->hibernate_mi = mi_new (_("Hibernate")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_hibernate), mgr); + + mi = mgr->restart_mi = mi_new (_("Restart\342\200\246")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_RESTART); + + mi = mgr->shutdown_mi = mi_new (_("Switch Off\342\200\246")); + dbusmenu_menuitem_child_append (mgr->parent_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_SHUTDOWN); + + update_confirmation_labels (mgr); +} + +/**** +***** User Menuitems +****/ + +/* Local Extensions to AccountsUser */ static GQuark get_menuitem_quark (void) @@ -532,12 +495,14 @@ user_get_menuitem (AccountsUser * user) static void user_set_menuitem (AccountsUser * user, DbusmenuMenuitem * mi) { - g_message ("%s %s() associating user %s with mi %p", G_STRLOC, G_STRFUNC, accounts_user_get_user_name(user), mi); - g_object_set_qdata_full (G_OBJECT(user), get_menuitem_quark(), g_object_ref(G_OBJECT(mi)), g_object_unref); + g_message ("%s %s() associating user %s with mi %p", + G_STRLOC, G_STRFUNC, accounts_user_get_user_name(user), mi); + g_object_set_qdata_full (G_OBJECT(user), get_menuitem_quark(), + g_object_ref(G_OBJECT(mi)), g_object_unref); } static GQuark -get_name_collision_quark (void) +get_collision_quark (void) { static GQuark q = 0; @@ -550,15 +515,15 @@ get_name_collision_quark (void) } static gboolean -get_user_name_collision (AccountsUser * user) +user_has_name_collision (AccountsUser * u) { - return g_object_get_qdata (G_OBJECT(user), get_name_collision_quark()) != NULL; + return g_object_get_qdata (G_OBJECT(u), get_collision_quark()) != NULL; } static void -set_user_name_collision (AccountsUser * user, gboolean b) +user_set_name_collision (AccountsUser * u, gboolean b) { - g_object_set_qdata (G_OBJECT(user), get_name_collision_quark(), GINT_TO_POINTER(b)); + g_object_set_qdata (G_OBJECT(u), get_collision_quark(), GINT_TO_POINTER(b)); } /*** @@ -566,7 +531,42 @@ set_user_name_collision (AccountsUser * user, gboolean b) ***/ static void -update_menuitem_icon (DbusmenuMenuitem * mi, AccountsUser * user) +on_guest_logged_in_changed (UsersServiceDbus * usd, + SessionMenuMgr * mgr) +{ + mi_set_logged_in (mgr->guest_mi, + users_service_dbus_is_guest_logged_in (usd)); +} + +/* When a user's login state changes, + update the corresponding menuitem's LOGGED_IN property */ +static void +on_user_logged_in_changed (UsersServiceDbus * usd, + AccountsUser * user, + SessionMenuMgr * mgr) +{ + DbusmenuMenuitem * mi = user_get_menuitem (user); + + if (mi != NULL) + { + mi_set_logged_in (mi, users_service_dbus_is_user_logged_in (usd, user)); + } +} + +static void +update_screensaver_shortcut (SessionMenuMgr * mgr) +{ + gchar * s = g_settings_get_string (mgr->keybinding_settings, "screensaver"); + g_debug ("Keybinding changed to: %s", s); + dbusmenu_menuitem_property_set_shortcut_string (mgr->lock_mi, s); + dbusmenu_menuitem_property_set_shortcut_string (mgr->lock_switch_mi, s); + g_free (s); +} + +static void +on_user_icon_file_changed (AccountsUser * user, + GParamSpec * pspec G_GNUC_UNUSED, + DbusmenuMenuitem * mi) { const gchar * str = accounts_user_get_icon_file (user); @@ -578,299 +578,439 @@ update_menuitem_icon (DbusmenuMenuitem * mi, AccountsUser * user) dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_ICON, str); } +typedef struct +{ + AccountsUser * user; + gulong handler_id; +} +UserChangeListenerData; + +/* when the menuitem is destroyed, + it should stop listening for changes to the UserAccount properties :) */ static void -on_user_icon_file_changed (AccountsUser * user, GParamSpec * pspec, DbusmenuMenuitem * mi) +on_user_menuitem_destroyed (UserChangeListenerData * data) { - update_menuitem_icon (mi, user); + g_signal_handler_disconnect (data->user, data->handler_id); + g_free (data); } static DbusmenuMenuitem* -create_user_menuitem (SessionMenuMgr * menu_mgr, AccountsUser * user) +user_menuitem_new (AccountsUser * user, SessionMenuMgr * mgr) { DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (mi, - DBUSMENU_MENUITEM_PROP_TYPE, - USER_ITEM_TYPE); + mi_set_type (mi, USER_ITEM_TYPE); /* set the name property */ - const gchar * const real_name = accounts_user_get_real_name (user); - const gchar * const user_name = accounts_user_get_user_name (user); - char * str = get_user_name_collision (user) - ? g_strdup_printf ("%s (%s)", real_name, user_name) - : g_strdup (real_name); - dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, str); - g_free (str); + GString * gstr = g_string_new (accounts_user_get_real_name (user)); + if (user_has_name_collision (user)) + { + g_string_append_printf (gstr, " (%s)", accounts_user_get_user_name(user)); + } + dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, gstr->str); + g_string_free (gstr, TRUE); /* set the logged-in property */ - const gboolean is_logged_in = users_service_dbus_is_user_logged_in (menu_mgr->users_dbus_interface, user); - dbusmenu_menuitem_property_set_bool (mi, - USER_ITEM_PROP_LOGGED_IN, - is_logged_in); + mi_set_logged_in (mi, + users_service_dbus_is_user_logged_in (mgr->users_dbus_facade, user)); - /* set the icon property */ - update_menuitem_icon (mi, user); - g_signal_connect (user, "notify::icon-file", G_CALLBACK(on_user_icon_file_changed), mi); + /* set the icon property & listen for changes */ + UserChangeListenerData * cd = g_new0 (UserChangeListenerData, 1); + cd->user = user; + cd->handler_id = g_signal_connect (user, "notify::icon-file", + G_CALLBACK(on_user_icon_file_changed), mi); + g_object_weak_ref (G_OBJECT(mi), (GWeakNotify)on_user_menuitem_destroyed, cd); + on_user_icon_file_changed (user, NULL, mi); /* set the is-current-user property */ + const gboolean is_current_user = + !g_strcmp0 (g_get_user_name(), accounts_user_get_user_name(user)); dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_IS_CURRENT_USER, - !g_strcmp0 (user_name, g_get_user_name())); + is_current_user); /* set the activate callback */ - struct ActivateUserSessionData * data = g_new (struct ActivateUserSessionData, 1); + ActivateUserSessionData * data = g_new (ActivateUserSessionData, 1); data->user = user; - data->menu_mgr = menu_mgr; + data->mgr = mgr; g_signal_connect_data (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_user_session), + G_CALLBACK (action_func_switch_to_user), data, (GClosureNotify)g_free, - 0); + G_CONNECT_SWAPPED); /* give this AccountsUser a hook back to this menuitem */ user_set_menuitem (user, mi); - /* done */ return mi; } -static void -on_guest_logged_in_changed (UsersServiceDbus * users_service_dbus, - SessionMenuMgr * self) +/* for sorting AccountsUsers from most to least frequently used */ +static gint +compare_users_by_login_frequency (gconstpointer a, gconstpointer b) { - if (self->guest_mi != NULL) - { - const gboolean b = users_service_dbus_is_guest_logged_in (users_service_dbus); - dbusmenu_menuitem_property_set_bool (self->guest_mi, USER_ITEM_PROP_LOGGED_IN, b); - } + const guint64 a_freq = accounts_user_get_login_frequency (ACCOUNTS_USER(a)); + const guint64 b_freq = accounts_user_get_login_frequency (ACCOUNTS_USER(b)); + if (a_freq > b_freq) return -1; + if (a_freq < b_freq) return 1; + return 0; } -/* When a user's login state changes, - update the corresponding menuitem's LOGGED_IN property */ -static void -on_user_logged_in_changed (UsersServiceDbus * users_service_dbus, - AccountsUser * user, - SessionMenuMgr * self) +/* for sorting AccountsUsers by name */ +static gint +compare_users_by_username (gconstpointer ga, gconstpointer gb) { - DbusmenuMenuitem * mi = user_get_menuitem (user); + AccountsUser * a = ACCOUNTS_USER(ga); + AccountsUser * b = ACCOUNTS_USER(gb); - if (mi != NULL) + const int ret = g_strcmp0 (accounts_user_get_real_name (a), + accounts_user_get_real_name (b)); + + if (!ret) /* names are the same, so both have a name collision */ { - const gboolean b = users_service_dbus_is_user_logged_in (users_service_dbus, user); - dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, b); + user_set_name_collision (a, TRUE); + user_set_name_collision (b, TRUE); } + + return ret; } -/* Builds up the menu for us */ -static void -menu_mgr_rebuild_users (SessionMenuMgr *self) +static gboolean +is_user_switching_allowed (SessionMenuMgr * mgr) { - GList *u; - gboolean can_activate; + /* maybe it's locked down */ + if (g_settings_get_boolean (mgr->lockdown_settings, "disable-user-switching")) + return FALSE; - /* Check to see which menu items we're allowed to have */ - can_activate = users_service_dbus_can_activate_session (self->users_dbus_interface) && - !g_settings_get_boolean (self->lockdown_settings, LOCKDOWN_KEY_USER); + /* maybe the seat doesn't support activation */ + if (!users_service_dbus_can_activate_session (mgr->users_dbus_facade)) + return FALSE; - /* Remove the old menu items if that makes sense */ -#warning FIXME -#if 0 - GList * children = dbusmenu_menuitem_take_children (self->root_item); - g_list_foreach (children, (GFunc)g_object_unref, NULL); - g_list_free (children); -#endif + return TRUE; +} - /* Set to NULL in case we don't end up building one */ - self->guest_mi = NULL; - - /* Build all of the user switching items */ - if (can_activate) - { - /* TODO: This needs to be updated once the ability to query guest session support is available */ - GList * users = users_service_dbus_get_user_list (self->users_dbus_interface); - const gboolean guest_enabled = users_service_dbus_guest_session_enabled (self->users_dbus_interface); - - /* TODO we should really return here if the menu is not going to be shown. */ - - DbusmenuMenuitem * switch_menuitem = dbusmenu_menuitem_new (); -/* - dbusmenu_menuitem_property_set (switch_menuitem, - DBUSMENU_MENUITEM_PROP_TYPE, - MENU_SWITCH_TYPE); -*/ - dbusmenu_menuitem_property_set (switch_menuitem, - USER_ITEM_PROP_NAME, - _("Switch User Account…")); - dbusmenu_menuitem_child_append (self->parent_mi, switch_menuitem); -g_message ("appending Switch button to %p", self->parent_mi); - g_signal_connect (G_OBJECT (switch_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_new_session), - self); - - if ( !is_this_guest_session () && guest_enabled) +static void +build_user_menuitems (SessionMenuMgr * mgr) +{ + DbusmenuMenuitem * mi; + GSList * items = NULL; + gint pos = mgr->user_menuitem_index; + const char * current_real_name = NULL; + + /** + *** Start Screen Saver + *** Switch Account... + *** Lock + *** Lock / Switch Account... + **/ + + const gboolean show_all = DEBUG_SHOW_ALL; + const SwitcherMode mode = get_switcher_mode (mgr); + + mi = mi_new (_("Start Screen Saver")); + mi_set_visible (mi, show_all || (mode == SWITCHER_MODE_SCREENSAVER)); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_lock), mgr); + + mi = mi_new (_("Switch User Account\342\200\246")); + mi_set_visible (mi, show_all || (mode == SWITCHER_MODE_SWITCH)); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_greeter), mgr); + + mi = mgr->lock_mi = mi_new (_("Lock")); + mi_set_visible (mi, show_all || (mode == SWITCHER_MODE_LOCK)); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_lockscreen), mgr); + + mi = mgr->lock_switch_mi = mi_new (_("Lock/Switch Account\342\200\246")); + mi_set_visible (mi, show_all || (mode == SWITCHER_MODE_SWITCH_OR_LOCK)); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_lockscreen), mgr); + + const gboolean guest_allowed = + users_service_dbus_guest_session_enabled (mgr->users_dbus_facade); + const gboolean is_guest = is_this_guest_session(); + mi = mi_new (_("Guest Session")); + mi_set_type (mi, USER_ITEM_TYPE); + mi_set_visible (mi, guest_allowed && !is_guest); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + on_guest_logged_in_changed (mgr->users_dbus_facade, mgr); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_guest), mgr); + mgr->guest_mi = mi; + if (guest_allowed && is_guest) { - self->guest_mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (self->guest_mi, - DBUSMENU_MENUITEM_PROP_TYPE, - USER_ITEM_TYPE); - dbusmenu_menuitem_property_set (self->guest_mi, - USER_ITEM_PROP_NAME, - _("Guest Session")); - on_guest_logged_in_changed (self->users_dbus_interface, self); - dbusmenu_menuitem_child_append (self->parent_mi, self->guest_mi); - g_signal_connect (G_OBJECT (self->guest_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_guest_session), - self); - } - else{ - session_dbus_set_users_real_name (self->session_dbus_interface, - _("Guest")); + current_real_name = _("Guest"); } - - - - users = g_list_sort (users, compare_users_by_username); + + /*** + **** Users + ***/ - for (u = users; u != NULL; u = g_list_next (u)) - { - AccountsUser * user = u->data; + /* if we can switch to another user account, show them here */ + if (is_user_switching_allowed (mgr)) + { + GList * users = users_service_dbus_get_user_list (mgr->users_dbus_facade); + + /* pick the most frequently used accounts */ + const int MAX_USERS = 12; /* this limit comes from the spec */ + if (g_list_length(users) > MAX_USERS) + { + users = g_list_sort (users, compare_users_by_login_frequency); + GList * last = g_list_nth (users, MAX_USERS-1); + GList * remainder = last->next; + last->next = NULL; + remainder->prev = NULL; + g_list_free (remainder); + } + + /* Sort the users by name for display */ + users = g_list_sort (users, compare_users_by_username); + + /* Create menuitems for them */ + int i; + GList * u; + const char * const username = g_get_user_name(); + for (i=0, u=users; inext, i++) + { + AccountsUser * user = u->data; + DbusmenuMenuitem * mi = user_menuitem_new (user, mgr); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); + + if (!g_strcmp0 (username, accounts_user_get_user_name(user))) + { + current_real_name = accounts_user_get_real_name (user); + } + } + g_list_free(users); + } - DbusmenuMenuitem * mi = create_user_menuitem (self, user); - dbusmenu_menuitem_child_append (self->parent_mi, mi); + /* separator */ + mi = mi_new_separator (); + dbusmenu_menuitem_child_add_position (mgr->parent_mi, mi, pos++); + items = g_slist_prepend (items, mi); - const char * const user_name = accounts_user_get_user_name (user); - if (!g_strcmp0 (user_name, g_get_user_name())) - { - const char * const real_name = accounts_user_get_real_name (user); - session_dbus_set_users_real_name (self->session_dbus_interface, real_name); - } - } + if (current_real_name != NULL) + { + session_dbus_set_users_real_name (mgr->session_dbus, + current_real_name); + } - g_list_free(users); - } + update_screensaver_shortcut (mgr); + mgr->user_menuitems = items; +} - // Add the user accounts and separator - DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (separator1, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append (self->parent_mi, separator1); +static void +update_user_menuitems (SessionMenuMgr * mgr) +{ + /* remove any previous user menuitems */ + GSList * l; + for (l=mgr->user_menuitems; l!=NULL; l=l->next) + { + dbusmenu_menuitem_child_delete (mgr->parent_mi, l->data); + } + g_slist_free (mgr->user_menuitems); + mgr->user_menuitems = NULL; - DbusmenuMenuitem * user_accounts_item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (user_accounts_item, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_DEFAULT); - dbusmenu_menuitem_property_set (user_accounts_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("User Accounts…")); + /* add fresh user menuitems */ + build_user_menuitems (mgr); +} - g_signal_connect (G_OBJECT (user_accounts_item), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_user_accounts), - NULL); - - dbusmenu_menuitem_child_append (self->parent_mi, user_accounts_item); +/*** +**** +***/ +static void +action_func_spawn_async (const char * fmt, ...) +{ + va_list marker; + va_start (marker, fmt); + gchar * cmd = g_strdup_vprintf (fmt, marker); + va_end (marker); + + GError * error = NULL; + if (!g_spawn_command_line_async (cmd, &error)) + { + g_warning ("Unable to show \"%s\": %s", cmd, error->message); + } + g_clear_error (&error); + g_free (cmd); } -/* Check to see if the lockdown key is protecting from - locking the screen. If not, lock it. */ +/* Calling "Lock" locks the screen & goes to black. + Calling "SimulateUserActivity" afterwards shows the Lock Screen. */ static void -lock_if_possible (SessionMenuMgr * menu_mgr) +lock_helper (SessionMenuMgr * mgr, gboolean show_lock_screen) { - if (!g_settings_get_boolean (menu_mgr->lockdown_settings, LOCKDOWN_KEY_SCREENSAVER)) + if (!g_settings_get_boolean (mgr->lockdown_settings, "disable-lock-screen")) { - lock_screen(NULL, 0, NULL); + GError * error = NULL; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.ScreenSaver", + "/org/gnome/ScreenSaver", + "org.gnome.ScreenSaver", + NULL, + &error); + + if (error == NULL) + { + g_dbus_proxy_call_sync (proxy, "Lock", + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + &error); + } + + if ((error == NULL) && show_lock_screen) + { + g_dbus_proxy_call_sync (proxy, "SimulateUserActivity", + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + &error); + } + + if (error != NULL) + { + g_warning ("Error locking screen: %s", error->message); + } + + g_clear_object (&proxy); + g_clear_error (&error); } } -/* Starts a new generic session */ static void -activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data) +action_func_lock (SessionMenuMgr * mgr) { - SessionMenuMgr * menu_mgr = SESSION_MENU_MGR (user_data); - g_return_if_fail (menu_mgr != NULL); + lock_helper (mgr, FALSE); +} - lock_if_possible (menu_mgr); - users_service_dbus_show_greeter (menu_mgr->users_dbus_interface); +static void +action_func_switch_to_lockscreen (SessionMenuMgr * mgr) +{ + lock_helper (mgr, TRUE); } -/* Activates a session for a particular user. */ static void -activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data) +action_func_switch_to_greeter (SessionMenuMgr * mgr) { - struct ActivateUserSessionData * data = user_data; + action_func_lock (mgr); + users_service_dbus_show_greeter (mgr->users_dbus_facade); +} - lock_if_possible (data->menu_mgr); - users_service_dbus_activate_user_session (data->menu_mgr->users_dbus_interface, data->user); +static void +action_func_switch_to_user (ActivateUserSessionData * data) +{ + action_func_lock (data->mgr); + users_service_dbus_activate_user_session (data->mgr->users_dbus_facade, + data->user); } -/* Comparison function to look into the UserData struct - to compare by using the username value */ -static gint -compare_users_by_username (gconstpointer ga, gconstpointer gb) +static void +action_func_switch_to_guest (SessionMenuMgr * mgr) { - AccountsUser * a = ACCOUNTS_USER(ga); - AccountsUser * b = ACCOUNTS_USER(gb); + action_func_lock (mgr); + users_service_dbus_activate_guest_session (mgr->users_dbus_facade); +} - const int ret = g_strcmp0 (accounts_user_get_real_name (a), - accounts_user_get_real_name (b)); +static void +action_func_suspend (SessionMenuMgr * mgr) +{ + GError * error = NULL; - if (!ret) /* names are the same, so both have a name collision */ + dbus_upower_call_suspend_sync (mgr->upower_proxy, + mgr->cancellable, + &error); + + if (error != NULL) { - set_user_name_collision (a, TRUE); - set_user_name_collision (b, TRUE); + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); } - - return ret; } static void -activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data) +action_func_hibernate (SessionMenuMgr * mgr) { GError * error = NULL; - if (!g_spawn_command_line_async("gnome-control-center user-accounts", &error)) - { - g_warning("Unable to show control centre: %s", error->message); - g_error_free(error); - } -} -/* Signal called when a user is added. - It updates the count and rebuilds the menu */ -static void -on_user_list_changed (UsersServiceDbus * service G_GNUC_UNUSED, - SessionMenuMgr * menu_mgr) -{ - g_return_if_fail (IS_SESSION_MENU_MGR(menu_mgr)); + dbus_upower_call_hibernate_sync (mgr->upower_proxy, + mgr->cancellable, + &error); - menu_mgr_rebuild_users (menu_mgr); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } } +/*** +**** +***/ -/* Checks to see if we should show the guest session item. - System users shouldn't have guest account shown. - Mostly this would be the case of the guest user itself. */ static gboolean is_this_guest_session (void) { return geteuid() < 500; } -/* Called when someone clicks on the guest session item. */ -static void -activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data) +static gboolean +is_this_live_session (void) +{ + const struct passwd * const pw = getpwuid (geteuid()); + return (pw->pw_uid==999) && !g_strcmp0("ubuntu",pw->pw_name); +} + +static SwitcherMode +get_switcher_mode (SessionMenuMgr * mgr) { - SessionMenuMgr * menu_mgr = SESSION_MENU_MGR (user_data); - g_return_if_fail (menu_mgr != NULL); + SwitcherMode mode; + + const gboolean can_lock = !g_settings_get_boolean (mgr->lockdown_settings, + "disable-lock-screen"); + const gboolean can_switch = is_user_switching_allowed (mgr); + + if (!can_lock && !can_switch) /* hmm, quite an extreme lockdown */ + { + mode = SWITCHER_MODE_SCREENSAVER; + } + else if (is_this_live_session()) /* live sessions can't lock or switch */ + { + mode = SWITCHER_MODE_SCREENSAVER; + } + else if (!can_switch) /* switching's locked down */ + { + mode = SWITCHER_MODE_LOCK; + } + else if (is_this_guest_session ()) /* guest sessions can't lock */ + { + mode = SWITCHER_MODE_SWITCH; + } + else + { + GList * l = users_service_dbus_get_user_list (mgr->users_dbus_facade); + const size_t user_count = g_list_length (l); + g_list_free (l); - lock_if_possible (menu_mgr); - users_service_dbus_activate_guest_session (menu_mgr->users_dbus_interface); + mode = user_count < 2 + ? SWITCHER_MODE_LOCK /* you can't switch if no other users */ + : SWITCHER_MODE_SWITCH_OR_LOCK; + } + + return mode; } + /*** **** ***/ @@ -879,11 +1019,14 @@ SessionMenuMgr* session_menu_mgr_new (DbusmenuMenuitem * parent_mi, SessionDbus * session_dbus, gboolean greeter_mode) { - SessionMenuMgr* menu_mgr = g_object_new (SESSION_TYPE_MENU_MGR, NULL); - menu_mgr->parent_mi = parent_mi; - menu_mgr->greeter_mode = greeter_mode; - menu_mgr->session_dbus_interface = session_dbus; - session_menu_mgr_build_static_items (menu_mgr, greeter_mode); - menu_mgr_rebuild_users (menu_mgr); - return menu_mgr; + SessionMenuMgr* mgr = g_object_new (SESSION_TYPE_MENU_MGR, NULL); + mgr->parent_mi = parent_mi; + mgr->greeter_mode = greeter_mode; + mgr->session_dbus = session_dbus; + build_admin_menuitems (mgr); + const guint n = g_list_length (dbusmenu_menuitem_get_children (parent_mi)); + mgr->user_menuitem_index = n; + build_user_menuitems (mgr); + build_session_menuitems (mgr); + return mgr; } diff --git a/src/session-menu-mgr.h b/src/session-menu-mgr.h index 0fa7baa..21d5356 100644 --- a/src/session-menu-mgr.h +++ b/src/session-menu-mgr.h @@ -45,8 +45,8 @@ struct _SessionMenuMgrClass GType session_menu_mgr_get_type (void) G_GNUC_CONST; SessionMenuMgr* session_menu_mgr_new (DbusmenuMenuitem * parent_mi, - SessionDbus * session_dbus, - gboolean greeter_mode); + SessionDbus * session_dbus, + gboolean greeter_mode); G_END_DECLS diff --git a/src/settings-helper.c b/src/settings-helper.c index d8e858f..0ab188a 100644 --- a/src/settings-helper.c +++ b/src/settings-helper.c @@ -20,138 +20,27 @@ with this program. If not, see . */ #include -#include - -#include -#include #include "dbus-shared-names.h" #include "settings-helper.h" static GSettings* settings = NULL; -static guint confirmation_notify = 0; -static guint logout_notify = 0; -static guint restart_notify = 0; -static guint shutdown_notify = 0; - static gboolean -build_settings (void) { - if (settings == NULL) { - settings = g_settings_new (SESSION_SCHEMA); - } - if (settings == NULL) { - return FALSE; - } - return TRUE; -} - -gboolean -supress_confirmations (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, FALSE); - return g_settings_get_boolean (settings, SUPPRESS_KEY) ; -} +build_settings (void) +{ + if (G_UNLIKELY(settings == NULL)) + { + settings = g_settings_new (SESSION_SCHEMA); + } -gboolean -show_logout (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, LOGOUT_KEY) ; + return settings != NULL; } gboolean -show_restart (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, RESTART_KEY) ; -} - -gboolean -show_shutdown (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, SHUTDOWN_KEY) ; -} - -static void update_menu_entries_callback (GSettings * settings, const gchar * key, gpointer data) { - RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = (RestartShutdownLogoutMenuItems*) data; - - if(g_strcmp0 (key, SUPPRESS_KEY) == 0) { - if (g_settings_get_boolean (settings, key)) { - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down")); - } else { - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out…")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart…")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down…")); - } - } -} - -static void -update_logout_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; +supress_confirmations (void) +{ + g_return_val_if_fail (build_settings(), FALSE); - if(g_strcmp0 (key, LOGOUT_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } + return g_settings_get_boolean (settings, SUPPRESS_KEY) ; } - -static void -update_restart_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; - - if(g_strcmp0 (key, RESTART_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } -} - -static void -update_shutdown_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; - - if(g_strcmp0 (key, SHUTDOWN_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } -} - -void -update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi) { - /* If we don't have a client, build one. */ - gboolean settings_built = build_settings(); - g_return_if_fail(settings_built); - - if (confirmation_notify != 0) { - g_signal_handler_disconnect (settings, confirmation_notify); - confirmation_notify = 0; - } - - if (logout_notify != 0) { - g_signal_handler_disconnect (settings, logout_notify); - logout_notify = 0; - } - - if (restart_notify != 0) { - g_signal_handler_disconnect (settings, restart_notify); - restart_notify = 0; - } - - if (shutdown_notify != 0) { - g_signal_handler_disconnect (settings, shutdown_notify); - shutdown_notify = 0; - } - - confirmation_notify = g_signal_connect (settings, "changed::" SUPPRESS_KEY, - G_CALLBACK(update_menu_entries_callback), restart_shutdown_logout_mi); - logout_notify = g_signal_connect (settings, "changed::" LOGOUT_KEY, - G_CALLBACK(update_logout_callback), restart_shutdown_logout_mi->logout_mi); - restart_notify = g_signal_connect (settings, "changed::" RESTART_KEY, - G_CALLBACK(update_restart_callback), restart_shutdown_logout_mi->restart_mi); - shutdown_notify = g_signal_connect (settings, "changed::" SHUTDOWN_KEY, - G_CALLBACK(update_shutdown_callback), restart_shutdown_logout_mi->shutdown_mi); - - return; -} - diff --git a/src/settings-helper.h b/src/settings-helper.h index 17304af..8c4b2e8 100644 --- a/src/settings-helper.h +++ b/src/settings-helper.h @@ -23,11 +23,6 @@ with this program. If not, see . #ifndef __GCONF_HELPER_H__ #define __GCONF_HELPER_H__ -#include - -#include -#include - #define SESSION_SCHEMA "com.canonical.indicator.session" #define SUPPRESS_KEY "suppress-logout-restart-shutdown" #define LOGOUT_KEY "suppress-logout-menuitem" @@ -35,25 +30,6 @@ with this program. If not, see . #define SHUTDOWN_KEY "suppress-shutdown-menuitem" #define SHOW_USER_MENU "user-show-menu" -#define LOCKDOWN_SCHEMA "org.gnome.desktop.lockdown" -#define LOCKDOWN_KEY_USER "disable-user-switching" -#define LOCKDOWN_KEY_SCREENSAVER "disable-lock-screen" -#define KEYBINDING_SCHEMA "org.gnome.settings-daemon.plugins.media-keys" -#define KEY_LOCK_SCREEN "screensaver" - -typedef struct _RestartShutdownLogoutMenuItems -{ - DbusmenuMenuitem * logout_mi; - DbusmenuMenuitem * restart_mi; - DbusmenuMenuitem * shutdown_mi; -} -RestartShutdownLogoutMenuItems; - -void update_menu_entries(RestartShutdownLogoutMenuItems*); gboolean supress_confirmations (void); -gboolean show_logout (void); -gboolean show_restart (void); -gboolean show_shutdown (void); - #endif /* __GCONF_HELPER__ */ -- cgit v1.2.3