diff -uprN gnome-session-2.28.0/gnome-session/gsm-consolekit.c gnome-session-2.28.0-new/gnome-session/gsm-consolekit.c --- gnome-session-2.28.0/gnome-session/gsm-consolekit.c 2009-09-09 19:16:53.000000000 +0800 +++ gnome-session-2.28.0-new/gnome-session/gsm-consolekit.c 2009-11-10 16:58:17.029348387 +0800 @@ -479,6 +479,70 @@ gsm_consolekit_attempt_stop (GsmConsolek } } +void +gsm_consolekit_get_available_systems (GsmConsolekit *manager, GPtrArray **array) +{ + gboolean res; + GError *error; + + error = NULL; + + if (!gsm_consolekit_ensure_ck_connection (manager, &error)) { + g_warning ("Could not connect to ConsoleKit: %s", + error->message); + emit_stop_complete (manager, error); + g_error_free (error); + return; + } + + res = dbus_g_proxy_call_with_timeout (manager->priv->ck_proxy, + "GetAvailableOperatingSystems", + INT_MAX, + &error, + G_TYPE_INVALID, + dbus_g_type_get_collection ("GPtrArray", OS_STRUCT_TYPE), + array, + G_TYPE_INVALID); + + if (!res) { + g_warning ("Unable to get available operating system: %s", error->message); + g_error_free (error); + } +} + +void +gsm_consolekit_restart_with_parameters (GsmConsolekit *manager, + const gchar *parameters) +{ + gboolean res; + GError *error; + + error = NULL; + + if (!gsm_consolekit_ensure_ck_connection (manager, &error)) { + g_warning ("Could not connect to ConsoleKit: %s", + error->message); + emit_stop_complete (manager, error); + g_error_free (error); + return; + } + + res = dbus_g_proxy_call_with_timeout (manager->priv->ck_proxy, + "RestartWithParameters", + INT_MAX, + &error, + G_TYPE_STRING, + parameters, + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (!res) { + g_warning ("Unable to restart system: %s", error->message); + emit_restart_complete (manager, error); + g_error_free (error); + } +} + static gboolean get_current_session_id (DBusConnection *connection, char **session_id) diff -uprN gnome-session-2.28.0/gnome-session/gsm-consolekit.h gnome-session-2.28.0-new/gnome-session/gsm-consolekit.h --- gnome-session-2.28.0/gnome-session/gsm-consolekit.h 2009-04-20 02:26:52.000000000 +0800 +++ gnome-session-2.28.0-new/gnome-session/gsm-consolekit.h 2009-11-10 16:58:17.029557135 +0800 @@ -94,6 +94,18 @@ void gsm_consolekit_set_sess gchar *gsm_consolekit_get_current_session_type (GsmConsolekit *manager); +#define OS_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \ + G_TYPE_INT, \ + G_TYPE_STRING, \ + G_TYPE_STRING, \ + G_TYPE_STRING, \ + G_TYPE_BOOLEAN, \ + G_TYPE_INVALID)) + + +void gsm_consolekit_get_available_systems (GsmConsolekit *manager, GPtrArray **array); +void gsm_consolekit_with_with_parameters (GsmConsolekit *manager, const gchar *parameters); + GsmConsolekit *gsm_get_consolekit (void); G_END_DECLS diff -uprN gnome-session-2.28.0/gnome-session/gsm-logout-dialog.c gnome-session-2.28.0-new/gnome-session/gsm-logout-dialog.c --- gnome-session-2.28.0/gnome-session/gsm-logout-dialog.c 2009-11-10 17:44:49.039510013 +0800 +++ gnome-session-2.28.0-new/gnome-session/gsm-logout-dialog.c 2009-11-10 17:43:21.340885644 +0800 @@ -59,6 +59,9 @@ struct _GsmLogoutDialogPrivate unsigned int timeout_id; unsigned int default_response; + + unsigned int fast; + int id; }; static GsmLogoutDialog *current_dialog = NULL; @@ -140,6 +143,9 @@ gsm_logout_dialog_init (GsmLogoutDialog logout_dialog->priv->timeout = 0; logout_dialog->priv->default_response = GTK_RESPONSE_CANCEL; + logout_dialog->priv->fast = 1; + logout_dialog->priv->id = -1; + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (logout_dialog), TRUE); gtk_window_set_keep_above (GTK_WINDOW (logout_dialog), TRUE); gtk_window_stick (GTK_WINDOW (logout_dialog)); @@ -352,6 +358,237 @@ gsm_logout_dialog_set_timeout (GsmLogout logout_dialog); } +#if defined(__x86) || defined(__x86__) +static void +fast_reboot_cb (GtkWidget *button, gpointer data) +{ + GsmLogoutDialog *logout_dialog = (GsmLogoutDialog *)data; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + logout_dialog->priv->fast = 1; + } else { + logout_dialog->priv->fast = 0; + } +} + +/* Option to skip boot menu on restart. */ +static GtkWidget * +get_fast_reboot_option (GsmLogoutDialog *logout_dialog) +{ + GtkWidget *check; + char *obuf = NULL; + + /* SUN_BRANDING */ + check = gtk_check_button_new_with_mnemonic (_("S_kip boot menu on restart")); + gtk_widget_show (check); + g_signal_connect (GTK_WIDGET (check), + "toggled", + G_CALLBACK (fast_reboot_cb), + logout_dialog); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (check), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE); + + return check; +} + +static void +boot_environment_cb (GtkWidget *button, gpointer data) +{ + GsmLogoutDialog *logout_dialog = (GsmLogoutDialog *)data; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + gint id; + + id = (gint)g_object_get_data (G_OBJECT (button), "id"); + logout_dialog->priv->id = id; + } +} + +static GtkWidget * +get_warning () +{ + GtkBox *hbox; + GtkImage *image; + GtkWidget *label; + + hbox = gtk_hbox_new (FALSE, 0); + + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_show (image); + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); + label = gtk_label_new (NULL); + gtk_widget_show (label); + gtk_label_set_markup (GTK_LABEL (label), + /* SUN_BRANDING */ + _("Options apply only after Restart, not after Shut Down")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + return hbox; +} + +/* Options to choose BE. */ +static GtkWidget * +get_be_option (GsmLogoutDialog *logout_dialog) +{ + GtkWidget *warning; + GtkWidget *label; + GtkWidget *radio; + GtkWidget *scroll; + GtkWidget *vbox; + GSList *group; + GPtrArray *array = NULL; + int i=0; + warning = get_warning (); + gtk_widget_show (warning); + + /* SUN_BRANDING */ + label = gtk_label_new_with_mnemonic (_("_Default boot environment at next restart:")); + gtk_widget_show (label); + + vbox = gtk_vbox_new (FALSE, 2); + gtk_widget_show (vbox); + + gsm_consolekit_get_available_systems (logout_dialog->priv->consolekit, + &array); + group = NULL; + for (i = 0; i < array->len; i++) { + GValue elem = {0}; + gint id; + gchar *name; + gboolean is_default = FALSE; + + g_value_init (&elem, OS_STRUCT_TYPE); + g_value_set_static_boxed (&elem, g_ptr_array_index (array, i)); + dbus_g_type_struct_get (&elem, + 0, &id, + 3, &name, + 4, &is_default, + G_MAXUINT); + + radio = gtk_radio_button_new_with_label (group, name); + gtk_widget_show (radio); + g_object_set_data (G_OBJECT (radio), "id", (gpointer)id); + if (is_default) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), + TRUE); + logout_dialog->priv->id = id; + } + gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0); + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); + g_signal_connect (GTK_WIDGET (radio), + "toggled", + G_CALLBACK (boot_environment_cb), + logout_dialog); + } + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_show (scroll); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), + vbox); + + /* a new vbox to put label, scrolled window and warning in */ + vbox = gtk_vbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), scroll, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), warning, FALSE, FALSE, 0); + + if (array->len > 1) + gtk_widget_show (vbox); + g_ptr_array_free (array, TRUE); + + return vbox; +} + +static void +create_fastreboot_options (GsmLogoutDialog *logout_dialog) +{ + GtkWidget *expander; + GtkWidget *align; + GtkWidget *check; + GtkWidget *be; + GtkWidget *hbox; + GtkWidget *vbox; + GList *list,*l; + gint spacing; + gint size; + + /* SUN_BRANDING */ + expander = gtk_expander_new_with_mnemonic (_("_More Options")); + gtk_widget_show (expander); + gtk_widget_style_get (expander, "expander-size", &size, + "expander-spacing", &spacing, NULL); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox); + + check = get_fast_reboot_option (logout_dialog); + align = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + gtk_widget_show (align); + gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, + (size + 2 * spacing), 0); + gtk_container_add (GTK_CONTAINER (align), check); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 10); + + be = get_be_option (logout_dialog); + align = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + gtk_widget_show (align); + gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, + (size + 2 * spacing), 0); + gtk_container_add (GTK_CONTAINER (align), be); + gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (expander), vbox); + + /* + * Find the right container to put the expander in. + * This is gtk dialog imeplementation specific. + * So if there is something wrong with the layout + * the code need to be udpated + */ + hbox = NULL; + vbox = gtk_dialog_get_content_area (GTK_DIALOG + (logout_dialog)); + list = gtk_container_get_children (GTK_CONTAINER (vbox)); + for (l = list; l != NULL; l = g_list_next (l)) { + GtkWidget *widget; + + widget = l->data; + if (GTK_IS_HBOX(widget)) { + hbox = widget; + break; + } + } + g_list_free (list); + g_assert (hbox != NULL); + + vbox = NULL; + list = gtk_container_get_children (GTK_CONTAINER (hbox)); + for (l = list; l != NULL; l = g_list_next (l)) { + GtkWidget *widget; + + widget = l->data; + if (GTK_IS_VBOX(widget)) { + vbox = widget; + break; + } + } + g_list_free (list); + g_assert (vbox != NULL); + + if (vbox) { + gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, + FALSE, 10); + } else { + gtk_widget_destroy (expander); + } + + return; +} +#endif + + static GtkWidget * gsm_get_dialog (GsmDialogLogoutType type, GdkScreen *screen, @@ -418,6 +653,10 @@ gsm_get_dialog (GsmDialogLogoutType type } if (gsm_logout_supports_reboot (logout_dialog)) { +#if defined(__x86) || defined(__x86__) + /* fast reboot support */ + create_fastreboot_options(logout_dialog); +#endif gtk_dialog_add_button (GTK_DIALOG (logout_dialog), _("_Restart"), GSM_LOGOUT_RESPONSE_REBOOT); @@ -454,6 +691,21 @@ gsm_get_dialog (GsmDialogLogoutType type return GTK_WIDGET (logout_dialog); } +gchar * +gsm_logout_dialog_get_restart_parameters (GsmLogoutDialog *logout_dialog) +{ + gchar *param = NULL; + + if (logout_dialog->priv->id < 0) + return NULL; + + param = g_strdup_printf("id:%d fast:%d", + logout_dialog->priv->id, + logout_dialog->priv->fast); + + return param; +} + GtkWidget * gsm_get_shutdown_dialog (GdkScreen *screen, guint32 activate_time) diff -uprN gnome-session-2.28.0/gnome-session/gsm-logout-dialog.h gnome-session-2.28.0-new/gnome-session/gsm-logout-dialog.h --- gnome-session-2.28.0/gnome-session/gsm-logout-dialog.h 2009-04-20 02:26:52.000000000 +0800 +++ gnome-session-2.28.0-new/gnome-session/gsm-logout-dialog.h 2009-11-10 16:58:17.030235487 +0800 @@ -68,6 +68,8 @@ GtkWidget *gsm_get_logout_dialog GtkWidget *gsm_get_shutdown_dialog (GdkScreen *screen, guint32 activate_time); +gchar *gsm_logout_dialog_get_restart_parameters (GsmLogoutDialog *logout_dialog); + G_END_DECLS #endif /* __GSM_LOGOUT_DIALOG_H__ */ diff -uprN gnome-session-2.28.0/gnome-session/gsm-manager.c gnome-session-2.28.0-new/gnome-session/gsm-manager.c diff -uprN gnome-session-2.28.0/gnome-session/gsm-manager.c.orig gnome-session-2.28.0-new/gnome-session/gsm-manager.c.orig --- gnome-session-2.28.0/gnome-session/gsm-manager.c 2009-11-10 17:44:49.055937229 +0800 +++ gnome-session-2.28.0/gnome-session/gsm-manager.c 2009-11-10 16:58:17.031615520 +0800 @@ -132,6 +132,8 @@ struct GsmManagerPrivate DBusGProxy *bus_proxy; DBusGConnection *connection; + + gchar *parameters; }; enum { @@ -416,7 +418,8 @@ gsm_manager_quit (GsmManager *manager) "request-completed", G_CALLBACK (quit_request_completed), GINT_TO_POINTER (GDM_LOGOUT_ACTION_REBOOT)); - gsm_consolekit_attempt_restart (consolekit); + gsm_consolekit_restart_with_parameters (consolekit, + manager->priv->parameters); break; case GSM_MANAGER_LOGOUT_REBOOT_GDM: gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT); @@ -2176,6 +2179,11 @@ gsm_manager_dispose (GObject *object) manager->priv->gconf_client = NULL; } + if (manager->priv->parameters) { + g_free (manager->priv->parameters); + manager->priv->parameters = NULL; + } + G_OBJECT_CLASS (gsm_manager_parent_class)->dispose (object); } @@ -2800,6 +2808,8 @@ logout_dialog_response (GsmLogoutDialog request_shutdown (manager); break; case GSM_LOGOUT_RESPONSE_REBOOT: + manager->priv->parameters = + gsm_logout_dialog_get_restart_parameters (logout_dialog); request_reboot (manager); break; case GSM_LOGOUT_RESPONSE_LOGOUT: