summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosselin Mouette <joss@malsain.org>2011-05-17 16:10:37 -0400
committerRay Strode <rstrode@redhat.com>2011-05-19 11:53:33 -0400
commit7efd04ace421b909f0de7d031e8616c98f569b83 (patch)
tree8ff91e1fc3f7c62978cdcdc1f7c9d6e25fd29ffb
parent29020f729640983f5604f90b2a8a792f26b1d33e (diff)
downloadgdm-7efd04ace421b909f0de7d031e8616c98f569b83.tar.gz
greeter: add small delay when presenting messages
When PAM sends a message up to the greeter to show the user, it shows it right away, immediately overwriting any previous message. This commit introduces a message queue, so that each pending message gets a reasonable amount of time on screen for the user to read. https://bugzilla.gnome.org/show_bug.cgi?id=583856
-rw-r--r--gui/simple-greeter/gdm-greeter-login-window.c160
1 files changed, 150 insertions, 10 deletions
diff --git a/gui/simple-greeter/gdm-greeter-login-window.c b/gui/simple-greeter/gdm-greeter-login-window.c
index 44e5fd12..e323bc25 100644
--- a/gui/simple-greeter/gdm-greeter-login-window.c
+++ b/gui/simple-greeter/gdm-greeter-login-window.c
@@ -88,6 +88,9 @@
#define GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_LOGIN_WINDOW, GdmGreeterLoginWindowPrivate))
#define GDM_CUSTOM_SESSION "custom"
+#define INFO_MESSAGE_DURATION 2
+#define PROBLEM_MESSAGE_DURATION 3
+
enum {
MODE_UNDEFINED = 0,
MODE_TIMED_LOGIN,
@@ -112,6 +115,7 @@ struct GdmGreeterLoginWindowPrivate
guint display_is_local : 1;
guint is_interactive : 1;
guint user_chooser_loaded : 1;
+ gboolean session_ready_to_start : 1;
GConfClient *client;
gboolean banner_message_enabled;
@@ -131,8 +135,22 @@ struct GdmGreeterLoginWindowPrivate
guint login_button_handler_id;
guint start_session_handler_id;
+
+ GQueue *message_queue;
+ guint message_timeout_id;
+ guint message_queue_empty_reset_dialog_mode;
};
+typedef enum {
+ QUEUE_MESSAGE_TYPE_INFO,
+ QUEUE_MESSAGE_TYPE_PROBLEM
+} QueuedMessageType;
+
+typedef struct {
+ char *text;
+ QueuedMessageType type;
+} QueuedMessage;
+
enum {
PROP_0,
PROP_DISPLAY_IS_LOCAL,
@@ -164,6 +182,8 @@ static void on_user_unchosen (GdmUserChooserWidget *user_chooser,
static void switch_mode (GdmGreeterLoginWindow *login_window,
int number);
static void update_banner_message (GdmGreeterLoginWindow *login_window);
+static void reset_dialog (GdmGreeterLoginWindow *login_window,
+ guint dialog_mode);
G_DEFINE_TYPE (GdmGreeterLoginWindow, gdm_greeter_login_window, GTK_TYPE_WINDOW)
@@ -225,6 +245,96 @@ set_message (GdmGreeterLoginWindow *login_window,
}
static void
+free_queued_message (QueuedMessage *message)
+{
+ g_free (message->text);
+ g_slice_free (QueuedMessage, message);
+}
+
+static void
+purge_message_queue (GdmGreeterLoginWindow *login_window)
+{
+ if (login_window->priv->message_timeout_id) {
+ g_source_remove (login_window->priv->message_timeout_id);
+ login_window->priv->message_timeout_id = 0;
+ }
+
+ g_queue_foreach (login_window->priv->message_queue,
+ (GFunc) free_queued_message,
+ NULL);
+ g_queue_clear (login_window->priv->message_queue);
+
+ login_window->priv->message_queue_empty_reset_dialog_mode = MODE_UNDEFINED;
+}
+
+static gboolean
+set_next_message_or_continue (GdmGreeterLoginWindow *login_window)
+{
+ if (!g_queue_is_empty (login_window->priv->message_queue)) {
+ int duration;
+ gboolean needs_beep;
+
+ QueuedMessage *message;
+ message = (QueuedMessage *) g_queue_pop_head (login_window->priv->message_queue);
+
+ switch (message->type) {
+ case QUEUE_MESSAGE_TYPE_INFO:
+ duration = INFO_MESSAGE_DURATION;
+ needs_beep = FALSE;
+ break;
+ case QUEUE_MESSAGE_TYPE_PROBLEM:
+ duration = PROBLEM_MESSAGE_DURATION;
+ needs_beep = TRUE;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ set_message (login_window, message->text);
+ login_window->priv->message_timeout_id = g_timeout_add_seconds (duration,
+ (GSourceFunc) set_next_message_or_continue,
+ login_window);
+ if (needs_beep) {
+ gdk_window_beep (gtk_widget_get_window (GTK_WIDGET (login_window)));
+ }
+
+ free_queued_message (message);
+ } else {
+ set_message (login_window, "");
+ login_window->priv->message_timeout_id = 0;
+
+ if (login_window->priv->message_queue_empty_reset_dialog_mode != MODE_UNDEFINED) {
+ /* All messages have been shown, reset */
+ g_debug ("GdmGreeterLoginWindow: finally resetting dialog");
+ reset_dialog (login_window,
+ login_window->priv->message_queue_empty_reset_dialog_mode);
+
+ } else if (login_window->priv->session_ready_to_start) {
+ /* All messages have been shown, proceed */
+ g_debug ("GdmGreeterLoginWindow: finally starting session");
+ g_signal_emit (login_window, signals[START_SESSION], 0);
+ }
+ }
+ return FALSE;
+}
+
+static void
+queue_message (GdmGreeterLoginWindow *login_window,
+ QueuedMessageType message_type,
+ const char *text)
+{
+ QueuedMessage *message = g_slice_new (QueuedMessage);
+
+ message->text = g_strdup (text);
+ message->type = message_type;
+
+ g_queue_push_tail (login_window->priv->message_queue, message);
+
+ if (login_window->priv->message_timeout_id == 0) {
+ set_next_message_or_continue (login_window);
+ }
+}
+
+static void
on_user_interaction (GdmGreeterLoginWindow *login_window)
{
g_debug ("GdmGreeterLoginWindow: user is interacting with session!\n");
@@ -641,6 +751,9 @@ reset_dialog (GdmGreeterLoginWindow *login_window,
login_window->priv->num_queries = 0;
+ purge_message_queue (login_window);
+ login_window->priv->session_ready_to_start = FALSE;
+
if (dialog_mode == MODE_SELECTION) {
if (login_window->priv->timed_login_enabled) {
gdm_chooser_widget_set_item_timer (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser),
@@ -710,6 +823,11 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window)
{
g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
+ if (login_window->priv->message_queue_empty_reset_dialog_mode != MODE_UNDEFINED) {
+ g_debug ("GdmGreeterLoginWindow: Ignoring daemon Ready event since still showing messages");
+ return TRUE;
+ }
+
set_sensitive (GDM_GREETER_LOGIN_WINDOW (login_window), TRUE);
set_ready (GDM_GREETER_LOGIN_WINDOW (login_window));
set_focus (GDM_GREETER_LOGIN_WINDOW (login_window));
@@ -732,16 +850,27 @@ gdm_greeter_login_window_ready (GdmGreeterLoginWindow *login_window)
return TRUE;
}
+static void
+reset_dialog_after_messages (GdmGreeterLoginWindow *login_window,
+ guint dialog_mode)
+{
+ if (!g_queue_is_empty (login_window->priv->message_queue)) {
+ g_debug ("GdmGreeterLoginWindow: will reset dialog after pending messages");
+ login_window->priv->message_queue_empty_reset_dialog_mode = dialog_mode;
+ } else {
+ g_debug ("GdmGreeterLoginWindow: resetting dialog");
+ reset_dialog (login_window, dialog_mode);
+ }
+
+}
+
gboolean
gdm_greeter_login_window_authentication_failed (GdmGreeterLoginWindow *login_window)
{
g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
g_debug ("GdmGreeterLoginWindow: got authentication failed");
-
- /* FIXME: shake? */
- reset_dialog (login_window, MODE_AUTHENTICATION);
-
+ reset_dialog_after_messages (login_window, MODE_AUTHENTICATION);
return TRUE;
}
@@ -751,7 +880,7 @@ gdm_greeter_login_window_reset (GdmGreeterLoginWindow *login_window)
g_return_val_if_fail (GDM_IS_GREETER_LOGIN_WINDOW (login_window), FALSE);
g_debug ("GdmGreeterLoginWindow: got reset");
- reset_dialog (login_window, MODE_SELECTION);
+ reset_dialog_after_messages (login_window, MODE_SELECTION);
return TRUE;
}
@@ -764,7 +893,9 @@ gdm_greeter_login_window_info (GdmGreeterLoginWindow *login_window,
g_debug ("GdmGreeterLoginWindow: info: %s", text);
- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text);
+ queue_message (GDM_GREETER_LOGIN_WINDOW (login_window),
+ QUEUE_MESSAGE_TYPE_INFO,
+ text);
maybe_show_cancel_button (login_window);
return TRUE;
@@ -779,8 +910,9 @@ gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window,
g_debug ("GdmGreeterLoginWindow: problem: %s", text);
maybe_show_cancel_button (login_window);
- set_message (GDM_GREETER_LOGIN_WINDOW (login_window), text);
- gdk_window_beep (gtk_widget_get_window (GTK_WIDGET (login_window)));
+ queue_message (GDM_GREETER_LOGIN_WINDOW (login_window),
+ QUEUE_MESSAGE_TYPE_PROBLEM,
+ text);
return TRUE;
}
@@ -834,8 +966,11 @@ static void
gdm_greeter_login_window_start_session_when_ready (GdmGreeterLoginWindow *login_window)
{
if (login_window->priv->is_interactive) {
- g_debug ("GdmGreeterLoginWindow: starting session");
- g_signal_emit (login_window, signals[START_SESSION], 0);
+ login_window->priv->session_ready_to_start = TRUE;
+
+ if (login_window->priv->message_timeout_id == 0) {
+ set_next_message_or_continue (login_window);
+ }
} else {
g_debug ("GdmGreeterLoginWindow: not starting session since "
"user hasn't had an opportunity to pick language "
@@ -1737,6 +1872,8 @@ gdm_greeter_login_window_init (GdmGreeterLoginWindow *login_window)
login_window->priv = GDM_GREETER_LOGIN_WINDOW_GET_PRIVATE (login_window);
login_window->priv->timed_login_enabled = FALSE;
login_window->priv->dialog_mode = MODE_UNDEFINED;
+ login_window->priv->message_queue = g_queue_new ();
+ login_window->priv->message_queue_empty_reset_dialog_mode = MODE_UNDEFINED;
client = gconf_client_get_default ();
error = NULL;
@@ -1800,6 +1937,9 @@ gdm_greeter_login_window_finalize (GObject *object)
g_object_unref (login_window->priv->client);
}
+ purge_message_queue (login_window);
+ g_queue_free (login_window->priv->message_queue);
+
G_OBJECT_CLASS (gdm_greeter_login_window_parent_class)->finalize (object);
}