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,
27 #include <X11/Xutil.h>
30 #include <X11/SM/SMlib.h>
40 #include "WindowMaker.h"
46 #include "workspace.h"
48 #include "properties.h"
49 #include "application.h"
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
;
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
;
94 if (sApplications
!=NULL
)
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");
115 getBool(proplist_t value
)
119 if (!PLIsString(value
)) {
122 if (!(val
= PLGetString(value
))) {
126 if ((val
[1]=='\0' && (val
[0]=='y' || val
[0]=='Y'))
127 || strcasecmp(val
, "YES")==0) {
130 } else if ((val
[1]=='\0' && (val
[0]=='n' || val
[0]=='N'))
131 || strcasecmp(val
, "NO")==0) {
135 if (sscanf(val
, "%i", &i
)==1) {
138 wwarning(_("can't convert \"%s\" to boolean"), val
);
147 makeWindowState(WWindow
*wwin
, WApplication
*wapp
)
149 WScreen
*scr
= wwin
->screen_ptr
;
153 char *class, *instance
, *command
=NULL
, buffer
[256];
154 proplist_t win_state
, cmd
, name
, workspace
;
155 proplist_t shaded
, miniaturized
, hidden
, geometry
;
158 if (wwin
->main_window
!=None
&& wwin
->main_window
!=wwin
->client_win
)
159 win
= wwin
->main_window
;
161 win
= wwin
->client_win
;
163 if (XGetCommand(dpy
, win
, &argv
, &argc
) && argc
>0) {
164 command
= FlattenStringList(argv
, argc
);
165 XFreeStringList(argv
);
170 if (PropGetWMClass(win
, &class, &instance
)) {
171 if (class && instance
)
172 sprintf(buffer
, "%s.%s", instance
, class);
174 sprintf(buffer
, "%s", instance
);
176 sprintf(buffer
, ".%s", class);
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
,
194 sWorkspace
, workspace
,
196 sMiniaturized
, miniaturized
,
203 PLRelease(workspace
);
205 if (wapp
&& wapp
->app_icon
&& wapp
->app_icon
->dock
) {
208 if (wapp
->app_icon
->dock
== scr
->dock
) {
211 for(i
=0; i
<scr
->workspace_count
; i
++)
212 if(scr
->workspaces
[i
]->clip
== wapp
->app_icon
->dock
)
214 assert( i
< scr
->workspace_count
);
216 name
= scr
->workspaces
[i
]->name
;
218 dock
= PLMakeString(name
);
219 PLInsertDictionaryEntry(win_state
, sDock
, dock
);
226 if (instance
) XFree(instance
);
227 if (class) XFree(class);
228 if (command
) free(command
);
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
;
245 if (!scr
->session_state
) {
246 scr
->session_state
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
247 if (!scr
->session_state
)
251 list
= PLMakeArrayFromElements(NULL
);
254 WApplication
*wapp
=wApplicationOf(wwin
->main_window
);
256 if (wwin
->transient_for
==None
&& list_find(wapp_list
, wapp
)==NULL
257 && !WFLAGP(wwin
, 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
);
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
);
272 PLRemoveDictionaryEntry(scr
->session_state
, sApplications
);
273 PLInsertDictionaryEntry(scr
->session_state
, sApplications
, list
);
276 wks
= PLMakeString(scr
->workspaces
[scr
->current_workspace
]->name
);
277 PLInsertDictionaryEntry(scr
->session_state
, sWorkspace
, wks
);
280 list_free(wapp_list
);
285 wSessionClearState(WScreen
*scr
)
289 if (!scr
->session_state
)
292 PLRemoveDictionaryEntry(scr
->session_state
, sApplications
);
293 PLRemoveDictionaryEntry(scr
->session_state
, sWorkspace
);
298 execCommand(WScreen
*scr
, char *command
, char *host
)
304 ParseCommand(command
, &argv
, &argc
);
310 if ((pid
=fork())==0) {
314 SetupEnvironment(scr
);
316 args
= malloc(sizeof(char*)*(argc
+1));
319 for (i
=0; i
<argc
; i
++) {
323 execvp(argv
[0], args
);
334 getWindowState(WScreen
*scr
, proplist_t win_state
)
336 WSavedState
*state
= wmalloc(sizeof(WSavedState
));
341 memset(state
, 0, sizeof(WSavedState
));
342 state
->workspace
= -1;
343 value
= PLGetDictionaryEntry(win_state
, sWorkspace
);
344 if (value
&& PLIsString(value
)) {
345 tmp
= PLGetString(value
);
346 if (sscanf(tmp
, "%i", &state
->workspace
)!=1) {
347 state
->workspace
= -1;
348 for (i
=0; i
< scr
->workspace_count
; i
++) {
349 if (strcmp(scr
->workspaces
[i
]->name
, tmp
)==0) {
350 state
->workspace
= i
;
358 if ((value
= PLGetDictionaryEntry(win_state
, sShaded
))!=NULL
)
359 state
->shaded
= getBool(value
);
360 if ((value
= PLGetDictionaryEntry(win_state
, sMiniaturized
))!=NULL
)
361 state
->miniaturized
= getBool(value
);
362 if ((value
= PLGetDictionaryEntry(win_state
, sHidden
))!=NULL
)
363 state
->hidden
= getBool(value
);
365 value
= PLGetDictionaryEntry(win_state
, sGeometry
);
366 if (value
&& PLIsString(value
)) {
367 if (sscanf(PLGetString(value
), "%ix%i+%i+%i",
368 &state
->w
, &state
->h
, &state
->x
, &state
->y
)==4 &&
369 (state
->w
>0 && state
->h
>0)) {
370 state
->use_geometry
= 1;
371 } else if (sscanf(PLGetString(value
), "%i,%i,%i,%i",
372 &state
->x
, &state
->y
, &state
->w
, &state
->h
)==4 &&
373 (state
->w
>0 && state
->h
>0)) {
374 /* TODO: remove redundant sscanf() in version 0.20.x */
375 state
->use_geometry
= 1;
384 #define SAME(x, y) (((x) && (y) && !strcmp((x), (y))) || (!(x) && !(y)))
387 wSessionRestoreState(WScreen
*scr
)
390 char *instance
, *class, *command
, *host
;
391 proplist_t win_info
, apps
, cmd
, value
;
401 if (!scr
->session_state
)
404 PLSetStringCmpHook(NULL
);
406 apps
= PLGetDictionaryEntry(scr
->session_state
, sApplications
);
410 count
= PLGetNumberOfElements(apps
);
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
))) {
422 value
= PLGetDictionaryEntry(win_info
, sName
);
426 ParseWindowName(value
, &instance
, &class, "session");
427 if (!instance
&& !class)
430 value
= PLGetDictionaryEntry(win_info
, sHost
);
431 if (value
&& PLIsString(value
))
432 host
= PLGetString(value
);
436 state
= getWindowState(scr
, win_info
);
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")) {
445 for (j
=0; j
< scr
->workspace_count
; j
++) {
446 if (strcmp(scr
->workspaces
[j
]->name
, tmp
)==0) {
447 dock
= scr
->workspaces
[j
]->clip
;
455 } else if (n
>0 && n
<=scr
->workspace_count
) {
456 dock
= scr
->workspaces
[n
-1]->clip
;
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
)) {
475 wDockLaunchWithState(dock
, btn
, state
);
476 } else if ((pid
= execCommand(scr
, command
, host
)) > 0) {
477 wWindowAddSavedState(instance
, class, command
, pid
, state
);
482 if (instance
) free(instance
);
483 if (class) free(class);
486 PLSetStringCmpHook(StringCompareHook
);
491 wSessionRestoreLastWorkspace(WScreen
*scr
)
499 if (!scr
->session_state
)
502 PLSetStringCmpHook(NULL
);
504 wks
= PLGetDictionaryEntry(scr
->session_state
, sWorkspace
);
505 if (!wks
|| !PLIsString(wks
))
508 tmp
= PLGetString(wks
);
511 PLSetStringCmpHook(StringCompareHook
);
513 if (sscanf(tmp
, "%i", &w
)!=1) {
515 for (i
=0; i
< scr
->workspace_count
; i
++) {
516 if (strcmp(scr
->workspaces
[i
]->name
, tmp
)==0) {
525 if (w
!=scr
->current_workspace
&& w
<scr
->workspace_count
) {
526 wWorkspaceChange(scr
, w
);
534 * With full session management support, the part of WMState
535 * that store client window state will become obsolete (maybe we can reuse
537 * but we still need to store state info like the dock and workspaces.
538 * It is better to keep dock/wspace info in WMState because the user
539 * might want to keep the dock configuration while not wanting to
540 * resume a previously saved session.
541 * So, wmaker specific state info can be saved in
542 * ~/GNUstep/.AppInfo/WindowMaker/statename.state
543 * Its better to not put it in the defaults directory because:
544 * - its not a defaults file (having domain names like wmaker0089504baa
545 * in the defaults directory wouldn't be very neat)
546 * - this state file is not meant to be edited by users
548 * The old session code will become obsolete. When wmaker is
549 * compiled with R6 sm support compiled in, itll be better to
550 * use a totally rewritten state saving code, but we can keep
551 * the current code for when R6SM is not compiled in.
553 * This will be confusing to old users (well get lots of "SAVE_SESSION broke!"
554 * messages), but itll be better.
561 * Windows are identified as:
562 * WM_CLASS(instance.class).WM_WINDOW_ROLE
570 * state = (miniaturized, shaded, etc)
573 * app state = (which dock, hidden)
578 makeAppState(WWindow
*wwin
)
582 WScreen
*scr
= wwin
->screen_ptr
;
584 state
= PLMakeArrayWithElements(NULL
, NULL
);
586 wapp
= wApplicationOf(wwin
->main_window
);
589 if (wapp
->app_icon
&& wapp
->app_icon
->dock
) {
591 if (wapp
->app_icon
->dock
== scr
->dock
) {
592 PLAppendArrayElement(state
, PLMakeString("Dock"));
596 for(i
=0; i
<scr
->workspace_count
; i
++)
597 if(scr
->workspaces
[i
]->clip
== wapp
->app_icon
->dock
)
600 assert(i
< scr
->workspace_count
);
602 PLAppendArrayElement(state
,
603 PLMakeString(scr
->workspaces
[i
]->name
));
607 PLAppendArrayElement(state
, PLMakeString(wapp
->hidden
? "1" : "0"));
615 makeAttributeState(WWindow
*wwin
)
617 unsigned int data1
, data2
;
620 #define W_FLAG(wwin, FLAG) ((wwin)->defined_user_flags.FLAG \
621 ? (wwin)->user_flags.FLAG : -1)
623 sprintf(buffer
, "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
625 W_FLAG(no_resizable
),
627 W_FLAG(no_miniaturizable
),
628 W_FLAG(no_resizebar
),
629 W_FLAG(no_close_button
),
630 W_FLAG(no_miniaturize_button
),
632 W_FLAG(broken_close),
635 W_FLAG(no_shadeable
),
637 W_FLAG(skip_window_list
),
640 W_FLAG(no_bind_keys
),
641 W_FLAG(no_bind_mouse
),
642 W_FLAG(no_hide_others
),
644 W_FLAG(dont_move_off
),
645 W_FLAG(no_focusable
),
646 W_FLAG(always_user_icon
),
647 W_FLAG(start_miniaturized
),
648 W_FLAG(start_hidden
),
649 W_FLAG(start_maximized
),
650 W_FLAG(dont_save_session
),
651 W_FLAG(emulate_appicon
));
653 return PLMakeString(buffer
);
658 makeClientState(WWindow
*wwin
)
666 state
= PLMakeArrayWithElements(NULL
, NULL
);
669 PLAppendArrayElement(state
, PLMakeString(wwin
->wm_instance
));
670 PLAppendArrayElement(state
, PLMakeString(wwin
->wm_class
));
672 PLAppendArrayElement(state
, PLMakeString(str
));
675 sprintf(buffer
, "%i %i %i %i", wwin
->frame_x
, wwin
->frame_y
,
676 wwin
->frame
->core
->width
, wwin
->frame
->core
->height
);
677 PLAppendArrayElement(state
, PLMakeString(buffer
));
680 sprintf(buffer
, "%i %i %i", wwin
->flags
.miniaturized
,
681 wwin
->flags
.shaded
, wwin
->flags
.maximized
);
682 PLAppendArrayElement(state
, PLMakeString(buffer
));
685 PLAppendArrayElement(state
, makeAttributeState(wwin
));
688 sprintf(buffer
, "%i", wwin
->frame
->workspace
);
689 PLAppendArrayElement(state
, PLMakeString(buffer
));
691 /* app state (repeated for all windows of the app) */
692 PLAppendArrayElement(state
, makeAppState(wwin
));
695 tmp
= PLMakeArrayWithElements(NULL
, NULL
);
697 for (i
= 0; i
< MAX_WINDOW_SHORTCUTS
; i
++) {
699 if (scr
->shortcutWindow
[i
] == wwin
) {
701 sprintf(buffer
, "%i", i
);
702 PLAppendArrayElement(tmp
, PLMakeString(buffer
));
705 PLAppendArrayElement(state
, tmp
);
712 smSaveYourselfPhase2Proc(SmcConn smc_conn
, SmPointer client_data
)
715 SmPropValue prop1val
, prop2val
, prop3val
, prop4val
;
716 char **argv
= (char**)client_data
;
720 char *statefile
= NULL
;
722 Bool gsPrefix
= False
;
723 char *discardCmd
= NULL
;
728 puts("received SaveYourselfPhase2 SM message");
731 /* save session state */
733 /* the file that will contain the state */
734 prefix
= getenv("SM_SAVE_DIR");
736 prefix
= wusergnusteppath();
741 prefix
= getenv("HOME");
746 statefile
= malloc(strlen(prefix
)+64);
750 wwarning(_("end of memory while saving session state"));
758 sprintf(statefile
, "%s/.AppInfo/WindowMaker/%l%i.state",
761 sprintf(statefile
, "%s/wmaker.%l%i.state", prefix
, t
, i
);
763 } while (access(F_OK
, statefile
)!=-1);
768 /* save the states of all windows we're managing */
769 state
= PLMakeArrayFromElements(NULL
, NULL
);
774 * state_file ::= dictionary with version_info ; state
775 * version_info ::= 'version' = '1';
776 * state ::= 'state' = array of screen_info
777 * screen_info ::= array of (screen number, window_info, window_info, ...)
780 for (i
=0; i
<wScreenCount
; i
++) {
786 scr
= wScreenWithNumber(i
);
788 sprintf(buf
, "%i", scr
->screen
);
789 pscreen
= PLMakeArrayFromElements(PLMakeString(buf
), NULL
);
791 wwin
= scr
->focused_window
;
795 pwindow
= makeClientState(wwin
);
796 PLAppendArrayElement(pscreen
, pwindow
);
801 PLAppendArrayElement(state
, pscreen
);
805 proplist_t statefile
;
807 statefile
= PLMakeDictionaryFromEntries(PLMakeString("Version"),
810 PLMakeString("Screens"),
815 PLSetFilename(statefile
, PLMakeString(statefile
));
816 PLSave(statefile
, NO
);
818 PLRelease(statefile
);
821 /* set the remaining properties that we didn't set at
824 for (argc
=0, i
=0; argv
[i
]!=NULL
; i
++) {
825 if (strcmp(argv
[i
], "-clientid")==0
826 || strcmp(argv
[i
], "-restore")==0) {
833 prop
[0].name
= SmRestartCommand
;
834 prop
[0].type
= SmLISTofARRAY8
;
835 prop
[0].vals
= malloc(sizeof(SmPropValue
)*(argc
+4));
836 prop
[0].num_vals
= argc
+4;
838 prop
[1].name
= SmCloneCommand
;
839 prop
[1].type
= SmLISTofARRAY8
;
840 prop
[1].vals
= malloc(sizeof(SmPropValue
)*(argc
));
841 prop
[1].num_vals
= argc
;
843 if (!prop
[0].vals
|| !prop
[1].vals
) {
844 wwarning(_("end of memory while saving session state"));
848 for (j
=0, i
=0; i
<argc
+4; i
++) {
849 if (strcmp(argv
[i
], "-clientid")==0
850 || strcmp(argv
[i
], "-restore")==0) {
853 prop
[0].vals
[j
].value
= argv
[i
];
854 prop
[0].vals
[j
].length
= strlen(argv
[i
]);
855 prop
[1].vals
[j
].value
= argv
[i
];
856 prop
[1].vals
[j
].length
= strlen(argv
[i
]);
860 prop
[0].vals
[j
].value
= "-clientid";
861 prop
[0].vals
[j
].length
= 9;
863 prop
[0].vals
[j
].value
= sClientID
;
864 prop
[0].vals
[j
].length
= strlen(sClientID
);
866 prop
[0].vals
[j
].value
= "-restore";
867 prop
[0].vals
[j
].length
= 11;
869 prop
[0].vals
[j
].value
= statefile
;
870 prop
[0].vals
[j
].length
= strlen(statefile
);
872 discardCmd
= malloc(strlen(statefile
)+8);
875 sprintf(discardCmd
, "rm %s", statefile
);
876 prop
[2].name
= SmDiscardCommand
;
877 prop
[2].type
= SmARRAY8
;
878 prop
[2].vals
[0] = discardCmd
;
879 prop
[2].num_vals
= 1;
881 SmcSetProperties(sSMCConn
, 3, prop
);
885 SmcSaveYourselfDone(smc_conn
, ok
);
903 smSaveYourselfProc(SmcConn smc_conn
, SmPointer client_data
, int save_type
,
904 Bool shutdown
, int interact_style
, Bool fast
)
907 puts("received SaveYourself SM message");
910 if (!SmcRequestSaveYourselfPhase2(smc_conn
, smSaveYourselfPhase2Proc
,
913 SmcSaveYourselfDone(smc_conn
, False
);
914 sWaitingPhase2
= False
;
917 puts("successfull request of SYS phase 2");
919 sWaitingPhase2
= True
;
925 smDieProc(SmcConn smc_conn
, SmPointer client_data
)
928 puts("received Die SM message");
931 wSessionDisconnectManager();
933 Shutdown(WSExitMode
);
939 smSaveCompleteProc(SmcConn smc_conn
)
941 /* it means that we can resume doing things that can change our state */
943 puts("received SaveComplete SM message");
949 smShutdownCancelledProc(SmcConn smc_conn
, SmPointer client_data
)
951 if (sWaitingPhase2
) {
953 sWaitingPhase2
= False
;
955 SmcSaveYourselfDone(smc_conn
, False
);
961 iceMessageProc(int fd
, int mask
, void *clientData
)
963 IceConn iceConn
= (IceConn
)clientData
;
965 IceProcessMessages(iceConn
, NULL
, NULL
);
970 iceIOErrorHandler(IceConnection ice_conn
)
972 /* This is not fatal but can mean the session manager exited.
973 * If the session manager exited normally we would get a
974 * Die message, so this probably means an abnormal exit.
975 * If the sm was the last client of session, then we'll die
976 * anyway, otherwise we can continue doing our stuff.
978 wwarning(_("connection to the session manager was lost"));
979 wSessionDisconnectManager();
984 wSessionConnectManager(char **argv
, int argc
)
987 char *previous_id
= NULL
;
989 SmcCallbacks callbacks
;
994 SmPropValue prop1val
, prop2val
, prop3val
, prop4val
;
998 mask
= SmcSaveYourselfProcMask
|SmcDieProcMask
|SmcSaveCompleteProcMask
999 |SmcShutdownCancelledProcMask
;
1001 callbacks
.save_yourself
.callback
= smSaveYourselfProc
;
1002 callbacks
.save_yourself
.client_data
= argv
;
1004 callbacks
.die
.callback
= smDieProc
;
1005 callbacks
.die
.client_data
= NULL
;
1007 callbacks
.save_complete
.callback
= smSaveCompleteProc
;
1008 callbacks
.save_complete
.client_data
= NULL
;
1010 callbacks
.shutdown_cancelled
.callback
= smShutdownCancelledProc
;
1011 callbacks
.shutdown_cancelled
.client_data
= NULL
;
1013 for (i
=0; i
<argc
; i
++) {
1014 if (strcmp(argv
[i
], "-clientid")==0) {
1015 previous_id
= argv
[i
+1];
1020 /* connect to the session manager */
1021 sSMCConn
= SmcOpenConnection(NULL
, NULL
, SmProtoMajor
, SmProtoMinor
,
1022 mask
, &callbacks
, previous_id
,
1023 &sClientID
, 255, buffer
);
1028 puts("connected to the session manager");
1031 /* IceSetIOErrorHandler(iceIOErrorHandler);*/
1033 /* check for session manager clients */
1034 iceConn
= SmcGetIceConnection(smcConn
);
1036 if (fcntl(IceConnectionNumber(iceConn
), F_SETFD
, FD_CLOEXEC
) < 0) {
1037 wsyserror("error setting close-on-exec flag for ICE connection");
1040 sSMInputHandler
= WMAddInputHandler(IceConnectionNumber(iceConn
),
1041 WIReadMask
, iceMessageProc
, iceConn
);
1043 /* setup information about ourselves */
1046 prop1val
.value
= argv
[0];
1047 prop1val
.length
= strlen(argv
[0]);
1048 prop
[0].name
= SmProgram
;
1049 prop
[0].type
= SmARRAY8
;
1050 prop
[0].num_vals
= 1;
1051 prop
[0].vals
= &prop1val
;
1053 /* The XSMP doc from X11R6.1 says it contains the user name,
1054 * but every client implementation I saw places the uid # */
1055 sprintf(uid
, "%i", getuid());
1056 prop2val
.value
= uid
;
1057 prop2val
.length
= strlen(uid
);
1058 prop
[1].name
= SmUserID
;
1059 prop
[1].type
= SmARRAY8
;
1060 prop
[1].num_vals
= 1;
1061 prop
[1].vals
= &prop2val
;
1063 /* Restart style. We should restart only if we were running when
1064 * the previous session finished. */
1065 restartStyle
= SmRestartIfRunning
;
1066 prop3val
.value
= &restartStyle
;
1067 prop3val
.length
= 1;
1068 prop
[2].name
= SmRestartStyleHint
;
1069 prop
[2].type
= SmCARD8
;
1070 prop
[2].num_vals
= 1;
1071 prop
[2].vals
= &prop3val
;
1073 /* Our PID. Not required but might be usefull */
1074 sprintf(pid
, "%i", getpid());
1075 prop4val
.value
= pid
;
1076 prop4val
.length
= strlen(pid
);
1077 prop
[3].name
= SmProcessID
;
1078 prop
[3].type
= SmARRAY8
;
1079 prop
[3].num_vals
= 1;
1080 prop
[3].vals
= &prop4val
;
1082 /* we'll set the rest of the hints later */
1084 SmcSetProperties(sSMCConn
, 4, props
);
1090 wSessionDisconnectManager(void)
1093 WMDeleteInputHandler(sSMInputHandler
);
1094 sSMInputHandler
= NULL
;
1096 SmcCloseConnection(sSMCConn
, 0, NULL
);
1102 wSessionRequestShutdown(void)
1104 /* request a shutdown to the session manager */
1106 SmcRequestSaveYourself(sSMCConn
, SmSaveBoth
, True
, SmInteractStyleAny
,
1111 wSessionIsManaged(void)
1113 return sSMCConn
!=NULL
;