~ubuntu-branches/ubuntu/vivid/xfce4-session/vivid-proposed

« back to all changes in this revision

Viewing changes to xfce4-session/xfsm-logout-dialog.c

  • Committer: Package Import Robot
  • Author(s): Lionel Le Folgoc
  • Date: 2012-05-18 20:21:52 UTC
  • mfrom: (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20120518202152-7bm9pla0j3ccfsnk
Tags: 4.10.0-1ubuntu1
* Merge from Debian experimental, remaining Ubuntu changes:
  - debian/control: build-depends on libgnome-keyring-dev to enable GNOME
    Keyring services support.
  - debian/rules: pass --enable-libgnome-keyring to dh_auto_configure.
  - debian/patches:
    + xubuntu_ignore-gdm-lang.patch: do not set $LANG to $GDM_LANG, there's
      already an xsession script to do that, and $GDM_LANG might not contain
      a valid locale code.

* debian/patches:
  - xubuntu_set-xdg-current-desktop.patch: added. Taken from xfce4-utils,
    export XDG_CURRENT_DESKTOP=XFCE, can be useful with alacarte and
    gnome-menus. lp #927172

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org>
 
3
 * Copyright (c) 2011      Nick Schermer <nick@xfce.org>
 
4
 * All rights reserved.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
19
 * MA 02110-1301 USA.
 
20
 *
 
21
 * Parts of this file where taken from gnome-session/logout.c, which
 
22
 * was written by Owen Taylor <otaylor@redhat.com>.
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#ifdef HAVE_SYS_WAIT_H
 
30
#include <sys/wait.h>
 
31
#endif
 
32
 
 
33
#ifdef HAVE_STDLIB_H
 
34
#include <stdlib.h>
 
35
#endif
 
36
#ifdef HAVE_STRING_H
 
37
#include <string.h>
 
38
#endif
 
39
#ifdef HAVE_UNISTD_H
 
40
#include <unistd.h>
 
41
#endif
 
42
#ifdef HAVE_MATH_H
 
43
#include <math.h>
 
44
#endif
 
45
 
 
46
#include <libxfce4util/libxfce4util.h>
 
47
#include <gtk/gtk.h>
 
48
 
 
49
#include <libxfsm/xfsm-util.h>
 
50
 
 
51
#include <xfce4-session/xfsm-logout-dialog.h>
 
52
#include <xfce4-session/xfsm-fadeout.h>
 
53
#include <xfce4-session/xfsm-global.h>
 
54
#include <xfce4-session/xfsm-legacy.h>
 
55
#include <xfce4-session/xfsm-error.h>
 
56
 
 
57
#ifdef GDK_WINDOWING_X11
 
58
#include <X11/Xlib.h>
 
59
#include <gdk/gdkx.h>
 
60
#endif
 
61
 
 
62
 
 
63
 
 
64
#define BORDER   6
 
65
#define SHOTSIZE 64
 
66
 
 
67
 
 
68
 
 
69
static void       xfsm_logout_dialog_finalize (GObject          *object);
 
70
static GtkWidget *xfsm_logout_dialog_button   (const gchar      *title,
 
71
                                               const gchar      *icon_name,
 
72
                                               const gchar      *icon_name_fallback,
 
73
                                               XfsmShutdownType  type,
 
74
                                               XfsmLogoutDialog *dialog);
 
75
static void       xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog);
 
76
 
 
77
 
 
78
 
 
79
enum
 
80
{
 
81
  MODE_LOGOUT_BUTTONS,
 
82
  MODE_ASK_PASSWORD,
 
83
  MODE_SHOW_ERROR,
 
84
  N_MODES
 
85
};
 
86
 
 
87
struct _XfsmLogoutDialogClass
 
88
{
 
89
  GtkDialogClass __parent__;
 
90
};
 
91
 
 
92
struct _XfsmLogoutDialog
 
93
{
 
94
  GtkDialog __parent__;
 
95
 
 
96
  /* set when a button is clicked */
 
97
  XfsmShutdownType  type_clicked;
 
98
 
 
99
  /* save session checkbox */
 
100
  GtkWidget        *save_session;
 
101
 
 
102
  /* mode widgets */
 
103
  GtkWidget        *box[N_MODES];
 
104
 
 
105
  /* dialog buttons */
 
106
  GtkWidget        *button_cancel;
 
107
  GtkWidget        *button_ok;
 
108
  GtkWidget        *button_close;
 
109
 
 
110
  /* password entry */
 
111
  GtkWidget        *password_entry;
 
112
 
 
113
  /* error label */
 
114
  GtkWidget        *error_label;
 
115
 
 
116
  /* pm instance */
 
117
  XfsmShutdown     *shutdown;
 
118
};
 
119
 
 
120
 
 
121
 
 
122
G_DEFINE_TYPE (XfsmLogoutDialog, xfsm_logout_dialog, GTK_TYPE_DIALOG)
 
123
 
 
124
 
 
125
 
 
126
static void
 
127
xfsm_logout_dialog_class_init (XfsmLogoutDialogClass *klass)
 
128
{
 
129
  GObjectClass *gobject_class;
 
130
 
 
131
  gobject_class = G_OBJECT_CLASS (klass);
 
132
  gobject_class->finalize = xfsm_logout_dialog_finalize;
 
133
}
 
134
 
 
135
 
 
136
 
 
137
static void
 
138
xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
 
139
{
 
140
  const gchar   *username;
 
141
  GtkWidget     *label;
 
142
  gchar         *label_str;
 
143
  PangoAttrList *attrs;
 
144
  GtkWidget     *vbox;
 
145
  GtkWidget     *button_vbox;
 
146
  GtkWidget     *main_vbox;
 
147
  GtkWidget     *hbox;
 
148
  GtkWidget     *button;
 
149
  gboolean       can_shutdown;
 
150
  gboolean       save_session = FALSE;
 
151
  gboolean       can_restart;
 
152
  gboolean       can_suspend = FALSE;
 
153
  gboolean       can_hibernate = FALSE;
 
154
  gboolean       auth_suspend = FALSE;
 
155
  gboolean       auth_hibernate = FALSE;
 
156
  GError        *error = NULL;
 
157
  XfconfChannel *channel;
 
158
  GtkWidget     *entry;
 
159
  GtkWidget     *image;
 
160
  GtkWidget     *separator;
 
161
  gboolean       upower_not_found = FALSE;
 
162
 
 
163
  dialog->type_clicked = XFSM_SHUTDOWN_LOGOUT;
 
164
  dialog->shutdown = xfsm_shutdown_get ();
 
165
 
 
166
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 
167
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
 
168
  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
 
169
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
170
 
 
171
  /* load xfconf settings */
 
172
  channel = xfsm_open_config ();
 
173
  if (xfsm_shutdown_can_save_session (dialog->shutdown))
 
174
    save_session = xfconf_channel_get_bool (channel, "/general/SaveOnExit", TRUE);
 
175
 
 
176
  main_vbox = gtk_vbox_new (FALSE, BORDER);
 
177
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_vbox, TRUE, TRUE, 0);
 
178
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), BORDER);
 
179
  gtk_widget_show (main_vbox);
 
180
 
 
181
  /* label showing the users' name */
 
182
  username = g_get_real_name ();
 
183
  if (username == NULL
 
184
      || *username == '\0'
 
185
      || strcmp ("Unknown", username) == 0)
 
186
    username = g_get_user_name ();
 
187
 
 
188
  label_str = g_strdup_printf (_("Log out %s"), username);
 
189
  label = gtk_label_new (label_str);
 
190
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
 
191
  gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, TRUE, 0);
 
192
  gtk_widget_show (label);
 
193
  g_free (label_str);
 
194
 
 
195
  attrs = pango_attr_list_new ();
 
196
  pango_attr_list_insert (attrs, pango_attr_scale_new (PANGO_SCALE_LARGE));
 
197
  pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
 
198
  gtk_label_set_attributes (GTK_LABEL (label), attrs);
 
199
  pango_attr_list_unref (attrs);
 
200
 
 
201
  separator = gtk_hseparator_new ();
 
202
  gtk_box_pack_start (GTK_BOX (main_vbox), separator, FALSE, TRUE, 0);
 
203
  gtk_widget_show (separator);
 
204
 
 
205
  /**
 
206
   * Start mode MODE_LOGOUT_BUTTONS
 
207
   **/
 
208
  dialog->box[MODE_LOGOUT_BUTTONS] = vbox = gtk_vbox_new (FALSE, BORDER);
 
209
  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
 
210
 
 
211
  /**
 
212
   * Cancel
 
213
   **/
 
214
  dialog->button_cancel = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
215
                                                 GTK_STOCK_CANCEL,
 
216
                                                 GTK_RESPONSE_CANCEL);
 
217
 
 
218
  /**
 
219
   * Ok, for password mode
 
220
   **/
 
221
  dialog->button_ok = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
222
                                             GTK_STOCK_OK,
 
223
                                             GTK_RESPONSE_OK);
 
224
  gtk_widget_hide (dialog->button_ok);
 
225
 
 
226
  /**
 
227
   * Close, for password error
 
228
   **/
 
229
  dialog->button_close = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
230
                                                GTK_STOCK_CLOSE,
 
231
                                                GTK_RESPONSE_CANCEL);
 
