Subject: Session Management

From: Matthias Clasen <[email-masked]>
Date: Tue, 9 Feb 1999 01:23:34 +0100

Here is another thing to (maybe) add after 2.2: Session Management.

I have started putting together a prototype implementation by 
adapting file session.c from Enlightenment. There are still some issues,
eg offscreen windows are not properly placed, no global configuration
is saved; but apart from that it seems to work. It is a bit hard for me 
to do proper testing, since the only SMP-aware client on my home machine
seems to be xclock.  

Matthias

diff -cN ../fvwm-2.1.11/fvwm/Makefile.am fvwm/Makefile.am
*** ../fvwm-2.1.11/fvwm/Makefile.am	Wed Jan 20 02:50:14 1999
--- fvwm/Makefile.am	Tue Feb  9 00:59:20 1999
***************
*** 5,11 ****
  EXTRA_DIST = $(man_MANS)
  man_MANS = fvwm2.1
  
! fvwm2_SOURCES = add_window.c bindings.c borders.c \
  builtins.c colormaps.c colors.c complex.c decorations.c defaults.h \
  events.c focus.c functions.c fvwm.c fvwm.h fvwmdebug.c fvwmdebug.h icons.c \
  menus.c menus.h misc.c misc.h modconf.c module.c module.h move.c \
--- 5,11 ----
  EXTRA_DIST = $(man_MANS)
  man_MANS = fvwm2.1
  
! fvwm2_SOURCES = session.c add_window.c bindings.c borders.c \
  builtins.c colormaps.c colors.c complex.c decorations.c defaults.h \
  events.c focus.c functions.c fvwm.c fvwm.h fvwmdebug.c fvwmdebug.h icons.c \
  menus.c menus.h misc.c misc.h modconf.c module.c module.h move.c \
diff -cN ../fvwm-2.1.11/fvwm/Makefile.in fvwm/Makefile.in
*** ../fvwm-2.1.11/fvwm/Makefile.in	Tue Feb  2 18:02:24 1999
--- fvwm/Makefile.in	Tue Feb  9 00:59:35 1999
***************
*** 88,94 ****
  EXTRA_DIST = $(man_MANS)
  man_MANS = fvwm2.1
  
! fvwm2_SOURCES = add_window.c bindings.c borders.c builtins.c colormaps.c colors.c complex.c decorations.c defaults.h events.c focus.c functions.c fvwm.c fvwm.h fvwmdebug.c fvwmdebug.h icons.c menus.c menus.h misc.c misc.h modconf.c module.c module.h move.c parse.h placement.c read.c resize.c screen.h style.c virtual.c windows.c

  fvwm2_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a
--- 88,94 ----
  EXTRA_DIST = $(man_MANS)
  man_MANS = fvwm2.1
  
! fvwm2_SOURCES = session.c add_window.c bindings.c borders.c builtins.c colormaps.c colors.c complex.c decorations.c defaults.h events.c focus.c functions.c fvwm.c fvwm.h fvwmdebug.c fvwmdebug.h icons.c menus.c menus.h misc.c misc.h modconf.c module.c module.h move.c parse.h placement.c read.c resize.c screen.h style.c virtual.c windows.c

  fvwm2_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a
***************
*** 111,117 ****
  X_LIBS = @X_LIBS@
  X_EXTRA_LIBS = @X_EXTRA_LIBS@
  X_PRE_LIBS = @X_PRE_LIBS@
! fvwm2_OBJECTS =  add_window.o bindings.o borders.o builtins.o \
  colormaps.o colors.o complex.o decorations.o events.o focus.o \
  functions.o fvwm.o fvwmdebug.o icons.o menus.o misc.o modconf.o \
  module.o move.o placement.o read.o resize.o style.o virtual.o windows.o
--- 111,117 ----
  X_LIBS = @X_LIBS@
  X_EXTRA_LIBS = @X_EXTRA_LIBS@
  X_PRE_LIBS = @X_PRE_LIBS@
! fvwm2_OBJECTS =  session.o add_window.o bindings.o borders.o builtins.o \
  colormaps.o colors.o complex.o decorations.o events.o focus.o \
  functions.o fvwm.o fvwmdebug.o icons.o menus.o misc.o modconf.o \
  module.o move.o placement.o read.o resize.o style.o virtual.o windows.o
***************
*** 132,137 ****
--- 132,144 ----
  
  TAR = tar
  GZIP_ENV = --best
+ DEP_FILES =  .deps/add_window.P .deps/bindings.P .deps/borders.P \
+ .deps/builtins.P .deps/colormaps.P .deps/colors.P .deps/complex.P \
+ .deps/decorations.P .deps/events.P .deps/focus.P .deps/functions.P \
+ .deps/fvwm.P .deps/fvwmdebug.P .deps/icons.P .deps/menus.P .deps/misc.P \
+ .deps/modconf.P .deps/module.P .deps/move.P .deps/placement.P \
+ .deps/read.P .deps/resize.P .deps/session.P .deps/style.P \
+ .deps/virtual.P .deps/windows.P
  SOURCES = $(fvwm2_SOURCES)
  OBJECTS = $(fvwm2_OBJECTS)
  
***************
*** 139,147 ****
  .SUFFIXES:
  .SUFFIXES: .S .c .o .s
  $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
! 	cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps fvwm/Makefile
  
! Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
  	cd $(top_builddir) \
  	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
  
--- 146,154 ----
  .SUFFIXES:
  .SUFFIXES: .S .c .o .s
  $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
! 	cd $(top_srcdir) && $(AUTOMAKE) --gnu fvwm/Makefile
  
! Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
  	cd $(top_builddir) \
  	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
  
***************
*** 171,179 ****
  	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
  	done
  
- .c.o:
- 	$(COMPILE) -c $<
- 
  .s.o:
  	$(COMPILE) -c $<
  
--- 178,183 ----
***************
*** 267,272 ****
--- 271,281 ----
  subdir = fvwm
  
  distdir: $(DISTFILES)
+ 	here=`cd $(top_builddir) && pwd`; \
+ 	top_distdir=`cd $(top_distdir) && pwd`; \
+ 	distdir=`cd $(distdir) && pwd`; \
+ 	cd $(top_srcdir) \
+ 	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu fvwm/Makefile
  	@for file in $(DISTFILES); do \
  	  d=$(srcdir); \
  	  if test -d $$d/$$file; then \
