diff -up gnome-session-2.31.6/configure.in.max-idle gnome-session-2.31.6/configure.in
--- gnome-session-2.31.6/configure.in.max-idle 2010-08-04 07:35:41.000000000 -0400
+++ gnome-session-2.31.6/configure.in 2010-08-06 20:18:07.157048001 -0400
@@ -50,6 +50,7 @@ AC_MSG_RESULT([$with_gtk])
GLIB_REQUIRED=2.16.0
DBUS_GLIB_REQUIRED=0.76
UPOWER_REQUIRED=0.9.0
+LIBNOTIFY_REQUIRED=0.4.3
case "$with_gtk" in
2.0) GTK_API_VERSION=2.0
@@ -71,6 +72,7 @@ PKG_CHECK_MODULES(GNOME_SESSION,
gtk+-$GTK_API_VERSION >= $GTK_REQUIRED
dbus-glib-1 >= $DBUS_GLIB_REQUIRED
upower-glib >= $UPOWER_REQUIRED
+ libnotify >= $LIBNOTIFY_REQUIRED
)
PKG_CHECK_MODULES(SESSION_PROPERTIES,
diff -up gnome-session-2.31.6/data/gnome-session.schemas.in.in.max-idle gnome-session-2.31.6/data/gnome-session.schemas.in.in
--- gnome-session-2.31.6/data/gnome-session.schemas.in.in.max-idle 2010-08-04 07:22:30.000000000 -0400
+++ gnome-session-2.31.6/data/gnome-session.schemas.in.in 2010-08-06 20:06:05.274048002 -0400
@@ -39,6 +39,36 @@
+ /schemas/desktop/gnome/session/max_idle_action
+ /desktop/gnome/session/max_idle_action
+ gnome
+ string
+
+
+ The action to take after the maximum idle time
+
+ The name of the action to take when the maximum allowed
+ idle time has been reached. The Delay is specified in
+ the "max_idle_time" key. Allowed values are: logout,
+ forced-logout. An empty string disables the action.
+
+
+
+
+ /schemas/desktop/gnome/session/max_idle_time
+ /desktop/gnome/session/max_idle_time
+ gnome
+ int
+ 120
+
+ Amount of time a user can remain idle
+
+ The number of minutes a user can remain idle before the
+ max_idle_action is automatically taken.
+
+
+
+
/schemas/desktop/gnome/session/default_session
/desktop/gnome/session/default_session
gnome
diff -up gnome-session-2.31.6/gnome-session/gsm-manager.c.max-idle gnome-session-2.31.6/gnome-session/gsm-manager.c
--- gnome-session-2.31.6/gnome-session/gsm-manager.c.max-idle 2010-07-15 08:53:08.000000000 -0400
+++ gnome-session-2.31.6/gnome-session/gsm-manager.c 2010-08-06 20:06:05.278048002 -0400
@@ -39,6 +39,7 @@
#include
#include
+#include
#include /* for logout dialog */
#include
@@ -67,6 +68,10 @@
#define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager"
#define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager"
+#define GS_NAME "org.gnome.ScreenSaver"
+#define GS_PATH "/org/gnome/ScreenSaver"
+#define GS_INTERFACE "org.gnome.ScreenSaver"
+
#define GSM_MANAGER_PHASE_TIMEOUT 10 /* seconds */
#define GDM_FLEXISERVER_COMMAND "gdmflexiserver"
@@ -79,6 +84,8 @@
#define KEY_DESKTOP_DIR "/desktop/gnome/session"
#define KEY_IDLE_DELAY KEY_DESKTOP_DIR "/idle_delay"
+#define KEY_MAX_IDLE_TIME KEY_DESKTOP_DIR "/max_idle_time"
+#define KEY_MAX_IDLE_ACTION KEY_DESKTOP_DIR "/max_idle_action"
#define KEY_GNOME_SESSION_DIR "/apps/gnome-session/options"
#define KEY_AUTOSAVE KEY_GNOME_SESSION_DIR "/auto_save_session"
@@ -114,6 +121,11 @@ struct GsmManagerPrivate
gboolean forceful_logout;
GSList *query_clients;
guint query_timeout_id;
+ guint max_idle_timeout_id;
+ guint max_idle_warning_timeout_id;
+ guint max_idle_time_secs;
+ int max_idle_action;
+ NotifyNotification *max_idle_notification;
/* This is used for GSM_MANAGER_PHASE_END_SESSION only at the moment,
* since it uses a sublist of all running client that replied in a
* specific way */
@@ -157,6 +169,19 @@ enum {
static guint signals [LAST_SIGNAL] = { 0 };
+typedef enum {
+ ACTION_NONE = 0,
+ ACTION_LOGOUT,
+ ACTION_FORCED_LOGOUT,
+} Action;
+
+static GConfEnumStringPair actions_enum_map [] = {
+ { ACTION_NONE, "" },
+ { ACTION_LOGOUT, "logout" },
+ { ACTION_FORCED_LOGOUT, "forced-logout" },
+ { 0, NULL }
+};
+
static void gsm_manager_class_init (GsmManagerClass *klass);
static void gsm_manager_init (GsmManager *manager);
static void gsm_manager_finalize (GObject *object);
@@ -2141,6 +2166,19 @@ gsm_manager_dispose (GObject *object)
g_debug ("GsmManager: disposing manager");
+ if (manager->priv->max_idle_notification != NULL) {
+ g_object_unref (manager->priv->max_idle_notification);
+ manager->priv->max_idle_notification = NULL;
+ }
+ if (manager->priv->max_idle_warning_timeout_id > 0) {
+ g_source_remove (manager->priv->max_idle_warning_timeout_id);
+ manager->priv->max_idle_warning_timeout_id = 0;
+ }
+ if (manager->priv->max_idle_timeout_id > 0) {
+ g_source_remove (manager->priv->max_idle_timeout_id);
+ manager->priv->max_idle_timeout_id = 0;
+ }
+
if (manager->priv->clients != NULL) {
g_signal_handlers_disconnect_by_func (manager->priv->clients,
on_store_client_added,
@@ -2337,6 +2375,321 @@ load_idle_delay_from_gconf (GsmManager *
}
static void
+load_max_idle_from_gconf (GsmManager *manager)
+{
+ GError *error;
+ glong value;
+ const char *str;
+
+ error = NULL;
+ value = gconf_client_get_int (manager->priv->gconf_client,
+ KEY_MAX_IDLE_TIME,
+ &error);
+ if (error == NULL) {
+ manager->priv->max_idle_time_secs = 60 * value;
+ } else {
+ g_warning ("Error retrieving configuration key '%s': %s",
+ KEY_MAX_IDLE_TIME,
+ error->message);
+ g_error_free (error);
+ }
+
+ error = NULL;
+ str = gconf_client_get_string (manager->priv->gconf_client,
+ KEY_MAX_IDLE_ACTION,
+ &error);
+ if (error == NULL) {
+ int action;
+
+ if (gconf_string_to_enum (actions_enum_map, str, &action)) {
+ manager->priv->max_idle_action = action;
+ } else {
+ manager->priv->max_idle_action = ACTION_NONE;
+ }
+ } else {
+ g_warning ("Error retrieving configuration key '%s': %s",
+ KEY_MAX_IDLE_TIME,
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+request_logout (GsmManager *manager,
+ gboolean forceful_logout)
+{
+ g_debug ("GsmManager: requesting logout");
+
+ manager->priv->forceful_logout = forceful_logout;
+ manager->priv->logout_type = GSM_MANAGER_LOGOUT_LOGOUT;
+
+ end_phase (manager);
+}
+
+static gboolean
+_on_max_idle_time_timeout (GsmManager *manager)
+{
+ manager->priv->max_idle_timeout_id = 0;
+ g_debug ("GsmManager: max idle time reached");
+
+ if (manager->priv->max_idle_warning_timeout_id > 0) {
+ g_source_remove (manager->priv->max_idle_warning_timeout_id);
+ manager->priv->max_idle_warning_timeout_id = 0;
+ }
+
+ switch (manager->priv->max_idle_action) {
+ case ACTION_LOGOUT:
+ g_debug ("GsmManager: max idle action: logout");
+ /* begin non-forceful logout */
+ request_logout (manager, FALSE);
+ break;
+ case ACTION_FORCED_LOGOUT:
+ g_debug ("GsmManager: max idle action: force-logout");
+ /* begin forceful logout */
+ request_logout (manager, TRUE);
+ break;
+ case ACTION_NONE:
+ g_debug ("GsmManager: no max idle action specified");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+on_max_idle_notification_closed (NotifyNotification *notification,
+ GsmManager *manager)
+{
+ if (manager->priv->max_idle_notification != NULL) {
+ g_object_unref (manager->priv->max_idle_notification);
+ manager->priv->max_idle_notification = NULL;
+ }
+}
+
+/* Adapted from totem_time_to_string_text */
+static char *
+time_to_string_text (long time)
+{
+ char *secs, *mins, *hours, *string;
+ int sec, min, hour;
+
+ sec = time % 60;
+ time = time - sec;
+ min = (time % (60 * 60)) / 60;
+ time = time - (min * 60);
+ hour = time / (60 * 60);
+
+ hours = g_strdup_printf (ngettext ("%d hour", "%d hours", hour), hour);
+
+ mins = g_strdup_printf (ngettext ("%d minute",
+ "%d minutes", min), min);
+
+ secs = g_strdup_printf (ngettext ("%d second",
+ "%d seconds", sec), sec);
+
+ if (hour > 0) {
+ /* hour:minutes:seconds */
+ string = g_strdup_printf (_("%s %s %s"), hours, mins, secs);
+ } else if (min > 0) {
+ /* minutes:seconds */
+ string = g_strdup_printf (_("%s %s"), mins, secs);
+ } else if (sec > 0) {
+ /* seconds */
+ string = g_strdup_printf (_("%s"), secs);
+ } else {
+ /* 0 seconds */
+ string = g_strdup (_("0 seconds"));
+ }
+
+ g_free (hours);
+ g_free (mins);
+ g_free (secs);
+
+ return string;
+}
+
+static void
+update_max_idle_notification (GsmManager *manager,
+ long secs_remaining)
+{
+ char *summary;
+ char *body;
+ char *remaining;
+ gboolean screensaver_active;
+
+ g_object_get (manager->priv->presence, "screensaver-active", &screensaver_active, NULL);
+
+ remaining = time_to_string_text (secs_remaining);
+ summary = NULL;
+ body = NULL;
+
+ switch (manager->priv->max_idle_action) {
+ case ACTION_LOGOUT:
+ case ACTION_FORCED_LOGOUT:
+ summary = g_strdup_printf (_("Automatic logout in %s"), remaining);
+ body = g_strdup (_("This session is configured to automatically log out after a period of inactivity."));
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_free (remaining);
+
+ if (screensaver_active) {
+ DBusGProxy *proxy;
+ GError *error;
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+ GS_NAME,
+ GS_PATH,
+ GS_INTERFACE);
+ error = NULL;
+ if (! dbus_g_proxy_call (proxy, "ShowMessage", &error,
+ G_TYPE_STRING, summary,
+ G_TYPE_STRING, body,
+ G_TYPE_STRING, "",
+ G_TYPE_INVALID,
+ G_TYPE_INVALID)) {
+ g_debug ("ShowMessage failed: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (proxy);
+ } else {
+ if (manager->priv->max_idle_notification != NULL) {
+ notify_notification_update (manager->priv->max_idle_notification,
+ summary,
+ body,
+ NULL);
+ } else {
+ manager->priv->max_idle_notification
+ = notify_notification_new (summary, body, NULL, NULL);
+ notify_notification_set_timeout (manager->priv->max_idle_notification,
+ NOTIFY_EXPIRES_NEVER);
+
+ g_signal_connect (manager->priv->max_idle_notification,
+ "closed",
+ G_CALLBACK (on_max_idle_notification_closed),
+ manager);
+ }
+
+ notify_notification_show (manager->priv->max_idle_notification, NULL);
+ }
+
+ g_free (body);
+ g_free (summary);
+}
+
+static gboolean
+_on_max_idle_warning_2_timeout (GsmManager *manager)
+{
+ manager->priv->max_idle_warning_timeout_id = 0;
+
+ g_debug ("Note: will perform idle action in %f seconds",
+ 0.02 * manager->priv->max_idle_time_secs);
+ update_max_idle_notification (manager, 0.02 * manager->priv->max_idle_time_secs);
+
+ return FALSE;
+}
+
+static gboolean
+_on_max_idle_warning_5_timeout (GsmManager *manager)
+{
+ long warn_secs;
+
+ warn_secs = 0.03 * manager->priv->max_idle_time_secs;
+ manager->priv->max_idle_warning_timeout_id
+ = g_timeout_add_seconds (warn_secs,
+ (GSourceFunc)_on_max_idle_warning_2_timeout,
+ manager);
+ g_debug ("Note: will perform idle action in %f seconds",
+ 0.05 * manager->priv->max_idle_time_secs);
+ update_max_idle_notification (manager, 0.05 * manager->priv->max_idle_time_secs);
+
+ return FALSE;
+}
+
+static gboolean
+_on_max_idle_warning_10_timeout (GsmManager *manager)
+{
+ long warn_secs;
+
+ warn_secs = 0.05 * manager->priv->max_idle_time_secs;
+ manager->priv->max_idle_warning_timeout_id
+ = g_timeout_add_seconds (warn_secs,
+ (GSourceFunc)_on_max_idle_warning_5_timeout,
+ manager);
+ g_debug ("Note: will perform idle action in %f seconds",
+ 0.1 * manager->priv->max_idle_time_secs);
+ update_max_idle_notification (manager, 0.1 * manager->priv->max_idle_time_secs);
+
+ return FALSE;
+}
+
+static gboolean
+_on_max_idle_warning_20_timeout (GsmManager *manager)
+{
+ long warn_secs;
+
+ warn_secs = 0.1 * manager->priv->max_idle_time_secs;
+ manager->priv->max_idle_warning_timeout_id
+ = g_timeout_add_seconds (warn_secs,
+ (GSourceFunc)_on_max_idle_warning_10_timeout,
+ manager);
+ g_debug ("Note: will perform idle action in %f seconds",
+ 0.2 * manager->priv->max_idle_time_secs);
+
+ update_max_idle_notification (manager, 0.2 * manager->priv->max_idle_time_secs);
+
+ return FALSE;
+}
+
+static void
+reset_max_idle_timer (GsmManager *manager)
+{
+ int status;
+
+ g_object_get (manager->priv->presence, "status", &status, NULL);
+
+
+ g_debug ("Resetting max idle timer status=%d action=%d time=%ds",
+ status, manager->priv->max_idle_action, manager->priv->max_idle_time_secs);
+ if (manager->priv->max_idle_timeout_id > 0) {
+ g_source_remove (manager->priv->max_idle_timeout_id);
+ manager->priv->max_idle_timeout_id = 0;
+ }
+ if (manager->priv->max_idle_warning_timeout_id > 0) {
+ g_source_remove (manager->priv->max_idle_warning_timeout_id);
+ manager->priv->max_idle_warning_timeout_id = 0;
+ }
+
+ if (status == GSM_PRESENCE_STATUS_IDLE
+ && manager->priv->max_idle_action != ACTION_NONE) {
+ long warn_secs;
+
+ /* start counting now. probably isn't quite
+ right if we're handling a configuration
+ value change but it may not matter */
+
+ manager->priv->max_idle_timeout_id
+ = g_timeout_add_seconds (manager->priv->max_idle_time_secs,
+ (GSourceFunc)_on_max_idle_time_timeout,
+ manager);
+
+ /* start warning at 80% of the way through the idle */
+ warn_secs = 0.8 * manager->priv->max_idle_time_secs;
+ manager->priv->max_idle_warning_timeout_id
+ = g_timeout_add_seconds (warn_secs,
+ (GSourceFunc)_on_max_idle_warning_20_timeout,
+ manager);
+ }
+}
+
+static void
on_gconf_key_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
@@ -2364,6 +2717,32 @@ on_gconf_key_changed (GConfClient *clien
} else {
invalid_type_warning (key);
}
+ } else if (strcmp (key, KEY_MAX_IDLE_TIME) == 0) {
+ if (value->type == GCONF_VALUE_INT) {
+ int t;
+
+ t = gconf_value_get_int (value);
+
+ manager->priv->max_idle_time_secs = t * 60;
+ reset_max_idle_timer (manager);
+ } else {
+ invalid_type_warning (key);
+ }
+ } else if (strcmp (key, KEY_MAX_IDLE_ACTION) == 0) {
+ if (value->type == GCONF_VALUE_STRING) {
+ int action;
+ const char *str;
+
+ str = gconf_value_get_string (value);
+ if (gconf_string_to_enum (actions_enum_map, str, &action)) {
+ manager->priv->max_idle_action = action;
+ } else {
+ manager->priv->max_idle_action = ACTION_NONE;
+ }
+ reset_max_idle_timer (manager);
+ } else {
+ invalid_type_warning (key);
+ }
} else if (strcmp (key, KEY_LOCK_DISABLE) == 0) {
if (value->type == GCONF_VALUE_BOOL) {
gboolean disabled;
@@ -2401,6 +2780,7 @@ on_presence_status_changed (GsmPresence
consolekit = gsm_get_consolekit ();
gsm_consolekit_set_session_idle (consolekit,
(status == GSM_PRESENCE_STATUS_IDLE));
+ reset_max_idle_timer (manager);
}
static void
@@ -2451,6 +2831,7 @@ gsm_manager_init (GsmManager *manager)
NULL, NULL);
load_idle_delay_from_gconf (manager);
+ load_max_idle_from_gconf (manager);
}
static void
@@ -2757,19 +3138,6 @@ request_hibernate (GsmManager *manager)
gtk_widget_show (manager->priv->inhibit_dialog);
}
-
-static void
-request_logout (GsmManager *manager,
- gboolean forceful_logout)
-{
- g_debug ("GsmManager: requesting logout");
-
- manager->priv->forceful_logout = forceful_logout;
- manager->priv->logout_type = GSM_MANAGER_LOGOUT_LOGOUT;
-
- end_phase (manager);
-}
-
static void
request_switch_user (GsmManager *manager)
{
diff -up gnome-session-2.31.6/gnome-session/gsm-presence.c.max-idle gnome-session-2.31.6/gnome-session/gsm-presence.c
--- gnome-session-2.31.6/gnome-session/gsm-presence.c.max-idle 2010-02-09 08:22:01.000000000 -0500
+++ gnome-session-2.31.6/gnome-session/gsm-presence.c 2010-08-06 20:06:05.281048002 -0400
@@ -66,6 +66,7 @@ enum {
PROP_STATUS_TEXT,
PROP_IDLE_ENABLED,
PROP_IDLE_TIMEOUT,
+ PROP_SCREENSAVER_ACTIVE,
};
@@ -187,6 +188,7 @@ on_screensaver_active_changed (DBusGProx
presence->priv->screensaver_active = is_active;
reset_idle_watch (presence);
set_session_idle (presence, is_active);
+ g_object_notify (G_OBJECT (presence), "screensaver-active");
}
}
@@ -439,6 +441,9 @@ gsm_presence_get_property (GObject *o
case PROP_IDLE_TIMEOUT:
g_value_set_uint (value, self->priv->idle_timeout);
break;
+ case PROP_SCREENSAVER_ACTIVE:
+ g_value_set_boolean (value, self->priv->screensaver_active);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -532,6 +537,13 @@ gsm_presence_class_init (GsmPresenceClas
G_MAXINT,
300000,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_SCREENSAVER_ACTIVE,
+ g_param_spec_boolean ("screensaver-active",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
dbus_g_object_type_install_info (GSM_TYPE_PRESENCE, &dbus_glib_gsm_presence_object_info);
dbus_g_error_domain_register (GSM_PRESENCE_ERROR, NULL, GSM_PRESENCE_TYPE_ERROR);
diff -up gnome-session-2.31.6/gnome-session/main.c.max-idle gnome-session-2.31.6/gnome-session/main.c
--- gnome-session-2.31.6/gnome-session/main.c.max-idle 2010-03-29 19:46:51.000000000 -0400
+++ gnome-session-2.31.6/gnome-session/main.c 2010-08-06 20:06:05.282048002 -0400
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#include "gdm-signal-handler.h"
#include "gdm-log.h"
@@ -471,6 +472,8 @@ main (int argc, char **argv)
exit (1);
}
+ notify_init ("GNOME session manager");
+
gdm_log_init ();
gdm_log_set_debug (debug);