232
  gtk_widget_hide (dialog->button_close);
 
233
 
 
234
  button_vbox = gtk_vbox_new (TRUE, BORDER);
 
235
  gtk_box_pack_start (GTK_BOX (vbox), button_vbox, FALSE, TRUE, 0);
 
236
  gtk_widget_show (button_vbox);
 
237
 
 
238
  /* row for logout/shutdown and reboot */
 
239
  hbox = gtk_hbox_new (TRUE, BORDER);
 
240
  gtk_box_pack_start (GTK_BOX (button_vbox), hbox, FALSE, TRUE, 0);
 
241
  gtk_widget_show (hbox);
 
242
 
 
243
  /**
 
244
   * Logout
 
245
   **/
 
246
  button = xfsm_logout_dialog_button (_("_Log Out"), "system-log-out",
 
247
                                      "xfsm-logout", XFSM_SHUTDOWN_LOGOUT,
 
248
                                      dialog);
 
249
 
 
250
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
 
251
  gtk_widget_show (button);
 
252
  gtk_widget_grab_focus (button);
 
253
 
 
254
  /**
 
255
   * Reboot
 
256
   **/
 
257
  if (!xfsm_shutdown_can_restart (dialog->shutdown, &can_restart, &error))
 
258
    {
 
259
      g_printerr ("%s: Querying CanRestart failed, %s\n\n",
 
260
                  PACKAGE_NAME, ERROR_MSG (error));
 
261
      g_clear_error (&error);
 
262
 
 
263
      can_restart = FALSE;
 
264
    }
 
265
 
 
266
  button = xfsm_logout_dialog_button (_("_Restart"), "system-reboot",
 
267
                                      "xfsm-reboot", XFSM_SHUTDOWN_RESTART,
 
268
                                      dialog);
 
269
 
 
270
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
 
271
  gtk_widget_set_sensitive (button, can_restart);
 
272
  gtk_widget_show (button);
 
273
 
 
274
  /**
 
275
   * Shutdown
 
276
   **/
 
277
  if (!xfsm_shutdown_can_shutdown (dialog->shutdown, &can_shutdown, &error))
 
278
    {
 
279
      g_printerr ("%s: Querying CanShutdown failed. %s\n\n",
 
280
                  PACKAGE_NAME, ERROR_MSG (error));
 
281
      g_clear_error (&error);
 
282
 
 
283
      can_shutdown = FALSE;
 
284
    }
 
285
 
 
286
  button = xfsm_logout_dialog_button (_("Shut _Down"), "system-shutdown",
 
287
                                      "xfsm-shutdown", XFSM_SHUTDOWN_SHUTDOWN,
 
288
                                      dialog);
 
289
 
 
290
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
 
291
  gtk_widget_set_sensitive (button, can_shutdown);
 
292
  gtk_widget_show (button);
 
293
 
 
294
  /* new row for suspend/hibernate */
 
295
  hbox = gtk_hbox_new (TRUE, BORDER);
 
296
  gtk_box_pack_start (GTK_BOX (button_vbox), hbox, FALSE, TRUE, 0);
 
297
 
 
298
  /**
 
299
   * Suspend
 
300
   *
 
301
   * Hide the button if UPower is not installed or system cannot suspend
 
302
   **/
 
303
  if (xfconf_channel_get_bool (channel, "/shutdown/ShowSuspend", TRUE))
 
304
    {
 
305
      if (xfsm_shutdown_can_suspend (dialog->shutdown, &can_suspend, &auth_suspend, &error))
 
306
        {
 
307
          if (can_suspend)
 
308
            {
 
309
              button = xfsm_logout_dialog_button (_("Sus_pend"), "system-suspend",
 
310
                                                  "xfsm-suspend", XFSM_SHUTDOWN_SUSPEND,
 
311
                                                  dialog);
 
312
 
 
313
              gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
 
314
              gtk_widget_set_sensitive (button, auth_suspend);
 
315
              gtk_widget_show (button);
 
316
 
 
317
              gtk_widget_show (hbox);
 
318
            }
 
319
        }
 
320
      else
 
321
        {
 
322
          g_printerr ("%s: Querying suspend failed: %s\n\n",
 
323
                      PACKAGE_NAME, ERROR_MSG (error));
 
324
          g_clear_error (&error);
 
325
 
 
326
          /* don't try hibernate again */
 
327
          upower_not_found = TRUE;
 
328
        }
 
329
    }
 
330
 
 
331
  /**
 
332
   * Hibernate
 
333
   *
 
334
   * Hide the button if UPower is not installed or system cannot suspend
 
335
   **/
 
336
  if (!upower_not_found
 
337
      && xfconf_channel_get_bool (channel, "/shutdown/ShowHibernate", TRUE))
 
