[gnome-session] gsm-manager: Improve the experience when required components fail



commit 4df48234f85f0a4cb617be7dc4dbf925fcc996f6
Author: Colin Walters <walters verbum org>
Date:   Tue Mar 22 14:19:49 2011 -0400

    gsm-manager: Improve the experience when required components fail
    
    Instead of just failing and leaving the user no way out, present
    a "fail whale" that allows the user to logout and try again.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=645251

 gnome-session/gsm-app.c               |   18 +-
 gnome-session/gsm-fail-whale-dialog.c |  447 +++++++++++++++++---------------
 gnome-session/gsm-fail-whale-dialog.h |   12 +-
 gnome-session/gsm-manager.c           |   53 ++---
 gnome-session/gsm-manager.h           |    2 -
 5 files changed, 267 insertions(+), 265 deletions(-)
---
diff --git a/gnome-session/gsm-app.c b/gnome-session/gsm-app.c
index ce2d5b2..eb73c25 100644
--- a/gnome-session/gsm-app.c
+++ b/gnome-session/gsm-app.c
@@ -31,8 +31,8 @@
 
 #define GSM_APP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_APP, GsmAppPrivate))
 
-/* This number was apparently picked mostly arbitrarily */
-#define APP_RESTART_LIMIT 20
+/* If a component crashes twice within a minute, we count that as a fatal error */
+#define _GSM_APP_RESPAWN_RATELIMIT_SECONDS 60
 
 struct _GsmAppPrivate
 {
@@ -40,7 +40,7 @@ struct _GsmAppPrivate
         char            *app_id;
         int              phase;
         char            *startup_id;
-        guint            restart_count;
+        GTimeVal         last_start_time;
         DBusGConnection *connection;
 };
 
@@ -428,7 +428,7 @@ gsm_app_start (GsmApp  *app,
                GError **error)
 {
         g_debug ("Starting app: %s", app->priv->id);
-        app->priv->restart_count = 0;
+        g_get_current_time (&(app->priv->last_start_time));
         return GSM_APP_GET_CLASS (app)->impl_start (app, error);
 }
 
@@ -436,16 +436,20 @@ gboolean
 gsm_app_restart (GsmApp  *app,
                  GError **error)
 {
+        GTimeVal current_time;
         g_debug ("Re-starting app: %s", app->priv->id);
 
-        app->priv->restart_count++;
-        if (app->priv->restart_count > APP_RESTART_LIMIT) {
+        g_get_current_time (&current_time);
+        if ((current_time.tv_sec - app->priv->last_start_time.tv_sec) < _GSM_APP_RESPAWN_RATELIMIT_SECONDS) {
+                g_warning ("App '%s' respawning too quickly", gsm_app_peek_app_id (app));
                 g_set_error (error,
                              GSM_APP_ERROR,
                              GSM_APP_ERROR_RESTART_LIMIT,
-                             "Application restart limit reached");
+                             "Component '%s' crashing too quickly",
+                             gsm_app_peek_app_id (app));
                 return FALSE;
         }
+        app->priv->last_start_time = current_time;
 
         return GSM_APP_GET_CLASS (app)->impl_restart (app, error);
 }
diff --git a/gnome-session/gsm-fail-whale-dialog.c b/gnome-session/gsm-fail-whale-dialog.c
index 8963c24..7bd656a 100644
--- a/gnome-session/gsm-fail-whale-dialog.c
+++ b/gnome-session/gsm-fail-whale-dialog.c
@@ -25,293 +25,320 @@
 
 #include <glib/gi18n.h>
 
+#include <gtk/gtkx.h>
+
 #include "gsm-fail-whale-dialog.h"
 
 #include "gsm-icon-names.h"
 #include "gsm-manager.h"
+#include "gsm-util.h"
 
 #define GSM_FAIL_WHALE_DIALOG_GET_PRIVATE(o)                                \
         (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_FAIL_WHALE_DIALOG, GsmFailWhaleDialogPrivate))
 
