~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to gnome-panel/libegg/eggsmclient.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-01-14 22:20:05 UTC
  • mto: (2.1.6 squeeze) (1.3.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 171.
  • Revision ID: james.westby@ubuntu.com-20100114222005-rll7tw9fojl3ac6z
Tags: upstream-2.29.5.1
ImportĀ upstreamĀ versionĀ 2.29.5.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007 Novell, Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
 
 
22
#include <string.h>
 
23
#include <glib/gi18n.h>
 
24
 
 
25
#include "eggsmclient.h"
 
26
#include "eggsmclient-private.h"
 
27
 
 
28
static void egg_sm_client_debug_handler (const char *log_domain,
 
29
                                         GLogLevelFlags log_level,
 
30
                                         const char *message,
 
31
                                         gpointer user_data);
 
32
 
 
33
enum {
 
34
  SAVE_STATE,
 
35
  QUIT_REQUESTED,
 
36
  QUIT_CANCELLED,
 
37
  QUIT,
 
38
  LAST_SIGNAL
 
39
};
 
40
 
 
41
static guint signals[LAST_SIGNAL];
 
42
 
 
43
struct _EggSMClientPrivate {
 
44
  GKeyFile *state_file;
 
45
};
 
46
 
 
47
#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
 
48
 
 
49
G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
 
50
 
 
51
static EggSMClient *global_client;
 
52
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
 
53
 
 
54
static void
 
55
egg_sm_client_init (EggSMClient *client)
 
56
{
 
57
  ;
 
58
}
 
59
 
 
60
static void
 
61
egg_sm_client_class_init (EggSMClientClass *klass)
 
62
{
 
63
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
64
 
 
65
  g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
 
66
 
 
67
  /**
 
68
   * EggSMClient::save_state:
 
69
   * @client: the client
 
70
   * @state_file: a #GKeyFile to save state information into
 
71
   *
 
72
   * Emitted when the session manager has requested that the
 
73
   * application save information about its current state. The
 
74
   * application should save its state into @state_file, and then the
 
75
   * session manager may then restart the application in a future
 
76
   * session and tell it to initialize itself from that state.
 
77
   *
 
78
   * You should not save any data into @state_file's "start group"
 
79
   * (ie, the %NULL group). Instead, applications should save their
 
80
   * data into groups with names that start with the application name,
 
81
   * and libraries that connect to this signal should save their data
 
82
   * into groups with names that start with the library name.
 
83
   *
 
84
   * Alternatively, rather than (or in addition to) using @state_file,
 
85
   * the application can save its state by calling
 
86
   * egg_sm_client_set_restart_command() during the processing of this
 
87
   * signal (eg, to include a list of files to open).
 
88
   **/
 
89
  signals[SAVE_STATE] =
 
90
    g_signal_new ("save_state",
 
91
                  G_OBJECT_CLASS_TYPE (object_class),
 
92
                  G_SIGNAL_RUN_LAST,
 
93
                  G_STRUCT_OFFSET (EggSMClientClass, save_state),
 
94
                  NULL, NULL,
 
95
                  g_cclosure_marshal_VOID__POINTER,
 
96
                  G_TYPE_NONE,
 
97
                  1, G_TYPE_POINTER);
 
98
 
 
99
  /**
 
100
   * EggSMClient::quit_requested:
 
101
   * @client: the client
 
102
   *
 
103
   * Emitted when the session manager requests that the application
 
104
   * exit (generally because the user is logging out). The application
 
105
   * should decide whether or not it is willing to quit (perhaps after
 
106
   * asking the user what to do with documents that have unsaved
 
107
   * changes) and then call egg_sm_client_will_quit(), passing %TRUE
 
108
   * or %FALSE to give its answer to the session manager. (It does not
 
109
   * need to give an answer before returning from the signal handler;
 
110
   * it can interact with the user asynchronously and then give its
 
111
   * answer later on.) If the application does not connect to this
 
112
   * signal, then #EggSMClient will automatically return %TRUE on its
 
113
   * behalf.
 
114
   *
 
115
   * The application should not save its session state as part of
 
116
   * handling this signal; if the user has requested that the session
 
117
   * be saved when logging out, then ::save_state will be emitted
 
118
   * separately.
 
119
   * 
 
120
   * If the application agrees to quit, it should then wait for either
 
121
   * the ::quit_cancelled or ::quit signals to be emitted.
 
122
   **/
 
123
  signals[QUIT_REQUESTED] =
 
124
    g_signal_new ("quit_requested",
 
125
                  G_OBJECT_CLASS_TYPE (object_class),
 
126
                  G_SIGNAL_RUN_LAST,
 
127
                  G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
 
128
                  NULL, NULL,
 
129
                  g_cclosure_marshal_VOID__VOID,
 
130
                  G_TYPE_NONE,
 
131
                  0);
 
132
 
 
133
  /**
 
134
   * EggSMClient::quit_cancelled:
 
135
   * @client: the client
 
136
   *
 
137
   * Emitted when the session manager decides to cancel a logout after
 
138
   * the application has already agreed to quit. After receiving this
 
139
   * signal, the application can go back to what it was doing before
 
140
   * receiving the ::quit_requested signal.
 
141
   **/
 
142
  signals[QUIT_CANCELLED] =
 
143
    g_signal_new ("quit_cancelled",
 
144
                  G_OBJECT_CLASS_TYPE (object_class),
 
145
                  G_SIGNAL_RUN_LAST,
 
146
                  G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
 
147
                  NULL, NULL,
 
148
                  g_cclosure_marshal_VOID__VOID,
 
149
                  G_TYPE_NONE,
 
150
                  0);
 
151
 
 
152
  /**
 
153
   * EggSMClient::quit:
 
154
   * @client: the client
 
155
   *
 
156
   * Emitted when the session manager wants the application to quit
 
157
   * (generally because the user is logging out). The application
 
158
   * should exit as soon as possible after receiving this signal; if
 
159
   * it does not, the session manager may choose to forcibly kill it.
 
160
   *
 
161
   * Normally a GUI application would only be sent a ::quit if it
 
162
   * agreed to quit in response to a ::quit_requested signal. However,
 
163
   * this is not guaranteed; in some situations the session manager
 
164
   * may decide to end the session without giving applications a
 
165
   * chance to object.
 
166
   **/
 
167
  signals[QUIT] =
 
168
    g_signal_new ("quit",
 
169
                  G_OBJECT_CLASS_TYPE (object_class),
 
170
                  G_SIGNAL_RUN_LAST,
 
171
                  G_STRUCT_OFFSET (EggSMClientClass, quit),
 
172
                  NULL, NULL,
 
173
                  g_cclosure_marshal_VOID__VOID,
 
174
                  G_TYPE_NONE,
 
175
                  0);
 
176
}
 
177
 
 
178
static gboolean sm_client_disable = FALSE;
 
179
static char *sm_client_state_file = NULL;
 
180
static char *sm_client_id = NULL;
 
181
static char *sm_config_prefix = NULL;
 
182
 
 
183
static gboolean
 
184
sm_client_post_parse_func (GOptionContext  *context,
 
185
                           GOptionGroup    *group,
 
186
                           gpointer         data,
 
187
                           GError         **error)
 
188
{
 
189
  EggSMClient *client = egg_sm_client_get ();
 
190
 
 
191
  if (sm_client_id == NULL)
 
192
    {
 
193
      const gchar *desktop_autostart_id;
 
194
 
 
195
      desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
 
196
 
 
197
      if (desktop_autostart_id != NULL)
 
198
        sm_client_id = g_strdup (desktop_autostart_id);
 
199
    }
 
200
 
 
201
  /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
 
202
   * use the same client id. */
 
203
  g_unsetenv ("DESKTOP_AUTOSTART_ID");
 
204
 
 
205
  if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
 
206
      EGG_SM_CLIENT_GET_CLASS (client)->startup)
 
207
    EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
 
208
  return TRUE;
 
209
}
 