338
    {
 
339
      if (xfsm_shutdown_can_hibernate (dialog->shutdown, &can_hibernate, &auth_hibernate, &error))
 
340
        {
 
341
          if (can_hibernate)
 
342
            {
 
343
              button = xfsm_logout_dialog_button (_("_Hibernate"), "system-hibernate",
 
344
                                                  "xfsm-hibernate", XFSM_SHUTDOWN_HIBERNATE,
 
345
                                                  dialog);
 
346
 
 
347
              gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
 
348
              gtk_widget_set_sensitive (button, auth_hibernate);
 
349
              gtk_widget_show (button);
 
350
 
 
351
              gtk_widget_show (hbox);
 
352
            }
 
353
        }
 
354
      else
 
355
        {
 
356
          g_printerr ("%s: Querying hibernate failed: %s\n\n",
 
357
                      PACKAGE_NAME, ERROR_MSG (error));
 
358
          g_clear_error (&error);
 
359
        }
 
360
    }
 
361
 
 
362
  /**
 
363
   * Save session
 
364
   **/
 
365
  if (xfsm_shutdown_can_save_session (dialog->shutdown)
 
366
      && !xfconf_channel_get_bool (channel, "/general/AutoSave", FALSE))
 
367
    {
 
368
      dialog->save_session = gtk_check_button_new_with_mnemonic (_("_Save session for future logins"));
 
369
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->save_session), save_session);
 
370
      gtk_box_pack_start (GTK_BOX (vbox), dialog->save_session, FALSE, TRUE, BORDER);
 
371
      gtk_widget_show (dialog->save_session);
 
372
    }
 
373
 
 
374
  attrs = pango_attr_list_new ();
 
375
  pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
 
376
 
 
377
  /**
 
378
   * Start mode MODE_ASK_PASSWORD
 
379
   **/
 
380
  dialog->box[MODE_ASK_PASSWORD] = vbox = gtk_vbox_new (FALSE, BORDER);
 
381
  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
 
382
 
 
383
  hbox = gtk_hbox_new (FALSE, BORDER * 2);
 
384
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
 
385
  gtk_widget_show (hbox);
 
386
 
 
387
  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
 
388
  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
 
389
  gtk_widget_show (image);
 
390
 
 
391
  vbox = gtk_vbox_new (FALSE, BORDER);
 
392
  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
 
393
  gtk_widget_show (vbox);
 
394
 
 
395
  label = gtk_label_new (_("Please enter your password"));
 
396
  gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
 
397
  gtk_label_set_attributes (GTK_LABEL (label), attrs);
 
398
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
399
  gtk_widget_show (label);
 
400
 
 
401
  dialog->password_entry = entry = gtk_entry_new ();
 
402
  gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
 
403
  gtk_entry_set_width_chars (GTK_ENTRY (entry), 30);
 
404
  gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
 
405
  g_signal_connect_swapped (G_OBJECT (entry), "activate",
 
406
                            G_CALLBACK (xfsm_logout_dialog_activate), dialog);
 
407
  gtk_widget_show (entry);
 
408
 
 
409
  /**
 
410
   * Start mode MODE_SHOW_ERROR
 
411
   **/
 
412
  dialog->box[MODE_SHOW_ERROR] = vbox = gtk_vbox_new (FALSE, BORDER);
 
413
  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
 
414
 
 
415
  hbox = gtk_hbox_new (FALSE, BORDER * 2);
 
416
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
 
417
  gtk_widget_show (hbox);
 
418
 
 
419
  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
 
420
  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
 
421
  gtk_widget_show (image);
 
422
 
 
423
  vbox = gtk_vbox_new (FALSE, BORDER);
 
424
  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
 
425
  gtk_widget_show (vbox);
 
426
 
 
427
  label = gtk_label_new (_("An error occurred"));
 
428
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
429
  gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
 
430
  gtk_label_set_attributes (GTK_LABEL (label), attrs);
 
431
  gtk_widget_show (label);
 
432
 
 
433
  label = gtk_label_new (_("Either the password you entered is "
 
434
                           "invalid, or the system administrator "
 
435
                           "disallows shutting down this computer "
 
436
                           "with your user account."));
 
437
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
 
438
  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
 
439
  gtk_widget_show (label);
 
440
 
 
441
  pango_attr_list_unref (attrs);
 
442
}
 
443
 
 
444
 
 
445
 
 
446
static void
 
447
xfsm_logout_dialog_finalize (GObject *object)
 
448
{
 
449
  XfsmLogoutDialog *dialog = XFSM_LOGOUT_DIALOG (object);
 
450
 
 
451
  g_object_unref (G_OBJECT (dialog->shutdown));
 
452
 
 
453
  (*G_OBJECT_CLASS (xfsm_logout_dialog_parent_class)->finalize) (object);
 
454
}
 