-/* Shared with gsm-logout-dialog.c */
-#define AUTOMATIC_ACTION_TIMEOUT 60
-
-enum
-{
-        GSM_FAIL_WHALE_DIALOG_RESPONSE_LOG_OUT,
-        GSM_FAIL_WHALE_DIALOG_RESPONSE_TRY_RECOVERY
-};
-
 struct _GsmFailWhaleDialogPrivate
 {
-        GsmFailWhaleDialogFailType type;
-
-        int                  timeout;
-        unsigned int         timeout_id;
-
-        unsigned int         default_response;
+        GtkWidget           *button_box;
+        GtkWidget           *message_label;
+        GdkRectangle         geometry;
 };
 
 static GsmFailWhaleDialog *current_dialog = NULL;
 
-static void gsm_fail_whale_dialog_get_preferred_width (GtkWidget *widget,
-                                                       gint      *minimum_size,
-                                                       gint      *natural_size);
-static void gsm_fail_whale_dialog_get_preferred_height (GtkWidget *widget,
-                                                        gint      *minimum_size,
-                                                        gint      *natural_size);
 static void gsm_fail_whale_dialog_destroy  (GsmFailWhaleDialog *fail_dialog,
                                             gpointer         data);
 
-enum {
-        PROP_0,
-        PROP_FAIL_TYPE
-};
-
-G_DEFINE_TYPE (GsmFailWhaleDialog, gsm_fail_whale_dialog, GTK_TYPE_MESSAGE_DIALOG);
+G_DEFINE_TYPE (GsmFailWhaleDialog, gsm_fail_whale_dialog, GTK_TYPE_WINDOW);
 
+/* copied from panel-toplevel.c */
 static void
-gsm_fail_whale_dialog_set_property (GObject      *object,
-                                guint         prop_id,
-                                const GValue *value,
-                                GParamSpec   *pspec)
+_window_move_resize_window (GsmFailWhaleDialog *window,
+                            gboolean  move,
+                            gboolean  resize)
 {
-        GsmFailWhaleDialog *dialog = GSM_FAIL_WHALE_DIALOG (object);
-        (void) dialog;
-
-        switch (prop_id) {
-        case PROP_FAIL_TYPE:
-                dialog->priv->type = g_value_get_enum (value);
-                break;
-        default:
-                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                break;
+        GtkWidget *widget;
+
+        widget = GTK_WIDGET (window);
+
+        g_assert (gtk_widget_get_realized (widget));
+
+        g_debug ("Move and/or resize window x=%d y=%d w=%d h=%d",
+                 window->priv->geometry.x,
+                 window->priv->geometry.y,
+                 window->priv->geometry.width,
+                 window->priv->geometry.height);
+
+        if (move && resize) {
+                gdk_window_move_resize (gtk_widget_get_window (widget),
+                                        window->priv->geometry.x,
+                                        window->priv->geometry.y,
+                                        window->priv->geometry.width,
+                                        window->priv->geometry.height);
+        } else if (move) {
+                gdk_window_move (gtk_widget_get_window (widget),
+                                 window->priv->geometry.x,
+                                 window->priv->geometry.y);
+        } else if (resize) {
+                gdk_window_resize (gtk_widget_get_window (widget),
+                                   window->priv->geometry.width,
+                                   window->priv->geometry.height);
         }
 }
 
 static void
-gsm_fail_whale_dialog_get_property (GObject     *object,
-                                    guint        prop_id,
-                                    GValue      *value,
-                                    GParamSpec  *pspec)
+update_geometry (GsmFailWhaleDialog *fail_dialog)
 {
-        GsmFailWhaleDialog *dialog = GSM_FAIL_WHALE_DIALOG (object);
-        (void) dialog;
-
-        switch (prop_id) {
-        case PROP_FAIL_TYPE:
-                g_value_set_enum (value, dialog->priv->type);
-                break;
-        default:
-                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-                break;
-        }
+        int monitor;
+        GdkScreen *screen;
+
+        screen = gtk_widget_get_screen (GTK_WIDGET (fail_dialog));
+        monitor = gdk_screen_get_primary_monitor (screen);
+
+        gdk_screen_get_monitor_geometry (screen,
+                                         monitor,
+                                         &fail_dialog->priv->geometry);
 }
 
 static void
-gsm_fail_whale_dialog_class_init (GsmFailWhaleDialogClass *klass)
+on_screen_size_changed (GdkScreen          *screen,
+                        GsmFailWhaleDialog *dialog)
 {
-        GObjectClass *gobject_class;
-        GtkWidgetClass *widget_class;
+        gtk_widget_queue_resize (GTK_WIDGET (dialog));
+}
 
-        gobject_class = G_OBJECT_CLASS (klass);
-        widget_class = GTK_WIDGET_CLASS (klass);
-        gobject_class->set_property = gsm_fail_whale_dialog_set_property;
-        gobject_class->get_property = gsm_fail_whale_dialog_get_property;
-        widget_class->get_preferred_width = gsm_fail_whale_dialog_get_preferred_width;
-        widget_class->get_preferred_height = gsm_fail_whale_dialog_get_preferred_height;
+/* derived from tomboy */
+static void
+_window_override_user_time (GsmFailWhaleDialog *window)
+{
+        guint32 ev_time = gtk_get_current_event_time ();
+
+        if (ev_time == 0) {
+                gint ev_mask = gtk_widget_get_events (GTK_WIDGET (window));
+                if (!(ev_mask & GDK_PROPERTY_CHANGE_MASK)) {
+                        gtk_widget_add_events (GTK_WIDGET (window),
+                                               GDK_PROPERTY_CHANGE_MASK);
+                }
+
+                /*
+                 * NOTE: Last resort for D-BUS or other non-interactive
+                 *       openings.  Causes roundtrip to server.  Lame.
+                 */
+                ev_time = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
+        }
 
-        g_type_class_add_private (klass, sizeof (GsmFailWhaleDialogPrivate));
+        gdk_x11_window_set_user_time (gtk_widget_get_window (GTK_WIDGET (window)), ev_time);
 }
 
 static void
-gsm_fail_whale_dialog_init (GsmFailWhaleDialog *fail_dialog)
+gsm_fail_whale_dialog_realize (GtkWidget *widget)
 {
-        fail_dialog->priv = GSM_FAIL_WHALE_DIALOG_GET_PRIVATE (fail_dialog);
+        if (GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->realize) {
+                GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->realize (widget);
+        }
 
-        fail_dialog->priv->timeout_id = 0;
-        fail_dialog->priv->timeout = 0;
-        fail_dialog->priv->default_response = GTK_RESPONSE_CANCEL;
+        _window_override_user_time (GSM_FAIL_WHALE_DIALOG (widget));
+        update_geometry (GSM_FAIL_WHALE_DIALOG (widget));
+        _window_move_resize_window (GSM_FAIL_WHALE_DIALOG (widget), TRUE, TRUE);
 
-        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (fail_dialog), TRUE);
-        gtk_window_set_keep_above (GTK_WINDOW (fail_dialog), TRUE);
-        gtk_window_stick (GTK_WINDOW (fail_dialog));
-
-        g_signal_connect (fail_dialog,
-                          "destroy",
-                          G_CALLBACK (gsm_fail_whale_dialog_destroy),
-                          NULL);
+        g_signal_connect (gtk_window_get_screen (GTK_WINDOW (widget)),
+                          "size_changed",
+                          G_CALLBACK (on_screen_size_changed),
+                          widget);
 }
 
 static void