***************
*** 277,329 ****
  	    || cp -p $$d/$$file $(distdir)/$$file || :; \
  	  fi; \
  	done
- add_window.o: add_window.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h screen.h misc.h defaults.h menus.h module.h
- bindings.o: bindings.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	misc.h defaults.h menus.h parse.h screen.h module.h
- borders.o: borders.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	misc.h defaults.h menus.h parse.h screen.h module.h
- colormaps.o: colormaps.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h misc.h defaults.h menus.h parse.h screen.h module.h
- colors.o: colors.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h
- complex.o: complex.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- decorations.o: decorations.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h misc.h defaults.h menus.h screen.h parse.h \
- 	../libs/lang-strings.h
- events.o: events.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- focus.o: focus.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- functions.o: functions.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h menus.h misc.h defaults.h parse.h screen.h module.h
- fvwmdebug.o: fvwmdebug.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h
- icons.o: icons.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h misc.h \
- 	defaults.h menus.h parse.h screen.h module.h
- menus.o: menus.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h
- misc.o: misc.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h menus.h \
- 	misc.h defaults.h parse.h screen.h module.h
- modconf.o: modconf.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- module.o: module.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- move.o: move.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h menus.h \
- 	misc.h defaults.h parse.h screen.h module.h
- placement.o: placement.c ../config.h fvwm.h ../libs/fvwmlib.h \
- 	fvwmdebug.h menus.h misc.h defaults.h parse.h screen.h
- resize.o: resize.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	misc.h defaults.h menus.h screen.h parse.h
- style.o: style.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h
- virtual.o: virtual.c ../config.h fvwm.h ../libs/fvwmlib.h fvwmdebug.h \
- 	menus.h misc.h defaults.h parse.h screen.h module.h
- windows.o: windows.c ../config.h ../libs/fvwmlib.h fvwm.h \
- 	../libs/fvwmlib.h fvwmdebug.h menus.h misc.h defaults.h parse.h \
- 	screen.h
  
  info-am:
  info: info-am
  dvi-am:
--- 286,323 ----
  	    || cp -p $$d/$$file $(distdir)/$$file || :; \
  	  fi; \
  	done
  
+ DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+ 
+ -include $(DEP_FILES)
+ 
+ mostlyclean-depend:
+ 
+ clean-depend:
+ 
+ distclean-depend:
+ 	-rm -rf .deps
+ 
+ maintainer-clean-depend:
+ 
+ %.o: %.c
+ 	@echo '$(COMPILE) -c $<'; \
+ 	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ 	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+ 	tr ' ' '\012' < .deps/$(*F).pp \
+ 	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ 	    >> .deps/$(*F).P; \
+ 	rm .deps/$(*F).pp
+ 
+ %.lo: %.c
+ 	@echo '$(LTCOMPILE) -c $<'; \
+ 	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ 	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+ 	  < .deps/$(*F).pp > .deps/$(*F).P; \
+ 	tr ' ' '\012' < .deps/$(*F).pp \
+ 	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ 	    >> .deps/$(*F).P; \
+ 	rm -f .deps/$(*F).pp
  info-am:
  info: info-am
  dvi-am:
***************
*** 361,383 ****
  
  maintainer-clean-generic:
  mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
! 		mostlyclean-tags mostlyclean-generic
  
  mostlyclean: mostlyclean-am
  
! clean-am:  clean-binPROGRAMS clean-compile clean-tags clean-generic \
! 		mostlyclean-am
  
  clean: clean-am
  
  distclean-am:  distclean-binPROGRAMS distclean-compile distclean-tags \
! 		distclean-generic clean-am
  
  distclean: distclean-am
  
  maintainer-clean-am:  maintainer-clean-binPROGRAMS \
  		maintainer-clean-compile maintainer-clean-tags \
! 		maintainer-clean-generic distclean-am
  	@echo "This command is intended for maintainers to use;"
  	@echo "it deletes files that may require special tools to rebuild."
  
--- 355,378 ----
  
  maintainer-clean-generic:
  mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
! 		mostlyclean-tags mostlyclean-depend mostlyclean-generic
  
  mostlyclean: mostlyclean-am
  
! clean-am:  clean-binPROGRAMS clean-compile clean-tags clean-depend \
! 		clean-generic mostlyclean-am
  
  clean: clean-am
  
  distclean-am:  distclean-binPROGRAMS distclean-compile distclean-tags \
! 		distclean-depend distclean-generic clean-am
  
  distclean: distclean-am
  
  maintainer-clean-am:  maintainer-clean-binPROGRAMS \
  		maintainer-clean-compile maintainer-clean-tags \
! 		maintainer-clean-depend maintainer-clean-generic \
! 		distclean-am
  	@echo "This command is intended for maintainers to use;"
  	@echo "it deletes files that may require special tools to rebuild."
  
***************
*** 388,395 ****
  mostlyclean-compile distclean-compile clean-compile \
  maintainer-clean-compile install-man1 uninstall-man1 install-man \
  uninstall-man tags mostlyclean-tags distclean-tags clean-tags \
! maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
! installcheck-am installcheck install-exec-am install-exec \
  install-data-am install-data install-am install uninstall-am uninstall \
  all-redirect all-am all installdirs mostlyclean-generic \
  distclean-generic clean-generic maintainer-clean-generic clean \
--- 383,391 ----
  mostlyclean-compile distclean-compile clean-compile \
  maintainer-clean-compile install-man1 uninstall-man1 install-man \
  uninstall-man tags mostlyclean-tags distclean-tags clean-tags \
! maintainer-clean-tags distdir mostlyclean-depend distclean-depend \
! clean-depend maintainer-clean-depend info-am info dvi-am dvi check \
! check-am installcheck-am installcheck install-exec-am install-exec \
  install-data-am install-data install-am install uninstall-am uninstall \
  all-redirect all-am all installdirs mostlyclean-generic \
  distclean-generic clean-generic maintainer-clean-generic clean \
diff -cN ../fvwm-2.1.11/fvwm/add_window.c fvwm/add_window.c
*** ../fvwm-2.1.11/fvwm/add_window.c	Tue Jan 12 22:07:41 1999
--- fvwm/add_window.c	Mon Feb  8 23:48:24 1999
***************
*** 117,122 ****
--- 117,124 ----
    tmp_win->flags = 0;
    tmp_win->tmpflags.ViewportMoved = 0;
    tmp_win->tmpflags.IconifiedByParent = 0;