455
 
 
456
 
 
457
 
 
458
static void
 
459
xfsm_logout_dialog_set_mode (XfsmLogoutDialog *dialog,
 
460
                             gint              mode)
 
461
{
 
462
  gint i;
 
463
 
 
464
  for (i = 0; i < N_MODES; i++)
 
465
    gtk_widget_set_visible (dialog->box[i], i == mode);
 
466
 
 
467
  gtk_widget_set_visible (dialog->button_cancel, mode != MODE_SHOW_ERROR);
 
468
  gtk_widget_set_visible (dialog->button_ok, mode == MODE_ASK_PASSWORD);
 
469
  gtk_widget_set_visible (dialog->button_close, mode == MODE_SHOW_ERROR);
 
470
}
 
471
 
 
472
 
 
473
 
 
474
static void
 
475
xfsm_logout_dialog_button_clicked (GtkWidget        *button,
 
476
                                   XfsmLogoutDialog *dialog)
 
477
{
 
478
  gint *val;
 
479
 
 
480
  val = g_object_get_data (G_OBJECT (button), "shutdown-type");
 
481
  g_assert (val != NULL);
 
482
  dialog->type_clicked = *val;
 
483
 
 
484
  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
485
}
 
486
 
 
487
 
 
488
 
 
489
static GtkWidget *
 
490
xfsm_logout_dialog_button (const gchar      *title,
 
491
                           const gchar      *icon_name,
 
492
                           const gchar      *icon_name_fallback,
 
493
                           XfsmShutdownType  type,
 
494
                           XfsmLogoutDialog *dialog)
 
495
{
 
496
  GtkWidget    *button;
 
497
  GtkWidget    *vbox;
 
498
  GdkPixbuf    *pixbuf;
 
499
  GtkWidget    *image;
 
500
  GtkWidget    *label;
 
501
  static gint   icon_size = 0;
 
502
  gint          w, h;
 
503
  gint         *val;
 
504
  GtkIconTheme *icon_theme;
 
505
 
 
506
  g_return_val_if_fail (XFSM_IS_LOGOUT_DIALOG (dialog), NULL);
 
507
 
 
508
  val = g_new0 (gint, 1);
 
509
  *val = type;
 
510
 
 
511
  button = gtk_button_new ();
 
512
  g_object_set_data_full (G_OBJECT (button), "shutdown-type", val, g_free);
 
513
  g_signal_connect (G_OBJECT (button), "clicked",
 
514
      G_CALLBACK (xfsm_logout_dialog_button_clicked), dialog);
 
515
 
 
516
  vbox = gtk_vbox_new (FALSE, BORDER);
 
517
  gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
 
518
  gtk_container_add (GTK_CONTAINER (button), vbox);
 
519
  gtk_widget_show (vbox);
 
520
 
 
521
  if (G_UNLIKELY (icon_size == 0))
 
522
    {
 
523
      if (gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &w, &h))
 
524
        icon_size = MAX (w, h);
 
525
      else
 
526
        icon_size = 32;
 
527
    }
 
528
 
 
529
  icon_theme = gtk_icon_theme_get_for_screen (gtk_window_get_screen (GTK_WINDOW (dialog)));
 
530
  pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, icon_size, 0, NULL);
 
531
  if (G_UNLIKELY (pixbuf == NULL))
 
532
    {
 
533
      pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name_fallback,
 
534
                                         icon_size, GTK_ICON_LOOKUP_GENERIC_FALLBACK,
 
535
                                         NULL);
 
536
    }
 
537
 
 
538
  image = gtk_image_new_from_pixbuf (pixbuf);
 
539
  gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
 
540
  gtk_widget_show (image);
 
541
 
 
542
  label = gtk_label_new_with_mnemonic (title);
 
543
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
544
  gtk_widget_show (label);
 
545
 
 
546
  return button;
 
547
}
 
548
 
 
549
 
 
550
 
 
551
static void
 
552
xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog)
 
553
{
 
554
  g_return_if_fail (XFSM_IS_LOGOUT_DIALOG (dialog));
 
555
  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
556
}
 
557
 
 
558
 
 
559
 
 
560
static GdkPixbuf *
 
561
xfsm_logout_dialog_screenshot_new (GdkScreen *screen)
 
562
{
 
563
  GdkRectangle  rect, screen_rect;
 
564
  GdkWindow    *window;
 
565
  GdkPixbuf    *screenshot;
 
566
  gint          x, y;
 
567
 
 
568
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
569
 
 
570
  screen_rect.x = 0;
 
571
  screen_rect.y = 0;
 
572
  screen_rect.width = gdk_screen_get_width (screen);
 
573
  screen_rect.height = gdk_screen_get_height (screen);
 
574
 
 
575
  window = gdk_screen_get_root_window (screen);
 
576
  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect.width, &rect.height);
 