-gsm_fail_whale_dialog_get_preferred_width (GtkWidget *widget,
-                                           gint      *minimum_size,
-                                           gint      *natural_size)
+gsm_fail_whale_dialog_unrealize (GtkWidget *widget)
 {
-        GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->get_preferred_width (widget,
-                                                              minimum_size,
-                                                              natural_size);
-        if (minimum_size && *minimum_size < 640)
-                *minimum_size = 640;
-        if (natural_size && *natural_size < 640)
-                *natural_size = 640;
+        g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (widget)),
+                                              on_screen_size_changed,
+                                              widget);
+
+        if (GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->unrealize) {
+                GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->unrealize (widget);
+        }
 }
 
 static void
-gsm_fail_whale_dialog_get_preferred_height (GtkWidget *widget,
-                                            gint      *minimum_size,
-                                            gint      *natural_size)
+gsm_fail_whale_dialog_size_request (GtkWidget      *widget,
+                                    GtkRequisition *requisition)
 {
-        GTK_WIDGET_CLASS (gsm_fail_whale_dialog_parent_class)->get_preferred_height (widget,
-                                                                                     minimum_size,
-                                                                                     natural_size);
-        if (minimum_size && *minimum_size < 480)
-                *minimum_size = 480;
-        if (natural_size && *natural_size < 480)
-                *natural_size = 480;
+        GsmFailWhaleDialog *window;
+        GtkBin        *bin;
+        GdkRectangle   old_geometry;
+        int            position_changed = FALSE;
+        int            size_changed = FALSE;
+
+        window = GSM_FAIL_WHALE_DIALOG (widget);
+        bin = GTK_BIN (widget);
+
+        if (gtk_bin_get_child (bin) && gtk_widget_get_visible (gtk_bin_get_child (bin))) {
+                gtk_widget_size_request (gtk_bin_get_child (bin), requisition);
+        }
+
+        update_geometry (window);
+
+        requisition->width  = window->priv->geometry.width;
+        requisition->height = window->priv->geometry.height;
+
+        if (!gtk_widget_get_realized (widget)) {
+                return;
+        }
+
+        if (old_geometry.width  != window->priv->geometry.width ||
+            old_geometry.height != window->priv->geometry.height) {
+                size_changed = TRUE;
+        }
+
+        if (old_geometry.x != window->priv->geometry.x ||
+            old_geometry.y != window->priv->geometry.y) {
+                position_changed = TRUE;
+        }
+
+        _window_move_resize_window (window, position_changed, size_changed);
 }
 
 static void
