static void save_yourself_possibly_done (gboolean shutdown, gboolean successful) { meta_topic (META_DEBUG_SM, "save possibly done shutdown = %d success = %d\n", shutdown, successful); if (current_state == STATE_SAVING_PHASE_1) { Status status; status = SmcRequestSaveYourselfPhase2 (session_connection, save_phase_2_callback, GINT_TO_POINTER (shutdown)); if (status) current_state = STATE_WAITING_FOR_PHASE_2; meta_topic (META_DEBUG_SM, "Requested phase 2, status = %d\n", status); } if (current_state == STATE_SAVING_PHASE_2 && interaction_allowed) { Status status; status = SmcInteractRequest (session_connection, /* ignore this feature of the protocol by always * claiming normal */ SmDialogNormal, interact_callback, GINT_TO_POINTER (shutdown)); if (status) current_state = STATE_WAITING_FOR_INTERACT; meta_topic (META_DEBUG_SM, "Requested interact, status = %d\n", status); } if (current_state == STATE_SAVING_PHASE_1 || current_state == STATE_SAVING_PHASE_2 || current_state == STATE_DONE_WITH_INTERACT || current_state == STATE_SKIPPING_GLOBAL_SAVE) { meta_topic (META_DEBUG_SM, "Sending SaveYourselfDone\n"); SmcSaveYourselfDone (session_connection, successful); if (shutdown) current_state = STATE_FROZEN; else current_state = STATE_IDLE; } }
static void smc_save_yourself_CB (SmcConn smcConn, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast) { #define NR_PROPS 5 SmProp *props[NR_PROPS]; SmProp prop_ptr[NR_PROPS]; SmPropValue values[20], *vp; int val_idx = 0, vp_idx = 0; int props_idx = 0; int i; char *smid_opt, *chdir_opt = NULL; Lisp_Object user_login_name = Fuser_login_name (Qnil); /* Must have these. */ if (! STRINGP (Vinvocation_name) || ! STRINGP (user_login_name)) return; /* How to start a new instance of Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmCloneCommand); props[props_idx]->type = xstrdup (SmLISTofARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; ++props_idx; /* The name of the program. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmProgram); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = SBYTES (Vinvocation_name); props[props_idx]->vals[0].value = SDATA (Vinvocation_name); ++props_idx; /* User id. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmUserID); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = SBYTES (user_login_name); props[props_idx]->vals[0].value = SDATA (user_login_name); ++props_idx; char *cwd = get_current_dir_name (); if (cwd) { props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmCurrentDirectory); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (cwd); props[props_idx]->vals[0].value = cwd; ++props_idx; } /* How to restart Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmRestartCommand); props[props_idx]->type = xstrdup (SmLISTofARRAY8); /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */ if (INT_ADD_WRAPV (initial_argc, 3, &i)) memory_full (SIZE_MAX); props[props_idx]->num_vals = i; vp = xnmalloc (i, sizeof *vp); props[props_idx]->vals = vp; props[props_idx]->vals[vp_idx].length = strlen (emacs_program); props[props_idx]->vals[vp_idx++].value = emacs_program; smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); strcpy (stpcpy (smid_opt, SMID_OPT), client_id); props[props_idx]->vals[vp_idx].length = strlen (smid_opt); props[props_idx]->vals[vp_idx++].value = smid_opt; props[props_idx]->vals[vp_idx].length = strlen (NOSPLASH_OPT); props[props_idx]->vals[vp_idx++].value = NOSPLASH_OPT; if (cwd) { chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1); strcpy (stpcpy (chdir_opt, CHDIR_OPT), cwd); props[props_idx]->vals[vp_idx].length = strlen (chdir_opt); props[props_idx]->vals[vp_idx++].value = chdir_opt; } for (i = 1; i < initial_argc; ++i) { props[props_idx]->vals[vp_idx].length = strlen (initial_argv[i]); props[props_idx]->vals[vp_idx++].value = initial_argv[i]; } ++props_idx; SmcSetProperties (smcConn, props_idx, props); xfree (smid_opt); xfree (chdir_opt); xfree (cwd); xfree (vp); for (i = 0; i < props_idx; ++i) { xfree (props[i]->type); xfree (props[i]->name); } /* See if we maybe shall interact with the user. */ if (interactStyle != SmInteractStyleAny || ! shutdown || saveType == SmSaveLocal || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) { /* No interaction, we are done saving ourself. */ SmcSaveYourselfDone (smcConn, True); } }
static void smc_save_yourself_CB (SmcConn smcConn, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast) { #define NR_PROPS 5 SmProp *props[NR_PROPS]; SmProp prop_ptr[NR_PROPS]; SmPropValue values[20]; int val_idx = 0; int props_idx = 0; char *cwd = NULL; char *smid_opt, *chdir_opt = NULL; /* How to start a new instance of Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmCloneCommand; props[props_idx]->type = SmLISTofARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; ++props_idx; /* The name of the program. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmProgram; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (SSDATA (Vinvocation_name)); props[props_idx]->vals[0].value = SDATA (Vinvocation_name); ++props_idx; /* How to restart Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmRestartCommand; props[props_idx]->type = SmLISTofARRAY8; /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir */ props[props_idx]->num_vals = 4; props[props_idx]->vals = &values[val_idx]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); strcpy (smid_opt, SMID_OPT); strcat (smid_opt, client_id); props[props_idx]->vals[1].length = strlen (smid_opt); props[props_idx]->vals[1].value = smid_opt; props[props_idx]->vals[2].length = strlen (NOSPLASH_OPT); props[props_idx]->vals[2].value = NOSPLASH_OPT; cwd = get_current_dir_name (); if (cwd) { chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1); strcpy (chdir_opt, CHDIR_OPT); strcat (chdir_opt, cwd); props[props_idx]->vals[3].length = strlen (chdir_opt); props[props_idx]->vals[3].value = chdir_opt; } val_idx += cwd ? 4 : 3; ++props_idx; /* User id. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmUserID; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (SSDATA (Vuser_login_name)); props[props_idx]->vals[0].value = SDATA (Vuser_login_name); ++props_idx; if (cwd) { props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmCurrentDirectory; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (cwd); props[props_idx]->vals[0].value = cwd; ++props_idx; } SmcSetProperties (smcConn, props_idx, props); xfree (smid_opt); xfree (chdir_opt); free (cwd); /* See if we maybe shall interact with the user. */ if (interactStyle != SmInteractStyleAny || ! shutdown || saveType == SmSaveLocal || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) { /* No interaction, we are done saving ourself. */ SmcSaveYourselfDone (smcConn, True); } }
void nsNativeAppSupportUnix::SaveYourselfCB(SmcConn smc_conn, SmPointer client_data, int save_style, Bool shutdown, int interact_style, Bool fast) { nsNativeAppSupportUnix *self = static_cast<nsNativeAppSupportUnix *>(client_data); // Expect a SaveYourselfCB if we're registering a new client. // All properties are already set in Start() so just reply with // SmcSaveYourselfDone if the callback matches the expected signature. // // Ancient versions (?) of xsm do not follow such an early SaveYourself with // SaveComplete. This is a problem if the application freezes interaction // while waiting for a response to SmcSaveYourselfDone. So never freeze // interaction when in STATE_REGISTERING. // // That aside, we could treat each combination of flags appropriately and not // special-case this. if (self->mClientState == STATE_REGISTERING) { self->SetClientState(STATE_IDLE); if (save_style == SmSaveLocal && interact_style == SmInteractStyleNone && !shutdown && !fast) { SmcSaveYourselfDone(self->mSessionConnection, True); return; } } if (self->mClientState == STATE_SHUTDOWN_CANCELLED) { // The last shutdown request was cancelled whilst we were interacting, // and we haven't finished interacting yet. Switch the state back again self->SetClientState(STATE_INTERACTING); } nsCOMPtr<nsIObserverService> obsServ = mozilla::services::GetObserverService(); if (!obsServ) { SmcSaveYourselfDone(smc_conn, True); return; } bool status = false; if (save_style != SmSaveGlobal) { nsCOMPtr<nsISupportsPRBool> didSaveSession = do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); if (!didSaveSession) { SmcSaveYourselfDone(smc_conn, True); return; } // Notify observers to save the session state didSaveSession->SetData(false); obsServ->NotifyObservers(didSaveSession, "session-save", nullptr); didSaveSession->GetData(&status); } // If the interact style permits us to, we are shutting down and we didn't // manage to (or weren't asked to) save the local state, then notify the user // in advance that we are doing to quit (assuming that we aren't already // doing so) if (!status && shutdown && interact_style != SmInteractStyleNone) { if (self->mClientState != STATE_INTERACTING) { SmcInteractRequest(smc_conn, SmDialogNormal, nsNativeAppSupportUnix::InteractCB, client_data); } } else { SmcSaveYourselfDone(smc_conn, True); } }