577
  gdk_window_get_origin (window, &x, &y);
 
578
 
 
579
  rect.x = x;
 
580
  rect.y = y;
 
581
 
 
582
  if (!gdk_rectangle_intersect (&rect, &screen_rect, &rect))
 
583
    return NULL;
 
584
 
 
585
  screenshot = gdk_pixbuf_get_from_drawable  (NULL,
 
586
                                             GDK_DRAWABLE (window),
 
587
                                             NULL,
 
588
                                             0, 0,
 
589
                                             0, 0,
 
590
                                             rect.width,
 
591
                                             rect.height);
 
592
 
 
593
  gdk_display_beep (gdk_screen_get_display (screen));
 
594
 
 
595
  return screenshot;
 
596
}
 
597
 
 
598
 
 
599
 
 
600
static GdkPixbuf *
 
601
exo_gdk_pixbuf_scale_ratio (GdkPixbuf *source,
 
602
                            gint       dest_size)
 
603
{
 
604
  gdouble wratio;
 
605
  gdouble hratio;
 
606
  gint    source_width;
 
607
  gint    source_height;
 
608
  gint    dest_width;
 
609
  gint    dest_height;
 
610
 
 
611
  g_return_val_if_fail (GDK_IS_PIXBUF (source), NULL);
 
612
  g_return_val_if_fail (dest_size > 0, NULL);
 
613
 
 
614
  source_width  = gdk_pixbuf_get_width  (source);
 
615
  source_height = gdk_pixbuf_get_height (source);
 
616
 
 
617
  wratio = (gdouble) source_width  / (gdouble) dest_size;
 
618
  hratio = (gdouble) source_height / (gdouble) dest_size;
 
619
 
 
620
  if (hratio > wratio)
 
621
    {
 
622
      dest_width  = rint (source_width / hratio);
 
623
      dest_height = dest_size;
 
624
    }
 
625
  else
 
626
    {
 
627
      dest_width  = dest_size;
 
628
      dest_height = rint (source_height / wratio);
 
629
    }
 
630
 
 
631
  return gdk_pixbuf_scale_simple (source, MAX (dest_width, 1),
 
632
                                  MAX (dest_height, 1), GDK_INTERP_BILINEAR);
 
633
}
 
634
 
 
635
 
 
636
 
 
637
static void
 
638
xfsm_logout_dialog_screenshot_save (GdkPixbuf   *screenshot,
 
639
                                    GdkScreen   *screen,
 
640
                                    const gchar *session_name)
 
641
{
 
642
  GdkPixbuf  *scaled;
 
643
  gchar      *path;
 
644
  gchar      *display_name;
 
645
  GdkDisplay *dpy;
 
646
  GError     *error = NULL;
 
647
  gchar      *filename;
 
648
 
 
649
  g_return_if_fail (GDK_IS_PIXBUF (screenshot));
 
650
  g_return_if_fail (GDK_IS_SCREEN (screen));
 
651
 
 
652
  scaled = exo_gdk_pixbuf_scale_ratio (screenshot, SHOTSIZE);
 
653
  if (G_LIKELY (scaled != NULL))
 
654
    {
 
655
      dpy = gdk_screen_get_display (screen);
 
656
      display_name = xfsm_gdk_display_get_fullname (dpy);
 
657
      path = g_strconcat ("sessions/thumbs-", display_name, "/", session_name, ".png", NULL);
 
658
      filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE, path, TRUE);
 
659
      g_free (display_name);
 
660
      g_free (path);
 
661
 
 
662
      if (!gdk_pixbuf_save (scaled, filename, "png", &error, NULL))
 
663
        {
 
664
          g_warning ("Failed to save session screenshot: %s", error->message);
 
665
          g_error_free (error);
 
666
        }
 
667
 
 
668
      g_free (filename);
 
669
      g_object_unref (G_OBJECT (scaled));
 
670
    }
 
671
}
 
672
 
 
673
 
 
674
 
 
675
static gint
 
676
xfsm_logout_dialog_run (GtkDialog *dialog,
 
677
                        gboolean   grab_input)
 