-gsm_fail_whale_dialog_destroy (GsmFailWhaleDialog *fail_dialog,
-                               gpointer         data)
+gsm_fail_whale_dialog_get_preferred_width (GtkWidget *widget,
+                                           gint      *minimal_width,
+                                           gint      *natural_width)
 {
-        if (fail_dialog->priv->timeout_id != 0) {
-                g_source_remove (fail_dialog->priv->timeout_id);
-                fail_dialog->priv->timeout_id = 0;
-        }
+        GtkRequisition requisition;
 
-        g_assert (current_dialog != NULL);
-        current_dialog = NULL;
+        gsm_fail_whale_dialog_size_request (widget, &requisition);
+
+        *minimal_width = *natural_width = requisition.width;
 }
 
-static gboolean
-gsm_fail_whale_dialog_timeout (gpointer data)
+static void
+gsm_fail_whale_dialog_get_preferred_height (GtkWidget *widget,
+                                            gint      *minimal_height,
+                                            gint      *natural_height)
 {
-        GsmFailWhaleDialog *fail_dialog;
-        char            *seconds_warning;
-        int              seconds_to_show;
+        GtkRequisition requisition;
 
-        fail_dialog = GSM_FAIL_WHALE_DIALOG (data);
+        gsm_fail_whale_dialog_size_request (widget, &requisition);
 
-        if (fail_dialog->priv->timeout == 0) {
-                gtk_dialog_response (GTK_DIALOG (fail_dialog), GSM_FAIL_WHALE_DIALOG_RESPONSE_LOG_OUT);
-                return FALSE;
-        }
+        *minimal_height = *natural_height = requisition.height;
+}
 
-        if (fail_dialog->priv->timeout <= 30) {
-                seconds_to_show = fail_dialog->priv->timeout;
-        } else {
-                seconds_to_show = (fail_dialog->priv->timeout/10) * 10;
+static void
+gsm_fail_whale_dialog_class_init (GsmFailWhaleDialogClass *klass)
+{
+        GObjectClass *gobject_class;
+        GtkWidgetClass *widget_class;
 
-                if (fail_dialog->priv->timeout % 10)
-                        seconds_to_show += 10;
-        }
+        gobject_class = G_OBJECT_CLASS (klass);
+        widget_class = GTK_WIDGET_CLASS (klass);
+
+        widget_class->realize = gsm_fail_whale_dialog_realize;
+        widget_class->unrealize = gsm_fail_whale_dialog_unrealize;
+        widget_class->get_preferred_width = gsm_fail_whale_dialog_get_preferred_width;
+        widget_class->get_preferred_height = gsm_fail_whale_dialog_get_preferred_height;
 
-        /* This string is shared with gsm-logout-dialog.c */
-        seconds_warning = ngettext ("You will be automatically logged "
-                                    "out in %d second.",
-                                    "You will be automatically logged "
-                                    "out in %d seconds.",
-                                    seconds_to_show);
-        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (fail_dialog),
-                                                  seconds_warning,
-                                                  seconds_to_show,
-                                                  NULL);
-        fail_dialog->priv->timeout--;
-
-        return TRUE;
+        g_type_class_add_private (klass, sizeof (GsmFailWhaleDialogPrivate));
 }
 
 static void