+   tmp_win->tmpflags.startMaximized = 0;
+   tmp_win->tmpflags.startShaded = 0;
    tmp_win->w = w;
  
    tmp_win->cmap_windows = (Window *)NULL;
***************
*** 400,405 ****
--- 402,415 ----
    tmp_win->stack_prev = &Scr.FvwmRoot;
    Scr.FvwmRoot.stack_next = tmp_win;
  
+   /* 
+       MatchWinToSM changes tmp_win->attr and tmp_win->stack_{prev,next}.
+       Thus it is important have this call *after* PlaceWindow and the
+       stacking order initialization.
+   */
+ 
+   SessionGetInfo(tmp_win);
+   MatchWinToSM(tmp_win);
  
    /* create windows */
    tmp_win->frame_x = tmp_win->attr.x + tmp_win->old_bw - tmp_win->bw;
***************
*** 667,672 ****
--- 678,694 ----
    tmp_win->frame_height = 0;
    SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,width,height, True);
  
+ /* the start... flags are set by MatchWinToSM earlier */
+   if (tmp_win->tmpflags.startShaded) {
+     fprintf(stderr, "trying to shade...\n");
+     WindowShade(&Event, tmp_win->w, tmp_win, C_WINDOW, "", 0);
+   }
+ 
+   if (tmp_win->tmpflags.startMaximized) {
+     fprintf(stderr, "trying to maximize...\n");
+     Maximize(&Event, tmp_win->w, tmp_win, C_WINDOW, "", 0);
+   }
+   
    /* wait until the window is iconified and the icon window is mapped
     * before creating the icon window
     */
***************
*** 695,701 ****
--- 717,739 ----
  	  XSaveContext(dpy,tmp_win->corners[i],FvwmContext, (caddr_t) tmp_win);
  	}
      }
+ #if 0
    RaiseWindow(tmp_win);
+ #else
+   { 
+     XWindowChanges xwc;
+     unsigned long vm;
+     if (tmp_win->stack_next == &Scr.FvwmRoot) {
+       xwc.stack_mode = Below;
+       vm = CWStackMode;
+     } else {
+       xwc.sibling = tmp_win->stack_next->frame;
+       xwc.stack_mode = Above;
+       vm = CWSibling|CWStackMode;
+     }
+     XConfigureWindow(dpy, tmp_win->frame, vm, &xwc);
+   }
+ #endif
    KeepOnTop();
    MyXUngrabServer(dpy);
  
diff -cN ../fvwm-2.1.11/fvwm/events.c fvwm/events.c
*** ../fvwm-2.1.11/fvwm/events.c	Wed Jan 27 20:11:49 1999
--- fvwm/events.c	Sun Feb  7 01:57:35 1999
***************
*** 453,458 ****
--- 453,459 ----
        OnThisPage  =  True;
      }
  
+   SessionGetInfo (Tmp_win);
    switch (Event.xproperty.atom)
      {
      case XA_WM_TRANSIENT_FOR:
***************
*** 1554,1562 ****
--- 1555,1566 ----
    fd_set in_fdset, out_fdset;
    Window targetWindow;
    int i;
+   int smfd;
  
    DBUG("My_XNextEvent","Routine Entered");
  
+   smfd = GetSMfd();
+ 
    /* Do this IMMEDIATELY prior to select, to prevent any nasty
     * queued up X events from just hanging around waiting to be
     * flushed */
***************
*** 1577,1582 ****
--- 1581,1588 ----
  
    FD_ZERO(&in_fdset);
    FD_SET(x_fd,&in_fdset);
+   if (smfd >= 0)
+     FD_SET(smfd, &in_fdset);
    FD_ZERO(&out_fdset);
    for(i=0; i<npipes; i++)
      {
***************
*** 1627,1632 ****
--- 1633,1642 ----
  	    }
  	}
      } /* for */
+ 
+   if ((smfd >= 0) && (FD_ISSET(smfd, &in_fdset)))
+     ProcessICEMSGS();
+ 
    }
    DBUG("My_XNextEvent","leaving My_XNextEvent");
    return 0;
diff -cN ../fvwm-2.1.11/fvwm/fvwm.c fvwm/fvwm.c
*** ../fvwm-2.1.11/fvwm/fvwm.c	Wed Jan 27 20:11:49 1999
--- fvwm/fvwm.c	Tue Feb  9 00:37:46 1999
***************
*** 165,170 ****
--- 165,176 ----
      {
        debugging = True;
      }
+     else if (strncasecmp(argv[i], "-smid", 5) == 0)
+       {
+ 	if (++i >= argc)
+ 	  usage();
+ 	SetSMID(argv[i]);
+       }
      else if (strncasecmp(argv[i],"-s",2)==0)
      {
        single = True;
***************
*** 409,414 ****
--- 415,422 ----
    XSync(dpy, 0);
  
    XSetErrorHandler(FvwmErrorHandler);
+ 
+   SessionInit();
  
    BlackoutScreen(); /* if they want to hide the capture/startup */
  
diff -cN ../fvwm-2.1.11/fvwm/fvwm.h fvwm/fvwm.h
*** ../fvwm-2.1.11/fvwm/fvwm.h	Tue Jan 12 22:07:42 1999
--- fvwm/fvwm.h	Mon Feb  8 21:51:03 1999
***************
*** 249,254 ****
--- 249,256 ----
        unsigned ViewportMoved : 1; /* To prevent double move in MoveViewport. */
        unsigned IconifiedByParent : 1; /* To prevent iconified transients in a
  				       * parent icon from counting for Next */
+       unsigned startMaximized : 1;
+       unsigned startShaded : 1;
      } tmpflags;
  #endif /* GSFR */
  
***************
*** 275,280 ****
--- 277,286 ----
      Pixel BackPixel;
      unsigned long buttons;
      icon_boxes *IconBoxes;              /* zero or more iconboxes */
+ 
+   char *session_id;
+   char *role;
+   char *command;
  } FvwmWindow;
  
  /* Window mask for Circulate and Direction functions */
