This update includes the 0.20.3pre3 code
[wmaker-crm.git] / src / session.c
blobbaa3d65dbff3f466b43aeaf23ecb7cfa41c558c0
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
61 /* requested for SaveYourselfPhase2 */
62 static Bool sWaitingPhase2 = False;
64 static SmcConn sSMCConn = NULL;
66 static WMHandlerID sSMInputHandler = NULL;
68 /* our SM client ID */
69 static char *sClientID = NULL;
70 #endif
73 static proplist_t sApplications = NULL;
74 static proplist_t sCommand;
75 static proplist_t sName;
76 static proplist_t sHost;
77 static proplist_t sWorkspace;
78 static proplist_t sShaded;
79 static proplist_t sMiniaturized;
80 static proplist_t sHidden;
81 static proplist_t sGeometry;
83 static proplist_t sDock;
85 static proplist_t sYes, sNo;
88 static void
89 make_keys()
91 if (sApplications!=NULL)
92 return;
94 sApplications = PLMakeString("Applications");
95 sCommand = PLMakeString("Command");
96 sName = PLMakeString("Name");
97 sHost = PLMakeString("Host");
98 sWorkspace = PLMakeString("Workspace");
99 sShaded = PLMakeString("Shaded");
100 sMiniaturized = PLMakeString("Miniaturized");
101 sHidden = PLMakeString("Hidden");
102 sGeometry = PLMakeString("Geometry");
103 sDock = PLMakeString("Dock");
105 sYes = PLMakeString("Yes");
106 sNo = PLMakeString("No");
111 static int
112 getBool(proplist_t value)
114 char *val;
116 if (!PLIsString(value)) {
117 return 0;
119 if (!(val = PLGetString(value))) {
120 return 0;
123 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
124 || strcasecmp(val, "YES")==0) {
126 return 1;
127 } else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
128 || strcasecmp(val, "NO")==0) {
129 return 0;
130 } else {
131 int i;
132 if (sscanf(val, "%i", &i)==1) {
133 return (i!=0);
134 } else {
135 wwarning(_("can't convert \"%s\" to boolean"), val);
136 return 0;
143 static proplist_t
144 makeWindowState(WWindow *wwin, WApplication *wapp)
146 WScreen *scr = wwin->screen_ptr;
147 Window win;
148 int argc;
149 char **argv;
150 char *class, *instance, *command=NULL, buffer[256];
151 proplist_t win_state, cmd, name, workspace;
152 proplist_t shaded, miniaturized, hidden, geometry;
153 proplist_t dock;
155 if (wwin->main_window!=None && wwin->main_window!=wwin->client_win)
156 win = wwin->main_window;
157 else
158 win = wwin->client_win;
160 if (XGetCommand(dpy, win, &argv, &argc) && argc>0) {
161 command = FlattenStringList(argv, argc);
162 XFreeStringList(argv);
164 if (!command)
165 return NULL;
167 if (PropGetWMClass(win, &class, &instance)) {
168 if (class && instance)
169 sprintf(buffer, "%s.%s", instance, class);
170 else if (instance)
171 sprintf(buffer, "%s", instance);
172 else if (class)
173 sprintf(buffer, ".%s", class);
174 else
175 sprintf(buffer, ".");
177 name = PLMakeString(buffer);
178 cmd = PLMakeString(command);
179 /*sprintf(buffer, "%d", wwin->frame->workspace+1);
180 workspace = PLMakeString(buffer);*/
181 workspace = PLMakeString(scr->workspaces[wwin->frame->workspace]->name);
182 shaded = wwin->flags.shaded ? sYes : sNo;
183 miniaturized = wwin->flags.miniaturized ? sYes : sNo;
184 hidden = wwin->flags.hidden ? sYes : sNo;
185 sprintf(buffer, "%ix%i+%i+%i", wwin->client.width, wwin->client.height,
186 wwin->frame_x, wwin->frame_y);
187 geometry = PLMakeString(buffer);
189 win_state = PLMakeDictionaryFromEntries(sName, name,
190 sCommand, cmd,
191 sWorkspace, workspace,
192 sShaded, shaded,
193 sMiniaturized, miniaturized,
194 sHidden, hidden,
195 sGeometry, geometry,
196 NULL);
198 PLRelease(name);
199 PLRelease(cmd);
200 PLRelease(workspace);
201 PLRelease(geometry);
202 if (wapp && wapp->app_icon && wapp->app_icon->dock) {
203 int i;
204 char *name;
205 if (wapp->app_icon->dock == scr->dock) {
206 name="Dock";
207 } else {
208 for(i=0; i<scr->workspace_count; i++)
209 if(scr->workspaces[i]->clip == wapp->app_icon->dock)
210 break;
211 assert( i < scr->workspace_count);
212 /*n = i+1;*/
213 name = scr->workspaces[i]->name;
215 dock = PLMakeString(name);
216 PLInsertDictionaryEntry(win_state, sDock, dock);
217 PLRelease(dock);
219 } else {
220 win_state = NULL;
223 if (instance) XFree(instance);
224 if (class) XFree(class);
225 if (command) free(command);
227 return win_state;
231 void
232 wSessionSaveState(WScreen *scr)
234 WWindow *wwin = scr->focused_window;
235 proplist_t win_info, wks;
236 proplist_t list=NULL;
237 LinkedList *wapp_list=NULL;
240 make_keys();
242 if (!scr->session_state) {
243 scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
244 if (!scr->session_state)
245 return;
248 list = PLMakeArrayFromElements(NULL);
250 while (wwin) {
251 WApplication *wapp=wApplicationOf(wwin->main_window);
253 if (wwin->transient_for==None && list_find(wapp_list, wapp)==NULL
254 && !wwin->window_flags.dont_save_session) {
255 /* A entry for this application was not yet saved. Save one. */
256 if ((win_info = makeWindowState(wwin, wapp))!=NULL) {
257 list = PLAppendArrayElement(list, win_info);
258 PLRelease(win_info);
259 /* If we were succesful in saving the info for this window
260 * add the application the window belongs to, to the
261 * application list, so no multiple entries for the same
262 * application are saved.
264 wapp_list = list_cons(wapp, wapp_list);
267 wwin = wwin->prev;
269 PLRemoveDictionaryEntry(scr->session_state, sApplications);
270 PLInsertDictionaryEntry(scr->session_state, sApplications, list);
271 PLRelease(list);
273 wks = PLMakeString(scr->workspaces[scr->current_workspace]->name);
274 PLInsertDictionaryEntry(scr->session_state, sWorkspace, wks);
275 PLRelease(wks);
277 list_free(wapp_list);
281 void
282 wSessionClearState(WScreen *scr)
284 make_keys();
286 if (!scr->session_state)
287 return;
289 PLRemoveDictionaryEntry(scr->session_state, sApplications);
290 PLRemoveDictionaryEntry(scr->session_state, sWorkspace);
294 static pid_t
295 execCommand(WScreen *scr, char *command, char *host)
297 pid_t pid;
298 char **argv;
299 int argc;
301 ParseCommand(command, &argv, &argc);
303 if (argv==NULL) {
304 return 0;
307 if ((pid=fork())==0) {
308 char **args;
309 int i;
311 SetupEnvironment(scr);
313 CloseDescriptors();
315 args = malloc(sizeof(char*)*(argc+1));
316 if (!args)
317 exit(111);
318 for (i=0; i<argc; i++) {
319 args[i] = argv[i];
321 args[argc] = NULL;
322 execvp(argv[0], args);
323 exit(111);
325 while (argc > 0)
326 free(argv[--argc]);
327 free(argv);
328 return pid;
332 static WSavedState*
333 getWindowState(WScreen *scr, proplist_t win_state)
335 WSavedState *state = wmalloc(sizeof(WSavedState));
336 proplist_t value;
337 char *tmp;
338 int i;
340 memset(state, 0, sizeof(WSavedState));
341 state->workspace = -1;
342 value = PLGetDictionaryEntry(win_state, sWorkspace);
343 if (value && PLIsString(value)) {
344 tmp = PLGetString(value);
345 if (sscanf(tmp, "%i", &state->workspace)!=1) {
346 state->workspace = -1;
347 for (i=0; i < scr->workspace_count; i++) {
348 if (strcmp(scr->workspaces[i]->name, tmp)==0) {
349 state->workspace = i;
350 break;
353 } else {
354 state->workspace--;
357 if ((value = PLGetDictionaryEntry(win_state, sShaded))!=NULL)
358 state->shaded = getBool(value);
359 if ((value = PLGetDictionaryEntry(win_state, sMiniaturized))!=NULL)
360 state->miniaturized = getBool(value);
361 if ((value = PLGetDictionaryEntry(win_state, sHidden))!=NULL)
362 state->hidden = getBool(value);
364 value = PLGetDictionaryEntry(win_state, sGeometry);
365 if (value && PLIsString(value)) {
366 if (sscanf(PLGetString(value), "%ix%i+%i+%i",
367 &state->w, &state->h, &state->x, &state->y)==4 &&
368 (state->w>0 && state->h>0)) {
369 state->use_geometry = 1;
370 } else if (sscanf(PLGetString(value), "%i,%i,%i,%i",
371 &state->x, &state->y, &state->w, &state->h)==4 &&
372 (state->w>0 && state->h>0)) {
373 /* TODO: remove redundant sscanf() in version 0.20.x */
374 state->use_geometry = 1;
379 return state;
383 #define SAME(x, y) (((x) && (y) && !strcmp((x), (y))) || (!(x) && !(y)))
386 void
387 wSessionRestoreState(WScreen *scr)
389 WSavedState *state;
390 char *instance, *class, *command, *host;
391 proplist_t win_info, apps, cmd, value;
392 pid_t pid;
393 int i, count;
394 WDock *dock;
395 WAppIcon *btn=NULL;
396 int j, n, found;
397 char *tmp;
399 make_keys();
401 if (!scr->session_state)
402 return;
404 PLSetStringCmpHook(NULL);
406 apps = PLGetDictionaryEntry(scr->session_state, sApplications);
407 if (!apps)
408 return;
410 count = PLGetNumberOfElements(apps);
411 if (count==0)
412 return;
414 for (i=0; i<count; i++) {
415 win_info = PLGetArrayElement(apps, i);
417 cmd = PLGetDictionaryEntry(win_info, sCommand);
418 if (!cmd || !PLIsString(cmd) || !(command = PLGetString(cmd))) {
419 continue;
422 value = PLGetDictionaryEntry(win_info, sName);
423 if (!value)
424 continue;
426 ParseWindowName(value, &instance, &class, "session");
427 if (!instance && !class)
428 continue;
430 value = PLGetDictionaryEntry(win_info, sHost);
431 if (value && PLIsString(value))
432 host = PLGetString(value);
433 else
434 host = NULL;
436 state = getWindowState(scr, win_info);
438 dock = NULL;
439 value = PLGetDictionaryEntry(win_info, sDock);
440 if (value && PLIsString(value) && (tmp = PLGetString(value))!=NULL) {
441 if (sscanf(tmp, "%i", &n)!=1) {
442 if (!strcasecmp(tmp, "DOCK")) {
443 dock = scr->dock;
444 } else {
445 for (j=0; j < scr->workspace_count; j++) {
446 if (strcmp(scr->workspaces[j]->name, tmp)==0) {
447 dock = scr->workspaces[j]->clip;
448 break;
452 } else {
453 if (n == 0) {
454 dock = scr->dock;
455 } else if (n>0 && n<=scr->workspace_count) {
456 dock = scr->workspaces[n-1]->clip;
461 found = 0;
462 if (dock!=NULL) {
463 for (j=0; j<dock->max_icons; j++) {
464 btn = dock->icon_array[j];
465 if (btn && SAME(instance, btn->wm_instance) &&
466 SAME(class, btn->wm_class) &&
467 SAME(command, btn->command)) {
468 found = 1;
469 break;
474 if (found) {
475 wDockLaunchWithState(dock, btn, state);
476 } else if ((pid = execCommand(scr, command, host)) > 0) {
477 wWindowAddSavedState(instance, class, command, pid, state);
478 } else {
479 free(state);
482 if (instance) free(instance);
483 if (class) free(class);
485 /* clean up */
486 PLSetStringCmpHook(StringCompareHook);
490 void
491 wSessionRestoreLastWorkspace(WScreen *scr)
493 proplist_t wks;
494 int w, i;
495 char *tmp;
497 make_keys();
499 if (!scr->session_state)
500 return;
502 PLSetStringCmpHook(NULL);
504 wks = PLGetDictionaryEntry(scr->session_state, sWorkspace);
505 if (!wks || !PLIsString(wks))
506 return;
508 tmp = PLGetString(wks);
510 /* clean up */
511 PLSetStringCmpHook(StringCompareHook);
513 if (sscanf(tmp, "%i", &w)!=1) {
514 w = -1;
515 for (i=0; i < scr->workspace_count; i++) {
516 if (strcmp(scr->workspaces[i]->name, tmp)==0) {
517 w = i;
518 break;
521 } else {
522 w--;
525 if (w!=scr->current_workspace && w<scr->workspace_count) {
526 wWorkspaceChange(scr, w);
532 #ifdef R6SM
534 * With full session management support, the part of WMState
535 * that store client window state will become obsolete,
536 * but we still need to store state info like the dock and workspaces.
537 * It is better to keep dock/wspace info in WMState because the user
538 * might want to keep the dock configuration while not wanting to
539 * resume a previously saved session.
540 * So, wmaker specific state info can be saved in
541 * ~/GNUstep/.AppInfo/WindowMaker/statename.state
542 * Its better to not put it in the defaults directory because:
543 * - its not a defaults file (having domain names like wmaker0089504baa
544 * in the defaults directory wouldn't be very neat)
545 * - this state file is not meant to be edited by users
547 * The old session code will become obsolete. When wmaker is
548 * compiled with R6 sm support compiled in, itll be better to
549 * use a totally rewritten state saving code, but we can keep
550 * the current code for when R6SM is not compiled in.
552 * This will be confusing to old users (well get lots of "SAVE_SESSION broke!"
553 * messages), but itll be better.
555 * -readme
560 * Windows are identified as:
561 * WM_CLASS(instance.class).WM_WINDOW_ROLE
565 static void
566 saveClientState(WWindow *wwin, proplist_t dict)
568 proplist_t key;
574 static void
575 smSaveYourselfPhase2Proc(SmcConn smc_conn, SmPointer client_data)
577 SmProp props[4];
578 SmPropValue prop1val, prop2val, prop3val, prop4val;
579 char **argv = (char**)client_data;
580 int argc;
581 int i, j;
582 Bool ok = False;
583 char *statefile = NULL;
584 char *prefix;
585 Bool gsPrefix = False;
586 char *discardCmd = NULL;
587 time_t t;
588 FILE *file;
590 #ifdef DEBUG1
591 puts("received SaveYourselfPhase2 SM message");
592 #endif
594 /* save session state */
596 /* the file that will contain the state */
597 prefix = getenv("SM_SAVE_DIR");
598 if (!prefix) {
599 prefix = wusergnusteppath();
600 if (prefix)
601 gsPrefix = True;
603 if (!prefix) {
604 prefix = getenv("HOME");
606 if (!prefix)
607 prefix = ".";
609 statefile = malloc(strlen(prefix)+64);
610 if (!statefile) {
611 if (gsPrefix)
612 free(prefix);
613 wwarning(_("end of memory while saving session state"));
614 goto fail;
617 t = time();
618 i = 0;
619 do {
620 if (gsPrefix)
621 sprintf(statefile, "%s/.AppInfo/WindowMaker/%l%i.state",
622 prefix, t, i);
623 else
624 sprintf(statefile, "%s/wmaker.%l%i.state", prefix, t, i);
625 i++;
626 } while (access(F_OK, statefile)!=-1);
628 if (gsPrefix)
629 free(prefix);
631 /* save the states of all windows we're managing */
633 file = fopen(statefile, "w");
634 if (!file) {
635 wsyserror(_("could not create state file %s"), statefile);
636 goto fail;
641 fclose(file);
644 /* set the remaining properties that we didn't set at
645 * startup time */
647 for (argc=0, i=0; argv[i]!=NULL; i++) {
648 if (strcmp(argv[i], "-clientid")==0
649 || strcmp(argv[i], "-restore")==0) {
650 i++;
651 } else {
652 argc++;
656 prop[0].name = SmRestartCommand;
657 prop[0].type = SmLISTofARRAY8;
658 prop[0].vals = malloc(sizeof(SmPropValue)*(argc+4));
659 prop[0].num_vals = argc+4;
661 prop[1].name = SmCloneCommand;
662 prop[1].type = SmLISTofARRAY8;
663 prop[1].vals = malloc(sizeof(SmPropValue)*(argc));
664 prop[1].num_vals = argc;
666 if (!prop[0].vals || !prop[1].vals) {
667 wwarning(_("end of memory while saving session state"));
668 goto fail;
671 for (j=0, i=0; i<argc+4; i++) {
672 if (strcmp(argv[i], "-clientid")==0
673 || strcmp(argv[i], "-restore")==0) {
674 i++;
675 } else {
676 prop[0].vals[j].value = argv[i];
677 prop[0].vals[j].length = strlen(argv[i]);
678 prop[1].vals[j].value = argv[i];
679 prop[1].vals[j].length = strlen(argv[i]);
680 j++;
683 prop[0].vals[j].value = "-clientid";
684 prop[0].vals[j].length = 9;
685 j++;
686 prop[0].vals[j].value = sClientID;
687 prop[0].vals[j].length = strlen(sClientID);
688 j++;
689 prop[0].vals[j].value = "-restore";
690 prop[0].vals[j].length = 11;
691 j++;
692 prop[0].vals[j].value = statefile;
693 prop[0].vals[j].length = strlen(statefile);
695 discardCmd = malloc(strlen(statefile)+8);
696 if (!discardCmd)
697 goto fail;
698 sprintf(discardCmd, "rm %s", statefile);
699 prop[2].name = SmDiscardCommand;
700 prop[2].type = SmARRAY8;
701 prop[2].vals[0] = discardCmd;
702 prop[2].num_vals = 1;
704 SmcSetProperties(sSMCConn, 3, prop);
706 ok = True;
707 fail:
708 SmcSaveYourselfDone(smc_conn, ok);
710 if (prop[0].vals)
711 free(prop[0].vals);
712 if (prop[1].vals)
713 free(prop[1].vals);
714 if (discardCmd)
715 free(discardCmd);
717 if (!ok) {
718 remove(statefile);
720 if (statefile)
721 free(statefile);
725 static void
726 smSaveYourselfProc(SmcConn smc_conn, SmPointer client_data, int save_type,
727 Bool shutdown, int interact_style, Bool fast)
729 #ifdef DEBUG1
730 puts("received SaveYourself SM message");
731 #endif
733 if (!SmcRequestSaveYourselfPhase2(smc_conn, smSaveYourselfPhase2Proc,
734 client_data)) {
736 SmcSaveYourselfDone(smc_conn, False);
737 sWaitingPhase2 = False;
738 } else {
739 #ifdef DEBUG1
740 puts("successfull request of SYS phase 2");
741 #endif
742 sWaitingPhase2 = True;
747 static void
748 smDieProc(SmcConn smc_conn, SmPointer client_data)
750 #ifdef DEBUG1
751 puts("received Die SM message");
752 #endif
754 wSessionDisconnectManager();
756 RestoreDesktop(NULL);
758 ExecExitScript();
759 Exit(0);
764 static void
765 smSaveCompleteProc(SmcConn smc_conn)
767 /* it means that we can resume doing things that can change our state */
768 #ifdef DEBUG1
769 puts("received SaveComplete SM message");
770 #endif
774 static void
775 smShutdownCancelledProc(SmcConn smc_conn, SmPointer client_data)
777 if (sWaitingPhase2) {
779 sWaitingPhase2 = False;
781 SmcSaveYourselfDone(smc_conn, False);
786 static void
787 iceMessageProc(int fd, int mask, void *clientData)
789 IceConn iceConn = (IceConn)clientData;
791 IceProcessMessages(iceConn, NULL, NULL);
795 static void
796 iceIOErrorHandler(IceConnection ice_conn)
798 /* This is not fatal but can mean the session manager exited.
799 * If the session manager exited normally we would get a
800 * Die message, so this probably means an abnormal exit.
801 * If the sm was the last client of session, then we'll die
802 * anyway, otherwise we can continue doing our stuff.
804 wwarning(_("connection to the session manager was lost"));
805 wSessionDisconnectManager();
809 void
810 wSessionConnectManager(char **argv, int argc)
812 IceConn iceConn;
813 char *previous_id = NULL;
814 char buffer[256];
815 SmcCallbacks callbacks;
816 unsigned long mask;
817 char uid[32];
818 char pid[32];
819 SmProp props[4];
820 SmPropValue prop1val, prop2val, prop3val, prop4val;
821 char restartStyle;
822 int i;
824 mask = SmcSaveYourselfProcMask|SmcDieProcMask|SmcSaveCompleteProcMask
825 |SmcShutdownCancelledProcMask;
827 callbacks.save_yourself.callback = smSaveYourselfProc;
828 callbacks.save_yourself.client_data = argv;
830 callbacks.die.callback = smDieProc;
831 callbacks.die.client_data = NULL;
833 callbacks.save_complete.callback = smSaveCompleteProc;
834 callbacks.save_complete.client_data = NULL;
836 callbacks.shutdown_cancelled.callback = smShutdownCancelledProc;
837 callbacks.shutdown_cancelled.client_data = NULL;
839 for (i=0; i<argc; i++) {
840 if (strcmp(argv[i], "-clientid")==0) {
841 previous_id = argv[i+1];
842 break;
846 /* connect to the session manager */
847 sSMCConn = SmcOpenConnection(NULL, NULL, SmProtoMajor, SmProtoMinor,
848 mask, &callbacks, previous_id,
849 &sClientID, 255, buffer);
850 if (!sSMCConn) {
851 return;
853 #ifdef DEBUG1
854 puts("connected to the session manager");
855 #endif
857 /* IceSetIOErrorHandler(iceIOErrorHandler);*/
859 /* check for session manager clients */
860 iceConn = SmcGetIceConnection(smcConn);
863 sSMInputHandler = WMAddInputHandler(IceConnectionNumber(iceConn),
864 WIReadMask, iceMessageProc, iceConn);
866 /* setup information about ourselves */
868 /* program name */
869 prop1val.value = argv[0];
870 prop1val.length = strlen(argv[0]);
871 prop[0].name = SmProgram;
872 prop[0].type = SmARRAY8;
873 prop[0].num_vals = 1;
874 prop[0].vals = &prop1val;
876 /* The XSMP doc from X11R6.1 says it contains the user name,
877 * but every client implementation I saw places the uid # */
878 sprintf(uid, "%i", getuid());
879 prop2val.value = uid;
880 prop2val.length = strlen(uid);
881 prop[1].name = SmUserID;
882 prop[1].type = SmARRAY8;
883 prop[1].num_vals = 1;
884 prop[1].vals = &prop2val;
886 /* Restart style. We should restart only if we were running when
887 * the previous session finished. */
888 restartStyle = SmRestartIfRunning;
889 prop3val.value = &restartStyle;
890 prop3val.length = 1;
891 prop[2].name = SmRestartStyleHint;
892 prop[2].type = SmCARD8;
893 prop[2].num_vals = 1;
894 prop[2].vals = &prop3val;
896 /* Our PID. Not required but might be usefull */
897 sprintf(pid, "%i", getpid());
898 prop4val.value = pid;
899 prop4val.length = strlen(pid);
900 prop[3].name = SmProcessID;
901 prop[3].type = SmARRAY8;
902 prop[3].num_vals = 1;
903 prop[3].vals = &prop4val;
905 /* we'll set the rest of the hints later */
907 SmcSetProperties(sSMCConn, 4, props);
911 void
912 _wSessionCloseDescriptors(void)
914 if (sSMCConn)
915 close(IceConnectionNumber(SmcGetIceConnection(smcConn)));
918 void
919 wSessionDisconnectManager(void)
921 if (sSMCConn) {
922 WMDeleteInputHandler(sSMInputHandler);
923 sSMInputHandler = NULL;
925 SmcCloseConnection(sSMCConn, 0, NULL);
926 sSMCConn = NULL;
930 void
931 wSessionRequestShutdown(void)
933 /* request a shutdown to the session manager */
934 if (sSMCConn)
935 SmcRequestSaveYourself(sSMCConn, SmSaveBoth, True, SmInteractStyleAny,
936 False, True);
939 Bool
940 wSessionIsManaged(void)
942 return sSMCConn!=NULL;
945 #endif /* !R6SM */