-gsm_fail_whale_dialog_on_response (GsmFailWhaleDialog *fail_dialog,
-                                   int                 response_id,
-                                   gpointer            user_data)
+on_logout_clicked (GtkWidget          *button,
+                   GsmFailWhaleDialog *fail_dialog)
 {
-        switch (response_id) {
-        case GSM_FAIL_WHALE_DIALOG_RESPONSE_LOG_OUT:
-                gsm_manager_logout (gsm_manager_get (),
-                                    GSM_MANAGER_LOGOUT_MODE_FORCE,
-                                    NULL);
-                break;
-        case GSM_FAIL_WHALE_DIALOG_RESPONSE_TRY_RECOVERY:
-                gsm_manager_try_recovery (gsm_manager_get ());
-                break;
-        default:
-                g_warning ("gsm-fail-whale-dialog: invalid response");
-                break;
-        }
+        gsm_manager_logout (gsm_manager_get (),
+                            GSM_MANAGER_LOGOUT_MODE_FORCE,
+                            NULL);
+
         gtk_widget_destroy (GTK_WIDGET (fail_dialog));
 }
 
-void
-gsm_fail_whale_dialog_we_failed (GsmFailWhaleDialogFailType fail_type,
-                                 const char *               additional_text)
+static void
+setup_window (GsmFailWhaleDialog *fail_dialog)
 {
-        GsmFailWhaleDialog *fail_dialog;
-        char *primary_text;
-
-        g_printerr ("gnome-session: %s failure: %s\n",
-                    fail_type == GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_FATAL ? "fatal" : "recoverable",
-                    additional_text ? additional_text : "");
-
-        if (current_dialog != NULL) {
-                /* Only allow replacing non-fatal dialogs */
-                if (fail_type == GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_FATAL)
-                        gtk_widget_destroy (GTK_WIDGET (current_dialog));
-                else
-                        return;
-        }
-
-        fail_dialog = g_object_new (GSM_TYPE_FAIL_WHALE_DIALOG,
-                                    "fail-type", fail_type,
-                                    NULL);
+        GtkWidget *alignment;
+        GtkWidget *box;
+        GtkWidget *image;
+        GtkWidget *label;
+        GtkWidget *button;
+        char *markup;
+
+        alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+        gtk_widget_show (alignment);
+        gtk_container_add (GTK_CONTAINER (fail_dialog), alignment);
+        g_object_set (alignment, "valign", GTK_ALIGN_CENTER, NULL);
+
+        box = gtk_vbox_new (FALSE, 10);
+        gtk_widget_show (box);
+        gtk_container_add (GTK_CONTAINER (alignment), box);
+
+        image = gtk_image_new_from_icon_name (GSM_ICON_COMPUTER_FAIL, gsm_util_get_computer_fail_icon_size ());
+        gtk_widget_show (image);
+        gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (NULL);
+        markup = g_strdup_printf ("<b><big>%s</big></b>", _("Oh no!  Something has gone wrong."));
+        gtk_label_set_markup (GTK_LABEL (label), markup);
+        g_free (markup);
+        gtk_widget_show (label);
+        gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+        /* make this changable at some point */
+        fail_dialog->priv->message_label = gtk_label_new (_("A problem has occured and the system can't recover.\nPlease log out and try again."));
+        gtk_label_set_justify (GTK_LABEL (fail_dialog->priv->message_label), GTK_JUSTIFY_CENTER);
+        gtk_label_set_line_wrap (GTK_LABEL (fail_dialog->priv->message_label), TRUE);
+
+        gtk_widget_show (fail_dialog->priv->message_label);
+        gtk_box_pack_start (GTK_BOX (box), fail_dialog->priv->message_label, FALSE, FALSE, 0);
+
+        fail_dialog->priv->button_box = gtk_hbutton_box_new ();
+        gtk_container_set_border_width (GTK_CONTAINER (fail_dialog->priv->button_box), 20);
+        gtk_widget_show (fail_dialog->priv->button_box);
+        gtk_box_pack_end (GTK_BOX (box), fail_dialog->priv->button_box, FALSE, FALSE, 0);
+
+        button = gtk_button_new_with_mnemonic (_("_Log Out"));
+        gtk_widget_show (button);
+        gtk_box_pack_end (GTK_BOX (fail_dialog->priv->button_box), button, FALSE, FALSE, 0);
+        g_signal_connect (button, "clicked", G_CALLBACK (on_logout_clicked), fail_dialog);
+}
 