diff -cN ../fvwm-2.1.11/fvwm/misc.h fvwm/misc.h
*** ../fvwm-2.1.11/fvwm/misc.h	Tue Jan 12 22:07:43 1999
--- fvwm/misc.h	Sun Feb  7 00:04:23 1999
***************
*** 484,488 ****
--- 484,499 ----
  #define ERR  2
  void fvwm_msg(int type,char *id,char *msg,...);
  
+ /* session management adapted from enlightenment */
+ void SessionInit(void);
+ void ProcessICEMSGS(void);
+ int GetSMfd(void);
+ void SessionGetInfo(FvwmWindow *t);
+ void SetSMID(char *smid);
+ void MatchWinToSM(FvwmWindow *t);
+ char *GetSMID(void);
+ 
  #endif /* MISC_H */
+ 
+ 
  
diff -cN ../fvwm-2.1.11/fvwm/session.c fvwm/session.c
*** ../fvwm-2.1.11/fvwm/session.c	Thu Jan  1 01:00:00 1970
--- fvwm/session.c	Tue Feb  9 01:00:52 1999
***************
*** 0 ****
--- 1,645 ----
+ /* 
+  This file is more or less completely taken from Enlightenment.
+  */
+ #include "config.h"
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <pwd.h>
+ #include <sys/types.h>
+ #include <signal.h>
+ #include "fvwm.h"
+ #include <X11/Xatom.h>
+ #include "screen.h"
+ #include "misc.h"
+  
+ #include <X11/SM/SMlib.h>
+ 
+ extern int master_pid;
+ 
+ 
+ typedef struct _match
+   {
+      char               *session_id;
+      char               *name;
+      char               *class;
+      char               *role;
+      char                used;
+      int                 x, y, w, h; 
+      int                 icon_x, icon_y;
+      int                 desktop, iconified, shaded, maximized, sticky;
+   }
+ Match;
+ 
+ static char        *sm_client_id = NULL;
+ SmcConn             sm_conn = NULL;
+ int                 sm_fd = -1;
+ static int          num_match = 0;
+ Match              *matches = NULL;
+ 
+ static void         set_save_props(SmcConn smc_conn);
+ static void         callback_save_yourself2(SmcConn smc_conn, SmPointer client_data);
+ static void         callback_save_yourself(SmcConn smc_conn, SmPointer client_data,
+ 			    int save_style, Bool shutdown, int interact_style,
+ 					   Bool fast);
+ static void         callback_die(SmcConn smc_conn, SmPointer client_data);
+ static void         callback_save_complete(SmcConn smc_conn, SmPointer client_data);
+ static void         callback_shutdown_cancelled(SmcConn smc_conn, SmPointer client_data);
+ 
+ static void         SaveWindowStates(void);
+ static void         LoadWindowStates(void);
+ 
+ extern char **g_argv;
+ 
+ static void
+ set_save_props(SmcConn smc_conn)
+ {
+    char               *user = NULL;
+    char               *program = "fvwm2";
+    char               *pristr = "Priority";
+    char                smid[] = "-smid";
+    char                priority = 10;
+    
+    char *command = g_argv[0];
+    struct passwd       *pwd;
+ 
+    SmPropValue         programVal =
+    {0, NULL};
+    SmPropValue         userIDVal =
+    {0, NULL};
+    SmPropValue         restartVal[3] =
+    {
+       {0, NULL},
+       {0, NULL},
+       {0, NULL}};
+    SmPropValue         priorityVal =
+    {0, NULL};
+    SmProp              programProp;
+    SmProp              userIDProp;
+    SmProp              restartProp;
+    SmProp              cloneProp;
+    SmProp              priorityProp;
+    SmProp             *props[5];
+ 
+    programProp.name = (char *)SmProgram;
+    programProp.type = (char *)SmLISTofARRAY8;
+    programProp.num_vals = 1;
+    programProp.vals = &programVal;
+ 
+    userIDProp.name = (char *)SmUserID;
+    userIDProp.type = (char *)SmLISTofARRAY8;
+    userIDProp.num_vals = 1;
+    userIDProp.vals = &userIDVal;
+ 
+    restartProp.name = (char *)SmRestartCommand;
+    restartProp.type = (char *)SmLISTofARRAY8;
+    restartProp.num_vals = 3;
+    restartProp.vals = (SmPropValue *) & restartVal;
+ 
+    cloneProp.name = (char *)SmCloneCommand;
+    cloneProp.type = (char *)SmLISTofARRAY8;
+    cloneProp.num_vals = 3;
+    cloneProp.vals = (SmPropValue *) & restartVal;
+ 
+    priorityProp.name = (char *)pristr;
+    priorityProp.type = (char *)SmCARD8;
+    priorityProp.num_vals = 1;
+    priorityProp.vals = (SmPropValue *) & priorityVal;
+ 
+    props[0] = &programProp;
+    props[1] = &userIDProp;
+    props[2] = &restartProp;
+    props[3] = &cloneProp;
+    props[4] = &priorityProp;
+ 
+    pwd = getpwuid(getuid());
+    user = pwd->pw_name;
+    userIDVal.length = strlen(user);
+    userIDVal.value = user;
+    programVal.length = strlen(program);
+    programVal.value = program;
+    restartVal[0].length = strlen(command);
+    restartVal[0].value = command;
+    restartVal[1].length = strlen(smid);
+    restartVal[1].value = smid;
+    restartVal[2].length = strlen(sm_client_id);
+    restartVal[2].value = sm_client_id;
+    priorityVal.length = 1;
+    priorityVal.value = &priority;
+    SmcSetProperties(smc_conn, sizeof(props) / sizeof(props[0]), (SmProp **) & props);
+ }
+ 
+ static void
+ SaveWindowStates(void)
+ {
+   FvwmWindow              *ewin;
+   int                 i, num, x, y;
+   FILE               *f;
+   char                s[4096];
+   int uid;
+   struct passwd      *pwd;
+ 
+   pwd = getpwuid(getuid());
+ 
+   if (sm_client_id)
+     snprintf(s, sizeof(s), "%s/.fvwm_clients_save.%s.%i", pwd->pw_dir, sm_client_id, Scr.screen);
+   else
+     snprintf(s, sizeof(s), "%s/.fvwm_clients_save.%i", pwd->pw_dir, Scr.screen);
+ 
+   f = fopen(s, "w");
+   if (f)
+     {
+       for (ewin=Scr.FvwmRoot.stack_next; ewin!=&Scr.FvwmRoot; ewin=ewin->stack_next) 
+ 	{
+ 	  if (ewin->session_id)
+ 	    {
+ 	      /* MUST have SESSION_ID to even try session manage it */
+ 	      fprintf(f, "[CLIENT] %i %i %i %i %i %i %i %i %i %i %i\n",
+ 		      ewin->orig_x - ewin->old_bw + ewin->bw,
+                       ewin->orig_y - ewin->old_bw + ewin->bw,
+ 		      ewin->orig_wd - 2*ewin->boundary_width , 
+                       ewin->orig_ht  - 2*ewin->boundary_width - ewin->title_height, 
+                       ewin->icon_x_loc,
+                       ewin->icon_y_loc,
+ 		      ewin->Desk, 
+                       !!(ewin->flags & ICONIFIED), 
+ 		      !!(ewin->buttons & WSHADE), 
+                       !!(ewin->flags & MAXIMIZED),
+ 		      !!(ewin->flags & STICKY) );
+ 	      fprintf(f, "  [SESSION_ID] %s\n", ewin->session_id);
+ 	      if (ewin->class.res_name)
+ 		fprintf(f, "  [NAME] %s\n", ewin->class.res_name);
+ 	      if (ewin->class.res_class)
+ 		fprintf(f, "  [CLASS] %s\n", ewin->class.res_class);
+ 	      if (ewin->role)
+ 		fprintf(f, "  [ROLE] %s\n", ewin->role);
+ 	      if (ewin->command)
+ 		fprintf(f, "  [COMMAND] %s\n", ewin->command);
+ 	      if (ewin->name)
+ 		fprintf(f, "  [TITLE] %s\n", ewin->name);
+ 	    }
+ 	}
+     }
+   fclose(f);
+ }
+ 
+ char *duplicate(char *s)
+ {
+   int l;
+   char *r;
+ 
+   if (!s) return NULL;
+   l = strlen(s);
+   r = (char *) malloc (sizeof(char)*(l+1));
+   strncpy(r, s, l+1);
+   return r;
+ }
+ 
+ static void
+ LoadWindowStates(void)
+ {
+    FILE               *f;
+    char                s[4096], s1[4096];
+ 
+   struct passwd      *pwd;
+ 
+   fprintf(stderr, "LoadWindowStates...\n");
+   pwd = getpwuid(getuid());
+ 
+    if (sm_client_id)
+      snprintf(s, sizeof(s), "%s/.fvwm_clients_save.%s.%i", pwd->pw_dir, sm_client_id, Scr.screen);
+    else
+      snprintf(s, sizeof(s), "%s/.fvwm_clients_save.%i", pwd->pw_dir, Scr.screen);
+ 
+    f = fopen(s, "r");
+    if (f)
+      {
+        while (fgets(s, sizeof(s), f))
+ 	 {
+ 	   sscanf(s, "%4000s", s1);
+ 	   if (!strcmp(s1, "[CLIENT]"))
+ 	     {
+ 	       num_match++;
+ 	       matches = realloc(matches, sizeof(Match) * num_match);
+ 	       matches[num_match - 1].session_id = NULL;
+ 	       matches[num_match - 1].name = NULL;
+ 	       matches[num_match - 1].class = NULL;
+ 	       matches[num_match - 1].role = NULL;
+ 	       matches[num_match - 1].used = 0;
+ 	       sscanf(s, "%*s %i %i %i %i %i %i %i %i %i %i %i",
+ 		      &(matches[num_match - 1].x),
+ 		      &(matches[num_match - 1].y),
+ 		      &(matches[num_match - 1].w),
+ 		      &(matches[num_match - 1].h),
+ 		      &(matches[num_match - 1].icon_x),
+ 		      &(matches[num_match - 1].icon_y),
+ 		      &(matches[num_match - 1].desktop),
+ 		      &(matches[num_match - 1].iconified),
+ 		      &(matches[num_match - 1].shaded),
+ 		      &(matches[num_match - 1].maximized),
+ 		      &(matches[num_match - 1].sticky)
+ 		      );
+ 	     }
+ 	   else if (!strcmp(s1, "[SESSION_ID]"))
+ 	     {
+ 	       sscanf(s, "%*s %4000s", s1);
+ 	       matches[num_match - 1].session_id = duplicate(s1);
+                fprintf(stderr,"[SESSION_ID] %s...\n", s1);
+ 	     }
+ 	   else if (!strcmp(s1, "[NAME]"))
+ 	     {
+ 	       sscanf(s, "%*s %4000s", s1);
+ 	       matches[num_match - 1].name = duplicate(s1);
+ 	     }
+ 	   else if (!strcmp(s1, "[CLASS]"))
+ 	     {
+ 	       sscanf(s, "%*s %4000s", s1);
+ 	       matches[num_match - 1].class = duplicate(s1);
+ 	     }
+ 	   else if (!strcmp(s1, "[ROLE]"))
+ 	     {
+ 	       sscanf(s, "%*s %4000s", s1);
+ 	       matches[num_match - 1].role = duplicate(s1);
+ 	     }
+ 	   
+ 	 }
+        fclose(f);
+      }
+ }
+ 
+ Bool matchWin(FvwmWindow *w, Match *m)
+ {
+    if (!w->session_id)
+      return 0; 
+    if (strcmp(w->session_id, m->session_id))
+      return 0;
+    if (w->class.res_name && m->name &&
+        strcmp(w->class.res_name, m->name))
+      return 0;
+    if (w->class.res_class && m->class &&
+        strcmp(w->class.res_class, m->class))
+      return 0;
+    if (w->role && m->role &&
+        strcmp(w->role, m->role))
+      return 0;
+    return 1;
+ }
+ 
+ /*
+    This routine (potentially) changes the flags STARTICONIC,
+    startShaded, startMaximized and STICKY and the Desk and
+    attr.x, .y, .width, .height entries. It also changes the
+    stack_before pointer to return information about the
+    desired stacking order. It expects the stacking order
+    to be set up correctly beforehand! 
+  */
+ void
+ MatchWinToSM(FvwmWindow *ewin)
+ {
+    int                 i, j;
+    FvwmWindow *t;
+ 
+    fprintf(stderr,"MatchWinToSM %s %s...\n", ewin->session_id, ewin->class.res_name);
+    if (!ewin->session_id)
+      return;
+    for (i = 0; i < num_match; i++)
+      {
+        fprintf(stderr, "trying %d...\n",i);
+        if (!matches[i].used && matchWin(ewin, &matches[i]))
+ 	     {
+                fprintf(stderr,"hit! %d %d %d %d  %d %d  %d %d %d %d %d\n",
+                  matches[i].x, matches[i].y, matches[i].w, matches[i].h,
+                  matches[i].icon_x, matches[i].icon_y, matches[i].desktop,
+                  matches[i].iconified, matches[i].shaded, matches[i].maximized,
+                  matches[i].sticky);
+ 	       matches[i].used = 1;
+ 	       if (matches[i].iconified) {
+                  /* 
+                     ICON_MOVED is necessary to make fvwm use icon_[xy]_loc 
+                     for icon placement
+                  */   
+                  ewin->flags |= STARTICONIC|ICON_MOVED;
+                } else { 
+                  ewin->flags &= ~STARTICONIC;
+                }
+                ewin->tmpflags.startShaded = !!matches[i].shaded;
+                ewin->tmpflags.startMaximized = !!matches[i].maximized;
+ 	       if (matches[i].sticky) {
+                  ewin->flags |= STICKY;
+ 	       } else {
+                  ewin->flags &= ~STICKY;
+                }
+ 	       if (!(ewin->flags & STICKY))
+ 		 ewin->Desk = matches[i].desktop;
+                ewin->attr.x = matches[i].x;
+                ewin->attr.y = matches[i].y;
+                ewin->attr.width = matches[i].w;
+                ewin->attr.height = matches[i].h;
+                ewin->icon_x_loc = matches[i].icon_x;
+                ewin->icon_y_loc = matches[i].icon_y;
+                 
+                /* Find the window to stack this one below. */
+ 
+                fprintf(stderr, "find stack...\n");
+                for (j = i-1; j >= 0; j--) {
+                
+ 
+                  /* matches are sorted in stacking order */
+ 
+                  if (matches[j].used) {
+                    fprintf(stderr, "candidate %d...\n",j);
+ 
+                    for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { 
+                      if (matchWin(t, &matches[j])) {
+                        fprintf(stderr,"hit!\n");
+                        ewin->stack_next->stack_prev = ewin->stack_prev;
+                        ewin->stack_prev->stack_next = ewin->stack_next;
+ 
+                        ewin->stack_prev = t;
+                        ewin->stack_next = t->stack_next;
+                        ewin->stack_prev->stack_next = ewin;
+                        ewin->stack_next->stack_prev = ewin;
+                        return;
+                      }
+                    }
+                  } 
+                }
+ 	       return;
+ 	     }
+ 	 }
+ }
+ 
+ static void
+ callback_save_yourself2(SmcConn smc_conn, SmPointer client_data)
+ {
+   char                master_flag;
+   
+   set_save_props(smc_conn);
+   master_flag = (master_pid == getpid())? 1 : 0;
+   if (master_flag)
+     {
+       SaveWindowStates();
+       /*
+       if (mode.autosave)
+ 	SaveUserControlConfig();
+       else
+ 	DeleteUserControlConfig();
+       */
+       /*
+       SetEInfoOnAll();
+       */
+     }
+   SmcSaveYourselfDone(smc_conn, True);
+   client_data = NULL;
+ }
+ 
+ static void
+ callback_save_yourself(SmcConn smc_conn, SmPointer client_data,
+ 		       int save_style, Bool shutdown, int interact_style,
+ 		       Bool fast)
+ {
+    SmcRequestSaveYourselfPhase2(smc_conn, callback_save_yourself2, NULL);
+    client_data = NULL;
+    save_style = 0;
+    shutdown = False;
+    interact_style = 0;
+    fast = False;
+ }
+ 
+ static void
+ callback_die(SmcConn smc_conn, SmPointer client_data)
+ {
+    char                sss[2048];
+    char                master_flag;
+    XEvent ev;
+    FvwmWindow *t;
+ 
+    setsid();
+    /* 
+       I believe this to be a bug in Enlightenment: 
+       SaveWindowStates();
+    */ 
+    master_flag = (master_pid == getpid())? 1 : 0;
+    if (!master_flag)
+       kill(master_pid, SIGTERM);
+    /*
+    if (dpy)
+       SetEInfoOnAll();
+    */
+   {
+     /* This part taken from Done in fvwm.c */
+     MenuRoot *mr;
+ 
+ #ifndef NON_VIRTUAL
+     MoveViewport(0,0,False);
+ #endif
+ 
+     mr = FindPopup("ExitFunction");
+     if(mr != NULL)
+       ExecuteFunction("Function ExitFunction",NULL,&Event,C_ROOT,-1);
+ 
+     /* Close all my pipes */
+     ClosePipes();
+ 
+     /* RestoreWithdrawnPosition should handle this... */
+     for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) {
+       if (!(t->flags & ICONIFIED)) {
+         if (t->flags & MAXIMIZED)
+           Maximize(&ev, t->w, t, C_WINDOW, "", 0);
+         if (t->buttons & WSHADE)
+           WindowShade(&ev, t->w, t, C_WINDOW, "", 0);
+       }
+     }
+     Reborder ();
+    }
+    MyXUngrabServer(dpy);
+    UngrabEm();
+    XCloseDisplay(dpy);
+    /*
+    if (mode.autosave)
+       SaveUserControlConfig();
+    else
+       DeleteUserControlConfig();
+    */
+    SmcSaveYourselfDone(smc_conn, True);
+    SmcCloseConnection(smc_conn, 0, NULL);
+    client_data = NULL;
+ }
+ 
+ static void
+ callback_save_complete(SmcConn smc_conn, SmPointer client_data)
+ {
+    smc_conn = NULL;
+    client_data = NULL;
+ }
+ 
+ static void
+ callback_shutdown_cancelled(SmcConn smc_conn, SmPointer client_data)
+ {
+    SmcSaveYourselfDone(smc_conn, False);
+    client_data = NULL;
+ }
+ 
+ void
+ SessionInit(void)
+ {
+    static SmPointer    context;
+    SmcCallbacks        callbacks;
+    char               *client_id = NULL;
+ 
+    callbacks.save_yourself.callback = callback_save_yourself;
+    callbacks.die.callback = callback_die;
+    callbacks.save_complete.callback = callback_save_complete;
+    callbacks.shutdown_cancelled.callback = callback_shutdown_cancelled;
+ 
+    callbacks.save_yourself.client_data =
+       callbacks.die.client_data =
+       callbacks.save_complete.client_data =
+       callbacks.shutdown_cancelled.client_data = (SmPointer) NULL;
+    if (getenv("SESSION_MANAGER"))
+      {
+ 	char                error_string_ret[4096] = "";
+ 
+ 	sm_conn = SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor,
+ 				    SmcSaveYourselfProcMask | SmcDieProcMask |
+ 				    SmcSaveCompleteProcMask |
+ 				    SmcShutdownCancelledProcMask,
+ 				    &callbacks, sm_client_id, &client_id,
+ 				    4096, error_string_ret);
+ 	if (error_string_ret[0])
+ 	  fprintf(stderr, "While connecting to session manager:\n%s.",
+ 		  error_string_ret);
+      }
+    if (sm_conn)
+      {
+ 	IceConn             ice_conn;
+ 	int                 restarted = 0;
+ 
+ 	if (sm_client_id == NULL)
+ 	  sm_client_id = client_id;
+ 	else if (!strcmp(sm_client_id, client_id) != 0)
+ 	  {
+ 	    free(sm_client_id);
+ 	    sm_client_id = client_id;
+ 	  }
+ 	else
+ 	  {
+ 	    free(client_id);
+ 	    restarted = 1;
+ 	  }
+ 	ice_conn = SmcGetIceConnection(sm_conn);
+ 	sm_fd = IceConnectionNumber(ice_conn);
+      }
+    LoadWindowStates();
+ }
+ 
+ void
+ ProcessICEMSGS(void)
+ {
+    IceProcessMessagesStatus status;
+ 
+    if (sm_fd < 0)
+       return;
+    status = IceProcessMessages(SmcGetIceConnection(sm_conn), NULL, NULL);
+    if (status == IceProcessMessagesIOError)
+      {
+        fprintf(stderr, "SM died!\n");
+ 	sm_conn = NULL;
+ 	sm_fd = -1;
+      }
+ }
+ 
+ int
+ GetSMfd(void)
+ {
+    return sm_fd;
+ }
+ 
+ void               *
+ AtomGet(Window win, Atom to_get, Atom type, int *size)
+ {
+    unsigned char      *retval;
+    Atom                type_ret;
+    unsigned long       bytes_after, num_ret;
+    int                 format_ret;
+    long                length;
+    void               *data;
+ 
+    retval = NULL;
+    length = 0x7fffffff;
+    XGetWindowProperty(dpy, win, to_get, 0,
+ 		      length,
+ 		      False, type,
+ 		      &type_ret,
+ 		      &format_ret,
+ 		      &num_ret,
+ 		      &bytes_after,
+ 		      &retval);
+    if ((retval) && (num_ret > 0) && (format_ret > 0))
+      {
+ 	data = malloc(num_ret * (format_ret >> 3));
+ 	if (data)
+ 	  memcpy(data, retval, num_ret * (format_ret >> 3));
+ 	XFree(retval);
+ 	*size = num_ret * (format_ret >> 3);
+ 	return data;
+      }
+    return NULL;
+ }
+ 
+ void
+ SessionGetInfo(FvwmWindow* ewin)
+ {
+    Atom                a;
+    char               *s;
+    int                 size;
+ 
+    fprintf(stderr, "Getting window info...\n");
+    if (ewin->session_id)
+      {
+ 	free(ewin->session_id);
+ 	ewin->session_id = NULL;
+      }
+    a = XInternAtom(dpy, "SM_CLIENT_ID", False);
+    s = AtomGet(ewin->w, a, XA_STRING, &size);
+    if (s)
+      {
+ 	ewin->session_id = (char *)malloc(sizeof(char)*(size + 1));
+ 	memcpy(ewin->session_id, s, size);
+ 	ewin->session_id[size] = 0;
+         fprintf(stderr, "session_id == %s\n",ewin->session_id);
+ 	free(s);
+ 	return;
+      }
+    s = AtomGet(ewin->wmhints->window_group, a, XA_STRING, &size);
+    if (s)
+      {
+        ewin->session_id = (char *)malloc(sizeof(char)*(size + 1));
+        memcpy(ewin->session_id, s, size);
+        ewin->session_id[size] = 0;
+        fprintf(stderr, "group leaders session_id == %s\n",ewin->session_id);
+        free(s);
+        return;
+      }
+ }
+ 
+ void
+ SetSMID(char *smid)
+ {
+   fprintf(stderr, "setting smid to %s...\n", smid);
+   if (sm_client_id)
+     free(sm_client_id);
+   sm_client_id = NULL;
+   sm_client_id = duplicate(smid);
+ }
+ 
+ char               *
+ GetSMID(void)
+ {
+   const char         *fake = "NONE";
+   
+   if (!sm_client_id)
+     return (char *)fake;
+   return sm_client_id;
+ }

