diff options
author | Eric Koegel <eric.koegel@gmail.com> | 2015-05-25 16:23:30 +0300 |
---|---|---|
committer | Eric Koegel <eric.koegel@gmail.com> | 2015-06-07 17:25:45 +0300 |
commit | 51e085159b9dd2b4be55bb77d42157c79cacacc2 (patch) | |
tree | 6216ac7f66b5bc3a1e1d4194a7d701f1fb9a96a1 | |
parent | 3c041293fdb8f7814603c8054e298bbb3ee2f57b (diff) | |
download | ConsoleKit2-51e085159b9dd2b4be55bb77d42157c79cacacc2.tar.gz |
Add "mode" to the inhibit call
Now we support the mode string of the inhibit dbus call. It can
either be a "block" or "delay". If no delay lock is done, a
system call action will delay 2 seconds to give applications time
to save state. Holding a delay lock will increase the timeout to
a max of 8 seconds.
-rw-r--r-- | src/ck-inhibit-manager.c | 195 | ||||
-rw-r--r-- | src/ck-inhibit-manager.h | 26 | ||||
-rw-r--r-- | src/ck-inhibit.c | 138 | ||||
-rw-r--r-- | src/ck-inhibit.h | 18 | ||||
-rw-r--r-- | src/ck-manager.c | 230 | ||||
-rw-r--r-- | src/ck-marshal.list | 1 | ||||
-rw-r--r-- | src/org.freedesktop.ConsoleKit.Manager.xml | 7 | ||||
-rw-r--r-- | src/test-inhibit.c | 48 | ||||
-rw-r--r-- | src/test-manager.c | 12 |
9 files changed, 538 insertions, 137 deletions
diff --git a/src/ck-inhibit-manager.c b/src/ck-inhibit-manager.c index dea354f..2031643 100644 --- a/src/ck-inhibit-manager.c +++ b/src/ck-inhibit-manager.c @@ -41,10 +41,12 @@ struct CkInhibitManagerPrivate * it's doubtful there will be more than a dozen items in the list. */ GList *inhibit_list; - /* inhibitors is an array of which events to suppress. + /* inhibitors is an 2-dimensional array of which events to suppress + * and how they are suppressed. * The CkInhibitEvent value is used to indicate how many different - * inhibits are suppressing that event. */ - gint inhibitors[CK_INHIBIT_EVENT_LAST]; + * inhibits are suppressing that event. The CkInhibitMode indicates + * if it's a block or delay event */ + gint inhibitors[CK_INHIBIT_MODE_LAST][CK_INHIBIT_EVENT_LAST]; }; typedef enum { @@ -76,9 +78,9 @@ ck_inhibit_manager_class_init (CkInhibitManagerClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkInhibitManagerClass, changed_event), NULL, NULL, - ck_marshal_VOID__INT_BOOLEAN, + ck_marshal_VOID__INT_INT_BOOLEAN, G_TYPE_NONE, - 2, G_TYPE_INT, G_TYPE_BOOLEAN); + 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN); } static void @@ -94,7 +96,11 @@ ck_inhibit_manager_finalize (GObject *object) } static void -cb_changed_event (CkInhibit *inhibit, gint event, gboolean enabled, gpointer user_data) +cb_changed_event (CkInhibit *inhibit, + gint inhibit_mode, + gint event, + gboolean enabled, + gpointer user_data) { CkInhibitManager *manager; CkInhibitManagerPrivate *priv; @@ -111,29 +117,31 @@ cb_changed_event (CkInhibit *inhibit, gint event, gboolean enabled, gpointer use } if (enabled) { - priv->inhibitors[event]++; + priv->inhibitors[inhibit_mode][event]++; - if (priv->inhibitors[event] == 1) { + if (priv->inhibitors[inhibit_mode][event] == 1) { /* event is now inhibited, send a notification */ g_signal_emit(G_OBJECT (manager), __signals[SIG_CHANGED_EVENT], 0, + inhibit_mode, event, TRUE); } } else { - priv->inhibitors[event]--; - if (priv->inhibitors[event] < 0) { - g_warning ("cb_changed_event: priv->inhibitors[%d] " + priv->inhibitors[inhibit_mode][event]--; + if (priv->inhibitors[inhibit_mode][event] < 0) { + g_warning ("cb_changed_event: priv->inhibitors[%d][%d] " "is negative, that's not supposed to happen", - event); + inhibit_mode, event); } - if (priv->inhibitors[event] == 0) { + if (priv->inhibitors[inhibit_mode][event] == 0) { /* event is no longer inhibited, send a notification */ g_signal_emit(G_OBJECT (manager), __signals[SIG_CHANGED_EVENT], 0, + inhibit_mode, event, FALSE); } @@ -152,6 +160,10 @@ cb_changed_event (CkInhibit *inhibit, gint event, gboolean enabled, gpointer use * @why: A human-readable, descriptive string of why the program * is taking the lock. Example: "Burning a DVD, interrupting now * will ruin the DVD." + * @mode: Must either be block or delay. block prevents the operation + * from happening and will cause a call to perform that action + * to fail. delay temporarly prevents the operation from happening + * until either the lock is released or a timeout is reached. * * Initializes an inhibit lock with the supplied paramters and returns * the named pipe. An application can only hold one lock at a time, multiple @@ -165,7 +177,8 @@ gint ck_inhibit_manager_create_lock (CkInhibitManager *manager, const gchar *who, const gchar *what, - const gchar *why) + const gchar *why, + const gchar *mode) { CkInhibitManagerPrivate *priv; CkInhibit *inhibit; @@ -187,7 +200,7 @@ ck_inhibit_manager_create_lock (CkInhibitManager *manager, */ signal_id = g_signal_connect (inhibit, "changed-event", G_CALLBACK (cb_changed_event), manager); - fd = ck_inhibit_create_lock (inhibit, who, what, why); + fd = ck_inhibit_create_lock (inhibit, who, what, why, mode); if (fd == -1) { g_error ("error creating inhibit lock"); @@ -269,86 +282,178 @@ ck_inhibit_manager_get (void) return CK_INHIBIT_MANAGER (manager); } +static gboolean +get_inhibit_status (CkInhibitManager *manager, CkInhibitEvent event, CkInhibitMode mode) +{ + g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + + return manager->priv->inhibitors[mode][event] > 0 ? TRUE : FALSE; +} + /** - * ck_inhibit_manager_is_shutdown_inhibited: + * ck_inhibit_manager_is_shutdown_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_shutdown_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_shutdown_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SHUTDOWN, CK_INHIBIT_MODE_DELAY); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_shutdown_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_shutdown_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SHUTDOWN, CK_INHIBIT_MODE_BLOCK); } /** - * ck_inhibit_manager_is_suspend_inhibited: + * ck_inhibit_manager_is_suspend_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_suspend_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_suspend_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND, CK_INHIBIT_MODE_DELAY); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_suspend_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_suspend_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND, CK_INHIBIT_MODE_BLOCK); } /** - * ck_inhibit_manager_is_idle_inhibited: + * ck_inhibit_manager_is_idle_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_idle_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_idle_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_IDLE, CK_INHIBIT_MODE_DELAY); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_IDLE] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_idle_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_idle_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_IDLE, CK_INHIBIT_MODE_BLOCK); } /** - * ck_inhibit_manager_is_power_key_inhibited: + * ck_inhibit_manager_is_power_key_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_power_key_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_power_key_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_MODE_DELAY); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_power_key_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_power_key_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_MODE_BLOCK); } /** - * ck_inhibit_manager_is_suspend_key_inhibited: + * ck_inhibit_manager_is_suspend_key_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_suspend_key_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_suspend_key_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_MODE_DELAY); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_suspend_key_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_suspend_key_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_MODE_BLOCK); } /** - * ck_inhibit_manager_is_hibernate_key_inhibited: + * ck_inhibit_manager_is_hibernate_key_delayed: * @manager: The @CkInhibitManager object * - * Return value: TRUE is inhibited. + * Return value: TRUE is delayed. **/ gboolean -ck_inhibit_manager_is_hibernate_key_inhibited (CkInhibitManager *manager) +ck_inhibit_manager_is_hibernate_key_delayed (CkInhibitManager *manager) { - g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); + return get_inhibit_status (manager, CK_INHIBIT_EVENT_HIBERNATE_KEY, CK_INHIBIT_MODE_DELAY); +} + +/** + * ck_inhibit_manager_is_hibernate_key_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_hibernate_key_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_HIBERNATE_KEY, CK_INHIBIT_MODE_BLOCK); +} - return manager->priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY] > 0 ? TRUE : FALSE; +/** + * ck_inhibit_manager_is_lid_switch_delayed: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is delayed. + **/ +gboolean +ck_inhibit_manager_is_lid_switch_delayed (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_MODE_DELAY); +} + +/** + * ck_inhibit_manager_is_lid_switch_blocked: + * @manager: The @CkInhibitManager object + * + * Return value: TRUE is blocked. + **/ +gboolean +ck_inhibit_manager_is_lid_switch_blocked (CkInhibitManager *manager) +{ + return get_inhibit_status (manager, CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_MODE_BLOCK); } diff --git a/src/ck-inhibit-manager.h b/src/ck-inhibit-manager.h index 0af33cd..aaa5ccb 100644 --- a/src/ck-inhibit-manager.h +++ b/src/ck-inhibit-manager.h @@ -46,7 +46,7 @@ typedef struct GObjectClass parent_class; /*< signals >*/ - void (*changed_event) (CkInhibitManager *manager, gint event, gboolean enabled); + void (*changed_event) (CkInhibitManager *manager, gint inhibit_mode, gint event, gboolean enabled); } CkInhibitManagerClass; @@ -57,17 +57,27 @@ CkInhibitManager *ck_inhibit_manager_get (void); gint ck_inhibit_manager_create_lock (CkInhibitManager *manager, const gchar *who, const gchar *what, - const gchar *why); + const gchar *why, + const gchar *mode); gboolean ck_inhibit_manager_remove_lock (CkInhibitManager *manager, const gchar *who); -gboolean ck_inhibit_manager_is_shutdown_inhibited (CkInhibitManager *manager); -gboolean ck_inhibit_manager_is_suspend_inhibited (CkInhibitManager *manager); -gboolean ck_inhibit_manager_is_idle_inhibited (CkInhibitManager *manager); -gboolean ck_inhibit_manager_is_power_key_inhibited (CkInhibitManager *manager); -gboolean ck_inhibit_manager_is_suspend_key_inhibited (CkInhibitManager *manager); -gboolean ck_inhibit_manager_is_hibernate_key_inhibited (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_shutdown_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_suspend_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_idle_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_power_key_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_suspend_key_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_hibernate_key_delayed (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_lid_switch_delayed (CkInhibitManager *manager); + +gboolean ck_inhibit_manager_is_shutdown_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_suspend_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_idle_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_power_key_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_suspend_key_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_hibernate_key_blocked (CkInhibitManager *manager); +gboolean ck_inhibit_manager_is_lid_switch_blocked (CkInhibitManager *manager); G_END_DECLS diff --git a/src/ck-inhibit.c b/src/ck-inhibit.c index 6e2a2e3..dff4690 100644 --- a/src/ck-inhibit.c +++ b/src/ck-inhibit.c @@ -51,6 +51,10 @@ struct CkInhibitPrivate */ const gchar *why; /* + * Mode is the CkInhibitMode, block or delay + */ + CkInhibitMode mode; + /* * named_pipe is a named pipe that the user app will hold onto * while they want the lock to be held. When they close all * references to the named pipe then the lock is released and @@ -96,9 +100,9 @@ ck_inhibit_class_init (CkInhibitClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkInhibitClass, changed_event), NULL, NULL, - ck_marshal_VOID__INT_BOOLEAN, + ck_marshal_VOID__INT_INT_BOOLEAN, G_TYPE_NONE, - 2, G_TYPE_INT, G_TYPE_BOOLEAN); + 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN); } static void @@ -195,6 +199,9 @@ parse_inhibitors_string (CkInhibit *inhibit, } else if (g_strcmp0 (tokens[i], "handle-hibernate-key") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY] = TRUE; inhibit_set = TRUE; + } else if (g_strcmp0 (tokens[i], "handle-lid-switch") == 0) { + priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH] = TRUE; + inhibit_set = TRUE; } else { g_warning ("requested inhibit operation not supported %s", tokens[i]); @@ -205,6 +212,32 @@ parse_inhibitors_string (CkInhibit *inhibit, return inhibit_set; } + +/* Parses what for the inhibitors to assign to inhibit, invalid options + * generate a warning but the operation continues. If at least one + * inhibitor was set then it returns TRUE. */ +static gboolean +parse_mode_string (CkInhibit *inhibit, + const gchar *mode) +{ + CkInhibitPrivate *priv; + + g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); + + priv = CK_INHIBIT_GET_PRIVATE (inhibit); + + /* Check for whatever inhibit modes we support */ + if (g_strcmp0 (mode, "block") == 0) { + priv->mode = CK_INHIBIT_MODE_BLOCK; + } else if (g_strcmp0 (mode, "delay") == 0) { + priv->mode = CK_INHIBIT_MODE_DELAY; + } else { + return FALSE; + } + + return TRUE; +} + /* * Creates the /run/ConsoleKit/inhibit directory. The * state_files will exist inside this directory. @@ -245,27 +278,31 @@ emit_initial_inhibit_signals (CkInhibit *inhibit) priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SHUTDOWN, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SHUTDOWN, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SUSPEND, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_IDLE]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_IDLE, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_IDLE, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_POWER_KEY, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_POWER_KEY, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SUSPEND_KEY, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND_KEY, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]) { - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_HIBERNATE_KEY, TRUE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_HIBERNATE_KEY, TRUE); + } + + if (priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]) { + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_LID_SWITCH, TRUE); } } @@ -282,32 +319,37 @@ emit_final_uninhibit_signals (CkInhibit *inhibit) if (priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN]) { priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SHUTDOWN, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SHUTDOWN, FALSE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND]) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SUSPEND, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND, FALSE); } if (priv->inhibitors[CK_INHIBIT_EVENT_IDLE]) { priv->inhibitors[CK_INHIBIT_EVENT_IDLE] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_IDLE, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_IDLE, FALSE); } if (priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_POWER_KEY, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_POWER_KEY, FALSE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_SUSPEND_KEY, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND_KEY, FALSE); } if (priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY] = FALSE; - g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, CK_INHIBIT_EVENT_HIBERNATE_KEY, FALSE); + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_HIBERNATE_KEY, FALSE); + } + + if (priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]) { + priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH] = FALSE; + g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_LID_SWITCH, FALSE); } } @@ -487,6 +529,10 @@ create_named_pipe (CkInhibit *inhibit) * @why: A human-readable, descriptive string of why the program * is taking the lock. Example: "Burning a DVD, interrupting now * will ruin the DVD." + * @mode: Must either be block or delay. block prevents the operation + * from happening and will cause a call to perform that action + * to fail. delay temporarly prevents the operation from happening + * until either the lock is released or a timeout is reached. * * Initializes the lock fd and populates the inhibit object with data. * @@ -498,7 +544,8 @@ gint ck_inhibit_create_lock (CkInhibit *inhibit, const gchar *who, const gchar *what, - const gchar *why) + const gchar *why, + const gchar *mode) { CkInhibitPrivate *priv; gint pipe; @@ -506,7 +553,7 @@ ck_inhibit_create_lock (CkInhibit *inhibit, g_return_val_if_fail (CK_IS_INHIBIT (inhibit), CK_INHIBIT_ERROR_INVALID_INPUT); /* These fields only get set here and are mandatory */ - if (!who || !what || !why) { + if (!who || !what || !why || !mode) { g_warning ("who, what, and why and mandatory for inhibit locks"); return CK_INHIBIT_ERROR_INVALID_INPUT; } @@ -514,7 +561,7 @@ ck_inhibit_create_lock (CkInhibit *inhibit, priv = CK_INHIBIT_GET_PRIVATE (inhibit); /* always make sure we have a directory to work in */ - if (create_inhibit_base_directory () < 0) { + if (create_inhibit_base_directory () == FALSE) { return CK_INHIBIT_ERROR_GENERAL; } @@ -526,6 +573,10 @@ ck_inhibit_create_lock (CkInhibit *inhibit, g_warning ("Failed to set any inhibitors."); return CK_INHIBIT_ERROR_INVALID_INPUT; } + if (!parse_mode_string(inhibit, mode)) { + g_warning ("Failed to set inhibit mode."); + return CK_INHIBIT_ERROR_INVALID_INPUT; + } if(priv->named_pipe_path == NULL) { g_warning ("Failed to allocate memory for inhibit state_file string"); @@ -582,6 +633,45 @@ ck_inhibit_get_why (CkInhibit *inhibit) } /** + * ck_inhibit_get_mode: + * @inhibit: The @CkInhibit object + * + * Return value: the inhibit mode, either "delay" or "block" (or NULL on failure). + **/ +const gchar* +ck_inhibit_get_mode (CkInhibit *inhibit) +{ + CkInhibitPrivate *priv; + + g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); + + priv = CK_INHIBIT_GET_PRIVATE (inhibit); + + if (priv->mode == CK_INHIBIT_MODE_BLOCK) { + return "block"; + } else if (priv->mode == CK_INHIBIT_MODE_DELAY) { + return "delay"; + } + + /* if mode wasn't set to block or delay, there was an error */ + return NULL; +} + +/** + * ck_inhibit_get_inhibit_mode: + * @inhibit: The @CkInhibit object + * + * Return value: The CkInhibitMode directly, rather than a string representation. + **/ +CkInhibitMode +ck_inhibit_get_inhibit_mode (CkInhibit *inhibit) +{ + g_return_val_if_fail (CK_IS_INHIBIT (inhibit), CK_INHIBIT_MODE_INVALID); + + return inhibit->priv->mode; +} + +/** * ck_inhibit_is_shutdown_inhibited: * @inhibit: The @CkInhibit object * @@ -664,3 +754,17 @@ ck_inhibit_is_hibernate_key_inhibited (CkInhibit *inhibit) return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]; } + +/** + * ck_inhibit_is_lid_switch_inhibited: + * @inhibit: The @CkInhibit object + * + * Return value: TRUE is inhibited. + **/ +gboolean +ck_inhibit_is_lid_switch_inhibited (CkInhibit *inhibit) +{ + g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); + + return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]; +} diff --git a/src/ck-inhibit.h b/src/ck-inhibit.h index 96bbcfe..82f7bfd 100644 --- a/src/ck-inhibit.h +++ b/src/ck-inhibit.h @@ -45,7 +45,7 @@ typedef struct GObjectClass parent_class; /*< signals >*/ - void (*changed_event) (CkInhibit *inhibit, gint event, gboolean enabled); + void (*changed_event) (CkInhibit *inhibit, gint inhibit_mode, gint event, gboolean enabled); } CkInhibitClass; /* The list of events that may be inhibited -- except for event_last :) */ @@ -57,9 +57,19 @@ typedef enum CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_EVENT_HIBERNATE_KEY, + CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_EVENT_LAST } CkInhibitEvent; +/* The list of inhibit modes -- except for mode_last and invalid */ +typedef enum +{ + CK_INHIBIT_MODE_INVALID = 0, + CK_INHIBIT_MODE_BLOCK, + CK_INHIBIT_MODE_DELAY, + CK_INHIBIT_MODE_LAST +} CkInhibitMode; + /* * Various error codes for CkInhibit. All the values will be negative except * for NO_ERROR @@ -80,12 +90,15 @@ CkInhibit *ck_inhibit_new (void); gint ck_inhibit_create_lock (CkInhibit *inhibit, const gchar *who, const gchar *what, - const gchar *why); + const gchar *why, + const gchar *mode); void ck_inhibit_remove_lock (CkInhibit *inhibit); const gchar *ck_inhibit_get_who (CkInhibit *inhibit); const gchar *ck_inhibit_get_why (CkInhibit *inhibit); +const gchar *ck_inhibit_get_mode (CkInhibit *inhibit); +CkInhibitMode ck_inhibit_get_inhibit_mode (CkInhibit *inhibit); gboolean ck_inhibit_is_shutdown_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_suspend_inhibited (CkInhibit *inhibit); @@ -93,6 +106,7 @@ gboolean ck_inhibit_is_idle_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_power_key_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_suspend_key_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_hibernate_key_inhibited (CkInhibit *inhibit); +gboolean ck_inhibit_is_lid_switch_inhibited (CkInhibit *inhibit); G_END_DECLS diff --git a/src/ck-manager.c b/src/ck-manager.c index bf247dd..dcf57bc 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -64,6 +64,22 @@ #define DBUS_SESSION_INTERFACE DBUS_NAME ".Session" #define DBUS_MANAGER_INTERFACE DBUS_NAME ".Manager" +typedef enum { + PREPARE_FOR_SHUTDOWN, + PREPARE_FOR_SLEEP, + LAST_SIGNAL +} SIGNALS; + +typedef struct +{ + CkManager *manager; + GDBusMethodInvocation *context; + const gchar *command; + CkLogEventType event_type; + const gchar *description; + SIGNALS signal; +} SystemActionData; + struct CkManagerPrivate { #ifdef HAVE_POLKIT @@ -85,31 +101,28 @@ struct CkManagerPrivate GTimeVal system_idle_since_hint; /* How long to delay after emitting the PREPARE_FOR_SHUTDOWN or - * PREPARE_FOR_SLEEP signal */ + * PREPARE_FOR_SLEEP signal + */ guint system_action_idle_delay; + /* How long to delay after emitting the PREPARE_FOR_SHUTDOWN or + * PREPARE_FOR_SLEEP signal with something holding the delay + * inhibit + */ + guint system_action_idle_inhibited_delay; /* The idle callback id so we can detect multiple attempts to - * perform a system action at the same time */ + * perform a system action at the same time + */ guint system_action_idle_id; + /* Now that the action data can be delayed and that delay can + * be lifted sooner than system_action_idle_inhibited_delay, + * we need to keep a pointer to the system action data so we + * can manually call system_action_idle_cb + */ + SystemActionData *system_action_data; CkInhibitManager *inhibit_manager; }; -typedef enum { - PREPARE_FOR_SHUTDOWN, - PREPARE_FOR_SLEEP, - LAST_SIGNAL -} SIGNALS; - -typedef struct -{ - CkManager *manager; - GDBusMethodInvocation *context; - const gchar *command; - CkLogEventType event_type; - const gchar *description; - SIGNALS signal; -} SystemActionData; - static void ck_manager_class_init (CkManagerClass *klass); static void ck_manager_init (CkManager *manager); static void ck_manager_iface_init (ConsoleKitManagerIface *iface); @@ -1287,6 +1300,9 @@ system_action_idle_cb(SystemActionData *data) /* reset this since we'll return FALSE here and kill the cb */ data->manager->priv->system_action_idle_id = 0; + /* set this to NULL as we've processed this event and are about + * to free the data */ + data->manager->priv->system_action_data = NULL; g_free (data); @@ -1298,6 +1314,7 @@ do_restart (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; + guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { @@ -1324,8 +1341,18 @@ do_restart (CkManager *manager, data->description = "Restart"; data->signal = PREPARE_FOR_SHUTDOWN; + if (ck_inhibit_manager_is_shutdown_delayed (manager->priv->inhibit_manager)) { + delay_time = manager->priv->system_action_idle_inhibited_delay; + /* We need to keep a pointer to the system action data because + * the inhibit lock can be lifted before the timeout + */ + manager->priv->system_action_data = data; + } else { + delay_time = manager->priv->system_action_idle_delay; + } + /* Sleep so user applications have time to respond */ - manager->priv->system_action_idle_id = g_timeout_add (data->manager->priv->system_action_idle_delay, + manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } @@ -1348,8 +1375,8 @@ dbus_restart (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_shutdown_inhibited (manager->priv->inhibit_manager)) { + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1399,6 +1426,7 @@ do_stop (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; + guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { @@ -1425,8 +1453,18 @@ do_stop (CkManager *manager, data->description = "Stop"; data->signal = PREPARE_FOR_SHUTDOWN; + if (ck_inhibit_manager_is_shutdown_delayed (manager->priv->inhibit_manager)) { + delay_time = manager->priv->system_action_idle_inhibited_delay; + /* We need to keep a pointer to the system action data because + * the inhibit lock can be lifted before the timeout + */ + manager->priv->system_action_data = data; + } else { + delay_time = manager->priv->system_action_idle_delay; + } + /* Sleep so user applications have time to respond */ - manager->priv->system_action_idle_id = g_timeout_add (data->manager->priv->system_action_idle_delay, + manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } @@ -1442,8 +1480,8 @@ dbus_stop (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_shutdown_inhibited (manager->priv->inhibit_manager)) { + /* Check if something is blocked that action */ + if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1504,8 +1542,8 @@ dbus_power_off (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_shutdown_inhibited (manager->priv->inhibit_manager)) { + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1583,8 +1621,8 @@ dbus_reboot (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_shutdown_inhibited (manager->priv->inhibit_manager)) { + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1648,6 +1686,7 @@ do_suspend (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; + guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { @@ -1674,8 +1713,18 @@ do_suspend (CkManager *manager, data->description = "Suspend"; data->signal = PREPARE_FOR_SLEEP; + if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { + delay_time = manager->priv->system_action_idle_inhibited_delay; + /* We need to keep a pointer to the system action data because + * the inhibit lock can be lifted before the timeout + */ + manager->priv->system_action_data = data; + } else { + delay_time = manager->priv->system_action_idle_delay; + } + /* Sleep so user applications have time to respond */ - manager->priv->system_action_idle_id = g_timeout_add (data->manager->priv->system_action_idle_delay, + manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } @@ -1699,9 +1748,9 @@ dbus_suspend (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_suspend_inhibited (manager->priv->inhibit_manager)) { - throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { + throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1769,6 +1818,13 @@ do_hibernate (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; + guint delay_time; + + /* Don't allow multiple system actions at the same time */ + if (manager->priv->system_action_idle_id != 0) { + throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); + return; + } /* Emit the signal */ console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), TRUE); @@ -1789,8 +1845,18 @@ do_hibernate (CkManager *manager, data->description = "Hibernate"; data->signal = PREPARE_FOR_SLEEP; + if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { + delay_time = manager->priv->system_action_idle_inhibited_delay; + /* We need to keep a pointer to the system action data because + * the inhibit lock can be lifted before the timeout + */ + manager->priv->system_action_data = data; + } else { + delay_time = manager->priv->system_action_idle_delay; + } + /* Sleep so user applications have time to respond */ - manager->priv->system_action_idle_id = g_timeout_add (data->manager->priv->system_action_idle_delay, + manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } @@ -1814,9 +1880,9 @@ dbus_hibernate (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_suspend_inhibited (manager->priv->inhibit_manager)) { - throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { + throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1884,6 +1950,13 @@ do_hybrid_sleep (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; + guint delay_time; + + /* Don't allow multiple system actions at the same time */ + if (manager->priv->system_action_idle_id != 0) { + throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); + return; + } /* Emit the signal */ console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), TRUE); @@ -1904,8 +1977,18 @@ do_hybrid_sleep (CkManager *manager, data->description = "Hybrid Sleep"; data->signal = PREPARE_FOR_SLEEP; + if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { + delay_time = manager->priv->system_action_idle_inhibited_delay; + /* We need to keep a pointer to the system action data because + * the inhibit lock can be lifted before the timeout + */ + manager->priv->system_action_data = data; + } else { + delay_time = manager->priv->system_action_idle_delay; + } + /* Sleep so user applications have time to respond */ - manager->priv->system_action_idle_id = g_timeout_add (data->manager->priv->system_action_idle_delay, + manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } @@ -1929,9 +2012,9 @@ dbus_hybrid_sleep (ConsoleKitManager *ckmanager, manager = CK_MANAGER (ckmanager); - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_suspend_inhibited (manager->priv->inhibit_manager)) { - throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { + throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } @@ -1999,7 +2082,8 @@ dbus_inhibit (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const gchar *what, const gchar *who, - const gchar *why) + const gchar *why, + const gchar *mode) { CkManagerPrivate *priv; gint fd = -1; @@ -2012,13 +2096,15 @@ dbus_inhibit (ConsoleKitManager *ckmanager, priv = CK_MANAGER_GET_PRIVATE (CK_MANAGER (ckmanager)); if (priv->inhibit_manager == NULL) { - priv->inhibit_manager = ck_inhibit_manager_get (); + throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Inhibit manager failed to initialize")); + return TRUE; } fd = ck_inhibit_manager_create_lock (priv->inhibit_manager, who, what, - why); + why, + mode); /* if we didn't get an inhibit lock, translate and throw the error */ if (fd < 0) { @@ -2295,8 +2381,8 @@ static gboolean manager_set_system_idle_hint (CkManager *manager, gboolean idle_hint) { - /* Check if something in inhibiting that action */ - if (ck_inhibit_manager_is_idle_inhibited (manager->priv->inhibit_manager)) { + /* Check if something is blocking that action */ + if (ck_inhibit_manager_is_idle_blocked (manager->priv->inhibit_manager)) { g_debug ("idle inhibited, forcing idle_hint to FALSE"); idle_hint = FALSE; } @@ -3340,6 +3426,54 @@ create_seats (CkManager *manager) } static void +on_inhibit_manager_changed_event (CkInhibitManager *manager, gint inhibit_mode, gint event, gboolean enabled, gpointer user_data) +{ + CkManagerPrivate *priv; + + g_return_if_fail (CK_IS_MANAGER (user_data)); + + priv = CK_MANAGER_GET_PRIVATE (CK_MANAGER (user_data)); + + /* No system action pending, return */ + if (priv->system_action_idle_id == 0) { + return; + } + + /* No system action data? normal shutdown/suspend, return */ + if (priv->system_action_data == NULL) { + return; + } + + /* this system action must be for a sleep or shutdown operation */ + if (priv->system_action_data->signal != PREPARE_FOR_SLEEP || + priv->system_action_data->signal != PREPARE_FOR_SHUTDOWN) { + return; + } + + /* the inhibit change must be for sleep or shutdown */ + if (event != CK_INHIBIT_EVENT_SUSPEND || event != CK_INHIBIT_EVENT_SHUTDOWN) { + return; + } + + /* must be a delay inhibitor */ + if (inhibit_mode != CK_INHIBIT_MODE_DELAY) { + return; + } + + /* the inhibit lock must be removed */ + if (enabled != FALSE) { + return; + } + + /* The inhibit lock for this action was removed. + * Stop the timeout and call the system action now. + */ + g_source_remove (priv->system_action_idle_id); + priv->system_action_idle_id = 0; + system_action_idle_cb (priv->system_action_data); +} + +static void ck_manager_init (CkManager *manager) { @@ -3367,8 +3501,12 @@ ck_manager_init (CkManager *manager) manager->priv->logger = ck_event_logger_new (LOG_FILE); manager->priv->inhibit_manager = ck_inhibit_manager_get (); + if (manager->priv->inhibit_manager) { + g_signal_connect (manager->priv->inhibit_manager, "changed-event", G_CALLBACK (on_inhibit_manager_changed_event), manager); + } - manager->priv->system_action_idle_delay = 4 * 1000; + manager->priv->system_action_idle_delay = 2 * 1000; + manager->priv->system_action_idle_inhibited_delay = 8 * 1000; manager->priv->system_action_idle_id = 0; } diff --git a/src/ck-marshal.list b/src/ck-marshal.list index 0baac5a..655b6d5 100644 --- a/src/ck-marshal.list +++ b/src/ck-marshal.list @@ -2,4 +2,5 @@ VOID:UINT,STRING BOOLEAN:POINTER VOID:OBJECT,OBJECT VOID:INT,BOOLEAN +VOID:INT,INT,BOOLEAN POINTER:POINTER diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml index a827ee1..1e498ef 100644 --- a/src/org.freedesktop.ConsoleKit.Manager.xml +++ b/src/org.freedesktop.ConsoleKit.Manager.xml @@ -252,6 +252,11 @@ <doc:summary>Why is a human-readable, descriptive string of why the program is taking the lock. Example: "Burning a DVD, interrupting now will ruin the DVD."</doc:summary> </doc:doc> </arg> + <arg name="mode" type="s" direction="in"> + <doc:doc> + <doc:summary>Mode is either "block" or "delay" which determines if the inhibit lock is mandatory or should just delay the operation to a certain maximum time.</doc:summary> + </doc:doc> + </arg> <arg name="fd" type="h" direction="out"> <doc:doc> <doc:summary>Returns a file descriptor that encapsulates the lock, or -1 on failure. As soon as the file descriptor is closed (and all its duplicates) the lock is automatically released. If the client dies while the lock is taken it is automatically closed and the lock is released.</doc:summary> @@ -272,6 +277,7 @@ const char *what = "shutdown:sleep"; const char *who = "Xfburn"; const char *why = "Burning a DVD, interrupting now will ruin the DVD."; + const char *mode = "block"; message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", @@ -288,6 +294,7 @@ DBUS_TYPE_STRING, &what, DBUS_TYPE_STRING, &who, DBUS_TYPE_STRING, &why, + DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID)) { g_warning ("Unable to call Inhibit()"); diff --git a/src/test-inhibit.c b/src/test-inhibit.c index 13bdd58..cbb4640 100644 --- a/src/test-inhibit.c +++ b/src/test-inhibit.c @@ -37,14 +37,16 @@ static const gchar* WHO = "test-inhibit"; static const gchar* WHAT = "sleep:idle"; static const gchar* WHY = "for testing"; +static const gchar* MODE = "block"; /* If this doesn't get escaped we won't have rights to write here */ static const gchar* WHO2 = "../../../../../root"; static const gchar* WHAT2 = "shutdown:sleep"; +static const gchar* MODE2 = "delay"; CkInhibitManager *manager; CkInhibit *inhibit; -gint fd; +gint fd, fd1, fd2; static void test_create_inhibit (void) @@ -69,7 +71,8 @@ test_ck_create_inhibit_lock (void) fd = ck_inhibit_create_lock (inhibit, WHO, WHAT, - WHY); + WHY, + MODE); /* ensure we succeeded */ g_assert (fd >= 0); @@ -120,9 +123,12 @@ test_unref_inhibit (void) } static void -cb_changed_event (CkInhibitManager *manager, gint event, gboolean enabled, gpointer user_data) +cb_changed_event (CkInhibitManager *manager, gint inhibit_mode, gint event, gboolean enabled, gpointer user_data) { - g_print ("cb_changed_event: event %d is now %s\n", event, + g_print ("cb_changed_event: mode %s event %d is now %s\n", + inhibit_mode == CK_INHIBIT_MODE_BLOCK ? "CK_INHIBIT_MODE_BLOCK" : + inhibit_mode == CK_INHIBIT_MODE_DELAY ? "CK_INHIBIT_MODE_DELAY" : "unknown", + event, enabled ? "TRUE" : "FALSE"); } @@ -139,32 +145,38 @@ static void test_manager_add_lock1 (void) { g_print ("\n"); - ck_inhibit_manager_create_lock (manager, - WHO, - WHAT, - WHY); + fd1 = ck_inhibit_manager_create_lock (manager, + WHO, + WHAT, + WHY, + MODE); + + g_assert (fd1 != 0); } static void test_manager_add_lock2 (void) { g_print ("\n"); - ck_inhibit_manager_create_lock (manager, - WHO2, - WHAT2, - WHY); + fd2 = ck_inhibit_manager_create_lock (manager, + WHO2, + WHAT2, + WHY, + MODE2); + + g_assert (fd2 != 0); } static void test_manager_which_are_inhibited (void) { - g_assert (ck_inhibit_manager_is_shutdown_inhibited (manager)); - g_assert (ck_inhibit_manager_is_suspend_inhibited (manager)); - g_assert (ck_inhibit_manager_is_idle_inhibited (manager)); + g_assert (ck_inhibit_manager_is_shutdown_delayed (manager)); + g_assert (ck_inhibit_manager_is_suspend_blocked (manager)); + g_assert (ck_inhibit_manager_is_idle_blocked (manager)); - g_assert (ck_inhibit_manager_is_hibernate_key_inhibited (manager) == FALSE); - g_assert (ck_inhibit_manager_is_suspend_key_inhibited (manager) == FALSE); - g_assert (ck_inhibit_manager_is_power_key_inhibited (manager) == FALSE); + g_assert (ck_inhibit_manager_is_hibernate_key_blocked (manager) == FALSE); + g_assert (ck_inhibit_manager_is_suspend_key_blocked (manager) == FALSE); + g_assert (ck_inhibit_manager_is_power_key_blocked (manager) == FALSE); } diff --git a/src/test-manager.c b/src/test-manager.c index 11a26d7..143f26f 100644 --- a/src/test-manager.c +++ b/src/test-manager.c @@ -233,7 +233,17 @@ print_inhibit_reply (GDBusProxy *proxy, const gchar *method) gint fd = -1; g_print ("calling %s\t", method); - var = g_dbus_proxy_call_sync (proxy, method, g_variant_new ("(sss)", "sleep:shutdown", "test-manager", "because it's good to test things?"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); + var = g_dbus_proxy_call_sync (proxy, + method, + g_variant_new ("(ssss)", + "sleep:shutdown", + "test-manager", + "testing inhibit", + "block"), + G_DBUS_CALL_FLAGS_NONE, + 3000, + NULL, + &error); if (var != NULL) { GString *string = g_variant_print_string (var, NULL, TRUE); g_print ("%s", string->str); |