-        current_dialog = fail_dialog;
+static void
+gsm_fail_whale_dialog_init (GsmFailWhaleDialog *fail_dialog)
+{
+        fail_dialog->priv = GSM_FAIL_WHALE_DIALOG_GET_PRIVATE (fail_dialog);
 
+        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (fail_dialog), TRUE);
+        gtk_window_set_keep_above (GTK_WINDOW (fail_dialog), TRUE);
+        gtk_window_stick (GTK_WINDOW (fail_dialog));
         gtk_window_set_title (GTK_WINDOW (fail_dialog), "");
-
         gtk_window_set_icon_name (GTK_WINDOW (fail_dialog), GSM_ICON_COMPUTER_FAIL);
         gtk_window_set_position (GTK_WINDOW (fail_dialog), GTK_WIN_POS_CENTER_ALWAYS);
+        /* only works if there is a window manager which is unlikely */
+        gtk_window_fullscreen (GTK_WINDOW (fail_dialog));
 
-        switch (fail_type) {
-        case GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_RECOVERABLE:
-                gtk_dialog_add_button (GTK_DIALOG (fail_dialog),
-                                       _("Try _Recovery"),
-                                       GSM_FAIL_WHALE_DIALOG_RESPONSE_TRY_RECOVERY);
-                primary_text = g_strdup_printf (_("A system error has occurred: %s"), additional_text);
-                break;
-        case GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_FATAL:
-                primary_text = g_strdup_printf (_("A fatal system error has occurred: %s"), additional_text);
-                break;
-        default:
-                g_assert_not_reached ();
-                return;
-        }
-
-        gtk_dialog_add_button (GTK_DIALOG (fail_dialog),
-                               _("_Log Out"),
-                               GSM_FAIL_WHALE_DIALOG_RESPONSE_LOG_OUT);
+        setup_window (fail_dialog);
 
-        gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (fail_dialog),
-                                       primary_text);
-        gtk_dialog_set_default_response (GTK_DIALOG (fail_dialog),
-                                         GSM_FAIL_WHALE_DIALOG_RESPONSE_LOG_OUT);
+        g_signal_connect (fail_dialog,
+                          "destroy",
+                          G_CALLBACK (gsm_fail_whale_dialog_destroy),
+                          NULL);
+}
 
-        fail_dialog->priv->timeout = AUTOMATIC_ACTION_TIMEOUT;
+static void
+gsm_fail_whale_dialog_destroy (GsmFailWhaleDialog *fail_dialog,
+                               gpointer         data)
+{
+        g_assert (current_dialog != NULL);
+        current_dialog = NULL;
+}
 
