1 /*
2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2021 Kim Woelders
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24 #include "E.h"
25 #include "dialog.h"
26 #include "emodule.h"
27 #include "events.h"
28 #include "ewins.h"
29 #include "session.h"
30 #include "settings.h"
31 #include "snaps.h"
32 #include "user.h"
33 #include "xwin.h"
34
35 #ifdef USE_EXT_INIT_WIN
36 static EX_Window new_init_win_ext = NoXID;
37 #endif
38
39 /* True if we are saving state for a doExit("restart") */
40 static char restarting = 0;
41
42 #if USE_SM
43
44 #include <fcntl.h>
45 #include <X11/SM/SMlib.h>
46
47 /*
48 * NB! If the discard property is revived, the dual use of buf must be fixed.
49 */
50 #define USE_DISCARD_PROPERTY 0
51
52 static char *sm_client_id = NULL;
53 static SmcConn sm_conn = NULL;
54
55 static int sm_efd = 0;
56
57 static void
set_save_props(SmcConn smc_conn,int master_flag)58 set_save_props(SmcConn smc_conn, int master_flag)
59 {
60 const char *s;
61 const char *user;
62 const char *program;
63 char priority = 10;
64 char style;
65 int i, n;
66 SmPropValue programVal;
67 SmPropValue userIDVal;
68
69 #if USE_DISCARD_PROPERTY
70 const char *sh = "sh";
71 const char *c = "-c";
72 const char *sm_file;
73 SmPropValue discardVal[3];
74 SmProp discardProp;
75 #endif
76 #ifdef USE_EXT_INIT_WIN
77 char bufx[32];
78 #endif
79 SmPropValue restartVal[32];
80 SmPropValue styleVal;
81 SmPropValue priorityVal;
82 SmProp programProp;
83 SmProp userIDProp;
84 SmProp restartProp;
85 SmProp cloneProp;
86 SmProp styleProp;
87 SmProp priorityProp;
88 SmProp *props[7];
89 char bufs[32], bufm[32];
90
91 if (EDebug(EDBUG_TYPE_SESSION))
92 Eprintf("%s\n", __func__);
93
94 programProp.name = (char *)SmProgram;
95 programProp.type = (char *)SmARRAY8;
96 programProp.num_vals = 1;
97 programProp.vals = &programVal;
98
99 userIDProp.name = (char *)SmUserID;
100 userIDProp.type = (char *)SmARRAY8;
101 userIDProp.num_vals = 1;
102 userIDProp.vals = &userIDVal;
103
104 #if USE_DISCARD_PROPERTY
105 discardProp.name = (char *)SmDiscardCommand;
106 discardProp.type = (char *)SmLISTofARRAY8;
107 discardProp.num_vals = 3;
108 discardProp.vals = discardVal;
109 #endif
110
111 restartProp.name = (char *)SmRestartCommand;
112 restartProp.type = (char *)SmLISTofARRAY8;
113 restartProp.vals = restartVal;
114
115 cloneProp.name = (char *)SmCloneCommand;
116 cloneProp.type = (char *)SmLISTofARRAY8;
117 cloneProp.vals = restartVal;
118
119 styleProp.name = (char *)SmRestartStyleHint;
120 styleProp.type = (char *)SmCARD8;
121 styleProp.num_vals = 1;
122 styleProp.vals = &styleVal;
123
124 priorityProp.name = (char *)"_GSM_Priority";
125 priorityProp.type = (char *)SmCARD8;
126 priorityProp.num_vals = 1;
127 priorityProp.vals = &priorityVal;
128
129 if (master_flag)
130 /* Master WM restarts immediately for a doExit("restart") */
131 style = restarting ? SmRestartImmediately : SmRestartIfRunning;
132 else
133 /* Slave WMs never restart */
134 style = SmRestartNever;
135
136 user = username();
137 /* The SM specs state that the SmProgram should be the argument passed
138 * to execve. Passing argv[0] is close enough. */
139 program = Mode.wm.exec_name;
140
141 userIDVal.length = (user) ? strlen(user) : 0;
142 userIDVal.value = (char *)user;
143 programVal.length = strlen(program);
144 programVal.value = (char *)program;
145 styleVal.length = 1;
146 styleVal.value = &style;
147 priorityVal.length = 1;
148 priorityVal.value = &priority;
149
150 #if USE_DISCARD_PROPERTY
151 /* Tell session manager how to clean up our old data */
152 sm_file = EGetSavePrefix();
153 Esnprintf(buf, sizeof(buf), "rm %s*.clients.*", sm_file);
154
155 discardVal[0].length = strlen(sh);
156 discardVal[0].value = sh;
157 discardVal[1].length = strlen(c);
158 discardVal[1].value = c;
159 discardVal[2].length = strlen(buf);
160 discardVal[2].value = buf; /* ??? Also used in restartVal ??? */
161 #endif
162
163 n = 0;
164 restartVal[n++].value = (char *)program;
165 if (Mode.wm.single)
166 {
167 Esnprintf(bufs, sizeof(bufs), "%i", Mode.wm.master_screen);
168 restartVal[n++].value = (char *)"-s";
169 restartVal[n++].value = (char *)bufs;
170 }
171 else if (restarting && !Mode.wm.master)
172 {
173 Esnprintf(bufm, sizeof(bufm), "%i", Mode.wm.master_screen);
174 restartVal[n++].value = (char *)"-m";
175 restartVal[n++].value = bufm;
176 }
177 #ifdef USE_EXT_INIT_WIN
178 if (restarting)
179 {
180 Esnprintf(bufx, sizeof(bufx), "%#x", new_init_win_ext);
181 restartVal[n++].value = (char *)"-X";
182 restartVal[n++].value = bufx;
183 }
184 #endif
185 #if 0
186 restartVal[n++].value = (char *)smfile;
187 restartVal[n++].value = (char *)sm_file;
188 #endif
189 s = Mode.conf.name;
190 if (s)
191 {
192 restartVal[n++].value = (char *)"-p";
193 restartVal[n++].value = (char *)s;
194 }
195 s = EDirUserConf();
196 if (s)
197 {
198 restartVal[n++].value = (char *)"-P";
199 restartVal[n++].value = (char *)s;
200 }
201 s = EDirUserCache();
202 if (s)
203 {
204 restartVal[n++].value = (char *)"-Q";
205 restartVal[n++].value = (char *)s;
206 }
207 s = sm_client_id;
208 restartVal[n++].value = (char *)"-S";
209 restartVal[n++].value = (char *)s;
210
211 for (i = 0; i < n; i++)
212 restartVal[i].length = strlen((const char *)restartVal[i].value);
213
214 restartProp.num_vals = n;
215
216 /* SM specs require SmCloneCommand excludes "--sm-client-id" option */
217 cloneProp.num_vals = restartProp.num_vals - 2;
218
219 if (EDebug(EDBUG_TYPE_SESSION))
220 for (i = 0; i < restartProp.num_vals; i++)
221 Eprintf("restartVal[i]: %2d: %s\n", restartVal[i].length,
222 (char *)restartVal[i].value);
223
224 n = 0;
225 props[n++] = &programProp;
226 props[n++] = &userIDProp;
227 #if USE_DISCARD_PROPERTY
228 props[n++] = &discardProp;
229 #endif
230 props[n++] = &restartProp;
231 props[n++] = &cloneProp;
232 props[n++] = &styleProp;
233 props[n++] = &priorityProp;
234
235 SmcSetProperties(smc_conn, n, props);
236 }
237
238 /* This function is usually exclusively devoted to saving data.
239 * However, E sometimes wants to save state and exit immediately afterwards
240 * so that the SM will restart it in a different theme. Therefore, we include
241 * a suicide clause at the end.
242 */
243 static void
callback_save_yourself2(SmcConn smc_conn,SmPointer client_data __UNUSED__)244 callback_save_yourself2(SmcConn smc_conn, SmPointer client_data __UNUSED__)
245 {
246 if (EDebug(EDBUG_TYPE_SESSION))
247 Eprintf("%s\n", __func__);
248
249 set_save_props(smc_conn, Mode.wm.master);
250 SmcSaveYourselfDone(smc_conn, True);
251 if (restarting)
252 EExit(0);
253 }
254
255 static void
callback_save_yourself(SmcConn smc_conn,SmPointer client_data __UNUSED__,int save_style __UNUSED__,Bool shutdown __UNUSED__,int interact_style __UNUSED__,Bool fast __UNUSED__)256 callback_save_yourself(SmcConn smc_conn, SmPointer client_data __UNUSED__,
257 int save_style __UNUSED__, Bool shutdown __UNUSED__,
258 int interact_style __UNUSED__, Bool fast __UNUSED__)
259 {
260 if (EDebug(EDBUG_TYPE_SESSION))
261 Eprintf("%s\n", __func__);
262
263 SmcRequestSaveYourselfPhase2(smc_conn, callback_save_yourself2, NULL);
264 }
265
266 static void
callback_die(SmcConn smc_conn __UNUSED__,SmPointer client_data __UNUSED__)267 callback_die(SmcConn smc_conn __UNUSED__, SmPointer client_data __UNUSED__)
268 {
269 if (EDebug(EDBUG_TYPE_SESSION))
270 Eprintf("%s\n", __func__);
271
272 SessionExit(EEXIT_EXIT, NULL);
273 }
274
275 static void
callback_save_complete(SmcConn smc_conn __UNUSED__,SmPointer client_data __UNUSED__)276 callback_save_complete(SmcConn smc_conn __UNUSED__,
277 SmPointer client_data __UNUSED__)
278 {
279 if (EDebug(EDBUG_TYPE_SESSION))
280 Eprintf("%s\n", __func__);
281 }
282
283 static void
callback_shutdown_cancelled(SmcConn smc_conn,SmPointer client_data __UNUSED__)284 callback_shutdown_cancelled(SmcConn smc_conn, SmPointer client_data __UNUSED__)
285 {
286 if (EDebug(EDBUG_TYPE_SESSION))
287 Eprintf("%s\n", __func__);
288
289 SmcSaveYourselfDone(smc_conn, False);
290 }
291
292 static IceConn ice_conn;
293
294 static void
ice_io_error_handler(IceConn connection __UNUSED__)295 ice_io_error_handler(IceConn connection __UNUSED__)
296 {
297 if (EDebug(EDBUG_TYPE_SESSION))
298 Eprintf("%s\n", __func__);
299
300 /* The less we do here the better - the default handler does an
301 * exit(1) instead of closing the losing connection. */
302 }
303
304 static void
ice_exit(void)305 ice_exit(void)
306 {
307 SmcCloseConnection(sm_conn, 0, NULL);
308 sm_conn = NULL;
309 EventFdUnregister(sm_efd);
310 }
311
312 static void
ice_msgs_process(void)313 ice_msgs_process(void)
314 {
315 IceProcessMessagesStatus status;
316
317 status = IceProcessMessages(ice_conn, NULL, NULL);
318 if (status == IceProcessMessagesIOError)
319 {
320 /* Less of the hope.... E survives */
321 Alert(_("ERROR!\n" "\n"
322 "Lost the Session Manager that was there?\n"
323 "Here here session manager... come here... want a bone?\n"
324 "Oh come now! Stop sulking! Bugger. Oh well. "
325 "Will continue without\n" "a session manager.\n" "\n"
326 "I'll survive somehow.\n" "\n" "\n" "... I hope.\n"));
327 ice_exit();
328 }
329 }
330
331 static void
ice_init(void)332 ice_init(void)
333 {
334 static SmPointer context;
335 SmcCallbacks callbacks;
336 char error_string_ret[4096];
337 char *client_id;
338 char style[2];
339 SmPropValue styleVal;
340 SmProp styleProp;
341 SmProp *props[1];
342 int sm_fd;
343
344 if (!getenv("SESSION_MANAGER"))
345 return;
346
347 IceSetIOErrorHandler(ice_io_error_handler);
348
349 callbacks.save_yourself.callback = callback_save_yourself;
350 callbacks.die.callback = callback_die;
351 callbacks.save_complete.callback = callback_save_complete;
352 callbacks.shutdown_cancelled.callback = callback_shutdown_cancelled;
353
354 callbacks.save_yourself.client_data = callbacks.die.client_data =
355 callbacks.save_complete.client_data =
356 callbacks.shutdown_cancelled.client_data = (SmPointer) NULL;
357
358 client_id = Estrdup(sm_client_id);
359
360 error_string_ret[0] = '\0';
361
362 sm_conn =
363 SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor,
364 SmcSaveYourselfProcMask | SmcDieProcMask |
365 SmcSaveCompleteProcMask |
366 SmcShutdownCancelledProcMask, &callbacks,
367 client_id, &sm_client_id, 4096, error_string_ret);
368 Efree(client_id);
369
370 if (error_string_ret[0])
371 Eprintf("While connecting to session manager: %s.", error_string_ret);
372
373 if (!sm_conn)
374 return;
375
376 style[0] = SmRestartIfRunning;
377 style[1] = 0;
378
379 styleVal.length = 1;
380 styleVal.value = style;
381
382 styleProp.name = (char *)SmRestartStyleHint;
383 styleProp.type = (char *)SmCARD8;
384 styleProp.num_vals = 1;
385 styleProp.vals = &styleVal;
386
387 props[0] = &styleProp;
388
389 ice_conn = SmcGetIceConnection(sm_conn);
390 sm_fd = IceConnectionNumber(ice_conn);
391 /* Just in case we are a copy of E created by a doExit("restart") */
392 SmcSetProperties(sm_conn, 1, props);
393 fcntl(sm_fd, F_SETFD, fcntl(sm_fd, F_GETFD, 0) | FD_CLOEXEC);
394
395 sm_efd = EventFdRegister(sm_fd, ice_msgs_process);
396 }
397
398 #endif /* USE_SM */
399
400 void
SessionInit(void)401 SessionInit(void)
402 {
403 if (!Conf.session.script)
404 Conf.session.script = Estrdup("$EROOT/scripts/session.sh");
405 if (!Conf.session.cmd_reboot)
406 Conf.session.cmd_reboot = Estrdup("reboot");
407 if (!Conf.session.cmd_halt)
408 Conf.session.cmd_halt = Estrdup("poweroff");
409
410 if (Mode.wm.window)
411 return;
412
413 #if USE_SM
414 ice_init();
415 #endif
416 }
417
418 #if USE_SM
419 void
SetSMID(const char * smid)420 SetSMID(const char *smid)
421 {
422 sm_client_id = Estrdup(smid);
423 }
424 #else
425 void
SetSMID(const char * smid __UNUSED__)426 SetSMID(const char *smid __UNUSED__)
427 {
428 }
429 #endif /* USE_SM */
430
431 static void
SessionSave(int shutdown)432 SessionSave(int shutdown)
433 {
434 if (EDebug(EDBUG_TYPE_SESSION))
435 Eprintf("%s: %d\n", __func__, shutdown);
436
437 SnapshotsSaveReal();
438
439 #if USE_SM
440 if (shutdown && sm_conn)
441 ice_exit();
442 #endif /* USE_SM */
443 }
444
445 /*
446 * Normally, the SM will throw away all the session data for a client
447 * that breaks its connection unexpectedly. In order to avoid this we
448 * have to let the SM handle the restart (by setting a SmRestartStyleHint
449 * of SmRestartImmediately). Rather than forcing all SM clients to do a
450 * checkpoint (which would be a bit cleaner) we just save our own state
451 * and then restore it on restart. We grab X input via the ext_init_win
452 * so the our clients remain frozen while we are down.
453 */
454 __NORETURN__ static void
doSMExit(int mode,const char * params)455 doSMExit(int mode, const char *params)
456 {
457 int l;
458 char s[1024];
459 const char *ss;
460
461 if (EDebug(EDBUG_TYPE_SESSION))
462 Eprintf("%s: mode=%d prm=%p\n", __func__, mode, params);
463
464 restarting = 1;
465
466 SessionSave(1);
467
468 if (mode != EEXIT_THEME && mode != EEXIT_RESTART)
469 SessionHelper(ESESSION_STOP);
470
471 LangExit();
472
473 if (disp)
474 {
475 /* We may get here from HandleXIOError */
476 EwinsSetFree();
477 ESelectInput(VROOT, 0);
478 ExtInitWinKill();
479 ESync(0);
480
481 /* Forget about cleaning up if no disp */
482 ModulesSignal(ESIGNAL_EXIT, NULL);
483 }
484
485 ss = NULL;
486 switch (mode)
487 {
488 case EEXIT_EXEC:
489 SoundPlay(SOUND_EXIT);
490 EDisplayClose();
491
492 if (EDebug(EDBUG_TYPE_SESSION))
493 Eprintf("%s: exec %s\n", __func__, params);
494 Eexec(params);
495 break;
496
497 case EEXIT_THEME:
498 ss = params;
499 /* FALLTHROUGH */
500 case EEXIT_RESTART:
501 SoundPlay(SOUND_WAIT);
502 #ifdef USE_EXT_INIT_WIN
503 if (disp)
504 new_init_win_ext = ExtInitWinCreate();
505 #endif
506 EDisplayClose();
507
508 l = 0;
509 l += Esnprintf(s + l, sizeof(s) - l, "%s -f", Mode.wm.exec_name);
510 if (Mode.wm.single)
511 l += Esnprintf(s + l, sizeof(s) - l, " -s %d", Dpy.screen);
512 else if (!Mode.wm.master)
513 l +=
514 Esnprintf(s + l, sizeof(s) - l, " -m %d", Mode.wm.master_screen);
515 if (Mode.wm.window)
516 l += Esnprintf(s + l, sizeof(s) - l, " -w %dx%d",
517 WinGetW(VROOT), WinGetH(VROOT));
518 #if USE_SM
519 if (sm_client_id)
520 l += Esnprintf(s + l, sizeof(s) - l, " -S %s", sm_client_id);
521 #endif
522 #ifdef USE_EXT_INIT_WIN
523 if (new_init_win_ext != NoXID)
524 l += Esnprintf(s + l, sizeof(s) - l, " -X %#x", new_init_win_ext);
525 #endif
526 if (ss)
527 Esnprintf(s + l, sizeof(s) - l, " -t %s", ss);
528
529 if (EDebug(EDBUG_TYPE_SESSION))
530 Eprintf("%s: exec %s\n", __func__, s);
531
532 Eexec(s);
533 break;
534 }
535
536 restarting = 0;
537 SoundPlay(SOUND_EXIT);
538 EExit(0);
539 }
540
541 static void
SessionLogout(void)542 SessionLogout(void)
543 {
544 #if USE_SM
545 if (sm_conn)
546 {
547 SmcRequestSaveYourself(sm_conn, SmSaveBoth, True, SmInteractStyleAny,
548 False, True);
549 }
550 else
551 #endif /* USE_SM */
552 {
553 SessionExit(EEXIT_EXIT, NULL);
554 }
555 }
556
557 #if ENABLE_DIALOGS
558 static void
LogoutCB(Dialog * d,int val,void * data __UNUSED__)559 LogoutCB(Dialog * d, int val, void *data __UNUSED__)
560 {
561 #if USE_SM
562 if (sm_conn)
563 {
564 SessionLogout();
565 }
566 else
567 #endif /* USE_SM */
568 {
569 /* 0:LogOut -: No -or- */
570 /* 0:Halt 1:Reboot 2:LogOut -:No */
571 switch (val)
572 {
573 default:
574 break;
575 case 1:
576 SessionExit(EEXIT_EXIT, NULL);
577 break;
578 case 2:
579 SessionExit(EEXIT_EXEC, Conf.session.cmd_reboot);
580 break;
581 case 3:
582 SessionExit(EEXIT_EXEC, Conf.session.cmd_halt);
583 break;
584 }
585 }
586
587 DialogClose(d);
588 }
589
590 static void
SessionLogoutConfirm(void)591 SessionLogoutConfirm(void)
592 {
593 Dialog *d;
594 DItem *table, *di;
595
596 d = DialogFind("LOGOUT_DIALOG");
597 if (!d)
598 {
599 SoundPlay(SOUND_LOGOUT);
600 d = DialogCreate("LOGOUT_DIALOG");
601 table = DialogInitItem(d);
602 DialogSetTitle(d, _("Are you sure?"));
603 di = DialogAddItem(table, DITEM_TEXT);
604 DialogItemSetText(di, _("Are you sure you wish to log out ?"));
605 table = DialogAddItem(table, DITEM_TABLE);
606 DialogItemSetAlign(table, 512, 0);
607 DialogItemSetFill(table, 0, 0);
608 DialogItemTableSetOptions(table, 2, 0, 1, 0);
609 if (Conf.session.enable_reboot_halt)
610 {
611 DialogItemTableSetOptions(table, 4, 0, 1, 0);
612 DialogItemAddButton(table, _("Yes, Shut Down"), LogoutCB, 3,
613 1, DLG_BUTTON_OK);
614 DialogItemAddButton(table, _("Yes, Reboot"), LogoutCB, 2,
615 1, DLG_BUTTON_OK);
616 }
617 DialogItemAddButton(table, _("Yes, Log Out"), LogoutCB, 1,
618 1, DLG_BUTTON_OK);
619 DialogItemAddButton(table, _("No"), NULL, 0, 1, DLG_BUTTON_CANCEL);
620 DialogBindKey(d, "Escape", DialogCallbackClose, 0, NULL);
621 DialogBindKey(d, "Return", LogoutCB, 1, NULL);
622 }
623
624 DialogShowCentered(d);
625 }
626 #endif /* ENABLE_DIALOGS */
627
628 void
SessionExit(int mode,const char * param)629 SessionExit(int mode, const char *param)
630 {
631 /* We do not want to be exited by children. */
632 if (getpid() != Mode.wm.pid)
633 return;
634
635 if (EDebug(EDBUG_TYPE_SESSION))
636 Eprintf("%s: mode=%d(%d) prm=%s\n", __func__, mode, Mode.wm.exit_mode,
637 param ? param : "(none)");
638
639 if (Mode.wm.exiting)
640 return;
641
642 if (Mode.wm.startup || Mode.wm.exit_now)
643 goto done;
644
645 switch (mode)
646 {
647 default:
648 /* In event loop - Set exit mode */
649 Mode.wm.exit_mode = mode;
650 Mode.wm.exit_param = Estrdup(param);
651 return;
652
653 case EEXIT_QUIT:
654 mode = Mode.wm.exit_mode;
655 param = Mode.wm.exit_param;
656 break;
657
658 case EEXIT_ERROR:
659 if (!Mode.wm.exiting)
660 break;
661 /* This may be possible during nested signal handling */
662 Eprintf("%s: already in progress ... now exiting\n", __func__);
663 exit(1);
664 break;
665
666 case EEXIT_LOGOUT:
667 #if ENABLE_DIALOGS
668 if (Conf.session.enable_logout_dialog)
669 SessionLogoutConfirm();
670 else
671 #endif
672 SessionLogout();
673 return;
674 }
675
676 done:
677 Mode.wm.exiting++;
678 doSMExit(mode, param);
679 }
680
681 static void
SessionRunProg(const char * prog,const char * params)682 SessionRunProg(const char *prog, const char *params)
683 {
684 if (EDebug(EDBUG_TYPE_SESSION))
685 Eprintf("%s: %s %s\n", __func__, prog, params);
686 Esystem("%s %s", prog, params);
687 }
688
689 void
SessionHelper(int when)690 SessionHelper(int when)
691 {
692 switch (when)
693 {
694 case ESESSION_INIT:
695 if (Conf.session.enable_script && Conf.session.script)
696 SessionRunProg(Conf.session.script, "init");
697 break;
698 case ESESSION_START:
699 if (Conf.session.enable_script && Conf.session.script)
700 SessionRunProg(Conf.session.script, "start");
701 break;
702 case ESESSION_STOP:
703 if (Conf.session.enable_script && Conf.session.script)
704 SessionRunProg(Conf.session.script, "stop");
705 break;
706 }
707 }
708
709 #if ENABLE_DIALOGS
710 /*
711 * Session dialog
712 */
713 static char tmp_session_script;
714 static char tmp_logout_dialog;
715 static char tmp_reboot_halt;
716
717 static void
_DlgApplySession(Dialog * d __UNUSED__,int val __UNUSED__,void * data __UNUSED__)718 _DlgApplySession(Dialog * d __UNUSED__, int val __UNUSED__,
719 void *data __UNUSED__)
720 {
721 Conf.session.enable_script = tmp_session_script;
722 Conf.session.enable_logout_dialog = tmp_logout_dialog;
723 Conf.session.enable_reboot_halt = tmp_reboot_halt;
724 autosave();
725 }
726
727 static void
_DlgFillSession(Dialog * d __UNUSED__,DItem * table,void * data __UNUSED__)728 _DlgFillSession(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
729 {
730 DItem *di;
731
732 tmp_session_script = Conf.session.enable_script;
733 tmp_logout_dialog = Conf.session.enable_logout_dialog;
734 tmp_reboot_halt = Conf.session.enable_reboot_halt;
735
736 DialogItemTableSetOptions(table, 2, 0, 0, 0);
737
738 di = DialogAddItem(table, DITEM_CHECKBUTTON);
739 DialogItemSetColSpan(di, 2);
740 DialogItemSetText(di, _("Enable Session Script"));
741 DialogItemCheckButtonSetPtr(di, &tmp_session_script);
742
743 di = DialogAddItem(table, DITEM_CHECKBUTTON);
744 DialogItemSetColSpan(di, 2);
745 DialogItemSetText(di, _("Enable Logout Dialog"));
746 DialogItemCheckButtonSetPtr(di, &tmp_logout_dialog);
747
748 di = DialogAddItem(table, DITEM_CHECKBUTTON);
749 DialogItemSetColSpan(di, 2);
750 DialogItemSetText(di, _("Enable Reboot/Halt on Logout"));
751 DialogItemCheckButtonSetPtr(di, &tmp_reboot_halt);
752 }
753
754 const DialogDef DlgSession = {
755 "CONFIGURE_SESSION",
756 N_("Session"), N_("Session Settings"),
757 0,
758 SOUND_SETTINGS_SESSION,
759 "pix/miscellaneous.png",
760 N_("Enlightenment Session\n" "Settings Dialog"),
761 _DlgFillSession,
762 DLG_OAC, _DlgApplySession, NULL
763 };
764 #endif /* ENABLE_DIALOGS */
765