/* session.c -- session manager skeleton $Id: session.c,v 1.14 2001/02/12 20:09:48 jsh Exp $ Copyright (C) 1999 John Harper This file is part of sawmill. sawmill is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. sawmill is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sawmill; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* AIX requires this to be the first thing in the file. */ #ifdef HAVE_CONFIG_H #include #endif #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #include "sawmill.h" #ifdef HAVE_X11_SM_SMLIB_H # include #endif DEFSYM(sm_save_yourself, "sm-save-yourself"); #ifdef HAVE_X11_SM_SMLIB_H static IceConn ice_conn; static SmcConn sm_conn; #endif /* Lisp functions */ DEFUN("sm-set-property", Fsm_set_property, Ssm_set_property, (repv prop, repv value), rep_Subr2) /* ::doc:sawfish.wm.session.util#sm-set-property:: sm-set-property PROPERTY-NAME VALUE Sets the session manager property called PROPERTY-NAME (a string) to VALUE. VALUE may be either an integer, a string, or a list of strings. ::end:: */ { #ifdef HAVE_X11_SM_SMLIB_H SmProp sm_prop, *sm_ptr = &sm_prop; rep_DECLARE1 (prop, rep_STRINGP); if (sm_conn == 0) return Qnil; sm_prop.name = rep_STR(prop); if (rep_INTP(value)) { u_char val = rep_INT(value); sm_prop.type = SmCARD8; sm_prop.num_vals = 1; sm_prop.vals = alloca (sizeof (SmPropValue)); sm_prop.vals->length = 1; sm_prop.vals->value = &val; } else if (rep_STRINGP(value)) { sm_prop.type = SmARRAY8; sm_prop.num_vals = 1; sm_prop.vals = alloca (sizeof (SmPropValue)); sm_prop.vals->length = rep_STRING_LEN(value); sm_prop.vals->value = rep_STR(value); } else if (rep_CONSP(value)) { repv len = Flength (value), tem; if (len && rep_INTP(len)) { int i; sm_prop.type = SmLISTofARRAY8; sm_prop.num_vals = rep_INT(len); sm_prop.vals = alloca (sizeof (SmPropValue) * sm_prop.num_vals); tem = value; for (i = 0; i < sm_prop.num_vals; i++) { if (!rep_STRINGP(rep_CAR(tem))) return rep_signal_arg_error (value, 2); sm_prop.vals[i].length = rep_STRING_LEN(rep_CAR(tem)); sm_prop.vals[i].value = rep_STR(rep_CAR(tem)); tem = rep_CDR(tem); } } } else return rep_signal_arg_error (value, 2); SmcSetProperties (sm_conn, 1, &sm_ptr); #endif return Qt; } DEFUN("sm-delete-property", Fsm_delete_property, Ssm_delete_property, (repv prop), rep_Subr1) /* ::doc:sawfish.wm.session.util#sm-delete-property:: sm-delete-property PROPERTY-NAME Deletes the session manager property called PROPERTY-NAME (a string). ::end:: */ { #ifdef HAVE_X11_SM_SMLIB_H char *name; rep_DECLARE1(prop, rep_STRING); if (sm_conn == 0) return Qnil; name = rep_STR(prop); SmcDeleteProperties (sm_conn, 1, &name); #endif return Qt; } /* SM callbacks */ #ifdef HAVE_X11_SM_SMLIB_H static bool outstanding_save_done; static void save_yourself_2 (SmcConn conn, SmPointer data) { repv ret = rep_call_lisp0 (global_symbol_value (Qsm_save_yourself)); SmcSaveYourselfDone (conn, (ret && ret != Qnil) ? True : False); outstanding_save_done = FALSE; } static void save_yourself (SmcConn conn, SmPointer data, int save_type, Bool shutdown, int interact_style, Bool fast) { if (save_type == SmSaveLocal || save_type == SmSaveBoth) { outstanding_save_done = TRUE; SmcRequestSaveYourselfPhase2 (conn, &save_yourself_2, 0); } else SmcSaveYourselfDone (conn, True); } static void die__ (void) { exit_code = ec_session_died; Fquit (); } static void die (SmcConn conn, SmPointer data) { die__ (); } static void save_complete (SmcConn conn, SmPointer data) { } static void shutdown_cancelled (SmcConn conn, SmPointer data) { if (outstanding_save_done) { SmcSaveYourselfDone (conn, True); outstanding_save_done = FALSE; } } #endif /* HAVE_X11_SM_SMLIB_H */ /* ICE hooks */ #ifdef HAVE_X11_SM_SMLIB_H static void ICE_input_ready (int fd) { if (IceProcessMessages (ice_conn, 0, 0) != IceProcessMessagesSuccess) { fputs ("ICE has broken?\n", stderr); die__ (); } } static void ICE_watch_callback (IceConn ice, IcePointer client_data, Bool open, IcePointer *watch_data) { if (open) rep_register_input_fd (IceConnectionNumber(ice), ICE_input_ready); else rep_deregister_input_fd (IceConnectionNumber(ice)); } #endif /* HAVE_X11_SM_SMLIB_H */ /* initialisation */ DEFUN("sm-connect", Fsm_connect, Ssm_connect, (repv id), rep_Subr1) { #ifdef HAVE_X11_SM_SMLIB_H SmcCallbacks call; char *ret_id; char err[256]; IceAddConnectionWatch (ICE_watch_callback, 0); call.save_yourself.callback = save_yourself; call.die.callback = die; call.save_complete.callback = save_complete; call.shutdown_cancelled.callback = shutdown_cancelled; sm_conn = SmcOpenConnection (0, 0, 1, 0, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, &call, rep_STRINGP(id) ? rep_STR(id) : 0, &ret_id, sizeof (err), err); if (sm_conn != 0) { ice_conn = SmcGetIceConnection (sm_conn); return rep_string_dup (ret_id); } else { return Fsignal (Qerror, rep_list_2 (rep_string_dup ("sm-open-connection"), rep_string_dup (err))); } #else return Qnil; #endif } DEFUN("sm-disconnect", Fsm_disconnect, Ssm_disconnect, (void), rep_Subr0) { #ifdef HAVE_X11_SM_SMLIB_H if (sm_conn != 0) SmcCloseConnection (sm_conn, 0, 0); sm_conn = 0; ice_conn = 0; #endif return Qt; } void session_init (void) { repv tem = rep_push_structure ("sawfish.wm.session.util"); rep_ADD_SUBR(Ssm_set_property); rep_ADD_SUBR(Ssm_delete_property); rep_ADD_SUBR(Ssm_connect); rep_ADD_SUBR(Ssm_disconnect); rep_INTERN(sm_save_yourself); rep_pop_structure (tem); } void session_kill (void) { Fsm_disconnect (); }