2006-09-27 [colin] 2.5.2cvs8
authorColin Leroy <colin@colino.net>
Wed, 27 Sep 2006 20:32:39 +0000 (20:32 +0000)
committerColin Leroy <colin@colino.net>
Wed, 27 Sep 2006 20:32:39 +0000 (20:32 +0000)
* configure.ac
* src/main.c
* src/mainwindow.h
Use libSM to communicate with the session
manager, so that we can know when the
session ends, save our caches, and draft
our compose windows.

ChangeLog
PATCHSETS
configure.ac
src/main.c
src/mainwindow.h

index 18a5e68..781a675 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2006-09-27 [colin]     2.5.2cvs8
+
+       * configure.ac
+       * src/main.c
+       * src/mainwindow.h
+               Use libSM to communicate with the session
+               manager, so that we can know when the 
+               session ends, save our caches, and draft
+               our compose windows.
+
 2006-09-27 [colin]     2.5.2cvs7
 
        * src/addressbook.c
index 1f5221f..9722107 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.12.2.13 -r 1.12.2.14 src/html.c;  ) > 2.5.2cvs5.patchset
 ( cvs diff -u -r 1.382.2.311 -r 1.382.2.312 src/compose.c;  cvs diff -u -r 1.50.2.26 -r 1.50.2.27 src/compose.h;  cvs diff -u -r 1.274.2.150 -r 1.274.2.151 src/mainwindow.c;  cvs diff -u -r 1.96.2.150 -r 1.96.2.151 src/textview.c;  cvs diff -u -r 1.43.2.52 -r 1.43.2.53 src/toolbar.c;  ) > 2.5.2cvs6.patchset
 ( cvs diff -u -r 1.60.2.64 -r 1.60.2.65 src/addressbook.c;  ) > 2.5.2cvs7.patchset
+( cvs diff -u -r 1.654.2.1971 -r 1.654.2.1972 configure.ac;  cvs diff -u -r 1.115.2.104 -r 1.115.2.105 src/main.c;  cvs diff -u -r 1.39.2.23 -r 1.39.2.24 src/mainwindow.h;  ) > 2.5.2cvs8.patchset
index a91d77a..fce5fa0 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=5
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=7
+EXTRA_VERSION=8
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
@@ -196,6 +196,29 @@ fi
 
 AC_CHECK_LIB(xpg4, setlocale)
 
+SM_LIBS=""
+dnl Check for LibSM
+AC_ARG_ENABLE(libsm,
+       [  --disable-libsm    Do not use libSM for session management.],
+       [ac_cv_enable_libsm=$enableval], [ac_cv_enable_libsm=yes])
+AC_MSG_CHECKING([whether to use LibSM])
+if test x"$ac_cv_enable_libsm" = xyes; then
+       AC_MSG_RESULT(yes)
+       AC_CHECK_LIB(SM, SmcSaveYourselfDone,
+               [SM_LIBS="$X_LIBS -lSM -lICE"],ac_cv_enable_libsm=no,
+               $X_LIBS -lICE)
+       AC_CHECK_HEADERS(X11/SM/SMlib.h,,SC_HAVE_SM=false)
+       if test x"$ac_cv_enable_libsm" = xyes; then
+               AC_DEFINE(HAVE_LIBSM, 1, [Define to 1 if you have libSM installed])
+       else
+               AC_MSG_RESULT(not found)
+               AC_MSG_WARN([*** LibSM will not be supported ***])
+       fi
+else
+       AC_MSG_RESULT(no)
+fi
+AC_SUBST(SM_LIBS)
+
 dnl for GThread support (currently disabled)
 dnl AC_ARG_ENABLE(threads,
 dnl    [  --enable-threads        Enable multithread support [default=no]],
@@ -878,6 +901,7 @@ echo "GNU/aspell    : $ac_cv_enable_aspell"
 echo "IMAP4         : $ac_cv_enable_libetpan"
 echo "Crash dialog  : $ac_cv_enable_crash_dialog"
 echo "Libgnomeprint : $ac_cv_enable_gnomeprint"
+echo "LibSM         : $ac_cv_enable_libsm"
 echo "Manual        : $ac_cv_enable_manual"
 echo "Plugins       : $PLUGINS"
 echo "Config dir    : $ac_cv_with_config_dir"
index 23bc361..fc29e96 100644 (file)
 #ifdef G_OS_UNIX
 #  include <signal.h>
 #endif
+#ifdef HAVE_LIBSM
+#include <X11/SM/SMlib.h>
+#include <fcntl.h>
+#endif
+
 #include "wizard.h"
 #ifdef HAVE_STARTUP_NOTIFICATION
 # define SN_API_NOT_YET_FROZEN
 #include "crash.h"
 
 gchar *prog_version;
-#ifdef CRASH_DIALOG
 gchar *argv0;
-#endif
 
 #ifdef HAVE_STARTUP_NOTIFICATION
 static SnLauncheeContext *sn_context = NULL;
@@ -183,6 +186,7 @@ static void exit_sylpheed           (MainWindow *mainwin);
 }
 
 static MainWindow *static_mainwindow;