-- 
Matthias Clasen, 
Tel. 0761/203-5606
Email: [email-masked]
Mathematisches Institut, Albert-Ludwigs-Universitaet Freiburg
--
Visit the official FVWM web page at <URL:http://fvwm.math.uh.edu/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 11 Feb 1999 13:24:13 +0100

> to do proper testing, since the only SMP-aware client on my home machine

Could you elaborate on what you mean with session mamagement?

Bye

Dominik

-- 
Dominik Vogt, Hewlett-Packard GmbH, Dept. BVS
Herrenberger Str.130, 71034 Boeblingen, Germany
phone: 07031/14-4596, fax: 07031/14-3883, [email-masked]
--
Visit the official FVWM web page at <URL:http://fvwm.math.uh.edu/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Jason L Tibbitts III <[email-masked]>
Date: 11 Feb 1999 10:10:31 -0600

>>>>> "DV" == Dominik Vogt <[email-masked]> writes:

DV> Could you elaborate on what you mean with session mamagement?

Session management is essentially the saving of state of a user's desktop
so that it (applications, window positions, etc.) can be restored when the
user next logs in.

It seems to require cooperation between X, the window manager, the
applications and probably the phase of the moon, but it is a useful thing
to have.  As Linux pushes onto the desktop it becomes increasingly
important.