678
{
 
679
  GdkWindow *window;
 
680
  gint       ret;
 
681
 
 
682
  if (grab_input)
 
683
    {
 
684
      gtk_widget_show_now (GTK_WIDGET (dialog));
 
685
 
 
686
      window = gtk_widget_get_window (GTK_WIDGET (dialog));
 
687
      if (gdk_keyboard_grab (window, FALSE, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS)
 
688
        g_critical ("Failed to grab the keyboard for logout window");
 
689
 
 
690
#ifdef GDK_WINDOWING_X11
 
691
      /* force input to the dialog */
 
692
      gdk_error_trap_push ();
 
693
      XSetInputFocus (GDK_DISPLAY (),
 
694
                      GDK_WINDOW_XWINDOW (window),
 
695
                      RevertToParent, CurrentTime);
 
696
      gdk_error_trap_pop ();
 
697
#endif
 
698
    }
 
699
 
 
700
  ret = gtk_dialog_run (dialog);
 
701
 
 
702
  if (grab_input)
 
703
    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
 
704
 
 
705
  return ret;
 
706
}
 
707
 
 
708
 
 
709
 
 
710
gboolean
 
711
xfsm_logout_dialog (const gchar      *session_name,
 
712
                    XfsmShutdownType *return_type,
 
713
                    gboolean         *return_save_session)
 
714
{
 
715
  gint              result;
 
716
  GtkWidget        *hidden;
 
717
  gboolean          a11y;
 
718
  GtkWidget        *dialog;
 
719
  GdkScreen        *screen;
 
720
  gint              monitor;
 
721
  GdkPixbuf        *screenshot = NULL;
 
722
  XfsmFadeout      *fadeout = NULL;
 
723
  XfsmLogoutDialog *xfsm_dialog;
 
724
  XfconfChannel    *channel = xfsm_open_config ();
 
725
  gboolean          autosave;
 
726
  const gchar      *text;
 
727
  XfsmPassState     state;
 
728
  XfsmShutdown     *shutdown;
 
729
 
 
730
  g_return_val_if_fail (return_type != NULL, FALSE);
 
731
  g_return_val_if_fail (return_save_session != NULL, FALSE);
 
732
 
 
733
  shutdown = xfsm_shutdown_get ();
 
734
  if (xfsm_shutdown_can_save_session (shutdown))
 
735
    autosave = xfconf_channel_get_bool (channel, "/general/AutoSave", FALSE);
 
736
  else
 
737
    autosave = FALSE;
 
738
  g_object_unref (shutdown);
 
739
 
 
740
  /* check if we need to bother the user */
 
741
  if (!xfconf_channel_get_bool (channel, "/general/PromptOnLogout", TRUE))
 
742
    {
 
743
      *return_type = XFSM_SHUTDOWN_LOGOUT;
 
744
      *return_save_session = autosave;
 
745
 
 
746
      return TRUE;
 
747
    }
 
748
 
 
749
  /* decide on which screen we should show the dialog */
 
750
  screen = xfce_gdk_screen_get_active (&monitor);
 
751
  if (G_UNLIKELY (screen == NULL))
 
752
    {
 
753
      screen = gdk_screen_get_default ();
 
754
      monitor = 0;
 
755
    }
 
756
 
 
757
  /* check if accessibility is enabled */
 
758
  hidden = gtk_invisible_new_for_screen (screen);
 
759
  gtk_widget_show (hidden);
 
760
  a11y = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (hidden));
 
761
 
 
762
  if (G_LIKELY (!a11y))
 
763
    {
 
764
      /* wait until we can grab the keyboard, we need this for
 
765
       * the dialog when running it */
 
766
      for (;;)
 
767
        {
 
768
          if (gdk_keyboard_grab (gtk_widget_get_window (hidden), FALSE,
 
769
                                 GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS)
 
770
            {
 
771
              gdk_keyboard_ungrab (GDK_CURRENT_TIME);
 
772
              break;
 
773
            }
 
774
 
 
775
          g_usleep (G_USEC_PER_SEC / 20);
 
776
        }
 
777
 
 
778
      /* make a screenshot */
 
779
      if (xfconf_channel_get_bool (channel, "/general/ShowScreenshots", TRUE))
 
780
        screenshot = xfsm_logout_dialog_screenshot_new (screen);
 
781
 
 
782
      /* display fadeout */
 
783
      fadeout = xfsm_fadeout_new (gdk_screen_get_display (screen));
 
784
      gdk_flush ();
 
785
 
 
786
      dialog = g_object_new (XFSM_TYPE_LOGOUT_DIALOG,
 
787
                             "type", GTK_WINDOW_POPUP,
 
788
                             "screen", screen, NULL);
 
789
 
 
790
      xfsm_window_add_border (GTK_WINDOW (dialog));
 
791
 
 
792
      gtk_widget_realize (dialog);
 
793
      gdk_window_set_override_redirect (dialog->window, TRUE);
 
794
      gdk_window_raise (dialog->window);
 
795
    }
 
796
  else
 
797
    {
 
798
      dialog = g_object_new (XFSM_TYPE_LOGOUT_DIALOG,
 
799
                             "decorated", !a11y,
 
800
                             "screen", screen, NULL);
 
801
 
 
802
      gtk_window_set_keep_above (GTK_WINDOW (dialog), TRUE);
 
803
      atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
 
804
    }
 
805
 
 
806
  gtk_widget_destroy (hidden);
 
807
 
 
808
  xfsm_dialog = XFSM_LOGOUT_DIALOG (dialog);
 
809
 
 
810
  /* set mode */
 
811
  xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_LOGOUT_BUTTONS);
 
812
 
 
813
  result = xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
 
814
 
 
815
  gtk_widget_hide (dialog);
 
816
 
 
817
  if (result == GTK_RESPONSE_OK)
 
818
    {
 
819
      /* check if the sudo helper needs a password */
 
820
      if (xfsm_shutdown_password_require (xfsm_dialog->shutdown, xfsm_dialog->type_clicked))
 
821
        {
 
822
          /* switch mode */
 
823
          xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_ASK_PASSWORD);
 
824
 
 
825
          /* don't leave artifacts on the background window */
 
826
          xfsm_fadeout_clear (fadeout);
 
827
 
 
828
          /* loop for sudo password tries */
 
829
          for (;;)
 
830
            {
 
831
              gtk_widget_grab_focus (xfsm_dialog->password_entry);
 
832
              gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
833
              result = xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
 
834
 
 
835
              if (result == GTK_RESPONSE_OK)
 
836
                {
 
837
                  /* bit of visual feedback we're processing the password */
 
838
                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, FALSE);
 
839
                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, FALSE);
 
840
 
 
841
                  /* update the widgets before we lock the loop */
 
842
                  while (gtk_events_pending ())
 
843
                    g_main_context_iteration (NULL, FALSE);
 
844
 
 
845
                  /* send the password to the helper */
 
846
                  text = gtk_entry_get_text (GTK_ENTRY (xfsm_dialog->password_entry));
 
847
                  state = xfsm_shutdown_password_send (xfsm_dialog->shutdown, xfsm_dialog->type_clicked, text);
 
848
                  gtk_entry_set_text (GTK_ENTRY (xfsm_dialog->password_entry), "");
 
849
 
 
850
                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, TRUE);
 
851
                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, TRUE);
 
