From cea7cb81dd95b447a8d5cb279307c435d9dc968c Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Mon, 17 Nov 2014 10:16:26 +0300 Subject: [PATCH 05/12] Add the PrepareForSleep/Shutdown signals This patch adds the PrepareForSleep/Shutdown signals so apps can listed for these signals and perform operations prior to the event such as logging out of online chatrooms. --- po/ConsoleKit2.pot | 14 +- src/ck-manager.c | 210 +++++++++++++++++++++++++---- src/ck-manager.h | 4 + src/org.freedesktop.ConsoleKit.Manager.xml | 31 +++++ 4 files changed, 224 insertions(+), 35 deletions(-) diff --git a/po/ConsoleKit2.pot b/po/ConsoleKit2.pot index 331b9e2..31f9ec7 100644 --- a/po/ConsoleKit2.pot +++ b/po/ConsoleKit2.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" -"POT-Creation-Date: 2014-11-02 15:43+0300\n" +"POT-Creation-Date: 2014-11-17 10:15+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -65,29 +65,29 @@ msgstr "" msgid "No consoles available" msgstr "" -#: src/ck-manager.c:2516 src/ck-manager.c:2615 src/ck-manager.c:2672 +#: src/ck-manager.c:2648 src/ck-manager.c:2747 src/ck-manager.c:2804 msgid "Unable to get information about the calling process" msgstr "" -#: src/ck-manager.c:2529 src/ck-session.c:278 +#: src/ck-manager.c:2661 src/ck-session.c:278 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "" -#: src/ck-manager.c:2553 src/ck-manager.c:2565 src/ck-manager.c:2822 +#: src/ck-manager.c:2685 src/ck-manager.c:2697 src/ck-manager.c:2954 msgid "Unable to find session for cookie" msgstr "" -#: src/ck-manager.c:2629 +#: src/ck-manager.c:2761 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "" -#: src/ck-manager.c:2830 +#: src/ck-manager.c:2962 msgid "User ID does not match the owner of cookie" msgstr "" -#: src/ck-manager.c:2840 +#: src/ck-manager.c:2972 msgid "Process ID does not match the owner of cookie" msgstr "" diff --git a/src/ck-manager.c b/src/ck-manager.c index cf5a40b..0110d89 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -83,15 +83,31 @@ struct CkManagerPrivate gboolean system_idle_hint; GTimeVal system_idle_since_hint; + /* How long to delay after emitting the PREPARE_FOR_SHUTDOWN or + * PREPARE_FOR_SLEEP signal */ + guint system_action_idle_delay; + CkInhibitManager *inhibit_manager; }; -enum { +typedef enum { SEAT_ADDED, SEAT_REMOVED, SYSTEM_IDLE_HINT_CHANGED, + PREPARE_FOR_SHUTDOWN, + PREPARE_FOR_SLEEP, LAST_SIGNAL -}; +} SIGNALS; + +typedef struct +{ + CkManager *manager; + DBusGMethodInvocation *context; + const gchar *command; + CkLogEventType event_type; + const gchar *description; + SIGNALS signal; +} SystemActionData; static guint signals [LAST_SIGNAL] = { 0, }; @@ -1198,7 +1214,7 @@ do_system_action (CkManager *manager, g_debug ("command is %s", command); error = NULL; - res = g_spawn_command_line_async (command, &error); + res = g_spawn_command_line_sync (command, NULL, NULL, NULL, &error); if (! res) { GError *new_error; @@ -1218,15 +1234,55 @@ do_system_action (CkManager *manager, } } +static gboolean +system_action_idle_cb(SystemActionData *data) +{ + g_return_val_if_fail (data != NULL, FALSE); + + /* Perform the action */ + do_system_action (data->manager, + data->context, + data->command, + data->event_type, + data->description); + + /* If we got here the sleep action is done and we're awake again + * or the operation failed. Either way we can signal to the apps */ + g_signal_emit (data->manager, signals [data->signal], 0, FALSE); + + g_free (data); + + return FALSE; +} + static void do_restart (CkManager *manager, DBusGMethodInvocation *context) { - do_system_action (manager, - context, - PREFIX "/lib/ConsoleKit/scripts/ck-system-restart", - CK_LOG_EVENT_SYSTEM_RESTART, - "Restart"); + SystemActionData *data; + + /* Emit the signal */ + g_signal_emit (manager, signals [PREPARE_FOR_SHUTDOWN], 0, TRUE); + + /* Allocate and fill the data struct to pass to the idle cb */ + data = g_new0 (SystemActionData, 1); + if (data == NULL) { + g_critical ("failed to allocate memory to perform shutdown\n"); + g_signal_emit (manager, signals [PREPARE_FOR_SHUTDOWN], 0, FALSE); + return; + } + + data->manager = manager; + data->context = context; + data->command = PREFIX "/lib/ConsoleKit/scripts/ck-system-restart"; + data->event_type = CK_LOG_EVENT_SYSTEM_RESTART; + data->description = "Restart"; + data->signal = PREPARE_FOR_SHUTDOWN; + + /* Sleep so user applications have time to respond */ + g_timeout_add (data->manager->priv->system_action_idle_delay, + (GSourceFunc)system_action_idle_cb, + data); } /* @@ -1289,11 +1345,30 @@ static void do_stop (CkManager *manager, DBusGMethodInvocation *context) { - do_system_action (manager, - context, - PREFIX "/lib/ConsoleKit/scripts/ck-system-stop", - CK_LOG_EVENT_SYSTEM_STOP, - "Stop"); + SystemActionData *data; + + /* Emit the signal */ + g_signal_emit (manager, signals [PREPARE_FOR_SHUTDOWN], 0, TRUE); + + /* Allocate and fill the data struct to pass to the idle cb */ + data = g_new0 (SystemActionData, 1); + if (data == NULL) { + g_critical ("failed to allocate memory to perform shutdown\n"); + g_signal_emit (manager, signals [PREPARE_FOR_SHUTDOWN], 0, FALSE); + return; + } + + data->manager = manager; + data->context = context; + data->command = PREFIX "/lib/ConsoleKit/scripts/ck-system-stop"; + data->event_type = CK_LOG_EVENT_SYSTEM_STOP; + data->description = "Stop"; + data->signal = PREPARE_FOR_SHUTDOWN; + + /* Sleep so user applications have time to respond */ + g_timeout_add (data->manager->priv->system_action_idle_delay, + (GSourceFunc)system_action_idle_cb, + data); } gboolean @@ -1486,11 +1561,30 @@ static void do_suspend (CkManager *manager, DBusGMethodInvocation *context) { - do_system_action (manager, - context, - PREFIX "/lib/ConsoleKit/scripts/ck-system-suspend", - CK_LOG_EVENT_SYSTEM_SUSPEND, - "Suspend"); + SystemActionData *data; + + /* Emit the signal */ + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, TRUE); + + /* Allocate and fill the data struct to pass to the idle cb */ + data = g_new0 (SystemActionData, 1); + if (data == NULL) { + g_critical ("failed to allocate memory to perform suspend\n"); + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, FALSE); + return; + } + + data->manager = manager; + data->context = context; + data->command = PREFIX "/lib/ConsoleKit/scripts/ck-system-suspend"; + data->event_type = CK_LOG_EVENT_SYSTEM_SUSPEND; + data->description = "Suspend"; + data->signal = PREPARE_FOR_SLEEP; + + /* Sleep so user applications have time to respond */ + g_timeout_add (data->manager->priv->system_action_idle_delay, + (GSourceFunc)system_action_idle_cb, + data); } /* @@ -1572,11 +1666,30 @@ static void do_hibernate (CkManager *manager, DBusGMethodInvocation *context) { - do_system_action (manager, - context, - PREFIX "/lib/ConsoleKit/scripts/ck-system-hibernate", - CK_LOG_EVENT_SYSTEM_HIBERNATE, - "Hibernate"); + SystemActionData *data; + + /* Emit the signal */ + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, TRUE); + + /* Allocate and fill the data struct to pass to the idle cb */ + data = g_new0 (SystemActionData, 1); + if (data == NULL) { + g_critical ("failed to allocate memory to perform suspend\n"); + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, FALSE); + return; + } + + data->manager = manager; + data->context = context; + data->command = PREFIX "/lib/ConsoleKit/scripts/ck-system-hibernate"; + data->event_type = CK_LOG_EVENT_SYSTEM_HIBERNATE; + data->description = "Hibernate"; + data->signal = PREPARE_FOR_SLEEP; + + /* Sleep so user applications have time to respond */ + g_timeout_add (data->manager->priv->system_action_idle_delay, + (GSourceFunc)system_action_idle_cb, + data); } /* @@ -1658,11 +1771,30 @@ static void do_hybrid_sleep (CkManager *manager, DBusGMethodInvocation *context) { - do_system_action (manager, - context, - PREFIX "/lib/ConsoleKit/scripts/ck-system-hybridsleep", - CK_LOG_EVENT_SYSTEM_HIBERNATE, - "Hybrid Sleep"); + SystemActionData *data; + + /* Emit the signal */ + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, TRUE); + + /* Allocate and fill the data struct to pass to the idle cb */ + data = g_new0 (SystemActionData, 1); + if (data == NULL) { + g_critical ("failed to allocate memory to perform suspend\n"); + g_signal_emit (manager, signals [PREPARE_FOR_SLEEP], 0, FALSE); + return; + } + + data->manager = manager; + data->context = context; + data->command = PREFIX "/lib/ConsoleKit/scripts/ck-system-hybridsleep"; + data->event_type = CK_LOG_EVENT_SYSTEM_HIBERNATE; + data->description = "Hybrid Sleep"; + data->signal = PREPARE_FOR_SLEEP; + + /* Sleep so user applications have time to respond */ + g_timeout_add (data->manager->priv->system_action_idle_delay, + (GSourceFunc)system_action_idle_cb, + data); } /* @@ -3043,6 +3175,26 @@ ck_manager_class_init (CkManagerClass *klass) g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + signals [PREPARE_FOR_SHUTDOWN] = + g_signal_new ("prepare-for-shutdown", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkManagerClass, prepare_for_shutdown), + NULL, + NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, G_TYPE_BOOLEAN); + signals [PREPARE_FOR_SLEEP] = + g_signal_new ("prepare-for-sleep", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkManagerClass, prepare_for_sleep), + NULL, + NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, G_TYPE_BOOLEAN); dbus_g_object_type_install_info (CK_TYPE_MANAGER, &dbus_glib_ck_manager_object_info); dbus_g_error_domain_register (CK_MANAGER_ERROR, NULL, CK_MANAGER_TYPE_ERROR); @@ -3256,6 +3408,8 @@ ck_manager_init (CkManager *manager) manager->priv->inhibit_manager = ck_inhibit_manager_get (); + manager->priv->system_action_idle_delay = 4 * 1000; + create_seats (manager); } diff --git a/src/ck-manager.h b/src/ck-manager.h index 098d464..5bdc76e 100644 --- a/src/ck-manager.h +++ b/src/ck-manager.h @@ -54,6 +54,10 @@ typedef struct const char *sid); void (* system_idle_hint_changed) (CkManager *manager, gboolean idle_hint); + void (* prepare_for_shutdown) (CkManager *manager, + gboolean active); + void (* prepare_for_sleep) (CkManager *manager, + gboolean active); } CkManagerClass; typedef enum diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml index eb44d45..9b94120 100644 --- a/src/org.freedesktop.ConsoleKit.Manager.xml +++ b/src/org.freedesktop.ConsoleKit.Manager.xml @@ -603,5 +603,36 @@ + + + + TRUE when the system is starting to halt. + + + + + Emitted when the system is halting (active = TRUE). If + successful there will not be a FALSE signal emitted since + the system will poweroff or reboot. It will emit a FALSE + signal if the shutdown operation failed. + + + + + + + + TRUE when starting to sleep. + + + + + Emitted when the system is starting the sleep process. + It will emit with an active = FALSE when resuming from sleep + or if the sleep operation failed. + + + + -- 2.2.1