+static gboolean emergency_exit = FALSE;
 
 #ifdef HAVE_STARTUP_NOTIFICATION
 static void sn_error_trap_push(SnDisplay *display, Display *xdisplay)
@@ -283,6 +287,174 @@ static gboolean migrate_old_config(const gchar *old_cfg_dir, const gchar *new_cf
        return (r == 0);
 }
 
+#ifdef HAVE_LIBSM
+static void
+sc_client_set_value (MainWindow *client,
+                 gchar       *name,
+                 char        *type,
+                 int          num_vals,
+                 SmPropValue *vals)
+{
+       SmProp *proplist[1];
+       SmProp prop;
+
+       prop.name = name;
+       prop.type = type;
+       prop.num_vals = num_vals;
+       prop.vals = vals;
+
+       proplist[0]= &prop;
+       SmcSetProperties ((SmcConn) client->smc_conn, 1, proplist);
+}
+
+static void sc_die_callback (SmcConn smc_conn, SmPointer client_data)
+{
+       clean_quit(NULL);
+}
+
+static void sc_save_complete_callback(SmcConn smc_conn, SmPointer client_data)
+{
+}
+
+static void sc_shutdown_cancelled_callback (SmcConn smc_conn, SmPointer client_data)
+{
+       MainWindow *mainwin = (MainWindow *)client_data;
+       SmcSaveYourselfDone ((SmcConn) mainwin->smc_conn, TRUE);
+}
+
+static void sc_save_yourself_callback (SmcConn   smc_conn,
+                              SmPointer client_data,
+                              int       save_style,
+                              gboolean  shutdown,
+                              int       interact_style,
+                              gboolean  fast) {
+
+       MainWindow *mainwin = (MainWindow *)client_data;
+       SmcSaveYourselfDone ((SmcConn) mainwin->smc_conn, TRUE);
+}
+
+static IceIOErrorHandler sc_ice_installed_handler;
+
+static void sc_ice_io_error_handler (IceConn connection)
+{
+       if (sc_ice_installed_handler)
+               (*sc_ice_installed_handler) (connection);
+}
+static gboolean sc_process_ice_messages (GIOChannel   *source,
+                     GIOCondition  condition,
+                     gpointer      data)
+{
+       IceConn connection = (IceConn) data;
+       IceProcessMessagesStatus status;
+
+       status = IceProcessMessages (connection, NULL, NULL);
+
+       if (status == IceProcessMessagesIOError) {
+               IcePointer context = IceGetConnectionContext (connection);
+
+               if (context && GTK_IS_OBJECT (context)) {
+               guint disconnect_id = g_signal_lookup ("disconnect", G_OBJECT_TYPE (context));
+
+               if (disconnect_id > 0)
+                       g_signal_emit (context, disconnect_id, 0);
+               } else {
+                       IceSetShutdownNegotiation (connection, False);
+                       IceCloseConnection (connection);
+               }
+       }
+
+       return TRUE;
+}
+
+static void new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
+                   IcePointer *watch_data)
+{
+       guint input_id;
+
+       if (opening) {
+               GIOChannel *channel;
+               /* Make sure we don't pass on these file descriptors to any
+               exec'ed children */
+               fcntl(IceConnectionNumber(connection),F_SETFD,
+               fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
+
+               channel = g_io_channel_unix_new (IceConnectionNumber (connection));
+               input_id = g_io_add_watch (channel,
+               G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
+               sc_process_ice_messages,
+               connection);
+               g_io_channel_unref (channel);
+
+               *watch_data = (IcePointer) GUINT_TO_POINTER (input_id);
+       } else {
+               input_id = GPOINTER_TO_UINT ((gpointer) *watch_data);
+               g_source_remove (input_id);
+       }
+}
+
+static void sc_session_manager_connect(MainWindow *mainwin)
+{
+       static gboolean connected = FALSE;
+       SmcCallbacks      callbacks;
+       gchar            *client_id;
+       IceIOErrorHandler default_handler;
+
+       if (connected)
+               return;
+       connected = TRUE;
+
+
+       sc_ice_installed_handler = IceSetIOErrorHandler (NULL);
+       default_handler = IceSetIOErrorHandler (sc_ice_io_error_handler);
+
+       if (sc_ice_installed_handler == default_handler)
+               sc_ice_installed_handler = NULL;
+
+       IceAddConnectionWatch (new_ice_connection, NULL);
+      
+      
+       callbacks.save_yourself.callback      = sc_save_yourself_callback;
+       callbacks.die.callback                = sc_die_callback;
+       callbacks.save_complete.callback      = sc_save_complete_callback;
+       callbacks.shutdown_cancelled.callback = sc_shutdown_cancelled_callback;
+
+       callbacks.save_yourself.client_data =
+               callbacks.die.client_data =
+               callbacks.save_complete.client_data =
+               callbacks.shutdown_cancelled.client_data = (SmPointer) mainwin;
+       if (g_getenv ("SESSION_MANAGER")) {
+               gchar error_string_ret[256] = "";
+
+               mainwin->smc_conn= (gpointer)
+                       SmcOpenConnection (NULL, mainwin,
+                               SmProtoMajor, SmProtoMinor,
+                               SmcSaveYourselfProcMask | SmcDieProcMask |
+                               SmcSaveCompleteProcMask |
+                               SmcShutdownCancelledProcMask,
+                               &callbacks,
+                               NULL, &client_id,
+                               256, error_string_ret);
+
+               if (error_string_ret[0])
+                       g_warning ("While connecting to session manager:\n%s.",
+                               error_string_ret);
+               else {
+                       SmPropValue *vals;
+                       vals = g_new (SmPropValue, 1);
+                       vals[0].length = strlen(argv0);
+                       vals[0].value = argv0;
+                       sc_client_set_value (mainwin, SmCloneCommand, SmLISTofARRAY8, 1, vals);
+                       sc_client_set_value (mainwin, SmRestartCommand, SmLISTofARRAY8, 1, vals);
+                       sc_client_set_value (mainwin, SmProgram, SmARRAY8, 1, vals);
+
+                       vals[0].length = strlen(g_get_user_name()?g_get_user_name():"");
+                       vals[0].value = g_strdup(g_get_user_name()?g_get_user_name():"");
+                       sc_client_set_value (mainwin, SmUserID, SmARRAY8, 1, vals);
+               }
+       }
+}
+#endif
+
 int main(int argc, char *argv[])
 {
        gchar *userrc;
@@ -296,9 +468,7 @@ int main(int argc, char *argv[])
        }
 
        prog_version = PROG_VERSION;
-#ifdef CRASH_DIALOG
        argv0 = g_strdup(argv[0]);
-#endif
 
        parse_cmd_opt(argc, argv);
 
@@ -589,6 +759,9 @@ int main(int argc, char *argv[])
 
 #ifdef HAVE_STARTUP_NOTIFICATION
        startup_notification_complete(FALSE);
+#endif
+#ifdef HAVE_LIBSM
+       sc_session_manager_connect(mainwin);
 #endif
        folder_item_update_thaw();
        gtk_clist_thaw(GTK_CLIST(mainwin->folderview->ctree));
@@ -648,13 +821,16 @@ static gboolean sc_exiting = FALSE;
 static void exit_sylpheed(MainWindow *mainwin)
 {
        gchar *filename;
+#ifdef HAVE_LIBSM
+       SmcConn smc_conn = mainwin->smc_conn;
+#endif
 
        sc_exiting = TRUE;
 
        debug_print("shutting down\n");
        inc_autocheck_timer_remove();
 
-       if (prefs_common.clean_on_exit) {
+       if (prefs_common.clean_on_exit && !emergency_exit) {
                main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
        }
 
@@ -722,7 +898,9 @@ static void exit_sylpheed(MainWindow *mainwin)
        gtkaspell_checkers_quit();
 #endif
        sylpheed_done();
-
+#ifdef HAVE_LIBSM
+       SmcCloseConnection (smc_conn, 0, NULL);
+#endif
 }
 
 static void parse_cmd_opt(int argc, char *argv[])
@@ -920,7 +1098,6 @@ static void draft_all_messages(void)
                compose_draft(c);
        }       
 }
-
 gboolean clean_quit(gpointer data)
 {
        static gboolean firstrun = TRUE;
@@ -947,7 +1124,7 @@ gboolean clean_quit(gpointer data)
        }
                
        draft_all_messages();
-
+       emergency_exit = TRUE;
        exit_sylpheed(static_mainwindow);
        exit(0);
 
index 13d80be..d536312 100644 (file)
@@ -140,6 +140,10 @@ struct _MainWindow
        
        GtkWidget       *colorlabel_menu;
        GtkWidget       *warning_btn;
+       
+#ifdef HAVE_LIBSM
+       gpointer smc_conn;
+#endif
 };
 
 MainWindow *main_window_create         (SeparateType    type);