Mercurial > emacs
comparison src/xsmfns.c @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | 381ccbf15cd9 |
children |
comparison
equal
deleted
inserted
replaced
88154:8ce476d3ba36 | 88155:d7ddb3e565de |
---|---|
1 /* Session management module for systems which understand the X Session | 1 /* Session management module for systems which understand the X Session |
2 management protocol. | 2 management protocol. |
3 Copyright (C) 2002 Free Software Foundation, Inc. | 3 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GNU Emacs. | 5 This file is part of GNU Emacs. |
6 | 6 |
7 GNU Emacs is free software; you can redistribute it and/or modify | 7 GNU Emacs is free software; you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 GNU General Public License for more details. | 15 GNU General Public License for more details. |
16 | 16 |
17 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
18 along with GNU Emacs; see the file COPYING. If not, write to | 18 along with GNU Emacs; see the file COPYING. If not, write to |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 Boston, MA 02111-1307, USA. */ | 20 Boston, MA 02110-1301, USA. */ |
21 | 21 |
22 #include <config.h> | 22 #include <config.h> |
23 | 23 |
24 #ifdef HAVE_X_SM | 24 #ifdef HAVE_X_SM |
25 | 25 |
26 #include <X11/SM/SMlib.h> | 26 #include <X11/SM/SMlib.h> |
27 #include <X11/Xlib.h> | |
28 #include <X11/Xutil.h> | |
29 | |
27 #ifdef HAVE_STRING_H | 30 #ifdef HAVE_STRING_H |
28 #include <string.h> | 31 #include <string.h> |
29 #else | 32 #else |
30 #ifdef HAVE_STRINGS_H | 33 #ifdef HAVE_STRINGS_H |
31 #include <strings.h> | 34 #include <strings.h> |
40 #endif | 43 #endif |
41 | 44 |
42 #include <sys/param.h> | 45 #include <sys/param.h> |
43 #include <stdio.h> | 46 #include <stdio.h> |
44 | 47 |
48 #include "lisp.h" | |
45 #include "systime.h" | 49 #include "systime.h" |
46 #include "sysselect.h" | 50 #include "sysselect.h" |
47 #include "lisp.h" | |
48 #include "termhooks.h" | 51 #include "termhooks.h" |
49 #include "termopts.h" | 52 #include "termopts.h" |
50 | 53 #include "xterm.h" |
51 #ifndef MAXPATHLEN | |
52 #define MAXPATHLEN 1024 | |
53 #endif /* not MAXPATHLEN */ | |
54 | |
55 | 54 |
56 /* The user login name. */ | 55 /* The user login name. */ |
57 | 56 |
58 extern Lisp_Object Vuser_login_name; | 57 extern Lisp_Object Vuser_login_name; |
59 | 58 |
67 | 66 |
68 /* A flag that says if we are in shutdown interactions or not. */ | 67 /* A flag that says if we are in shutdown interactions or not. */ |
69 | 68 |
70 static int doing_interact = False; | 69 static int doing_interact = False; |
71 | 70 |
72 /* The session manager object for the session manager connection */ | 71 /* The session manager object for the session manager connection. */ |
73 | 72 |
74 static SmcConn smc_conn; | 73 static SmcConn smc_conn; |
75 | 74 |
76 /* The client session id for this session */ | 75 /* The client session id for this session. */ |
76 | |
77 static char *client_id; | 77 static char *client_id; |
78 | 78 |
79 /* The full path name to the Emacs program */ | 79 /* The full path name to the Emacs program. */ |
80 | |
80 static char *emacs_program; | 81 static char *emacs_program; |
81 | 82 |
82 /* The client session id for this session as a lisp object. */ | 83 /* The client session id for this session as a lisp object. */ |
83 | 84 |
84 Lisp_Object Vx_session_id; | 85 Lisp_Object Vx_session_id; |
85 | 86 |
86 /* The id we had the previous session. This is only available if we | 87 /* The id we had the previous session. This is only available if we |
87 have been started by the session manager with SMID_OPT. */ | 88 have been started by the session manager with SMID_OPT. */ |
88 | 89 |
89 Lisp_Object Vx_session_previous_id; | 90 Lisp_Object Vx_session_previous_id; |
90 | 91 |
91 /* The option we tell the session manager to start Emacs with when | 92 /* The option we tell the session manager to start Emacs with when |
92 restarting Emacs. The client_id is appended. */ | 93 restarting Emacs. The client_id is appended. */ |
93 | 94 |
94 #define SMID_OPT "--smid=" | 95 #define SMID_OPT "--smid=" |
96 | |
97 | |
98 /* The option to start Emacs without the splash screen when | |
99 restarting Emacs. */ | |
100 | |
101 #define NOSPLASH_OPT "--no-splash" | |
95 | 102 |
96 | 103 |
97 /* Handle any messages from the session manager. If no connection is | 104 /* Handle any messages from the session manager. If no connection is |
98 open to a session manager, just return 0. | 105 open to a session manager, just return 0. |
99 Otherwise returns the number of events stored in buffer BUFP, | 106 Otherwise returns 1 if SAVE_SESSION_EVENT is stored in buffer BUFP. */ |
100 which can hold up to *NUMCHARS characters. At most one event is | 107 |
101 stored, a SAVE_SESSION_EVENT. */ | |
102 int | 108 int |
103 x_session_check_input (bufp, numchars) | 109 x_session_check_input (bufp) |
104 struct input_event *bufp; | 110 struct input_event *bufp; |
105 int *numchars; | |
106 { | 111 { |
107 SELECT_TYPE read_fds; | 112 SELECT_TYPE read_fds; |
108 EMACS_TIME tmout; | 113 EMACS_TIME tmout; |
109 | 114 |
110 if (ice_fd == -1) return 0; | 115 if (ice_fd == -1) return 0; |
116 tmout.tv_usec = 0; | 121 tmout.tv_usec = 0; |
117 | 122 |
118 /* Reset this so wo can check kind after callbacks have been called by | 123 /* Reset this so wo can check kind after callbacks have been called by |
119 IceProcessMessages. The smc_interact_CB sets the kind to | 124 IceProcessMessages. The smc_interact_CB sets the kind to |
120 SAVE_SESSION_EVENT, but we don't know beforehand if that callback | 125 SAVE_SESSION_EVENT, but we don't know beforehand if that callback |
121 will be called. */ | 126 will be called. */ |
122 emacs_event.kind = NO_EVENT; | 127 emacs_event.kind = NO_EVENT; |
123 | 128 |
124 if (select (ice_fd+1, &read_fds, | 129 if (select (ice_fd+1, &read_fds, |
125 (SELECT_TYPE *)0, (SELECT_TYPE *)0, &tmout) < 0) | 130 (SELECT_TYPE *)0, (SELECT_TYPE *)0, &tmout) < 0) |
126 { | 131 { |
133 IceProcessMessages (SmcGetIceConnection (smc_conn), | 138 IceProcessMessages (SmcGetIceConnection (smc_conn), |
134 (IceReplyWaitInfo *)0, (Bool *)0); | 139 (IceReplyWaitInfo *)0, (Bool *)0); |
135 | 140 |
136 | 141 |
137 /* Check if smc_interact_CB was called and we shall generate a | 142 /* Check if smc_interact_CB was called and we shall generate a |
138 SAVE_SESSION_EVENT. */ | 143 SAVE_SESSION_EVENT. */ |
139 if (*numchars > 0 && emacs_event.kind != NO_EVENT) | 144 if (emacs_event.kind == NO_EVENT) |
140 { | 145 return 0; |
141 bcopy (&emacs_event, bufp, sizeof (struct input_event)); | 146 |
142 bufp++; | 147 bcopy (&emacs_event, bufp, sizeof (struct input_event)); |
143 (*numchars)--; | 148 return 1; |
144 | 149 } |
145 return 1; | 150 |
146 } | 151 /* Return non-zero if we have a connection to a session manager. */ |
147 | 152 |
148 return 0; | |
149 } | |
150 | |
151 /* Return non-zero if we have a connection to a session manager.*/ | |
152 int | 153 int |
153 x_session_have_connection () | 154 x_session_have_connection () |
154 { | 155 { |
155 return ice_fd != -1; | 156 return ice_fd != -1; |
156 } | 157 } |
157 | 158 |
158 /* This is called when the session manager says it is OK to interact with the | 159 /* This is called when the session manager says it is OK to interact with the |
159 user. Here we set the kind to SAVE_SESSION_EVENT so an event is generated. | 160 user. Here we set the kind to SAVE_SESSION_EVENT so an event is generated. |
160 Then lisp code can interact with the user. */ | 161 Then lisp code can interact with the user. */ |
162 | |
161 static void | 163 static void |
162 smc_interact_CB (smcConn, clientData) | 164 smc_interact_CB (smcConn, clientData) |
163 SmcConn smcConn; | 165 SmcConn smcConn; |
164 SmPointer clientData; | 166 SmPointer clientData; |
165 { | 167 { |
171 We set the required properties so the session manager can restart us, | 173 We set the required properties so the session manager can restart us, |
172 plus the current working directory property (not mandatory) so we | 174 plus the current working directory property (not mandatory) so we |
173 are started in the correct directory. | 175 are started in the correct directory. |
174 | 176 |
175 If this is a shutdown and we can request to interact with the user, | 177 If this is a shutdown and we can request to interact with the user, |
176 we do so, because we don't know what the lisp code might do. */ | 178 we do so, because we don't know what the lisp code might do. */ |
179 | |
177 static void | 180 static void |
178 smc_save_yourself_CB (smcConn, | 181 smc_save_yourself_CB (smcConn, |
179 clientData, | 182 clientData, |
180 saveType, | 183 saveType, |
181 shutdown, | 184 shutdown, |
195 | 198 |
196 SmPropValue values[20]; | 199 SmPropValue values[20]; |
197 int val_idx = 0; | 200 int val_idx = 0; |
198 int props_idx = 0; | 201 int props_idx = 0; |
199 | 202 |
200 char cwd[MAXPATHLEN+1]; | 203 char *cwd = NULL; |
201 char *smid_opt; | 204 char *smid_opt; |
202 | 205 |
203 /* How to start a new instance of Emacs */ | 206 /* How to start a new instance of Emacs. */ |
204 props[props_idx] = &prop_ptr[props_idx]; | 207 props[props_idx] = &prop_ptr[props_idx]; |
205 props[props_idx]->name = SmCloneCommand; | 208 props[props_idx]->name = SmCloneCommand; |
206 props[props_idx]->type = SmLISTofARRAY8; | 209 props[props_idx]->type = SmLISTofARRAY8; |
207 props[props_idx]->num_vals = 1; | 210 props[props_idx]->num_vals = 1; |
208 props[props_idx]->vals = &values[val_idx++]; | 211 props[props_idx]->vals = &values[val_idx++]; |
209 props[props_idx]->vals[0].length = strlen (emacs_program); | 212 props[props_idx]->vals[0].length = strlen (emacs_program); |
210 props[props_idx]->vals[0].value = emacs_program; | 213 props[props_idx]->vals[0].value = emacs_program; |
211 ++props_idx; | 214 ++props_idx; |
212 | 215 |
213 /* The name of the program */ | 216 /* The name of the program. */ |
214 props[props_idx] = &prop_ptr[props_idx]; | 217 props[props_idx] = &prop_ptr[props_idx]; |
215 props[props_idx]->name = SmProgram; | 218 props[props_idx]->name = SmProgram; |
216 props[props_idx]->type = SmARRAY8; | 219 props[props_idx]->type = SmARRAY8; |
217 props[props_idx]->num_vals = 1; | 220 props[props_idx]->num_vals = 1; |
218 props[props_idx]->vals = &values[val_idx++]; | 221 props[props_idx]->vals = &values[val_idx++]; |
219 props[props_idx]->vals[0].length = strlen (SDATA (Vinvocation_name)); | 222 props[props_idx]->vals[0].length = strlen (SDATA (Vinvocation_name)); |
220 props[props_idx]->vals[0].value = SDATA (Vinvocation_name); | 223 props[props_idx]->vals[0].value = SDATA (Vinvocation_name); |
221 ++props_idx; | 224 ++props_idx; |
222 | 225 |
223 /* How to restart Emacs (i.e.: /path/to/emacs --smid=xxxx). */ | 226 /* How to restart Emacs (i.e.: /path/to/emacs --smid=xxxx --no-splash). */ |
224 props[props_idx] = &prop_ptr[props_idx]; | 227 props[props_idx] = &prop_ptr[props_idx]; |
225 props[props_idx]->name = SmRestartCommand; | 228 props[props_idx]->name = SmRestartCommand; |
226 props[props_idx]->type = SmLISTofARRAY8; | 229 props[props_idx]->type = SmLISTofARRAY8; |
227 props[props_idx]->num_vals = 2; /* 2 values: /path/to/emacs, --smid=xxx */ | 230 props[props_idx]->num_vals = 3; /* /path/to/emacs, --smid=xxx --no-splash */ |
228 props[props_idx]->vals = &values[val_idx]; | 231 props[props_idx]->vals = &values[val_idx]; |
229 props[props_idx]->vals[0].length = strlen (emacs_program); | 232 props[props_idx]->vals[0].length = strlen (emacs_program); |
230 props[props_idx]->vals[0].value = emacs_program; | 233 props[props_idx]->vals[0].value = emacs_program; |
231 | 234 |
232 smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); | 235 smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); |
233 strcpy (smid_opt, SMID_OPT); | 236 strcpy (smid_opt, SMID_OPT); |
234 strcat (smid_opt, client_id); | 237 strcat (smid_opt, client_id); |
235 | 238 |
236 props[props_idx]->vals[1].length = strlen (smid_opt); | 239 props[props_idx]->vals[1].length = strlen (smid_opt); |
237 props[props_idx]->vals[1].value = smid_opt; | 240 props[props_idx]->vals[1].value = smid_opt; |
238 val_idx += 2; | 241 |
242 props[props_idx]->vals[2].length = strlen (NOSPLASH_OPT); | |
243 props[props_idx]->vals[2].value = NOSPLASH_OPT; | |
244 val_idx += 3; | |
239 ++props_idx; | 245 ++props_idx; |
240 | 246 |
241 /* User id */ | 247 /* User id. */ |
242 props[props_idx] = &prop_ptr[props_idx]; | 248 props[props_idx] = &prop_ptr[props_idx]; |
243 props[props_idx]->name = SmUserID; | 249 props[props_idx]->name = SmUserID; |
244 props[props_idx]->type = SmARRAY8; | 250 props[props_idx]->type = SmARRAY8; |
245 props[props_idx]->num_vals = 1; | 251 props[props_idx]->num_vals = 1; |
246 props[props_idx]->vals = &values[val_idx++]; | 252 props[props_idx]->vals = &values[val_idx++]; |
247 props[props_idx]->vals[0].length = strlen (SDATA (Vuser_login_name)); | 253 props[props_idx]->vals[0].length = strlen (SDATA (Vuser_login_name)); |
248 props[props_idx]->vals[0].value = SDATA (Vuser_login_name); | 254 props[props_idx]->vals[0].value = SDATA (Vuser_login_name); |
249 ++props_idx; | 255 ++props_idx; |
250 | 256 |
251 /* The current directory property, not mandatory */ | 257 cwd = get_current_dir_name (); |
252 #ifdef HAVE_GETCWD | 258 |
253 if (getcwd (cwd, MAXPATHLEN+1) != 0) | 259 if (cwd) |
254 #else | |
255 if (getwd (cwd) != 0) | |
256 #endif | |
257 { | 260 { |
258 props[props_idx] = &prop_ptr[props_idx]; | 261 props[props_idx] = &prop_ptr[props_idx]; |
259 props[props_idx]->name = SmCurrentDirectory; | 262 props[props_idx]->name = SmCurrentDirectory; |
260 props[props_idx]->type = SmARRAY8; | 263 props[props_idx]->type = SmARRAY8; |
261 props[props_idx]->num_vals = 1; | 264 props[props_idx]->num_vals = 1; |
268 | 271 |
269 SmcSetProperties (smcConn, props_idx, props); | 272 SmcSetProperties (smcConn, props_idx, props); |
270 | 273 |
271 xfree (smid_opt); | 274 xfree (smid_opt); |
272 | 275 |
273 /* See if we maybe shall interact with the user. */ | 276 if (cwd) |
277 free (cwd); | |
278 | |
279 /* See if we maybe shall interact with the user. */ | |
274 if (interactStyle != SmInteractStyleAny | 280 if (interactStyle != SmInteractStyleAny |
275 || ! shutdown | 281 || ! shutdown |
276 || saveType == SmSaveLocal | 282 || saveType == SmSaveLocal |
277 || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) | 283 || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) |
278 { | 284 { |
279 /* No interaction, we are done saving ourself. */ | 285 /* No interaction, we are done saving ourself. */ |
280 SmcSaveYourselfDone (smcConn, True); | 286 SmcSaveYourselfDone (smcConn, True); |
281 } | 287 } |
282 } | 288 } |
283 | 289 |
284 /* According to the SM specification, this shall close the connection */ | 290 /* According to the SM specification, this shall close the connection. */ |
291 | |
285 static void | 292 static void |
286 smc_die_CB (smcConn, clientData) | 293 smc_die_CB (smcConn, clientData) |
287 SmcConn smcConn; | 294 SmcConn smcConn; |
288 SmPointer clientData; | 295 SmPointer clientData; |
289 { | 296 { |
293 | 300 |
294 /* We don't use the next two but they are mandatory, leave them empty. | 301 /* We don't use the next two but they are mandatory, leave them empty. |
295 According to the SM specification, we should not interact with the | 302 According to the SM specification, we should not interact with the |
296 user between smc_save_yourself_CB is called and until smc_save_complete_CB | 303 user between smc_save_yourself_CB is called and until smc_save_complete_CB |
297 is called. It seems like a lot of job to implement this and it doesn't | 304 is called. It seems like a lot of job to implement this and it doesn't |
298 even seem necessary. */ | 305 even seem necessary. */ |
306 | |
299 static void | 307 static void |
300 smc_save_complete_CB (smcConn, clientData) | 308 smc_save_complete_CB (smcConn, clientData) |
301 SmcConn smcConn; | 309 SmcConn smcConn; |
302 SmPointer clientData; | 310 SmPointer clientData; |
303 { | 311 { |
311 { | 319 { |
312 /* Empty */ | 320 /* Empty */ |
313 } | 321 } |
314 | 322 |
315 /* Error handlers for SM and ICE. We don't want to exit Emacs just | 323 /* Error handlers for SM and ICE. We don't want to exit Emacs just |
316 because there is some error in the session management. */ | 324 because there is some error in the session management. */ |
325 | |
317 static void | 326 static void |
318 smc_error_handler (smcConn, | 327 smc_error_handler (smcConn, |
319 swap, | 328 swap, |
320 offendingMinorOpcode, | 329 offendingMinorOpcode, |
321 offendingSequence, | 330 offendingSequence, |
328 unsigned long offendingSequence; | 337 unsigned long offendingSequence; |
329 int errorClass; | 338 int errorClass; |
330 int severity; | 339 int severity; |
331 SmPointer values; | 340 SmPointer values; |
332 { | 341 { |
333 /* Empty */ | 342 /* Empty */ |
334 } | 343 } |
335 | 344 |
336 static void | 345 static void |
337 ice_error_handler (iceConn, | 346 ice_error_handler (iceConn, |
338 swap, | 347 swap, |
347 unsigned long offendingSequence; | 356 unsigned long offendingSequence; |
348 int errorClass; | 357 int errorClass; |
349 int severity; | 358 int severity; |
350 IcePointer values; | 359 IcePointer values; |
351 { | 360 { |
352 /* Empty */ | 361 /* Empty */ |
353 } | 362 } |
354 | 363 |
355 | 364 |
356 static void | 365 static void |
357 ice_io_error_handler (iceConn) | 366 ice_io_error_handler (iceConn) |
358 IceConn iceConn; | 367 IceConn iceConn; |
359 { | 368 { |
360 /* Connection probably gone. */ | 369 /* Connection probably gone. */ |
361 ice_fd = -1; | 370 ice_fd = -1; |
362 } | 371 } |
363 | 372 |
364 /* This is called when the ICE connection is created or closed. The SM library | 373 /* This is called when the ICE connection is created or closed. The SM library |
365 uses ICE as it transport protocol. */ | 374 uses ICE as it transport protocol. */ |
375 | |
366 static void | 376 static void |
367 ice_conn_watch_CB (iceConn, clientData, opening, watchData) | 377 ice_conn_watch_CB (iceConn, clientData, opening, watchData) |
368 IceConn iceConn; | 378 IceConn iceConn; |
369 IcePointer clientData; | 379 IcePointer clientData; |
370 Bool opening; | 380 Bool opening; |
392 if (interrupt_input) | 402 if (interrupt_input) |
393 init_sigio (ice_fd); | 403 init_sigio (ice_fd); |
394 #endif /* ! defined (SIGIO) */ | 404 #endif /* ! defined (SIGIO) */ |
395 } | 405 } |
396 | 406 |
397 /* Try to open a connection to the session manager. */ | 407 /* Create the client leader window. */ |
408 | |
409 static void | |
410 create_client_leader_window (dpyinfo, client_id) | |
411 struct x_display_info *dpyinfo; | |
412 char *client_id; | |
413 { | |
414 Window w; | |
415 XClassHint class_hints; | |
416 Atom sm_id; | |
417 | |
418 w = XCreateSimpleWindow (dpyinfo->display, | |
419 dpyinfo->root_window, | |
420 -1, -1, 1, 1, | |
421 CopyFromParent, CopyFromParent, CopyFromParent); | |
422 | |
423 class_hints.res_name = (char *) SDATA (Vx_resource_name); | |
424 class_hints.res_class = (char *) SDATA (Vx_resource_class); | |
425 XSetClassHint (dpyinfo->display, w, &class_hints); | |
426 XStoreName (dpyinfo->display, w, class_hints.res_name); | |
427 | |
428 sm_id = XInternAtom (dpyinfo->display, "SM_CLIENT_ID", False); | |
429 XChangeProperty (dpyinfo->display, w, sm_id, XA_STRING, 8, PropModeReplace, | |
430 client_id, strlen (client_id)); | |
431 | |
432 dpyinfo->client_leader_window = w; | |
433 } | |
434 | |
435 /* Try to open a connection to the session manager. */ | |
436 | |
398 void | 437 void |
399 x_session_initialize () | 438 x_session_initialize (dpyinfo) |
439 struct x_display_info *dpyinfo; | |
400 { | 440 { |
401 #define SM_ERRORSTRING_LEN 512 | 441 #define SM_ERRORSTRING_LEN 512 |
402 char errorstring[SM_ERRORSTRING_LEN]; | 442 char errorstring[SM_ERRORSTRING_LEN]; |
403 char* previous_id = NULL; | 443 char* previous_id = NULL; |
404 SmcCallbacks callbacks; | 444 SmcCallbacks callbacks; |
405 int name_len = 0; | 445 int name_len = 0; |
406 | 446 |
407 /* Check if we where started by the session manager. If so, we will | 447 /* Check if we where started by the session manager. If so, we will |
408 have a previous id. */ | 448 have a previous id. */ |
409 if (! EQ (Vx_session_previous_id, Qnil) && STRINGP (Vx_session_previous_id)) | 449 if (! EQ (Vx_session_previous_id, Qnil) && STRINGP (Vx_session_previous_id)) |
410 previous_id = SDATA (Vx_session_previous_id); | 450 previous_id = SDATA (Vx_session_previous_id); |
411 | 451 |
412 /* Construct the path to the Emacs program. */ | 452 /* Construct the path to the Emacs program. */ |
413 if (! EQ (Vinvocation_directory, Qnil)) | 453 if (! EQ (Vinvocation_directory, Qnil)) |
414 name_len += strlen (SDATA (Vinvocation_directory)); | 454 name_len += strlen (SDATA (Vinvocation_directory)); |
415 name_len += strlen (SDATA (Vinvocation_name)); | 455 name_len += strlen (SDATA (Vinvocation_name)); |
416 | 456 |
417 /* This malloc will not be freed, but it is only done once, and hopefully | 457 /* This malloc will not be freed, but it is only done once, and hopefully |
418 not very large */ | 458 not very large */ |
419 emacs_program = xmalloc (name_len + 1); | 459 emacs_program = xmalloc (name_len + 1); |
420 emacs_program[0] = '\0'; | 460 emacs_program[0] = '\0'; |
421 | 461 |
422 if (! EQ (Vinvocation_directory, Qnil)) | 462 if (! EQ (Vinvocation_directory, Qnil)) |
423 strcpy (emacs_program, SDATA (Vinvocation_directory)); | 463 strcpy (emacs_program, SDATA (Vinvocation_directory)); |
424 strcat (emacs_program, SDATA (Vinvocation_name)); | 464 strcat (emacs_program, SDATA (Vinvocation_name)); |
425 | 465 |
426 /* The SM protocol says all callbacks are mandatory, so set up all | 466 /* The SM protocol says all callbacks are mandatory, so set up all |
427 here and in the mask passed to SmcOpenConnection */ | 467 here and in the mask passed to SmcOpenConnection. */ |
428 callbacks.save_yourself.callback = smc_save_yourself_CB; | 468 callbacks.save_yourself.callback = smc_save_yourself_CB; |
429 callbacks.save_yourself.client_data = 0; | 469 callbacks.save_yourself.client_data = 0; |
430 callbacks.die.callback = smc_die_CB; | 470 callbacks.die.callback = smc_die_CB; |
431 callbacks.die.client_data = 0; | 471 callbacks.die.client_data = 0; |
432 callbacks.save_complete.callback = smc_save_complete_CB; | 472 callbacks.save_complete.callback = smc_save_complete_CB; |
433 callbacks.save_complete.client_data = 0; | 473 callbacks.save_complete.client_data = 0; |
434 callbacks.shutdown_cancelled.callback = smc_shutdown_cancelled_CB; | 474 callbacks.shutdown_cancelled.callback = smc_shutdown_cancelled_CB; |
435 callbacks.shutdown_cancelled.client_data = 0; | 475 callbacks.shutdown_cancelled.client_data = 0; |
436 | 476 |
437 /* Set error handlers. */ | 477 /* Set error handlers. */ |
438 SmcSetErrorHandler (smc_error_handler); | 478 SmcSetErrorHandler (smc_error_handler); |
439 IceSetErrorHandler (ice_error_handler); | 479 IceSetErrorHandler (ice_error_handler); |
440 IceSetIOErrorHandler (ice_io_error_handler); | 480 IceSetIOErrorHandler (ice_io_error_handler); |
441 | 481 |
442 /* Install callback for when connection status changes. */ | 482 /* Install callback for when connection status changes. */ |
443 IceAddConnectionWatch (ice_conn_watch_CB, 0); | 483 IceAddConnectionWatch (ice_conn_watch_CB, 0); |
444 | 484 |
445 /* Open the connection to the session manager. A failure is not | 485 /* Open the connection to the session manager. A failure is not |
446 critical, it usually means that no session manager is running. | 486 critical, it usually means that no session manager is running. |
447 The errorstring is here for debugging. */ | 487 The errorstring is here for debugging. */ |
448 smc_conn = SmcOpenConnection (NULL, NULL, 1, 0, | 488 smc_conn = SmcOpenConnection (NULL, NULL, 1, 0, |
449 (SmcSaveYourselfProcMask| | 489 (SmcSaveYourselfProcMask| |
450 SmcDieProcMask| | 490 SmcDieProcMask| |
451 SmcSaveCompleteProcMask| | 491 SmcSaveCompleteProcMask| |
452 SmcShutdownCancelledProcMask), | 492 SmcShutdownCancelledProcMask), |
455 &client_id, | 495 &client_id, |
456 SM_ERRORSTRING_LEN, | 496 SM_ERRORSTRING_LEN, |
457 errorstring); | 497 errorstring); |
458 | 498 |
459 if (smc_conn != 0) | 499 if (smc_conn != 0) |
460 Vx_session_id = make_string (client_id, strlen (client_id)); | 500 { |
501 Vx_session_id = make_string (client_id, strlen (client_id)); | |
502 | |
503 #ifdef USE_GTK | |
504 /* GTK creats a leader window by itself, but we need to tell | |
505 it about our client_id. */ | |
506 gdk_set_sm_client_id (client_id); | |
507 #else | |
508 create_client_leader_window (dpyinfo, client_id); | |
509 #endif | |
510 } | |
461 } | 511 } |
462 | 512 |
463 | 513 |
464 DEFUN ("handle-save-session", Fhandle_save_session, | 514 DEFUN ("handle-save-session", Fhandle_save_session, |
465 Shandle_save_session, 1, 1, "e", | 515 Shandle_save_session, 1, 1, "e", |
533 | 583 |
534 defsubr (&Shandle_save_session); | 584 defsubr (&Shandle_save_session); |
535 } | 585 } |
536 | 586 |
537 #endif /* HAVE_X_SM */ | 587 #endif /* HAVE_X_SM */ |
588 | |
589 /* arch-tag: 56a2c58c-adfa-430a-b772-130abd29fd2e | |
590 (do not change this comment) */ |