210
 
 
211
/**
 
212
 * egg_sm_client_get_option_group:
 
213
 *
 
214
 * Creates a %GOptionGroup containing the session-management-related
 
215
 * options. You should add this group to the application's
 
216
 * %GOptionContext if you want to use #EggSMClient.
 
217
 *
 
218
 * Return value: the %GOptionGroup
 
219
 **/
 
220
GOptionGroup *
 
221
egg_sm_client_get_option_group (void)
 
222
{
 
223
  const GOptionEntry entries[] = {
 
224
    { "sm-client-disable", 0, 0,
 
225
      G_OPTION_ARG_NONE, &sm_client_disable,
 
226
      N_("Disable connection to session manager"), NULL },
 
227
    { "sm-client-state-file", 0, 0,
 
228
      G_OPTION_ARG_FILENAME, &sm_client_state_file,
 
229
      N_("Specify file containing saved configuration"), N_("FILE") },
 
230
    { "sm-client-id", 0, 0,
 
231
      G_OPTION_ARG_STRING, &sm_client_id,
 
232
      N_("Specify session management ID"), N_("ID") },
 
233
    /* GnomeClient compatibility option */
 
234
    { "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
 
235
      G_OPTION_ARG_NONE, &sm_client_disable,
 
236
      NULL, NULL },
 
237
    /* GnomeClient compatibility option. This is a dummy option that only
 
238
     * exists so that sessions saved by apps with GnomeClient can be restored
 
239
     * later when they've switched to EggSMClient. See bug #575308.
 
240
     */
 
241
    { "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
 
242
      G_OPTION_ARG_STRING, &sm_config_prefix,
 
243
      NULL, NULL },
 
244
    { NULL }
 
245
  };
 
246
  GOptionGroup *group;
 
247
 
 
248
  /* Use our own debug handler for the "EggSMClient" domain. */
 
249
  g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
 
250
                     egg_sm_client_debug_handler, NULL);
 
