Window Maker 0.20.3
[wmaker-crm.git] / src / session.c
blobb04661614120a94850622a77d2942d33b3012610
1 /* session.c - session state handling and R6 style session management
3 * Copyright (c) 1998 Dan Pascu
4 * Copyright (c) 1998 Alfredo Kojima
6 * Window Maker window manager
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
29 #ifdef R6SM
30 #include <X11/SM/SMlib.h>
31 #endif
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <time.h>
40 #include "WindowMaker.h"
41 #include "screen.h"
42 #include "window.h"
43 #include "session.h"
44 #include "wcore.h"
45 #include "framewin.h"
46 #include "workspace.h"
47 #include "funcs.h"
48 #include "properties.h"
49 #include "application.h"
50 #include "appicon.h"
53 #include "dock.h"
55 #include "list.h"
57 #include <proplist.h>
60 #ifdef R6SM
62 extern int wScreenCount;
64 /* requested for SaveYourselfPhase2 */
65 static Bool sWaitingPhase2 = False;
67 static SmcConn sSMCConn = NULL;
69 static WMHandlerID sSMInputHandler = NULL;
71 /* our SM client ID */
72 static char *sClientID = NULL;
73 #endif
76 static proplist_t sApplications = NULL;
77 static proplist_t sCommand;
78 static proplist_t sName;
79 static proplist_t sHost;
80 static proplist_t sWorkspace;
81 static proplist_t sShaded;
82 static proplist_t sMiniaturized;
83 static proplist_t sHidden;
84 static proplist_t sGeometry;
86 static proplist_t sDock;
88 static proplist_t sYes, sNo;
91 static void
92 make_keys()
94 if (sApplications!=NULL)
95 return;
97 sApplications = PLMakeString("Applications");
98 sCommand = PLMakeString("Command");
99 sName = PLMakeString("Name");
100 sHost = PLMakeString("Host");
101 sWorkspace = PLMakeString("Workspace");
102 sShaded = PLMakeString("Shaded");
103 sMiniaturized = PLMakeString("Miniaturized");
104 sHidden = PLMakeString("Hidden");
105 sGeometry = PLMakeString("Geometry");
106 sDock = PLMakeString("Dock");
108 sYes = PLMakeString("Yes");
109 sNo = PLMakeString("No");
114 static int
115 getBool(proplist_t value)
117 char *val;
119 if (!PLIsString(value)) {
120 return 0;
122 if (!(val = PLGetString(value))) {
123 return 0;
126 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
127 || strcasecmp(val, "YES")==0) {
129 return 1;
130 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
131 || strcasecmp(val, "NO")==0) {
132 return 0;
133 } else {
134 int i;
135 if (sscanf(val, "%i", &i)==1) {
136 return (i!=0);
137 } else {
138 wwarning(_("can't convert \"%s\" to boolean"), val);
139 return 0;
146 static proplist_t
147 makeWindowState(WWindow *wwin, WApplication *wapp)
149 WScreen *scr = wwin->screen_ptr;
150 Window win;
151 int argc;
152 char **argv;
153 char *class, *instance, *command=NULL, buffer[256];
154 proplist_t win_state, cmd, name, workspace;
155 proplist_t shaded, miniaturized, hidden, geometry;
156 proplist_t dock;
158 if (wwin->main_window!=None && wwin->main_window!=wwin->client_win)
159 win = wwin->main_window;
160 else
161 win = wwin->client_win;
163 if (XGetCommand(dpy, win, &argv, &argc) && argc>0) {
164 command = FlattenStringList(argv, argc);
165 XFreeStringList(argv);
167 if (!command)
168 return NULL;
170 if (PropGetWMClass(win, &class, &instance)) {
171 if (class && instance)
172 sprintf(buffer, "%s.%s", instance, class);
173 else if (instance)
174 sprintf(buffer, "%s", instance);
175 else if (class)
176 sprintf(buffer, ".%s", class);
177 else
178 sprintf(buffer, ".");
180 name = PLMakeString(buffer);
181 cmd = PLMakeString(command);
182 /*sprintf(buffer, "%d", wwin->frame->workspace+1);
183 workspace = PLMakeString(buffer);*/
184 workspace = PLMakeString(scr->workspaces[wwin->frame->workspace]->name);
185 shaded = wwin->flags.shaded ? sYes : sNo;
186 miniaturized = wwin->flags.miniaturized ? sYes : sNo;
187 hidden = wwin->flags.hidden ? sYes : sNo;
188 sprintf(buffer, "%ix%i+%i+%i", wwin->client.width, wwin->client.height,
189 wwin->frame_x, wwin->frame_y);
190 geometry = PLMakeString(buffer);
192 win_state = PLMakeDictionaryFromEntries(sName, name,
193 sCommand, cmd,
194 sWorkspace, workspace,
195 sShaded, shaded,
196 sMiniaturized, miniaturized,
197 sHidden, hidden,
198 sGeometry, geometry,
199 NULL);
201 PLRelease(name);
202 PLRelease(cmd);
203 PLRelease(workspace);
204 PLRelease(geometry);
205 if (wapp && wapp->app_icon && wapp->app_icon->dock) {
206 int i;
207 char *name;
208 if (wapp->app_icon->dock == scr->dock) {
209 name="Dock";
210 } else {
211 for(i=0; i<scr->workspace_count; i++)
212 if(scr->workspaces[i]->clip == wapp->app_icon->dock)
213 break;
214 assert( i < scr->workspace_count);
215 /*n = i+1;*/
216 name = scr->workspaces[i]->name;
218 dock = PLMakeString(name);
219 PLInsertDictionaryEntry(win_state, sDock, dock);
220 PLRelease(dock);
222 } else {
223 win_state = NULL;
226 if (instance) XFree(instance);
227 if (class) XFree(class);
228 if (command) free(command);
230 return win_state;
234 void
235 wSessionSaveState(WScreen *scr)
237 WWindow *wwin = scr->focused_window;
238 proplist_t win_info, wks;
239 proplist_t list=NULL;
240 LinkedList *wapp_list=NULL;
243 make_keys();
245 if (!scr->session_state) {
246 scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
247 if (!scr->session_state)
248 return;
251 list = PLMakeArrayFromElements(NULL);
253 while (wwin) {
254 WApplication *wapp=wApplicationOf(wwin->main_window);
256 if (wwin->transient_for==None && list_find(wapp_list, wapp)==NULL
257 && !wwin->window_flags.dont_save_session) {
258 /* A entry for this application was not yet saved. Save one. */
259 if ((win_info = makeWindowState(wwin, wapp))!=NULL) {
260 list = PLAppendArrayElement(list, win_info);
261 PLRelease(win_info);
262 /* If we were succesful in saving the info for this window
263 * add the application the window belongs to, to the
264 * application list, so no multiple entries for the same
265 * application are saved.
267 wapp_list = list_cons(wapp, wapp_list);
270 wwin = wwin->prev;
272 PLRemoveDictionaryEntry(scr->session_state, sApplications);
273 PLInsertDictionaryEntry(scr->session_state, sApplications, list);
274 PLRelease(list);
276 wks = PLMakeString(scr->workspaces[scr->current_workspace]->name);
277 PLInsertDictionaryEntry(scr->session_state, sWorkspace, wks);
278 PLRelease(wks);
280 list_free(wapp_list);
284 void
285 wSessionClearState(WScreen *scr)
287 make_keys();
289 if (!scr->session_state)
290 return;
292 PLRemoveDictionaryEntry(scr->session_state, sApplications);
293 PLRemoveDictionaryEntry(scr->session_state, sWorkspace);
297 static pid_t
298 execCommand(WScreen *scr, char *command, char *host)
300 pid_t pid;
301 char **argv;
302 int argc;
304 ParseCommand(command, &argv, &argc);
306 if (argv==NULL) {
307 return 0;
310 if ((pid=fork())==0) {
311 char **args;
312 int i;
314 SetupEnvironment(scr);
316 CloseDescriptors();
318 args = malloc(sizeof(char*)*(argc+1));
319 if (!args)
320 exit(111);
321 for (i=0; i<argc; i++) {
322 args[i] = argv[i];
324 args[argc] = NULL;
325 execvp(argv[0], args);
326 exit(111);
328 while (argc > 0)
329 free(argv[--argc]);
330 free(argv);
331 return pid;
335 static WSavedState*
336 getWindowState(WScreen *scr, proplist_t win_state)
338 WSavedState *state = wmalloc(sizeof(WSavedState));
339 proplist_t value;
340 char *tmp;
341 int i;
343 memset(state, 0, sizeof(WSavedState));
344 state->workspace = -1;
345 value = PLGetDictionaryEntry(win_state, sWorkspace);
346 if (value && PLIsString(value)) {
347 tmp = PLGetString(value);
348 if (sscanf(tmp, "%i", &state->workspace)!=1) {
349 state->workspace = -1;
350 for (i=0; i < scr->workspace_count; i++) {
351 if (strcmp(scr->workspaces[i]->name, tmp)==0) {
352 state->workspace = i;
353 break;
356 } else {
357 state->workspace--;
360 if ((value = PLGetDictionaryEntry(win_state, sShaded))!=NULL)
361 state->shaded = getBool(value);
362 if ((value = PLGetDictionaryEntry(win_state, sMiniaturized))!=NULL)
363 state->miniaturized = getBool(value);
364 if ((value = PLGetDictionaryEntry(win_state, sHidden))!=NULL)
365 state->hidden = getBool(value);
367 value = PLGetDictionaryEntry(win_state, sGeometry);
368 if (value && PLIsString(value)) {
369 if (sscanf(PLGetString(value), "%ix%i+%i+%i",
370 &state->w, &state->h, &state->x, &state->y)==4 &&
371 (state->w>0 && state->h>0)) {
372 state->use_geometry = 1;
373 } else if (sscanf(PLGetString(value), "%i,%i,%i,%i",
374 &state->x, &state->y, &state->w, &state->h)==4 &&
375 (state->w>0 && state->h>0)) {
376 /* TODO: remove redundant sscanf() in version 0.20.x */
377 state->use_geometry = 1;
382 return state;
386 #define SAME(x, y) (((x) && (y) && !strcmp((x), (y))) || (!(x) && !(y)))
389 void
390 wSessionRestoreState(WScreen *scr)
392 WSavedState *state;
393 char *instance, *class, *command, *host;
394 proplist_t win_info, apps, cmd, value;
395 pid_t pid;
396 int i, count;
397 WDock *dock;
398 WAppIcon *btn=NULL;
399 int j, n, found;
400 char *tmp;
402 make_keys();
404 if (!scr->session_state)
405 return;
407 PLSetStringCmpHook(NULL);
409 apps = PLGetDictionaryEntry(scr->session_state, sApplications);
410 if (!apps)
411 return;
413 count = PLGetNumberOfElements(apps);
414 if (count==0)
415 return;
417 for (i=0; i<count; i++) {
418 win_info = PLGetArrayElement(apps, i);
420 cmd = PLGetDictionaryEntry(win_info, sCommand);
421 if (!cmd || !PLIsString(cmd) || !(command = PLGetString(cmd))) {
422 continue;
425 value = PLGetDictionaryEntry(win_info, sName);
426 if (!value)
427 continue;
429 ParseWindowName(value, &instance, &class, "session");
430 if (!instance && !class)
431 continue;
433 value = PLGetDictionaryEntry(win_info, sHost);
434 if (value && PLIsString(value))
435 host = PLGetString(value);
436 else
437 host = NULL;
439 state = getWindowState(scr, win_info);
441 dock = NULL;
442 value = PLGetDictionaryEntry(win_info, sDock);
443 if (value && PLIsString(value) && (tmp = PLGetString(value))!=NULL) {
444 if (sscanf(tmp, "%i", &n)!=1) {
445 if (!strcasecmp(tmp, "DOCK")) {
446 dock = scr->dock;
447 } else {
448 for (j=0; j < scr->workspace_count; j++) {
449 if (strcmp(scr->workspaces[j]->name, tmp)==0) {
450 dock = scr->workspaces[j]->clip;
451 break;
455 } else {
456 if (n == 0) {
457 dock = scr->dock;
458 } else if (n>0 && n<=scr->workspace_count) {
459 dock = scr->workspaces[n-1]->clip;
464 found = 0;
465 if (dock!=NULL) {
466 for (j=0; j<dock->max_icons; j++) {
467 btn = dock->icon_array[j];
468 if (btn && SAME(instance, btn->wm_instance) &&
469 SAME(class, btn->wm_class) &&
470 SAME(command, btn->command)) {
471 found = 1;
472 break;
477 if (found) {
478 wDockLaunchWithState(dock, btn, state);
479 } else if ((pid = execCommand(scr, command, host)) > 0) {
480 wWindowAddSavedState(instance, class, command, pid, state);
481 } else {
482 free(state);
485 if (instance) free(instance);
486 if (class) free(class);
488 /* clean up */
489 PLSetStringCmpHook(StringCompareHook);
493 void
494 wSessionRestoreLastWorkspace(WScreen *scr)
496 proplist_t wks;
497 int w, i;
498 char *tmp;
500 make_keys();
502 if (!scr->session_state)
503 return;
505 PLSetStringCmpHook(NULL);
507 wks = PLGetDictionaryEntry(scr->session_state, sWorkspace);
508 if (!wks || !PLIsString(wks))
509 return;
511 tmp = PLGetString(wks);
513 /* clean up */
514 PLSetStringCmpHook(StringCompareHook);
516 if (sscanf(tmp, "%i", &w)!=1) {
517 w = -1;
518 for (i=0; i < scr->workspace_count; i++) {
519 if (strcmp(scr->workspaces[i]->name, tmp)==0) {
520 w = i;
521 break;
524 } else {
525 w--;
528 if (w!=scr->current_workspace && w<scr->workspace_count) {
529 wWorkspaceChange(scr, w);
535 #ifdef R6SM
537 * With full session management support, the part of WMState
538 * that store client window state will become obsolete (maybe we can reuse
539 * the old code too),
540 * but we still need to store state info like the dock and workspaces.
541 * It is better to keep dock/wspace info in WMState because the user
542 * might want to keep the dock configuration while not wanting to
543 * resume a previously saved session.
544 * So, wmaker specific state info can be saved in
545 * ~/GNUstep/.AppInfo/WindowMaker/statename.state
546 * Its better to not put it in the defaults directory because:
547 * - its not a defaults file (having domain names like wmaker0089504baa
548 * in the defaults directory wouldn't be very neat)
549 * - this state file is not meant to be edited by users
551 * The old session code will become obsolete. When wmaker is
552 * compiled with R6 sm support compiled in, itll be better to
553 * use a totally rewritten state saving code, but we can keep
554 * the current code for when R6SM is not compiled in.
556 * This will be confusing to old users (well get lots of "SAVE_SESSION broke!"
557 * messages), but itll be better.
559 * -readme
564 * Windows are identified as:
565 * WM_CLASS(instance.class).WM_WINDOW_ROLE
567 * Saved Info:
569 * WM_CLASS.instance
570 * WM_CLASSS.class
571 * WM_WINDOW_ROLE
572 * geometry
573 * (state array (miniaturized, shaded, etc))
574 * workspace
575 * wich dock
577 static proplist_t
578 makeClientState(WWindow *wwin)
580 proplist_t key;
586 static void
587 smSaveYourselfPhase2Proc(SmcConn smc_conn, SmPointer client_data)
589 SmProp props[4];
590 SmPropValue prop1val, prop2val, prop3val, prop4val;
591 char **argv = (char**)client_data;
592 int argc;
593 int i, j;
594 Bool ok = False;
595 char *statefile = NULL;
596 char *prefix;
597 Bool gsPrefix = False;
598 char *discardCmd = NULL;
599 time_t t;
600 proplist_t state;
602 #ifdef DEBUG1
603 puts("received SaveYourselfPhase2 SM message");
604 #endif
606 /* save session state */
608 /* the file that will contain the state */
609 prefix = getenv("SM_SAVE_DIR");
610 if (!prefix) {
611 prefix = wusergnusteppath();
612 if (prefix)
613 gsPrefix = True;
615 if (!prefix) {
616 prefix = getenv("HOME");
618 if (!prefix)
619 prefix = ".";
621 statefile = malloc(strlen(prefix)+64);
622 if (!statefile) {
623 if (gsPrefix)
624 free(prefix);
625 wwarning(_("end of memory while saving session state"));
626 goto fail;
629 t = time();
630 i = 0;
631 do {
632 if (gsPrefix)
633 sprintf(statefile, "%s/.AppInfo/WindowMaker/%l%i.state",
634 prefix, t, i);
635 else
636 sprintf(statefile, "%s/wmaker.%l%i.state", prefix, t, i);
637 i++;
638 } while (access(F_OK, statefile)!=-1);
640 if (gsPrefix)
641 free(prefix);
643 /* save the states of all windows we're managing */
644 state = PLMakeArrayFromElements(NULL, NULL);
647 * Format:
649 * state_file ::= dictionary with version_info ; state
650 * version_info ::= version = 1;
651 * state ::= state = array of screen_info
652 * screen_info ::= array of (screen number, window_info, window_info, ...)
653 * window_info ::=
655 for (i=0; i<wScreenCount; i++) {
656 WScreen *scr;
657 WWindow *wwin;
658 char buf[32];
659 proplist_t pscreen;
661 scr = wScreenWithNumber(i);
663 sprintf(buf, "%i", scr->screen);
664 pscreen = PLMakeArrayFromElements(PLMakeString(buf), NULL);
666 wwin = scr->focused_window;
667 while (wwin) {
668 proplist_t pwindow;
670 pwindow = makeClientState(wwin);
671 PLAppendArrayElement(pscreen, pwindow);
673 wwin = wwin->prev;
676 PLAppendArrayElement(state, pscreen);
680 proplist_t statefile;
682 statefile = PLMakeDictionaryFromEntries(PLMakeString("Version"),
683 PLMakeString("1"),
685 PLMakeString("Screens"),
686 state,
688 NULL);
690 PLSetFilename(statefile, PLMakeString(statefile));
691 PLSave(statefile, NO);
693 PLRelease(statefile);
696 /* set the remaining properties that we didn't set at
697 * startup time */
699 for (argc=0, i=0; argv[i]!=NULL; i++) {
700 if (strcmp(argv[i], "-clientid")==0
701 || strcmp(argv[i], "-restore")==0) {
702 i++;
703 } else {
704 argc++;
708 prop[0].name = SmRestartCommand;
709 prop[0].type = SmLISTofARRAY8;
710 prop[0].vals = malloc(sizeof(SmPropValue)*(argc+4));
711 prop[0].num_vals = argc+4;
713 prop[1].name = SmCloneCommand;
714 prop[1].type = SmLISTofARRAY8;
715 prop[1].vals = malloc(sizeof(SmPropValue)*(argc));
716 prop[1].num_vals = argc;
718 if (!prop[0].vals || !prop[1].vals) {
719 wwarning(_("end of memory while saving session state"));
720 goto fail;
723 for (j=0, i=0; i<argc+4; i++) {
724 if (strcmp(argv[i], "-clientid")==0
725 || strcmp(argv[i], "-restore")==0) {
726 i++;
727 } else {
728 prop[0].vals[j].value = argv[i];
729 prop[0].vals[j].length = strlen(argv[i]);
730 prop[1].vals[j].value = argv[i];
731 prop[1].vals[j].length = strlen(argv[i]);
732 j++;
735 prop[0].vals[j].value = "-clientid";
736 prop[0].vals[j].length = 9;
737 j++;
738 prop[0].vals[j].value = sClientID;
739 prop[0].vals[j].length = strlen(sClientID);
740 j++;
741 prop[0].vals[j].value = "-restore";
742 prop[0].vals[j].length = 11;
743 j++;
744 prop[0].vals[j].value = statefile;
745 prop[0].vals[j].length = strlen(statefile);
747 discardCmd = malloc(strlen(statefile)+8);
748 if (!discardCmd)
749 goto fail;
750 sprintf(discardCmd, "rm %s", statefile);
751 prop[2].name = SmDiscardCommand;
752 prop[2].type = SmARRAY8;
753 prop[2].vals[0] = discardCmd;
754 prop[2].num_vals = 1;
756 SmcSetProperties(sSMCConn, 3, prop);
758 ok = True;
759 fail:
760 SmcSaveYourselfDone(smc_conn, ok);
762 if (prop[0].vals)
763 free(prop[0].vals);
764 if (prop[1].vals)
765 free(prop[1].vals);
766 if (discardCmd)
767 free(discardCmd);
769 if (!ok) {
770 remove(statefile);
772 if (statefile)
773 free(statefile);
777 static void
778 smSaveYourselfProc(SmcConn smc_conn, SmPointer client_data, int save_type,
779 Bool shutdown, int interact_style, Bool fast)
781 #ifdef DEBUG1
782 puts("received SaveYourself SM message");
783 #endif
785 if (!SmcRequestSaveYourselfPhase2(smc_conn, smSaveYourselfPhase2Proc,
786 client_data)) {
788 SmcSaveYourselfDone(smc_conn, False);
789 sWaitingPhase2 = False;
790 } else {
791 #ifdef DEBUG1
792 puts("successfull request of SYS phase 2");
793 #endif
794 sWaitingPhase2 = True;
799 static void
800 smDieProc(SmcConn smc_conn, SmPointer client_data)
802 #ifdef DEBUG1
803 puts("received Die SM message");
804 #endif
806 wSessionDisconnectManager();
808 RestoreDesktop(NULL);
810 ExecExitScript();
811 Exit(0);
816 static void
817 smSaveCompleteProc(SmcConn smc_conn)
819 /* it means that we can resume doing things that can change our state */
820 #ifdef DEBUG1
821 puts("received SaveComplete SM message");
822 #endif
826 static void
827 smShutdownCancelledProc(SmcConn smc_conn, SmPointer client_data)
829 if (sWaitingPhase2) {
831 sWaitingPhase2 = False;
833 SmcSaveYourselfDone(smc_conn, False);
838 static void
839 iceMessageProc(int fd, int mask, void *clientData)
841 IceConn iceConn = (IceConn)clientData;
843 IceProcessMessages(iceConn, NULL, NULL);
847 static void
848 iceIOErrorHandler(IceConnection ice_conn)
850 /* This is not fatal but can mean the session manager exited.
851 * If the session manager exited normally we would get a
852 * Die message, so this probably means an abnormal exit.
853 * If the sm was the last client of session, then we'll die
854 * anyway, otherwise we can continue doing our stuff.
856 wwarning(_("connection to the session manager was lost"));
857 wSessionDisconnectManager();
861 void
862 wSessionConnectManager(char **argv, int argc)
864 IceConn iceConn;
865 char *previous_id = NULL;
866 char buffer[256];
867 SmcCallbacks callbacks;
868 unsigned long mask;
869 char uid[32];
870 char pid[32];
871 SmProp props[4];
872 SmPropValue prop1val, prop2val, prop3val, prop4val;
873 char restartStyle;
874 int i;
876 mask = SmcSaveYourselfProcMask|SmcDieProcMask|SmcSaveCompleteProcMask
877 |SmcShutdownCancelledProcMask;
879 callbacks.save_yourself.callback = smSaveYourselfProc;
880 callbacks.save_yourself.client_data = argv;
882 callbacks.die.callback = smDieProc;
883 callbacks.die.client_data = NULL;
885 callbacks.save_complete.callback = smSaveCompleteProc;
886 callbacks.save_complete.client_data = NULL;
888 callbacks.shutdown_cancelled.callback = smShutdownCancelledProc;
889 callbacks.shutdown_cancelled.client_data = NULL;
891 for (i=0; i<argc; i++) {
892 if (strcmp(argv[i], "-clientid")==0) {
893 previous_id = argv[i+1];
894 break;
898 /* connect to the session manager */
899 sSMCConn = SmcOpenConnection(NULL, NULL, SmProtoMajor, SmProtoMinor,
900 mask, &callbacks, previous_id,
901 &sClientID, 255, buffer);
902 if (!sSMCConn) {
903 return;
905 #ifdef DEBUG1
906 puts("connected to the session manager");
907 #endif
909 /* IceSetIOErrorHandler(iceIOErrorHandler);*/
911 /* check for session manager clients */
912 iceConn = SmcGetIceConnection(smcConn);
915 sSMInputHandler = WMAddInputHandler(IceConnectionNumber(iceConn),
916 WIReadMask, iceMessageProc, iceConn);
918 /* setup information about ourselves */
920 /* program name */
921 prop1val.value = argv[0];
922 prop1val.length = strlen(argv[0]);
923 prop[0].name = SmProgram;
924 prop[0].type = SmARRAY8;
925 prop[0].num_vals = 1;
926 prop[0].vals = &prop1val;
928 /* The XSMP doc from X11R6.1 says it contains the user name,
929 * but every client implementation I saw places the uid # */
930 sprintf(uid, "%i", getuid());
931 prop2val.value = uid;
932 prop2val.length = strlen(uid);
933 prop[1].name = SmUserID;
934 prop[1].type = SmARRAY8;
935 prop[1].num_vals = 1;
936 prop[1].vals = &prop2val;
938 /* Restart style. We should restart only if we were running when
939 * the previous session finished. */
940 restartStyle = SmRestartIfRunning;
941 prop3val.value = &restartStyle;
942 prop3val.length = 1;
943 prop[2].name = SmRestartStyleHint;
944 prop[2].type = SmCARD8;
945 prop[2].num_vals = 1;
946 prop[2].vals = &prop3val;
948 /* Our PID. Not required but might be usefull */
949 sprintf(pid, "%i", getpid());
950 prop4val.value = pid;
951 prop4val.length = strlen(pid);
952 prop[3].name = SmProcessID;
953 prop[3].type = SmARRAY8;
954 prop[3].num_vals = 1;
955 prop[3].vals = &prop4val;
957 /* we'll set the rest of the hints later */
959 SmcSetProperties(sSMCConn, 4, props);
963 void
964 _wSessionCloseDescriptors(void)
966 if (sSMCConn)
967 close(IceConnectionNumber(SmcGetIceConnection(smcConn)));
970 void
971 wSessionDisconnectManager(void)
973 if (sSMCConn) {
974 WMDeleteInputHandler(sSMInputHandler);
975 sSMInputHandler = NULL;
977 SmcCloseConnection(sSMCConn, 0, NULL);
978 sSMCConn = NULL;
982 void
983 wSessionRequestShutdown(void)
985 /* request a shutdown to the session manager */
986 if (sSMCConn)
987 SmcRequestSaveYourself(sSMCConn, SmSaveBoth, True, SmInteractStyleAny,
988 False, True);
991 Bool
992 wSessionIsManaged(void)
994 return sSMCConn!=NULL;
997 #endif /* !R6SM */