aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2010-03-16 14:47:59 -0500
committerTed Gould <ted@gould.cx>2010-03-16 14:47:59 -0500
commit1e43b72a71addb0dd45b0e7ea5dc195b0b250196 (patch)
treef2beb19767afa62ec082f540f97c1f53e1f85dce /src
parent0cfa0d154f3e3fcea6c4d0c946fa665c0b12aa9a (diff)
parent87d0374245134a7a723ee6dd8a1a1aec90ca4776 (diff)
downloadayatana-indicator-session-1e43b72a71addb0dd45b0e7ea5dc195b0b250196.tar.gz
ayatana-indicator-session-1e43b72a71addb0dd45b0e7ea5dc195b0b250196.tar.bz2
ayatana-indicator-session-1e43b72a71addb0dd45b0e7ea5dc195b0b250196.zip
Sync up to trunk.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am9
-rw-r--r--src/gconf-helper.c23
-rw-r--r--src/gconf-helper.h8
-rw-r--r--src/lock-helper.c2
-rw-r--r--src/session-service.c229
-rw-r--r--src/upower.xml309
6 files changed, 492 insertions, 88 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3037a3b..db41db6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,13 @@ users-service-client.h: $(srcdir)/users-service.xml
--output=users-service-client.h \
$(srcdir)/users-service.xml
+upower-client.h: $(srcdir)/upower.xml
+ dbus-binding-tool \
+ --prefix=_upower_client \
+ --mode=glib-client \
+ --output=upower-client.h \
+ $(srcdir)/upower.xml
+
session-dbus-client.h: $(srcdir)/session-dbus.xml
dbus-binding-tool \
--prefix=_session_dbus_client \
@@ -108,6 +115,7 @@ BUILT_SOURCES = \
consolekit-manager-client.h \
session-dbus-client.h \
session-dbus-server.h \
+ upower-client.h \
users-service-client.h \
users-service-marshal.h \
users-service-marshal.c
@@ -115,6 +123,7 @@ BUILT_SOURCES = \
EXTRA_DIST = \
consolekit-manager.xml \
session-dbus.xml \
+ upower.xml \
users-service.xml \
users-service.list
diff --git a/src/gconf-helper.c b/src/gconf-helper.c
index 5efc439..588b11c 100644
--- a/src/gconf-helper.c
+++ b/src/gconf-helper.c
@@ -43,6 +43,14 @@ supress_confirmations (void) {
return gconf_client_get_bool (gconf_client, SUPPRESS_KEY, NULL) ;
}
+gboolean
+show_logout (void) {
+ if(!gconf_client) {
+ gconf_client = gconf_client_get_default ();
+ }
+ return !gconf_client_get_bool (gconf_client, LOGOUT_KEY, NULL) ;
+}
+
static void update_menu_entries_callback (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer data) {
RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = (RestartShutdownLogoutMenuItems*) data;
GConfValue * value = gconf_entry_get_value (entry);
@@ -61,8 +69,19 @@ static void update_menu_entries_callback (GConfClient *client, guint cnxn_id, GC
}
}
+static void
+update_logout_callback (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer data) {
+ DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data;
+ GConfValue * value = gconf_entry_get_value (entry);
+ const gchar * key = gconf_entry_get_key (entry);
+
+ if(g_strcmp0 (key, LOGOUT_KEY) == 0) {
+ dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !gconf_value_get_bool(value));
+ }
+}
+
void
-update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi) {
+update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi, DbusmenuMenuitem * logoutitem) {
if(!gconf_client) {
gconf_client = gconf_client_get_default ();
}
@@ -70,5 +89,7 @@ update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi)
GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
gconf_client_notify_add (gconf_client, SUPPRESS_KEY,
update_menu_entries_callback, restart_shutdown_logout_mi, NULL, NULL);
+ gconf_client_notify_add (gconf_client, LOGOUT_KEY,
+ update_logout_callback, logoutitem, NULL, NULL);
}
diff --git a/src/gconf-helper.h b/src/gconf-helper.h
index 951bb0f..6f9bcb7 100644
--- a/src/gconf-helper.h
+++ b/src/gconf-helper.h
@@ -33,8 +33,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
-#define SUPPRESS_KEY "/apps/indicator-session/suppress_logout_restart_shutdown"
-#define GLOBAL_DIR "/apps/indicator-session"
+#define GLOBAL_DIR "/apps/indicator-session"
+#define SUPPRESS_KEY GLOBAL_DIR "/suppress_logout_restart_shutdown"
+#define LOGOUT_KEY GLOBAL_DIR "/suppress_logout_menuitem"
typedef struct _RestartShutdownLogoutMenuItems
{
@@ -44,7 +45,8 @@ typedef struct _RestartShutdownLogoutMenuItems
}
RestartShutdownLogoutMenuItems;
-void update_menu_entries(RestartShutdownLogoutMenuItems*);
+void update_menu_entries(RestartShutdownLogoutMenuItems*, DbusmenuMenuitem * logoutitem);
gboolean supress_confirmations (void);
+gboolean show_logout (void);
#endif /* __GCONF_HELPER__ */
diff --git a/src/lock-helper.c b/src/lock-helper.c
index 894801e..20149ab 100644
--- a/src/lock-helper.c
+++ b/src/lock-helper.c
@@ -192,7 +192,7 @@ lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
{
g_debug("Lock Screen");
if (!will_lock_screen()) {
- g_debug("\tGDM set to autologin, blocking lock");
+ g_debug("\tUser is guest, blocking lock");
return;
}
diff --git a/src/session-service.c b/src/session-service.c
index fa90da2..fb20f3b 100644
--- a/src/session-service.c
+++ b/src/session-service.c
@@ -47,6 +47,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "session-dbus.h"
#include "users-service-dbus.h"
#include "lock-helper.h"
+#include "upower-client.h"
#define UP_ADDRESS "org.freedesktop.UPower"
#define UP_OBJECT "/org/freedesktop/UPower"
@@ -56,8 +57,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch"
-#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
-#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching"
+#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
+#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching"
+#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen"
typedef struct _ActivateData ActivateData;
struct _ActivateData
@@ -88,8 +90,14 @@ static DbusmenuMenuitem * logout_mi = NULL;
static DbusmenuMenuitem * restart_mi = NULL;
static DbusmenuMenuitem * shutdown_mi = NULL;
+static gboolean can_hibernate = TRUE;
+static gboolean can_suspend = TRUE;
+static gboolean allow_hibernate = TRUE;
+static gboolean allow_suspend = TRUE;
+
static GConfClient * gconf_client = NULL;
-static guint notify_lockdown_id = 0;
+
+static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
static void
lockdown_changed (GConfClient *client,
@@ -97,42 +105,44 @@ lockdown_changed (GConfClient *client,
GConfEntry *entry,
gpointer user_data)
{
- GConfValue *value = gconf_entry_get_value (entry);
- const gchar *key = gconf_entry_get_key (entry);
+ GConfValue *value = gconf_entry_get_value (entry);
+ const gchar *key = gconf_entry_get_key (entry);
- if (!value || !key)
- return;
+ if (value == NULL || key == NULL) {
+ return;
+ }
- if (g_strcmp0 (key, LOCKDOWN_KEY) == 0)
- {
- if (switch_menuitem)
- {
- if (gconf_value_get_bool (value))
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
- else
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
- }
- }
+ if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
+ rebuild_items(root_menuitem, dbus_interface);
+ }
+
+ return;
}
+/* Ensures that we have a GConf client and if we build one
+ set up the signal handler. */
static void
ensure_gconf_client (void)
{
- if (!gconf_client)
- {
- gconf_client = gconf_client_get_default ();
-
- notify_lockdown_id = gconf_client_notify_add (gconf_client,
- LOCKDOWN_KEY,
- lockdown_changed,
- NULL,
- NULL,
- NULL);
- }
+ if (!gconf_client) {
+ gconf_client = gconf_client_get_default ();
+ gconf_client_add_dir(gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ gconf_client_notify_add(gconf_client, LOCKDOWN_DIR, lockdown_changed, NULL, NULL, NULL);
+ }
+ return;
+}
+
+/* Check to see if the lockdown key is protecting from
+ locking the screen. If not, lock it. */
+static void
+lock_if_possible (void) {
+ ensure_gconf_client ();
+
+ if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
+ lock_screen(NULL, 0, NULL);
+ }
+
+ return;
}
/* A return from the command to sleep the system. Make sure
@@ -156,7 +166,7 @@ machine_sleep (DbusmenuMenuitem * mi, guint timestamp, gpointer userdata)
}
screensaver_throttle(type);
- lock_screen(NULL, 0, NULL);
+ lock_if_possible();
dbus_g_proxy_begin_call(up_main_proxy,
type,
@@ -184,8 +194,10 @@ suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
}
g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
- if (suspend_mi != NULL) {
- dbusmenu_menuitem_property_set_value(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
+ gboolean local_can_suspend = g_value_get_boolean(&candoit);
+ if (local_can_suspend != can_suspend) {
+ can_suspend = local_can_suspend;
+ rebuild_items(root_menuitem, dbus_interface);
}
return;
@@ -207,8 +219,10 @@ hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
}
g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
- if (suspend_mi != NULL) {
- dbusmenu_menuitem_property_set_value(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
+ gboolean local_can_hibernate = g_value_get_boolean(&candoit);
+ if (local_can_hibernate != can_hibernate) {
+ can_hibernate = local_can_hibernate;
+ rebuild_items(root_menuitem, dbus_interface);
}
return;
@@ -254,6 +268,25 @@ up_changed_cb (DBusGProxy * proxy, gpointer user_data)
return;
}
+/* Handle the callback from the allow functions to check and
+ see if we're changing the value, and if so, rebuilding the
+ menus based on that info. */
+static void
+allowed_cb (DBusGProxy *proxy, gboolean OUT_allowed, GError *error, gpointer userdata)
+{
+ if (error != NULL) {
+ g_warning("Unable to get information on what is allowed from UPower: %s", error->message);
+ return;
+ }
+
+ gboolean * can_do = (gboolean *)userdata;
+
+ if (OUT_allowed != *can_do) {
+ *can_do = OUT_allowed;
+ rebuild_items (root_menuitem, dbus_interface);
+ }
+}
+
/* 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 */
@@ -275,23 +308,31 @@ setup_up (void) {
UP_ADDRESS,
UP_OBJECT,
DBUS_INTERFACE_PROPERTIES);
+ /* Connect to changed signal */
+ dbus_g_proxy_add_signal(up_main_proxy,
+ "Changed",
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(up_main_proxy,
+ "Changed",
+ G_CALLBACK(up_changed_cb),
+ NULL,
+ NULL);
}
g_return_if_fail(up_prop_proxy != NULL);
- /* Connect to changed signal */
- dbus_g_proxy_add_signal(up_main_proxy,
- "Changed",
- G_TYPE_INVALID);
-
- dbus_g_proxy_connect_signal(up_main_proxy,
- "Changed",
- G_CALLBACK(up_changed_cb),
- NULL,
- NULL);
/* Force an original "changed" event */
up_changed_cb(up_main_proxy, NULL);
+ /* Check to see if these are getting blocked by PolicyKit */
+ org_freedesktop_UPower_suspend_allowed_async(up_main_proxy,
+ allowed_cb,
+ &allow_suspend);
+ org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy,
+ allowed_cb,
+ &allow_hibernate);
+
return;
}
@@ -342,6 +383,9 @@ static void
activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
{
GError * error = NULL;
+
+ lock_if_possible();
+
if (!g_spawn_command_line_async(GUEST_SESSION_LAUNCHER, &error)) {
g_warning("Unable to start guest session: %s", error->message);
g_error_free(error);
@@ -382,6 +426,9 @@ static void
activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
{
GError * error = NULL;
+
+ lock_if_possible();
+
if (!g_spawn_command_line_async("gdmflexiserver --startnew", &error)) {
g_warning("Unable to start new session: %s", error->message);
g_error_free(error);
@@ -397,6 +444,8 @@ activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data
UserData *user = (UserData *)user_data;
UsersServiceDbus *service = user->service;
+ lock_if_possible();
+
users_service_dbus_activate_user_session (service, user);
}
@@ -440,29 +489,44 @@ rebuild_items (DbusmenuMenuitem *root,
GList *u;
UserData *user;
gboolean can_activate;
+ gboolean can_lockscreen;
GList *children;
- can_activate = users_service_dbus_can_activate_session (service);
+ /* Make sure we have a valid GConf client, and build one
+ if needed */
+ ensure_gconf_client ();
+
+ /* Check to see which menu items we're allowed to have */
+ can_activate = users_service_dbus_can_activate_session (service) &&
+ !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL);
+ can_lockscreen = !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL);
+ /* Remove the old menu items if that makes sense */
children = dbusmenu_menuitem_take_children (root);
g_list_foreach (children, (GFunc)g_object_unref, NULL);
g_list_free (children);
- lock_menuitem = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
- g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
- dbusmenu_menuitem_child_append(root, lock_menuitem);
- if (!will_lock_screen()) {
- dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
- } else {
- dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ /* Lock screen item */
+ if (can_lockscreen) {
+ lock_menuitem = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
+ g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
+ dbusmenu_menuitem_child_append(root, lock_menuitem);
+ if (!will_lock_screen()) {
+ dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+ } else {
+ dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ }
}
+ /* Build all of the user switching items */
if (can_activate == TRUE)
{
- DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root, separator1);
+ if (can_lockscreen) {
+ DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator1);
+ }
if (check_guest_session ())
{
@@ -476,22 +540,12 @@ rebuild_items (DbusmenuMenuitem *root,
if (check_new_session ())
{
- ensure_gconf_client ();
switch_menuitem = dbusmenu_menuitem_new ();
dbusmenu_menuitem_property_set (switch_menuitem, DBUSMENU_MENUITEM_PROP_TYPE, MENU_SWITCH_TYPE);
dbusmenu_menuitem_property_set (switch_menuitem, MENU_SWITCH_USER, g_get_user_name());
dbusmenu_menuitem_child_append (root, switch_menuitem);
g_signal_connect (G_OBJECT (switch_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), NULL);
-
- if (gconf_client_get_bool (gconf_client, LOCKDOWN_KEY, NULL))
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
- else
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
}
GList * users = NULL;
@@ -544,9 +598,15 @@ rebuild_items (DbusmenuMenuitem *root,
g_list_free(users);
}
- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root, separator);
+ /* If there were a bunch of items before us, we need a
+ separator. */
+ if (can_lockscreen || can_activate) {
+ DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
+ }
+
+ /* Start going through the session based items. */
logout_mi = dbusmenu_menuitem_new();
if (supress_confirmations()) {
@@ -554,20 +614,23 @@ rebuild_items (DbusmenuMenuitem *root,
} else {
dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out..."));
}
+ dbusmenu_menuitem_property_set_bool(logout_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_logout());
dbusmenu_menuitem_child_append(root, logout_mi);
g_signal_connect(G_OBJECT(logout_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "logout");
- suspend_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set_bool(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sleep"));
- dbusmenu_menuitem_child_append(root, suspend_mi);
- g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
+ if (can_suspend && allow_suspend) {
+ suspend_mi = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sleep"));
+ dbusmenu_menuitem_child_append(root, suspend_mi);
+ g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
+ }
- hibernate_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set_bool(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
- dbusmenu_menuitem_child_append(root, hibernate_mi);
- g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Hibernate");
+ if (can_hibernate && allow_hibernate) {
+ hibernate_mi = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
+ dbusmenu_menuitem_child_append(root, hibernate_mi);
+ g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Hibernate");
+ }
restart_mi = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_TYPE, RESTART_ITEM_TYPE);
@@ -593,7 +656,7 @@ rebuild_items (DbusmenuMenuitem *root,
restart_shutdown_logout_mi->restart_mi = restart_mi;
restart_shutdown_logout_mi->shutdown_mi = shutdown_mi;
- update_menu_entries(restart_shutdown_logout_mi);
+ update_menu_entries(restart_shutdown_logout_mi, logout_mi);
if (g_file_test(DESKTOP_FILE, G_FILE_TEST_EXISTS)) {
GAppInfo * appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(DESKTOP_FILE));
diff --git a/src/upower.xml b/src/upower.xml
new file mode 100644
index 0000000..a4066ff
--- /dev/null
+++ b/src/upower.xml
@@ -0,0 +1,309 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.UPower">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The DeviceKit-power service is available via the system message
+ bus. To access the service, use
+ the <doc:tt>org.freedesktop.UPower</doc:tt> interface on
+ the <doc:tt>/org/freedesktop/UPower</doc:tt> object on
+ the D-Bus system bus service with the well-known
+ name <doc:tt>org.freedesktop.UPower</doc:tt>.
+ </doc:para>
+ <doc:para>
+ <doc:example language="shell" title="simple example">
+ <doc:code>
+$ dbus-send --print-reply \
+ --system \
+ --dest=org.freedesktop.UPower \
+ /org/freedesktop/UPower \
+ org.freedesktop.UPower.EnumerateDevices
+
+method return sender=:1.386 -> dest=:1.451 reply_serial=2
+ array [
+ object path "/org/freedesktop/UPower/devices/line_power_AC"
+ object path "/org/freedesktop/UPower/devices/battery_BAT0"
+ ]
+ </doc:code>
+ </doc:example>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+
+ <!-- ************************************************************ -->
+
+ <method name="EnumerateDevices">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="devices" direction="out" type="ao">
+ <doc:doc><doc:summary>An array of object paths for devices.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enumerate all power objects on the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceAdded">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was added.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is added.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceRemoved">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was removed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is removed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceChanged">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Changed">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when one or more properties on the object changes.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Sleeping">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session is about to be suspended or
+ hibernated.
+ Session and system programs have one second to do anything required
+ before the sleep action is taken (such as sending out Avahi or
+ Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Resuming">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session has just returned from
+ Suspend() or Hibernate().
+ Session and system programs can then do anything required (such as
+ sending out Avahi or Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <method name="AboutToSleep">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This method tells UPower that the Suspend() or Hibernate() method
+ is about to be called.
+ This allows UPower to emit the Suspending signal whilst
+ session activities are happening that have to be done before the
+ suspend process is started.
+ </doc:para>
+ <doc:para>
+ This method would typically be called by the session power
+ management daemon, before it locks the screen and waits for the
+ screen to fade to black.
+ The session power management component would then call Suspend() or
+ Hibernate() when these syncronous tasks have completed.
+ </doc:para>
+ <doc:para>
+ If this method is not called than nothing bad will happen and
+ Suspend() or Hibernate() will block for the required second.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Suspend">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Suspends the computer into a low power state.
+ System state is not preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="SuspendAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Suspend">Suspend</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Hibernate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Hibernates the computer into a low power state.
+ System state is preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="HibernateAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Hibernate">Hibernate</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <property name="DaemonVersion" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Version of the running daemon, e.g. <doc:tt>002</doc:tt>.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanSuspend" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to suspend.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanHibernate" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to hibernate.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnLowBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power and if the battery is critically low.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="LidIsClosed" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Indicates if the laptop lid is closed where the display cannot be seen.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="LidIsPresent" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ If the system has a lid device.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+
+</node>