251
 
 
252
  group = g_option_group_new ("sm-client",
 
253
                              _("Session management options:"),
 
254
                              _("Show session management options"),
 
255
                              NULL, NULL);
 
256
  g_option_group_add_entries (group, entries);
 
257
  g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
 
258
 
 
259
  return group;
 
260
}
 
261
 
 
262
/**
 
263
 * egg_sm_client_set_mode:
 
264
 * @mode: an #EggSMClient mode
 
265
 *
 
266
 * Sets the "mode" of #EggSMClient as follows:
 
267
 *
 
268
 *    %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
 
269
 *    disabled, until the mode is changed again. The application will
 
270
 *    not even connect to the session manager. (egg_sm_client_get()
 
271
 *    will still return an #EggSMClient object.)
 
272
 *
 
273
 *    %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
 
274
 *    the session manager (and thus will receive notification when the
 
275
 *    user is logging out, etc), but will request to not be
 
276
 *    automatically restarted with saved state in future sessions.
 
277
 *
 
278
 *    %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
 
279
 *    function normally.
 
280
 *
 
281
 * This must be called before the application's main loop begins and
 
282
 * before any call to egg_sm_client_get(), unless the mode was set
 
283
 * earlier to %EGG_SM_CLIENT_MODE_DISABLED and this call enables
 
284
 * session management. Note that option parsing will call
 
285
 * egg_sm_client_get().
 
286
 **/
 
287
void
 
288
egg_sm_client_set_mode (EggSMClientMode mode)
 