Some docs are in ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/SM/.

 - J<

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 11 Feb 1999 17:31:37 +0100

> to have.  As Linux pushes onto the desktop it becomes increasingly

OK, I understand now. But isn't that what a 'desktop environment'
is supposed to do? Certainly it's nice to have, but I don't see
it as a task of the window manager. Or could we have a module
for that?

Bye

Dominik

---

From: Brad Giaccio <[email-masked]>
Date: Thu, 11 Feb 1999 13:54:17 -0500

> it as a task of the window manager. Or could we have a module

I though we already had a module for that SaveDesk, although it doesn
need some work it doesn't save everything that is on the desktop not
really sure why.  The ida is you would but a wrapper function that calls
Module FvwmSaveDesk and then quits.  And somewhere in the arc you do a
read of .fvwm2desk

Brad
-- 
--- There are two kinds of knowledge, you either know the answer or
			you know where to find it
		      -Kane, Johnson, and anonymous
--
Visit the official FVWM web page at <URL:http://fvwm.math.uh.edu/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Jason L Tibbitts III <[email-masked]>
Date: 11 Feb 1999 13:32:12 -0600

>>>>> "BG" == Brad Giaccio <[email-masked]> writes:

BG> I though we already had a module for that SaveDesk, [...]

This, though has nothing to do with X session management, which is a
defined protocol for doing this kind of thing.

 - J<

