From e90b426fbab1d91302abefc12306edcd6b40d9b3 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Wed, 27 Sep 2006 20:32:39 +0000 Subject: [PATCH] 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. --- ChangeLog | 10 +++ PATCHSETS | 1 + configure.ac | 26 ++++++- src/main.c | 193 +++++++++++++++++++++++++++++++++++++++++++++-- src/mainwindow.h | 4 + 5 files changed, 225 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18a5e68f6..781a675e0 100644 --- 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 diff --git a/PATCHSETS b/PATCHSETS index 1f5221f68..972210716 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -1921,3 +1921,4 @@ ( 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 diff --git a/configure.ac b/configure.ac index a91d77a21..fce5fa01d 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/src/main.c b/src/main.c index 23bc361d8..fc29e96a8 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,11 @@ #ifdef G_OS_UNIX # include #endif +#ifdef HAVE_LIBSM +#include +#include +#endif + #include "wizard.h" #ifdef HAVE_STARTUP_NOTIFICATION # define SN_API_NOT_YET_FROZEN @@ -105,9 +110,7 @@ #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]= ∝ + 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); diff --git a/src/mainwindow.h b/src/mainwindow.h index 13d80be37..d5363125d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -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); -- 2.25.1