289
{
 
290
  EggSMClientMode old_mode = global_client_mode;
 
291
 
 
292
  g_return_if_fail (global_client == NULL || global_client_mode == EGG_SM_CLIENT_MODE_DISABLED);
 
293
  g_return_if_fail (!(global_client != NULL && mode == EGG_SM_CLIENT_MODE_DISABLED));
 
294
 
 
295
  global_client_mode = mode;
 
296
 
 
297
  if (global_client != NULL && old_mode == EGG_SM_CLIENT_MODE_DISABLED)
 
298
    {
 
299
      if (EGG_SM_CLIENT_GET_CLASS (global_client)->startup)
 
300
        EGG_SM_CLIENT_GET_CLASS (global_client)->startup (global_client, sm_client_id);
 
301
    }
 
302
}
 
303
 
 
304
/**
 
305
 * egg_sm_client_get_mode:
 
306
 *
 
307
 * Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
 
308
 * for details.
 
309
 *
 
310
 * Return value: the global #EggSMClientMode
 
311
 **/
 
312
EggSMClientMode
 
313
egg_sm_client_get_mode (void)
 
314
{
 
315
  return global_client_mode;
 
316
}
 
317
 
 
318
/**
 
319
 * egg_sm_client_get:
 
320
 *
 
321
 * Returns the master #EggSMClient for the application.
 
322
 *
 
323
 * On platforms that support saved sessions (ie, POSIX/X11), the
 
324
 * application will only request to be restarted by the session
 
325
 * manager if you call egg_set_desktop_file() to set an application
 
326
 * desktop file. In particular, if the desktop file contains the key
 
327
 * "X
 
328
 *
 
329
 * Return value: the master #EggSMClient.
 
330
 **/
 
331
EggSMClient *
 
332
egg_sm_client_get (void)
 
333
{
 
334
  if (!global_client)
 
335
    {
 
336
      if (!sm_client_disable)
 
337
        {
 
338
#if defined (GDK_WINDOWING_WIN32)
 
339
          global_client = egg_sm_client_win32_new ();
 
340
#elif defined (GDK_WINDOWING_QUARTZ)
 
341
          global_client = egg_sm_client_osx_new ();
 
342
#else
 
343
          /* If both D-Bus and XSMP are compiled in, try XSMP first
 
344
           * (since it supports state saving) and fall back to D-Bus
 
345
           * if XSMP isn't available.
 
346
           */
 
347
# ifdef EGG_SM_CLIENT_BACKEND_XSMP
 
348
          global_client = egg_sm_client_xsmp_new ();
 
349
# endif
 
350
# ifdef EGG_SM_CLIENT_BACKEND_DBUS
 
351
          if (!global_client)
 
352
            global_client = egg_sm_client_dbus_new ();
 
353
# endif
 
354
#endif
 
355
        }
 
356
 
 
357
      /* Fallback: create a dummy client, so that callers don't have
 
358
       * to worry about a %NULL return value.
 
359
       */
 
360
      if (!global_client)
 
361
        global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
 
362
    }
 
363
 
 
364
  return global_client;
 
365
}
 
366
 
 
367
/**
 
368
 * egg_sm_client_is_resumed:
 
369
 * @client: the client
 
370
 *
 
371
 * Checks whether or not the current session has been resumed from
 
372
 * a previous saved session. If so, the application should call
 
373
 * egg_sm_client_get_state_file() and restore its state from the
 
374
 * returned #GKeyFile.
 
375
 *
 
376
 * Return value: %TRUE if the session has been resumed
 
377
 **/
 
378
gboolean
 
379
egg_sm_client_is_resumed (EggSMClient *client)
 
380
{
 
381
  g_return_val_if_fail (client == global_client, FALSE);
 
382
 
 
383
  return sm_client_state_file != NULL;
 
384
}
 