---

From: Dan Espen <[email-masked]>
Date: Thu, 11 Feb 1999 15:18:36 -0500

> it as a task of the window manager. Or could we have a module

I've just read the web documents that Jason pointed out.

Recently I was forced to use CDE  for a week or  so.  I assume the CDE
feature that attempts to restart applications you  have open on logout
is based on this.  (I know assumptions are dangerous.)

If thats what this is, my first observation is, I  was careful to exit
everything when  I logged out.  Making logging  out extra work.  There
are loads of things you don't want restarted automatically.  The whole
thing seemed to boil down to a tool that writes your .xinitrc for you.

Since Matthias came up with this, I  wish he would offer some opinions
about how useful this is.

--
Dan Espen
444 Hoes Lane  Room RRC 1C-214           E-mail: [email-masked]
Piscataway, NJ 08854                     Phone: (732) 699-5570
--
Visit the official FVWM web page at <URL:http://fvwm.math.uh.edu/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Matthias Clasen <[email-masked]>
Date: Fri, 12 Feb 1999 09:50:42 +0100

> about how useful this is.

Wow, a lot of response... let me try to answer

First, Dominik is right, it is not the job of the WM to be a session 
manager. But a well-behaved WM should be SM-aware, ie be a client of
the session manager (a session manager is a separate program like xsm
or gnome-session). 

