--- gnome-session-2.16.1/gnome-session/logout.c +++ gnome-session-2.16.1/gnome-session/logout.c @@ -41,6 +41,15 @@ #include "gdm-logout-action.h" #include "gsm-multiscreen.h" + +enum +{ + GS_RESPONSE_LOGOUT, + GS_RESPONSE_SHUTDOWN, + GS_RESPONSE_RESTART, + GS_RESPONSE_LOCK +}; + enum { OPTION_LOGOUT, @@ -73,7 +82,26 @@ int callback_id; } FadeoutData; +static GtkWidget *ssui_get_tile(GtkWidget *image, const gchar *title, + const gchar *desc); +static void logout_button_clicked(GtkButton *button, gpointer user_data); +static void shutdown_button_clicked(GtkButton *button, gpointer user_data); +static void restart_button_clicked(GtkButton *button, gpointer user_data); +static void lock_button_clicked(GtkButton *button, gpointer user_data); +static gboolean logout_dialog_callback (GtkWidget *dialog); +static gboolean logout_dialog_configure_cb( GtkWidget *widget, + GdkEventConfigure *event, + gpointer data); +static gboolean logout_dialog_focus_out_cb( GtkWidget *widget, + GdkEventFocus *event, + gpointer data); +static void window_get_frame_extents (GdkWindow *window, gint *left, + gint *right, gint *top, gint *bottom); + + static GList *fadeout_windows = NULL; +static GList *ionly_windows = NULL; + /* Go for five seconds */ #define FADE_DURATION 1500.0 @@ -122,115 +150,234 @@ if (elapsed > FADE_DURATION) { - get_current_frame (fadeout, 0.0); - gdk_draw_pixbuf (fadeout->draw_pixmap, - fadeout->gc, - fadeout->frame, - 0, 0, - 0, 0, - fadeout->area.width, - fadeout->area.height, - GDK_RGB_DITHER_NONE, - 0, 0); - gdk_window_clear (fadeout->draw_window); + get_current_frame (fadeout, 0.0); + gdk_draw_pixbuf (fadeout->draw_pixmap, + fadeout->gc, + fadeout->frame, + 0, 0, + 0, 0, + fadeout->area.width, + fadeout->area.height, + GDK_RGB_DITHER_NONE, + 0, 0); + gdk_window_clear (fadeout->draw_window); - fadeout->callback_id = 0; - return FALSE; - } + fadeout->callback_id = 0; + return FALSE; + } percent = elapsed / FADE_DURATION; get_current_frame (fadeout, 1.0 - percent); gdk_draw_pixbuf (fadeout->draw_pixmap, - fadeout->gc, - fadeout->frame, - 0, 0, - 0, 0, - fadeout->area.width, - fadeout->area.height, - GDK_RGB_DITHER_NONE, - 0, 0); + fadeout->gc, + fadeout->frame, + 0, 0, + 0, 0, + fadeout->area.width, + fadeout->area.height, + GDK_RGB_DITHER_NONE, + 0, 0); gdk_window_clear (fadeout->draw_window); gdk_flush (); - + return TRUE; } - + static void -fadeout_screen (GdkScreen *screen, - int monitor) +fadeout_screen (GdkScreen *screen, int monitor) { - GdkWindowAttr attr; - int attr_mask; - GdkGCValues values; - FadeoutData *fadeout; - GdkAtom property = gdk_atom_intern ("_NET_WM_STATE_DISPLAY_MODAL", FALSE); - - if (gdk_x11_screen_supports_net_wm_hint (screen, property)) - return; - - fadeout = g_new (FadeoutData, 1); - - fadeout->screen = screen; - fadeout->monitor = monitor; - - fadeout->area.x = gsm_screen_get_x (screen, monitor); - fadeout->area.y = gsm_screen_get_y (screen, monitor); - fadeout->area.width = gsm_screen_get_width (screen, monitor); - fadeout->area.height = gsm_screen_get_height (screen, monitor); - - fadeout->root_window = gdk_screen_get_root_window (screen); - attr.window_type = GDK_WINDOW_CHILD; - attr.x = fadeout->area.x; - attr.y = fadeout->area.y; - attr.width = fadeout->area.width; - attr.height = fadeout->area.height; - attr.wclass = GDK_INPUT_OUTPUT; - attr.visual = gdk_screen_get_system_visual (fadeout->screen); - attr.colormap = gdk_screen_get_default_colormap (fadeout->screen); - attr.override_redirect = TRUE; - attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_NOREDIR; - - fadeout->draw_window = gdk_window_new (fadeout->root_window, &attr, attr_mask); - fadeout->draw_pixmap = gdk_pixmap_new (fadeout->draw_window, fadeout->area.width, fadeout->area.height, gdk_drawable_get_depth (fadeout->draw_window)); - fadeout_windows = g_list_prepend (fadeout_windows, fadeout); - - fadeout->start_pb = gdk_pixbuf_get_from_drawable (NULL, - fadeout->root_window, - NULL, - fadeout->area.x, - fadeout->area.y, - 0, 0, - fadeout->area.width, - fadeout->area.height); - - fadeout->frame = gdk_pixbuf_copy (fadeout->start_pb); - fadeout->rowstride = gdk_pixbuf_get_rowstride (fadeout->start_pb); + GdkGCValues values; + GdkWindowAttr attr; + int attr_mask; + FadeoutData *fadeout; + FadeoutData *indata; + + indata = g_new (FadeoutData, 1); + + indata->screen = screen; + indata->monitor = monitor; + + indata->area.x = gsm_screen_get_x (screen, monitor); + indata->area.y = gsm_screen_get_y (screen, monitor); + indata->area.width = gsm_screen_get_width (screen, monitor); + indata->area.height = gsm_screen_get_height (screen, monitor); + + indata->root_window = gdk_screen_get_root_window (screen); + + attr.window_type = GDK_WINDOW_CHILD; + attr.x = indata->area.x; + attr.y = indata->area.y; + attr.width = indata->area.width; + attr.height = indata->area.height; + attr.wclass = GDK_INPUT_ONLY; + attr.override_redirect = TRUE; + attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR; + + indata->draw_window = gdk_window_new (indata->root_window, + &attr, attr_mask); + indata->draw_pixmap = NULL; + indata->start_pb = NULL; + indata->frame = NULL; + indata->gc = NULL; + indata->callback_id = 0; + gdk_window_show (indata->draw_window); + ionly_windows = g_list_prepend (ionly_windows, indata); + + GdkAtom property = gdk_atom_intern ("_NET_WM_STATE_DISPLAY_MODAL", FALSE); + // if we have setup our little window manager coolness, then + // just create a GTK_INPUT_ONLY window to handle no input + if(!gdk_x11_screen_supports_net_wm_hint (screen, property)) + { + fadeout = g_new (FadeoutData, 1); - fadeout->start_p = gdk_pixbuf_get_pixels (fadeout->start_pb); - fadeout->frame_p = gdk_pixbuf_get_pixels (fadeout->frame); - - values.subwindow_mode = GDK_INCLUDE_INFERIORS; + fadeout->screen = screen; + fadeout->monitor = monitor; - fadeout->gc = gdk_gc_new_with_values (fadeout->root_window, &values, GDK_GC_SUBWINDOW); + fadeout->area.x = gsm_screen_get_x (screen, monitor); + fadeout->area.y = gsm_screen_get_y (screen, monitor); + fadeout->area.width = gsm_screen_get_width (screen, monitor); + fadeout->area.height = gsm_screen_get_height (screen, monitor); + + fadeout->root_window = gdk_screen_get_root_window (screen); + + attr.window_type = GDK_WINDOW_TOPLEVEL; + attr.x = fadeout->area.x; + attr.y = fadeout->area.y; + attr.width = fadeout->area.width; + attr.height = fadeout->area.height; + attr.wclass = GDK_INPUT_OUTPUT; + attr.visual = gdk_screen_get_system_visual (fadeout->screen); + attr.colormap = gdk_screen_get_default_colormap (fadeout->screen); + attr.override_redirect = FALSE; + attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | + GDK_WA_NOREDIR; + + fadeout->draw_window = gdk_window_new (fadeout->root_window, + &attr, attr_mask); + + gdk_window_set_decorations(fadeout->draw_window, 0); + + fadeout->draw_pixmap = gdk_pixmap_new (fadeout->draw_window, + fadeout->area.width, fadeout->area.height, + gdk_drawable_get_depth (fadeout->draw_window)); + + fadeout_windows = g_list_prepend (fadeout_windows, fadeout); + + fadeout->start_pb = gdk_pixbuf_get_from_drawable (NULL, + fadeout->root_window, + NULL, + fadeout->area.x, + fadeout->area.y, + 0, 0, + fadeout->area.width, + fadeout->area.height); + + fadeout->frame = gdk_pixbuf_copy (fadeout->start_pb); + fadeout->rowstride = gdk_pixbuf_get_rowstride (fadeout->start_pb); + + fadeout->start_p = gdk_pixbuf_get_pixels (fadeout->start_pb); + fadeout->frame_p = gdk_pixbuf_get_pixels (fadeout->frame); + + values.subwindow_mode = GDK_INCLUDE_INFERIORS; + + fadeout->gc = gdk_gc_new_with_values (fadeout->root_window, &values, + GDK_GC_SUBWINDOW); + + gdk_window_set_back_pixmap (fadeout->draw_window, NULL, FALSE); + gdk_window_show (fadeout->draw_window); + + gdk_window_move(fadeout->draw_window, attr.x, attr.y); + gdk_window_stick(fadeout->draw_window); + gdk_window_set_keep_above(fadeout->draw_window, TRUE); + + gdk_draw_pixbuf (fadeout->draw_pixmap, + fadeout->gc, + fadeout->frame, + 0, 0, + 0, 0, + fadeout->area.width, + fadeout->area.height, + GDK_RGB_DITHER_NONE, + 0, 0); + + gdk_window_set_back_pixmap (fadeout->draw_window, + fadeout->draw_pixmap, FALSE); + gdk_window_clear (fadeout->draw_window); + g_get_current_time (&fadeout->start_time); - gdk_window_set_back_pixmap (fadeout->draw_window, NULL, FALSE); - gdk_window_show (fadeout->draw_window); - gdk_draw_pixbuf (fadeout->draw_pixmap, - fadeout->gc, - fadeout->frame, - 0, 0, - 0, 0, - fadeout->area.width, - fadeout->area.height, - GDK_RGB_DITHER_NONE, - 0, 0); - gdk_window_set_back_pixmap (fadeout->draw_window, fadeout->draw_pixmap, FALSE); - gdk_window_clear (fadeout->draw_window); - - g_get_current_time (&fadeout->start_time); - fadeout->callback_id = g_idle_add ((GSourceFunc) fadeout_callback, fadeout); + fadeout->callback_id = g_idle_add ((GSourceFunc) fadeout_callback, + fadeout); + } + +} + +static void +ssui_punch_hole_fadeout_windows (GtkWindow *dialog) +{ + GList *l; + GdkRectangle dialogRect, parentRect; + gint left, right, top, bottom; + gint monitor; + GdkWindow *parent; + GdkOverlapType overlap; + GdkRegion *parentRegion, *dialogRegion; + + // Loop through screens and monitors and punch and fill holes where needed + for (l = ionly_windows; l; l = l->next) + { + FadeoutData *fadeout = l->data; + parent = fadeout->draw_window; + + // don't use this, it doesn't work with compiz correctly + // gdk_window_get_frame_extents(dialog, &dialogRect); + + gdk_window_get_position(GTK_WIDGET(dialog)->window, &dialogRect.x, + &dialogRect.y); + gdk_window_get_geometry(GTK_WIDGET(dialog)->window, NULL, NULL, + &dialogRect.width, &dialogRect.height, NULL); + window_get_frame_extents (GTK_WIDGET(dialog)->window, &left, &right, + &top, &bottom); + dialogRect.x -= left; + dialogRect.y -= top; + dialogRect.width += left + right; + dialogRect.height += top + bottom; + + gdk_window_get_frame_extents(parent, &parentRect); + + // Adjust the dialog rect to be relative to this the parent + dialogRect.x = dialogRect.x - parentRect.x; + dialogRect.y = dialogRect.y - parentRect.y; + + // set the parents rect to be relative to this display (0,0) + parentRect.x = 0; + parentRect.y = 0; + parentRegion = gdk_region_rectangle(&parentRect); + if(parentRegion) + { + overlap = gdk_region_rect_in(parentRegion, &dialogRect); + if(overlap == GDK_OVERLAP_RECTANGLE_OUT) + { + // re-protect the parent + gdk_window_shape_combine_region(parent, NULL, 0, 0); + } + else + { + dialogRegion = gdk_region_rectangle(&dialogRect); + if(dialogRegion) + { + + // subtract the dialog from the parent + gdk_region_subtract(parentRegion, dialogRegion); + gdk_window_shape_combine_region(parent, parentRegion, 0, 0); + + gdk_region_destroy(dialogRegion); + } + } + gdk_region_destroy(parentRegion); + } + } } static void @@ -258,83 +405,52 @@ g_list_free (fadeout_windows); fadeout_windows = NULL; -} - -static GtkWidget * -make_title_label (const char *text) -{ - GtkWidget *label; - char *full; - - full = g_strdup_printf ("%s", text); - label = gtk_label_new (full); - g_free (full); - - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - return label; -} + for (l = ionly_windows; l; l = l->next) + { + FadeoutData *fadeout = l->data; + gdk_window_hide (fadeout->draw_window); -static int -get_default_option (void) -{ - GConfClient *gconf_client; - char *str; - int option; + if (fadeout->callback_id) + g_source_remove (fadeout->callback_id); - gconf_client = gsm_get_conf_client (); - str = gconf_client_get_string (gconf_client, LOGOUT_OPTION_KEY, NULL); + if(fadeout->gc) + g_object_unref (fadeout->gc); + if(fadeout->start_pb) + g_object_unref (fadeout->start_pb); + if(fadeout->frame) + g_object_unref (fadeout->frame); + + if(fadeout->draw_window) + g_object_unref (fadeout->draw_window); + if(fadeout->draw_pixmap) + g_object_unref (fadeout->draw_pixmap); - if (str == NULL || !gconf_string_to_enum (logout_options_lookup_table, str, &option)) - option = OPTION_LOGOUT; + g_free (fadeout); + } - g_free (str); - return option; + g_list_free (ionly_windows); + ionly_windows = NULL; } -static void -set_default_option (int option) -{ - GConfClient *gconf_client; - const char *str; - - gconf_client = gsm_get_conf_client (); - - str = gconf_enum_to_string (logout_options_lookup_table, option); - g_assert (str != NULL); - - gconf_client_set_string (gconf_client, LOGOUT_OPTION_KEY, str, NULL); -} static gboolean display_gui (void) { - GtkWidget *box; - GtkWidget *title; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *image; - GtkWidget *toggle_button = NULL; - gint response; - GtkWidget *halt = NULL; - GtkWidget *reboot = NULL; - GtkWidget *suspend = NULL; - GtkWidget *invisible; - gboolean halt_supported = FALSE; - gboolean reboot_supported = FALSE; - gboolean suspend_supported = FALSE; - gboolean retval = FALSE; - gboolean save_active = FALSE; - gboolean halt_active = FALSE; - gboolean reboot_active = FALSE; - gboolean suspend_active = FALSE; - GdmLogoutAction logout_action = GDM_LOGOUT_ACTION_NONE; - gboolean a11y_enabled; - GError *error = NULL; - GdkScreen *screen; - int monitor; - int selected_option; + GtkWidget *logoutDlg; + GtkWidget *vbox; + GtkWidget *image; + GtkWidget *tile; + gint response; + GtkWidget *invisible; + GtkIconTheme *iconTheme; + GdkPixbuf *themePixbuf = NULL; + gboolean retval = FALSE; + gboolean showDialog = FALSE; + gboolean a11y_enabled; + GError *error = NULL; + GdkScreen *screen; + int monitor; gsm_verbose ("display_gui: showing logout dialog\n"); @@ -355,278 +471,364 @@ a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (invisible)); - /* Only create a managed window if a11y is enabled */ + logoutDlg = g_object_new (GTK_TYPE_DIALOG, + "type", GTK_WINDOW_TOPLEVEL, + NULL); if (!a11y_enabled) - { - while (1) + { + atk_object_set_role (gtk_widget_get_accessible (logoutDlg), + ATK_ROLE_ALERT); + } + gtk_window_set_decorated (GTK_WINDOW (logoutDlg), TRUE); + gtk_window_set_title(GTK_WINDOW(logoutDlg), _("Log Out")); + gtk_dialog_set_has_separator (GTK_DIALOG (logoutDlg), FALSE); + + // setup specs from Gnome HIG + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (logoutDlg)->vbox), 12); + gtk_container_set_border_width (GTK_CONTAINER(logoutDlg), 6); + + vbox = gtk_vbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (logoutDlg)->vbox), vbox, + FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER (vbox), 6); + gtk_widget_show (vbox); + + + gtk_window_set_screen (GTK_WINDOW (logoutDlg), screen); + gtk_window_set_policy (GTK_WINDOW (logoutDlg), FALSE, FALSE, TRUE); + gtk_window_set_keep_above(GTK_WINDOW(logoutDlg), TRUE); + gtk_window_stick(GTK_WINDOW(logoutDlg)); + + iconTheme = gtk_icon_theme_get_for_screen(screen); + //iconTheme = gtk_icon_theme_get_default (); + + // add help button in every case + gtk_dialog_add_button (GTK_DIALOG (logoutDlg), GTK_STOCK_HELP, + GTK_RESPONSE_HELP); + + gtk_dialog_add_button (GTK_DIALOG (logoutDlg), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + + // ============ LOGOUT TILE ============ + image = NULL; + if(gtk_icon_theme_has_icon(iconTheme, "system-log-out")) { - if (gdk_pointer_grab (invisible->window, FALSE, 0, - NULL, NULL, GDK_CURRENT_TIME) == Success) - { - if (gdk_keyboard_grab (invisible->window, FALSE, GDK_CURRENT_TIME) - == Success) - break; - gdk_pointer_ungrab (GDK_CURRENT_TIME); - } - sleep (1); - } - - box = g_object_new (GTK_TYPE_DIALOG, - "type", GTK_WINDOW_POPUP, - NULL); - } - else - { - box = gtk_dialog_new (); - atk_object_set_role (gtk_widget_get_accessible (box), ATK_ROLE_ALERT); - gtk_window_set_decorated (GTK_WINDOW (box), FALSE); - } + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "system-log-out", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + else if(gtk_icon_theme_has_icon(iconTheme, "gnome-logout")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "gnome-logout", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + if(image == NULL) + { + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG); + } + tile = ssui_get_tile(image, _("_Log Out"), + _("Ends your session and logs you out.")); + g_signal_connect (G_OBJECT (tile), "clicked", + G_CALLBACK (logout_button_clicked), logoutDlg); - gtk_dialog_set_has_separator (GTK_DIALOG (box), FALSE); + gtk_box_pack_start (GTK_BOX (vbox), tile, TRUE, TRUE, 0); + gtk_widget_show_all(tile); - vbox = gtk_vbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (box)->vbox), vbox, FALSE, FALSE, 0); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (box)->vbox), 2); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); - gtk_widget_show (vbox); - - hbox = gtk_hbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); - gtk_widget_show (image); - - title = make_title_label (_("Are you sure you want to log out?")); - gtk_box_pack_start (GTK_BOX (hbox), title, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (title), 0, 0.5); - gtk_widget_show (title); - - gtk_dialog_add_button (GTK_DIALOG (box), GTK_STOCK_HELP, GTK_RESPONSE_HELP); - gtk_dialog_add_button (GTK_DIALOG (box), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (box), GTK_STOCK_OK, GTK_RESPONSE_OK); - gtk_dialog_set_default_response (GTK_DIALOG (box), GTK_RESPONSE_OK); - gtk_window_set_screen (GTK_WINDOW (box), screen); - gtk_window_set_policy (GTK_WINDOW (box), FALSE, FALSE, TRUE); - gtk_container_set_border_width (GTK_CONTAINER (box), 5); + // ============ LOCK TILE ============ + image = NULL; + if(gtk_icon_theme_has_icon(iconTheme, "system-lock-screen")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "system-lock-screen", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + else if(gtk_icon_theme_has_icon(iconTheme, "gnome-lockscreen")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "gnome-lockscreen", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + if(image == NULL) + { + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG); + } + tile = ssui_get_tile(image, _("Loc_k Screen"), + _("Locks this computer's screen.")); + g_signal_connect (G_OBJECT (tile), "clicked", + G_CALLBACK (lock_button_clicked), logoutDlg); - if (!autosave) - { - toggle_button = gtk_check_button_new_with_mnemonic (_("_Save current setup")); - gtk_widget_show (toggle_button); - gtk_box_pack_start (GTK_BOX (vbox), - toggle_button, - FALSE, TRUE, 0); - } + gtk_box_pack_start (GTK_BOX (vbox), tile, TRUE, TRUE, 0); + gtk_widget_show_all(tile); - halt_supported = gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); - reboot_supported = gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT); - suspend_supported = gdm_supports_logout_action (GDM_LOGOUT_ACTION_SUSPEND); - if (halt_supported || reboot_supported || suspend_supported) - { - GtkWidget *title, *spacer; - GtkWidget *action_vbox, *hbox; - GtkWidget *category_vbox; - GtkWidget *r; - - selected_option = get_default_option (); - - category_vbox = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (vbox), category_vbox, TRUE, TRUE, 0); - gtk_widget_show (category_vbox); - - title = make_title_label (_("Action")); - gtk_box_pack_start (GTK_BOX (category_vbox), - title, FALSE, FALSE, 0); - gtk_widget_show (title); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (category_vbox), hbox, TRUE, TRUE, 0); - gtk_widget_show (hbox); - - spacer = gtk_label_new (" "); - gtk_box_pack_start (GTK_BOX (hbox), spacer, FALSE, FALSE, 0); - gtk_widget_show (spacer); - - action_vbox = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (hbox), action_vbox, TRUE, TRUE, 0); - gtk_widget_show (action_vbox); - - r = gtk_radio_button_new_with_mnemonic (NULL, _("_Log out")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), (selected_option == OPTION_LOGOUT)); - gtk_box_pack_start (GTK_BOX (action_vbox), r, FALSE, FALSE, 0); - gtk_widget_show (r); - - if (halt_supported) - { - r = halt = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (r), _("Sh_ut down")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), (selected_option == OPTION_HALT)); - gtk_box_pack_start (GTK_BOX (action_vbox), r, FALSE, FALSE, 0); - gtk_widget_show (r); - } - - if (reboot_supported) - { - r = reboot = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (r), _("_Restart the computer")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), (selected_option == OPTION_REBOOT)); - gtk_box_pack_start (GTK_BOX (action_vbox), r, FALSE, FALSE, 0); - gtk_widget_show (r); - } - if (suspend_supported) - { - r = suspend = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (r), _("_Suspend the computer")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r), (selected_option == OPTION_SUSPEND)); - gtk_box_pack_start (GTK_BOX (action_vbox), r, FALSE, FALSE, 0); - gtk_widget_show (r); + + // ============ SHUTDOWN TILE ============ + //if(panel_power_manager_can_power_down (powerManager)) + if(gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN)) + { + image = NULL; + if(gtk_icon_theme_has_icon(iconTheme, "system-shutdown")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "system-shutdown", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + else if(gtk_icon_theme_has_icon(iconTheme, "gnome-shutdown")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "gnome-shutdown", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + if(image == NULL) + { + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG); + } + tile = ssui_get_tile(image, _("_Shutdown"), + _("Ends your session and turns off the computer.")); + g_signal_connect (G_OBJECT (tile), "clicked", + G_CALLBACK (shutdown_button_clicked), logoutDlg); + + gtk_box_pack_start (GTK_BOX (vbox), tile, TRUE, TRUE, 0); + gtk_widget_show_all(tile); } - } - gsm_center_window_on_screen (GTK_WINDOW (box), screen, monitor); - /* Grabbing the Xserver when accessibility is enabled will cause - * a hang. See #93103 for details. - */ - if (!a11y_enabled) - { - /* Really necessary? - XGrabServer (GDK_DISPLAY ()); - */ - gsm_foreach_screen (fadeout_screen); - } - gtk_widget_show_all (box); + // ============ RESTART TILE ============ + //if(panel_power_manager_can_power_down (powerManager)) + if(gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT)) + { + image = NULL; + if(gtk_icon_theme_has_icon(iconTheme, "stock_refresh")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "stock_refresh", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + else if(gtk_icon_theme_has_icon(iconTheme, "gnome-reboot")) + { + themePixbuf = gtk_icon_theme_load_icon(iconTheme, + "gnome-reboot", 48, 0, &error); + if(themePixbuf != NULL) + image = gtk_image_new_from_pixbuf(themePixbuf); + else + image = NULL; + } + if(image == NULL) + { + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG); + } + tile = ssui_get_tile(image, _("_Restart"), + _("Ends your session and restarts the computer.")); + g_signal_connect (G_OBJECT (tile), "clicked", + G_CALLBACK (restart_button_clicked), logoutDlg); - /* XXX: Appending experimental display modal state */ - { - Display *xdisplay = GDK_WINDOW_XDISPLAY (box->window); - Window xwindow = GDK_WINDOW_XID (box->window); - Atom state_atom, display_modal_atom; - - state_atom = XInternAtom (xdisplay, "_NET_WM_STATE", 0); - display_modal_atom = XInternAtom (xdisplay, - "_NET_WM_STATE_DISPLAY_MODAL", 0); - - XChangeProperty (xdisplay, - xwindow, - state_atom, - XA_ATOM, 32, PropModeAppend, - (guchar *) &display_modal_atom, 1); - } + gtk_box_pack_start (GTK_BOX (vbox), tile, TRUE, TRUE, 0); + gtk_widget_show_all(tile); + } - if (!a11y_enabled) - { - /* Move the grabs to our message box */ - gdk_pointer_grab (box->window, TRUE, 0, - NULL, NULL, GDK_CURRENT_TIME); - gdk_keyboard_grab (box->window, FALSE, GDK_CURRENT_TIME); - XSetInputFocus (GDK_DISPLAY (), - GDK_WINDOW_XWINDOW (box->window), - RevertToParent, - CurrentTime); - } - response = gtk_dialog_run (GTK_DIALOG (box)); + gtk_dialog_set_default_response (GTK_DIALOG (logoutDlg), + GTK_RESPONSE_CANCEL); - if (halt) - halt_active = GTK_TOGGLE_BUTTON (halt)->active; + gsm_center_window_on_screen (GTK_WINDOW (logoutDlg), screen, monitor); - if (reboot) - reboot_active = GTK_TOGGLE_BUTTON (reboot)->active; - if (suspend) - suspend_active = GTK_TOGGLE_BUTTON (suspend)->active; - - if (toggle_button) - save_active = GTK_TOGGLE_BUTTON (toggle_button)->active; - - if (reboot_active) - selected_option = OPTION_REBOOT; - else if (halt_active) - selected_option = OPTION_HALT; - else if (suspend_active) - selected_option = OPTION_SUSPEND; - else - selected_option = OPTION_LOGOUT; + /* Grabbing the Xserver when accessibility is enabled will cause + * a hang. See #93103 for details. + */ + if (!a11y_enabled) + { + /* Really necessary? + XGrabServer (GDK_DISPLAY ()); + */ + gsm_foreach_screen (fadeout_screen); + } - gtk_widget_destroy (box); - gtk_widget_destroy (invisible); + gtk_widget_show_all (logoutDlg); - if (!a11y_enabled) - { - hide_fadeout_windows (); - /* XUngrabServer (GDK_DISPLAY ()); */ + /* setup properties for window manager to special case the + dialog (compiz does some awesome fading here) */ + { + Display *xdisplay = GDK_WINDOW_XDISPLAY (logoutDlg->window); + Window xwindow = GDK_WINDOW_XID (logoutDlg->window); + Atom state_atom, display_modal_atom; + + state_atom = XInternAtom (xdisplay, "_NET_WM_STATE", 0); + display_modal_atom = XInternAtom (xdisplay, + "_NET_WM_STATE_DISPLAY_MODAL", 0); + + XChangeProperty (xdisplay, + xwindow, + state_atom, + XA_ATOM, 32, PropModeAppend, + (guchar *) &display_modal_atom, 1); + } - gdk_pointer_ungrab (GDK_CURRENT_TIME); - gdk_keyboard_ungrab (GDK_CURRENT_TIME); + if (!a11y_enabled) + { + // adds a callback to start the fading of all windows after + // the primary display is captured and the logout dialog is + // shown + g_idle_add ((GSourceFunc) logout_dialog_callback, logoutDlg); + + g_signal_connect (G_OBJECT(GTK_WIDGET(logoutDlg)), "configure-event", + G_CALLBACK (logout_dialog_configure_cb), + NULL); + + g_signal_connect (G_OBJECT(GTK_WIDGET(logoutDlg)), "focus-out-event", + G_CALLBACK (logout_dialog_focus_out_cb), + NULL); + } - gdk_flush (); - } + do + { - switch (response) { - case GTK_RESPONSE_OK: - /* We want to know if we should trash changes (and lose forever) - * or save them */ - retval = TRUE; - if(save_active) - save_selected = save_active; - if (halt_active) - logout_action = GDM_LOGOUT_ACTION_SHUTDOWN; - else if (reboot_active) - logout_action = GDM_LOGOUT_ACTION_REBOOT; - else if (suspend_active) - { - logout_action = GDM_LOGOUT_ACTION_SUSPEND; - g_spawn_command_line_async ("powersave --suspend-to-disk", NULL); - retval = FALSE; - } - set_default_option (selected_option); - break; - default: - case GTK_RESPONSE_CANCEL: - retval = FALSE; - break; - case GTK_RESPONSE_HELP: - gnome_help_display_desktop_on_screen (NULL, "user-guide", - "user-guide.xml", - "gosgetstarted-73", - screen, - &error); - - if (error) - { - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - ("There was an error displaying help: \n%s"), - error->message); - - g_signal_connect (G_OBJECT (dialog), "response", - G_CALLBACK (gtk_widget_destroy), - NULL); - - gtk_window_set_screen (GTK_WINDOW (dialog), screen); - - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); - gtk_widget_show (dialog); - g_error_free (error); - } - - retval = FALSE; - break; - } + response = gtk_dialog_run (GTK_DIALOG (logoutDlg)); + showDialog = FALSE; + + switch(response) + { + case GS_RESPONSE_LOGOUT: + gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE); + retval = TRUE; +// ssui_request_logout(); + break; + case GS_RESPONSE_SHUTDOWN: + gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); + retval = TRUE; +// ssui_request_logout(); + break; + case GS_RESPONSE_RESTART: + gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT); + retval = TRUE; +// ssui_request_logout(); + break; + case GS_RESPONSE_LOCK: + g_spawn_command_line_async( + "gnome-screensaver-command --lock", NULL); + retval = FALSE; + break; + case GTK_RESPONSE_HELP: + gnome_help_display_desktop_on_screen (NULL, "user-guide", + "user-guide.xml", + "gosgetstarted-73", + screen, + &error); + + if (error) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + ("There was an error displaying help: \n%s"), + error->message); + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_window_set_screen (GTK_WINDOW (dialog), screen); + + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + gtk_widget_show (dialog); + g_error_free (error); + } + + retval = FALSE; + break; + case GTK_RESPONSE_NONE: + case GTK_RESPONSE_DELETE_EVENT: + case GTK_RESPONSE_CANCEL: + retval = FALSE; + break; + default: + g_assert_not_reached(); + } + + }while(showDialog); + + gtk_widget_destroy (logoutDlg); + gtk_widget_destroy (invisible); - gdm_set_logout_action (logout_action); - return retval; + if (!a11y_enabled) + { + hide_fadeout_windows (); + /* XUngrabServer (GDK_DISPLAY ()); */ + + gdk_flush (); + } + + return retval; +} + +static gboolean logout_dialog_callback (GtkWidget *dialog) +{ + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (dialog->window), + RevertToParent, + CurrentTime); + + return FALSE; +} + +static gboolean logout_dialog_configure_cb( GtkWidget *widget, + GdkEventConfigure *event, + gpointer data) +{ + ssui_punch_hole_fadeout_windows(GTK_WINDOW(widget)); + return FALSE; +} + +static gboolean logout_dialog_focus_out_cb( GtkWidget *widget, + GdkEventFocus *event, + gpointer data) +{ + if(event->in == FALSE) + { + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (widget->window), + RevertToParent, + CurrentTime); + } + + return FALSE; } + + /* Display GUI if user wants it. Returns TRUE if save should continue, FALSE otherwise. */ gboolean @@ -650,3 +852,121 @@ return result; } + + +static void logout_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_dialog_response(GTK_DIALOG(user_data), GS_RESPONSE_LOGOUT); +} + +static void shutdown_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_dialog_response(GTK_DIALOG(user_data), GS_RESPONSE_SHUTDOWN); +} + +static void restart_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_dialog_response(GTK_DIALOG(user_data), GS_RESPONSE_RESTART); +} + +static void lock_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_dialog_response(GTK_DIALOG(user_data), GS_RESPONSE_LOCK); +} + +static GtkWidget *ssui_get_tile(GtkWidget *image, const gchar *title, + const gchar *desc) +{ + GtkWidget *button; + GtkWidget *alignment; + GtkWidget *hbox; + GtkWidget *vbox; + + g_assert(title != NULL); + + button = GTK_WIDGET(gtk_button_new()); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); +// GTK_WIDGET_UNSET_FLAGS(button, GTK_HAS_FOCUS); + + alignment = gtk_alignment_new(0, 0.5, 0, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 6, 6); + gtk_container_add(GTK_CONTAINER(button), alignment); + + hbox = gtk_hbox_new(FALSE, 12); + gtk_container_add(GTK_CONTAINER(alignment), hbox); + if(image != NULL) + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + + vbox = gtk_vbox_new(FALSE, 2); + + if(title != NULL) + { + gchar *full; + GtkWidget *label; + + full = g_strdup_printf ("%s", title); + label = gtk_label_new(full); + g_free (full); + + gtk_label_set_use_markup (GTK_LABEL(label), TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_label_set_use_underline(GTK_LABEL(label), TRUE); + + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); + } + + if(desc != NULL) + { + gchar *full; + GtkWidget *label; + + full = g_strdup_printf ("%s", + desc); + label = gtk_label_new(full); + g_free (full); + + gtk_label_set_use_markup (GTK_LABEL(label), TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_label_set_use_underline(GTK_LABEL(label), TRUE); + gtk_label_set_line_wrap(GTK_LABEL (label), TRUE); + + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); + } + + gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); + + return button; +} + + +static void +window_get_frame_extents (GdkWindow *window, gint *left, gint *right, + gint *top, gint *bottom) +{ + unsigned long *extents = NULL; + + /* some guesses in case this fails to read */ + *left = 6; + *right = 6; + *top = 21; + *bottom = 6; + + /* Attempt to retrieve window's frame extents. */ + if (gdk_property_get (window, + gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (unsigned long) * 4, + FALSE, + NULL, + NULL, + NULL, + (guchar **)&extents)) + { + *left = extents [0]; + *right = extents [1]; + *top = extents [2]; + *bottom = extents [3]; + } +} +