385
 
 
386
/**
 
387
 * egg_sm_client_get_state_file:
 
388
 * @client: the client
 
389
 *
 
390
 * If the application was resumed by the session manager, this will
 
391
 * return the #GKeyFile containing its state from the previous
 
392
 * session.
 
393
 *
 
394
 * Note that other libraries and #EggSMClient itself may also store
 
395
 * state in the key file, so if you call egg_sm_client_get_groups(),
 
396
 * on it, the return value will likely include groups that you did not
 
397
 * put there yourself. (It is also not guaranteed that the first
 
398
 * group created by the application will still be the "start group"
 
399
 * when it is resumed.)
 
400
 *
 
401
 * Return value: the #GKeyFile containing the application's earlier
 
402
 * state, or %NULL on error. You should not free this key file; it
 
403
 * is owned by @client.
 
404
 **/
 
405
GKeyFile *
 
406
egg_sm_client_get_state_file (EggSMClient *client)
 
407
{
 
408
  EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
 
409
  char *state_file_path;
 
410
  GError *err = NULL;
 
411
 
 
412
  g_return_val_if_fail (client == global_client, NULL);
 
413
 
 
414
  if (!sm_client_state_file)
 
415
    return NULL;
 
416
  if (priv->state_file)
 
417
    return priv->state_file;
 
418
 
 
419
  if (!strncmp (sm_client_state_file, "file://", 7))
 
420
    state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
 
421
  else
 
422
    state_file_path = g_strdup (sm_client_state_file);
 
423
 
 
424
  priv->state_file = g_key_file_new ();
 
425
  if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
 
426
    {
 
427
      g_warning ("Could not load SM state file '%s': %s",
 
428
                 sm_client_state_file, err->message);
 
429
      g_clear_error (&err);
 
430
      g_key_file_free (priv->state_file);
 
431
      priv->state_file = NULL;
 
432
    }
 
433
 
 
434
  g_free (state_file_path);
 
435
  return priv->state_file;
 
436
}
 
437
 
 
438
/**
 
439
 * egg_sm_client_set_restart_command:
 
440
 * @client: the client
 
441
 * @argc: the length of @argv
 
442
 * @argv: argument vector
 
443
 *
 
444
 * Sets the command used to restart @client if it does not have a
 
445
 * .desktop file that can be used to find its restart command.
 
446
 *
 
447
 * This can also be used when handling the ::save_state signal, to
 
448
 * save the current state via an updated command line. (Eg, providing
 
449
 * a list of filenames to open when the application is resumed.)
 
450
 **/
 
451
void
 
452
egg_sm_client_set_restart_command (EggSMClient  *client,
 
453
                                   int           argc,
 
454
                                   const char  **argv)
 
455
{
 
456
  g_return_if_fail (EGG_IS_SM_CLIENT (client));
 
457
 
 
458
  if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
 
459
    EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
 
460
}
 
461
 
 
462
/**
 
463
 * egg_sm_client_will_quit:
 
464
 * @client: the client
 
465
 * @will_quit: whether or not the application is willing to quit
 
466
 *
 
467
 * This MUST be called in response to the ::quit_requested signal, to
 
468
 * indicate whether or not the application is willing to quit. The
 
469
 * application may call it either directly from the signal handler, or
 
470
 * at some later point (eg, after asynchronously interacting with the
 
471
 * user).
 
472
 *
 
473
 * If the application does not connect to ::quit_requested,
 
474
 * #EggSMClient will call this method on its behalf (passing %TRUE
 
475
 * for @will_quit).
 
476
 *
 
477
 * After calling this method, the application should wait to receive
 
478
 * either ::quit_cancelled or ::quit.
 
479
 **/
 
480
void
 
481
egg_sm_client_will_quit (EggSMClient *client,
 
482
                         gboolean     will_quit)
 
483
{
 
484
  g_return_if_fail (EGG_IS_SM_CLIENT (client));
 
485
 
 
486
  if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
 
487
    EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
 
488
}
 