Session management under X means basically supporting the X SMP (Session
Management Protocol), as defined by the documents mentioned by Jason.

Being SM-aware requires the WM to do things like the mentioned module,
FvwmSaveDesk, does. But it has to be done in a SMP-compliant way. The
SM has control over when the client should die or save its state. This
is achieved via communication over an ICE connection. Every SM-client
is given a globally unique ID by the SM and the WM should look up 
information about a clients windows based on this ID, window class, 
name (and an optional role property to further disambiguate multiple 
windows of a client)

Finally, session management certainly aims to be more than automated
.xinitrc writing. Continuing a session means that all clients should be
restarted and put in the state they were before, ie an editor should come
up with the cursor at the same position in the same file, the WM should 
sort the clients windows in the same stacking order, preserve iconification,
etc. My patch was only a beginning, I already have a better version at
home which is saving much more state (including the stacking order).

I'm not sure if it would be feasible to put this functionality into a 
module. It certainly was easier to adapt the enlightenment implementation
to become part of fvwm proper.

Making fvwm SM-aware would be nice, since it would improve the 
interplay between fvwm and desktop environments (Gnome uses X SMP, don't
know about KDE)...and it would mean that the Enlightenment authors couldn't
claim any longer that Enlightenment is the only fully SM-aware WM out there. 

Matthias

---

From: Dominik Vogt <[email-masked]>
Date: Sun, 14 Feb 1999 15:36:32 +0100

On Fri, Feb 12, 1999 at 09:50:42AM +0100, Matthias Clasen wrote:
> up with the cursor at the same position in the same file,

But then the clients have to be aware of session management too. Right?
Are there any applications who are?

> the WM should 

Hm, if it isn't a module is should definitely be a compile time option
(--with-session-management, off by default?). The changes are quite large
and probably not too many people will use it (?)

Bye

Dominik

--
Dominik Vogt, [email-masked]
Reply-To: [email-masked]

---

From: Matthias Clasen <[email-masked]>
Date: Tue, 16 Feb 1999 13:28:18 +0100

> Are there any applications who are?

Well, on my home system, the only app I could find was xclock :-(, 
but there is a program called smproxy that can be used to increase the
sm-awareness of X programs. It allows programs using older versions
of the XSMP (ie the SAVE_YOURSELF protocol in WM_PROTOCOLS) to become
fully session aware. 

I guess this will change with when the free desktop environments mature
a bit more. 

> and probably not too many people will use it (?)

The biggest part of my patch was a new file, session.c, which contains
the new stuff. Apart from that there are only minor changes to 
fvwm.c (initialization), add_window.c (making client windows use their
saved state), icons.c (right now fvwm lowers clients and moves the
icon on the current page - this has to be avoided if the client was
left in iconic state from a previous session).

The patch I'm going to present for post-2.2 inclusion will be fully
ifdef'ed and have --enable-session.

---

From: Matthias Clasen <[email-masked]>
Date: Wed, 17 Feb 1999 22:18:17 +0100

> Date: Tue, 16 Feb 1999 13:28:18 +0100
> X-Authentication-Warning: peano.mathematik.uni-freiburg.de: clasen set sender to [email-masked] using -f
> From: Matthias Clasen <clasen@pong>
> CC: [email-masked]
> Sender: [email-masked]
> Precedence: list
> X-Majordomo: 1.94.jlt7
> 
> > 

Actually, after digging deeper in the X source tree, I found something
quite surprising: Another sm-aware X client is twm ! It seems that
the sm-stuff was added to it in '94, after fwvm started a separate life.

So you could think of my patch as "going back to the roots".