-        gsm_fail_whale_dialog_timeout (fail_dialog);
+void
+gsm_fail_whale_dialog_we_failed (void)
+{
+        GsmFailWhaleDialog *fail_dialog;
 
-        if (fail_dialog->priv->timeout_id != 0) {
-                g_source_remove (fail_dialog->priv->timeout_id);
+        if (current_dialog != NULL) {
+                return;
         }
-        fail_dialog->priv->timeout_id = g_timeout_add (1000,
-                                                       gsm_fail_whale_dialog_timeout,
-                                                       fail_dialog);
-        g_signal_connect (fail_dialog, "response",
-                          G_CALLBACK (gsm_fail_whale_dialog_on_response),
-                          fail_dialog);
-        /* A minimum size to ensure we're seen */
-        gtk_window_set_default_size (GTK_WINDOW (fail_dialog), 640, 480);
+
+        fail_dialog = g_object_new (GSM_TYPE_FAIL_WHALE_DIALOG, NULL);
+        current_dialog = fail_dialog;
         gtk_widget_show (GTK_WIDGET (fail_dialog));
 }
 
diff --git a/gnome-session/gsm-fail-whale-dialog.h b/gnome-session/gsm-fail-whale-dialog.h
index 98f7288..cc43165 100644
--- a/gnome-session/gsm-fail-whale-dialog.h
+++ b/gnome-session/gsm-fail-whale-dialog.h
@@ -39,27 +39,21 @@ typedef struct _GsmFailWhaleDialog         GsmFailWhaleDialog;
 typedef struct _GsmFailWhaleDialogClass    GsmFailWhaleDialogClass;
 typedef struct _GsmFailWhaleDialogPrivate  GsmFailWhaleDialogPrivate;
 
-typedef enum {
-        GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_RECOVERABLE,
-        GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_FATAL
-} GsmFailWhaleDialogFailType;
-
 struct _GsmFailWhaleDialog
 {
-        GtkMessageDialog        parent;
+        GtkWindow                  parent;
 
         GsmFailWhaleDialogPrivate *priv;
 };
 
 struct _GsmFailWhaleDialogClass
 {
-        GtkMessageDialogClass  parent_class;
+        GtkWindowClass  parent_class;
 };
 
 GType        gsm_fail_whale_dialog_get_type   (void) G_GNUC_CONST;
 
-void         gsm_fail_whale_dialog_we_failed  (GsmFailWhaleDialogFailType fail_type,
-                                               const char *additional_text);
+void         gsm_fail_whale_dialog_we_failed  (void);
 
 G_END_DECLS
 
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index fc3539e..e40c426 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -264,15 +264,7 @@ on_required_app_failure (GsmManager  *manager,
                          GsmApp      *app,
                          const char  *msg)
 {
-        char *full_msg;
-        /* Translators: This will look like: Component 'gnome-shell.desktop': Killed by signal 9.
-         * It is admittedly mostly technical goop. */
-        full_msg = g_strdup_printf (_("Component '%s': %s"),
-                                    gsm_app_peek_app_id (app),
-                                    msg);
-        gsm_fail_whale_dialog_we_failed (GSM_FAIL_WHALE_DIALOG_FAIL_TYPE_RECOVERABLE,
-                                         full_msg);
-        g_free (full_msg);
+        gsm_fail_whale_dialog_we_failed ();
 }
 
 
@@ -571,16 +563,25 @@ static void
 app_died (GsmApp     *app,
           GsmManager *manager)
 {
+        GError *error = NULL;
+
         manager->priv->pending_apps = g_slist_remove (manager->priv->pending_apps, app);
         g_signal_handlers_disconnect_by_func (app, app_registered, manager);
 
         g_warning ("Application '%s' killed by signal", gsm_app_peek_app_id (app));
-        if (is_app_required (manager, app))
-                on_required_app_failure (manager, app, _("Killed by signal"));
-        /* For now, we don't do anything with crashes from non-required apps;
-         * practically speaking they will be caught by ABRT/apport type
-         * infrastructure, and it'd be better to pick up the crash from
-         * there and do something un-intrusive about it generically.
+        
+        if (!gsm_app_restart (app, &error)) {
+                if (is_app_required (manager, app)) {
+                        on_required_app_failure (manager, app, _("Killed by signal"));
+                }
+        }
+        /* For now, we don't do anything with crashes from
+         * non-required apps after they hit the restart limit.
+         *
+         * Note that both required and not-required apps will be
+         * caught by ABRT/apport type infrastructure, and it'd be
+         * better to pick up the crash from there and do something
+         * un-intrusive about it generically.
          */
 }
 
@@ -3329,28 +3330,6 @@ gsm_manager_logout (GsmManager *manager,
         return TRUE;
 }
 
-/**
- * gsm_manager_try_recovery:
- * @manager: a #GsmManager
- *
- * Attempt to restart any required components which aren't running.
- */
-void
-gsm_manager_try_recovery (GsmManager     *manager)
-{
-        GSList *iter;
-
-        g_debug ("Trying recovery");
-
-        for (iter = manager->priv->required_apps; iter; iter = iter->next) {
-                GsmApp *app = iter->data;
-
-                if (gsm_app_is_running (app))
-                        continue;
-                start_app_or_warn (manager, app);
-        }
-}
-
 gboolean
 gsm_manager_register_client (GsmManager            *manager,
                              const char            *app_id,
diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h
index 73b6c5e..342a76d 100644
--- a/gnome-session/gsm-manager.h
+++ b/gnome-session/gsm-manager.h
@@ -171,8 +171,6 @@ gboolean            gsm_manager_logout                         (GsmManager     *
                                                                 guint           logout_mode,
                                                                 GError        **error);
 
-void                gsm_manager_try_recovery                   (GsmManager     *manager);
-
 gboolean            gsm_manager_setenv                         (GsmManager     *manager,
                                                                 const char     *variable,
                                                                 const char     *value,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]