852
 
 
853
                  if (state == PASSWORD_RETRY)
 
854
                    continue;
 
855
 
 
856
                  if (state == PASSWORD_FAILED)
 
857
                    {
 
858
                      gtk_widget_hide (dialog);
 
859
 
 
860
                      xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_SHOW_ERROR);
 
861
                      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 
862
 
 
863
                      /* don't leave artifacts on the background window */
 
864
                      xfsm_fadeout_clear (fadeout);
 
865
 
 
866
                      /* show error */
 
867
                      xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
 
868
 
 
869
                      result = GTK_RESPONSE_CANCEL;
 
870
                    }
 
871
                }
 
872
 
 
873
              /* cancel clicked, succeeded or helper killed */
 
874
              break;
 
875
            }
 
876
 
 
877
          gtk_widget_hide (dialog);
 
878
        }
 
879
 
 
880
      if (result == GTK_RESPONSE_OK)
 
881
        {
 
882
          /* store autosave state */
 
883
          if (autosave)
 
884
            *return_save_session = TRUE;
 
885
          else if (xfsm_dialog->save_session != NULL)
 
886
            *return_save_session = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xfsm_dialog->save_session));
 
887
          else
 
888
            *return_save_session = FALSE;
 
889
 
 
890
          /* return the clicked action */
 
891
          *return_type = xfsm_dialog->type_clicked;
 
892
        }
 
893
    }
 
894
 
 
895
  if (fadeout != NULL)
 
896
    xfsm_fadeout_destroy (fadeout);
 
897
 
 
898
  gtk_widget_destroy (dialog);
 
899
 
 
900
  /* store channel settings if everything worked fine */
 
901
  if (result == GTK_RESPONSE_OK)
 
902
    {
 
903
      xfconf_channel_set_string (channel, "/general/SessionName", session_name);
 
904
      xfconf_channel_set_bool (channel, "/general/SaveOnExit", *return_save_session);
 
905
    }
 
906
 
 
907
  /* save the screenshot */
 
908
  if (screenshot != NULL)
 
909
    {
 
910
      if (result == GTK_RESPONSE_OK)
 
911
        xfsm_logout_dialog_screenshot_save (screenshot, screen, session_name);
 
912
      g_object_unref (G_OBJECT (screenshot));
 
913
    }
 
914
 
 
915
  return (result == GTK_RESPONSE_OK);
 
916
}