diff options
Diffstat (limited to 'src/session-service.c')
-rw-r--r-- | src/session-service.c | 185 |
1 files changed, 177 insertions, 8 deletions
diff --git a/src/session-service.c b/src/session-service.c index c8b3170..235d0bc 100644 --- a/src/session-service.c +++ b/src/session-service.c @@ -9,9 +9,171 @@ #include "dbus-shared-names.h" +#define DKP_ADDRESS "org.freedesktop.DeviceKit.Power" +#define DKP_OBJECT "/org/freedesktop/DeviceKit/Power" +#define DKP_INTERFACE "org.freedesktop.DeviceKit.Power" + static DbusmenuMenuitem * root_menuitem = NULL; static GMainLoop * mainloop = NULL; +static DBusGProxy * dkp_main_proxy = NULL; +static DBusGProxy * dkp_prop_proxy = NULL; + +static DBusGProxyCall * suspend_call = NULL; +static DBusGProxyCall * hibernate_call = NULL; + +static DbusmenuMenuitem * hibernate_mi = NULL; +static DbusmenuMenuitem * suspend_mi = NULL; + +/* Let's put this machine to sleep, with some info on how + it should sleep. */ +static void +sleep (DbusmenuMenuitem * mi, gpointer userdata) +{ + gchar * type = (gchar *)userdata; + + if (dkp_main_proxy == NULL) { + g_warning("Can not %s as no DeviceKit Power Proxy", type); + } + dbus_g_proxy_call_no_reply(dkp_main_proxy, + type, + G_TYPE_INVALID, + G_TYPE_INVALID); + + return; +} + +/* A response to getting the suspend property */ +static void +suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) +{ + suspend_call = NULL; + + GValue candoit = {0}; + GError * error = NULL; + dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID); + if (error != NULL) { + g_warning("Unable to check suspend: %s", error->message); + g_error_free(error); + return; + } + g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false"); + + if (suspend_mi != NULL) { + dbusmenu_menuitem_property_set(suspend_mi, "visible", g_value_get_boolean(&candoit) ? "true" : "false"); + } + + return; +} + +/* Response to getting the hibernate property */ +static void +hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) +{ + hibernate_call = NULL; + + GValue candoit = {0}; + GError * error = NULL; + dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID); + if (error != NULL) { + g_warning("Unable to check hibernate: %s", error->message); + g_error_free(error); + return; + } + g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false"); + + if (suspend_mi != NULL) { + dbusmenu_menuitem_property_set(hibernate_mi, "visible", g_value_get_boolean(&candoit) ? "true" : "false"); + } + + return; +} + +/* A signal that we need to recheck to ensure we can still + hibernate and/or suspend */ +static void +dpk_changed_cb (DBusGProxy * proxy, gpointer user_data) +{ + /* Start Async call to see if we can hibernate */ + if (suspend_call == NULL) { + suspend_call = dbus_g_proxy_begin_call(dkp_prop_proxy, + "Get", + suspend_prop_cb, + NULL, + NULL, + G_TYPE_STRING, + DKP_INTERFACE, + G_TYPE_STRING, + "can-suspend", + G_TYPE_INVALID, + G_TYPE_VALUE, + G_TYPE_INVALID); + } + + /* Start Async call to see if we can suspend */ + if (hibernate_call == NULL) { + hibernate_call = dbus_g_proxy_begin_call(dkp_prop_proxy, + "Get", + hibernate_prop_cb, + NULL, + NULL, + G_TYPE_STRING, + DKP_INTERFACE, + G_TYPE_STRING, + "can-hibernate", + G_TYPE_INVALID, + G_TYPE_VALUE, + G_TYPE_INVALID); + } + + return; +} + +/* 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_dkp (void) { + DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + g_return_if_fail(bus != NULL); + + if (dkp_main_proxy == NULL) { + dkp_main_proxy = dbus_g_proxy_new_for_name(bus, + DKP_ADDRESS, + DKP_OBJECT, + DKP_INTERFACE); + } + g_return_if_fail(dkp_main_proxy != NULL); + + if (dkp_prop_proxy == NULL) { + dkp_prop_proxy = dbus_g_proxy_new_for_name(bus, + DKP_ADDRESS, + DKP_OBJECT, + DBUS_INTERFACE_PROPERTIES); + } + g_return_if_fail(dkp_prop_proxy != NULL); + + /* Connect to changed signal */ + dbus_g_proxy_add_signal(dkp_main_proxy, + "Changed", + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(dkp_main_proxy, + "Changed", + G_CALLBACK(dpk_changed_cb), + NULL, + NULL); + + /* Force an original "changed" event */ + dpk_changed_cb(dkp_main_proxy, NULL); + + return; +} + +/* 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, gchar * type) { @@ -32,6 +194,8 @@ show_dialog (DbusmenuMenuitem * mi, gchar * type) return; } +/* This function creates all of the menuitems that the service + provides in the UI. It also connects them to the callbacks. */ static void create_items (DbusmenuMenuitem * root) { DbusmenuMenuitem * mi = NULL; @@ -41,15 +205,17 @@ create_items (DbusmenuMenuitem * root) { dbusmenu_menuitem_child_append(root, mi); g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "logout"); - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mi, "label", _("Suspend")); - dbusmenu_menuitem_child_append(root, mi); - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "suspend"); + suspend_mi = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(suspend_mi, "visible", "false"); + dbusmenu_menuitem_property_set(suspend_mi, "label", _("Suspend")); + dbusmenu_menuitem_child_append(root, suspend_mi); + g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Suspend"); - mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mi, "label", _("Hibernate")); - dbusmenu_menuitem_child_append(root, mi); - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "hibernate"); + hibernate_mi = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(hibernate_mi, "visible", "false"); + dbusmenu_menuitem_property_set(hibernate_mi, "label", _("Hibernate")); + dbusmenu_menuitem_child_append(root, hibernate_mi); + g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(sleep), "Hibernate"); mi = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(mi, "label", _("Restart")); @@ -64,6 +230,8 @@ create_items (DbusmenuMenuitem * root) { return; } +/* Main, is well, main. It brings everything up and throws + us into the mainloop of no return. */ int main (int argc, char ** argv) { @@ -88,6 +256,7 @@ main (int argc, char ** argv) g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem)); create_items(root_menuitem); + setup_dkp(); DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT); dbusmenu_server_set_root(server, root_menuitem); |