489
 
 
490
/**
 
491
 * egg_sm_client_end_session:
 
492
 * @style: a hint at how to end the session
 
493
 * @request_confirmation: whether or not the user should get a chance
 
494
 * to confirm the action
 
495
 *
 
496
 * Requests that the session manager end the current session. @style
 
497
 * indicates how the session should be ended, and
 
498
 * @request_confirmation indicates whether or not the user should be
 
499
 * given a chance to confirm the logout/reboot/shutdown. Both of these
 
500
 * flags are merely hints though; the session manager may choose to
 
501
 * ignore them.
 
502
 *
 
503
 * Return value: %TRUE if the request was sent; %FALSE if it could not
 
504
 * be (eg, because it could not connect to the session manager).
 
505
 **/
 
506
gboolean
 
507
egg_sm_client_end_session (EggSMClientEndStyle  style,
 
508
                           gboolean             request_confirmation)
 
509
{
 
510
  EggSMClient *client = egg_sm_client_get ();
 
511
 
 
512
  g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
 
513
 
 
514
  if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
 
515
    {
 
516
      return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
 
517
                                                            request_confirmation);
 
518
    }
 
519
  else
 
520
    return FALSE;
 
521
}
 
522
 
 
523
/* Signal-emitting callbacks from platform-specific code */
 
524
 
 
525
GKeyFile *
 
526
egg_sm_client_save_state (EggSMClient *client)
 
527
{
 
528
  GKeyFile *state_file;
 
529
  char *group;
 
530
 
 
531
  g_return_val_if_fail (client == global_client, NULL);
 
532
 
 
533
  state_file = g_key_file_new ();
 
534
 
 
535
  g_debug ("Emitting save_state");
 
536
  g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
 
537
  g_debug ("Done emitting save_state");
 
538
 
 
539
  group = g_key_file_get_start_group (state_file);
 
540
  if (group)
 
541
    {
 
542
      g_free (group);
 
543
      return state_file;
 
544
    }
 
545
  else
 
546
    {
 
547
      g_key_file_free (state_file);
 
548
      return NULL;
 
549
    }
 
550
}
 
551
 
 
552
void
 
553
egg_sm_client_quit_requested (EggSMClient *client)
 
554
{
 
555
  g_return_if_fail (client == global_client);
 
556
 
 
557
  if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
 
558
    {
 
559
      g_debug ("Not emitting quit_requested because no one is listening");
 
560
      egg_sm_client_will_quit (client, TRUE);
 
561
      return;
 
562
    }
 
563
 
 
564
  g_debug ("Emitting quit_requested");
 
565
  g_signal_emit (client, signals[QUIT_REQUESTED], 0);
 
566
  g_debug ("Done emitting quit_requested");
 
567
}
 
568
 
 
569
void
 
570
egg_sm_client_quit_cancelled (EggSMClient *client)
 
571
{
 
572
  g_return_if_fail (client == global_client);
 
573
 
 
574
  g_debug ("Emitting quit_cancelled");
 
575
  g_signal_emit (client, signals[QUIT_CANCELLED], 0);
 
576
  g_debug ("Done emitting quit_cancelled");
 
577
}
 
578
 
 
579
void
 
580
egg_sm_client_quit (EggSMClient *client)
 
581
{
 
582
  g_return_if_fail (client == global_client);
 
583
 
 
584
  g_debug ("Emitting quit");
 
585
  g_signal_emit (client, signals[QUIT], 0);
 
586
  g_debug ("Done emitting quit");
 
587
 
 
588
  /* FIXME: should we just call gtk_main_quit() here? */
 
589
}
 
590
 
 
591
static void
 
592
egg_sm_client_debug_handler (const char *log_domain,
 
593
                             GLogLevelFlags log_level,
 
594
                             const char *message,
 
595
                             gpointer user_data)
 
596
{
 
597
  static int debug = -1;
 
598
 
 
599
  if (debug < 0)
 
600
    debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
 
601
 
 
602
  if (debug)
 
603
    g_log_default_handler (log_domain, log_level, message, NULL);
 
604
}