[monkey-bubble: 4/753] Wrote functions to handle client side of session management. Modified desktop property programs to s



commit e5debcee028eb6cd8fed6616cba6758a096856e8
Author: Tom Tromey <tromey src gnome org>
Date:   Sun Dec 7 06:57:01 1997 +0000

    Wrote functions to handle client side of session management.
    Modified desktop property programs to save state in a hacky way
    as a test.

 libgnomeui/Makefile.am     |    6 +-
 libgnomeui/gnome-session.c |  379 ++++++++++++++++++++++++++++++++++++++++++++
 libgnomeui/gnome-session.h |  115 +++++++++++++
 3 files changed, 498 insertions(+), 2 deletions(-)
---
diff --git a/libgnomeui/Makefile.am b/libgnomeui/Makefile.am
index 7f8f60c..46c619c 100644
--- a/libgnomeui/Makefile.am
+++ b/libgnomeui/Makefile.am
@@ -14,7 +14,8 @@ libgnomeui_la_SOURCES = \
 	gnome-messagebox.c		\
 	gnome-pixmap.c			\
 	gnome-toolbar.c			\
-	gnome-colors.c
+	gnome-colors.c			\
+	gnome-session.c
 
 libgnomeuiinclude_HEADERS = 		\
         gnome-actionarea.h     		\
@@ -24,7 +25,8 @@ libgnomeuiinclude_HEADERS = 		\
 	gnome-properties.h     		\
 	gnome-pixmap.h			\
 	gnome-toolbar.h			\
-	libgnomeui.h
+	libgnomeui.h			\
+	gnome-session.h
 
 
 libgnomeui_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir)
diff --git a/libgnomeui/gnome-session.c b/libgnomeui/gnome-session.c
new file mode 100644
index 0000000..316f62f
--- /dev/null
+++ b/libgnomeui/gnome-session.c
@@ -0,0 +1,379 @@
+/* gnome-session.c - Gnome session client library.  */
+
+#include <config.h>
+
+#include <assert.h>
+#include <X11/ICE/ICElib.h>
+
+#include "gnome.h"
+#include "gnome-session.h"
+
+#define PAD(n,P)  ((((n) % (P)) == 0) ? (n) : ((n) + (P) - ((n) % (P))))
+
+#ifdef HAVE_LIBSM
+
+typedef enum
+{
+  c_idle,
+  c_save_yourself,
+  c_shutdown_cancelled,
+  c_interact_request,
+  c_interact,
+  c_die,
+} client_state;
+
+/* A struct of this type holds information about the client.  */
+struct client_info
+{
+  client_state state;
+  gpointer client_data;
+  GnomeSaveFunction *saver;
+  GnomeDeathFunction *death;
+  SmcConn connection;
+};
+
+/* The state for this client.  */
+static struct client_info *info;
+
+/* True if we've started listening to ICE.  */
+static int ice_init = 0;
+
+/* ICE connection tag as known by GDK event loop.  */
+static guint ice_tag;
+
+
+/* This is called when data is available on an ICE connection.  */
+static void
+process_ice_messages (gpointer client_data, gint source,
+		      GdkInputCondition condition)
+{
+  IceProcessMessagesStatus status;
+  IceConn connection = (IceConn) client_data;
+
+  status = IceProcessMessages (connection, NULL, NULL);
+  /* FIXME: handle case when status==closed.  */
+}
+
+/* This is called when a new ICE connection is made.  It arranges for
+   the ICE connection to be handled via the event loop.  */
+static void
+new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
+		    IcePointer *watch_data)
+{
+  if (opening)
+    ice_tag = gdk_input_add (IceConnectionNumber (connection),
+			     GDK_INPUT_READ, process_ice_messages,
+			     (gpointer) connection);
+  else
+    gdk_input_remove (ice_tag);
+}
+
+static void
+save_yourself (SmcConn connection, SmPointer client_data, int save_type,
+	       Bool shutdown, int interact_style, Bool fast)
+{
+  int status;
+
+  info->state = c_save_yourself;
+  if (info->saver)
+    status = info->saver (info->client_data, save_type, shutdown,
+			  interact_style, fast);
+  else
+    status = True;
+  SmcSaveYourselfDone (connection, status);
+
+  /* State might have changed while calling SAVER.  Assume that if it
+     has changed, then we are ok.  */
+  /* FIXME: Make it impossible for the user to interact.  */
+  while (info->state == c_save_yourself
+	 && ! gtk_main_iteration ())
+    ;
+
+  info->state = c_idle;
+}
+
+static void
+die (SmcConn connection, SmPointer client_data)
+{
+  info->state = c_die;
+  SmcCloseConnection (connection, 0, NULL);
+  if (info->death)
+    info->death (info->client_data);
+  /* FIXME.  */
+  exit (0);
+}
+
+static void
+save_complete (SmcConn connection, SmPointer client_data)
+{
+  assert (info->state == c_save_yourself);
+  info->state = c_idle;
+}
+
+static void
+shutdown_cancelled (SmcConn connection, SmPointer client_data)
+{
+  assert (info->state == c_save_yourself || info->state == c_interact_request);
+  info->state = c_shutdown_cancelled;
+}
+
+#endif /* HAVE_LIBSM */
+
+char *
+gnome_init_session (GnomeSaveFunction saver,
+		    GnomeDeathFunction death,
+		    gpointer client_data,
+		    char *previous)
+{
+#ifdef HAVE_LIBSM
+  SmcConn connection;
+  unsigned long mask;
+  SmcCallbacks callbacks;
+  char *client_id;
+  char buf[256];
+
+  assert (! info);
+
+  if (! ice_init)
+    {
+      IceAddConnectionWatch (new_ice_connection, NULL);
+      ice_init = 1;
+    }
+
+  info = g_new (struct client_info, 1);
+  info->state = c_idle;
+  info->client_data = client_data;
+  info->saver = saver;
+  info->death = death;
+
+  callbacks.save_yourself.callback = save_yourself;
+  callbacks.save_yourself.client_data = NULL;
+  callbacks.die.callback = die;
+  callbacks.die.client_data = NULL;
+  callbacks.save_complete.callback = save_complete;
+  callbacks.save_complete.client_data = NULL;
+  callbacks.shutdown_cancelled.callback = shutdown_cancelled;
+  callbacks.shutdown_cancelled.client_data = NULL;
+
+  mask = (SmcSaveYourselfProcMask | SmcDieProcMask
+	  | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask);
+
+  info->connection = SmcOpenConnection (NULL, NULL, SmProtoMajor, SmProtoMinor,
+					mask, &callbacks, previous, &client_id,
+					sizeof buf, buf);
+  if (! info->connection)
+    {
+      free (info);
+      info = NULL;
+      return NULL;
+    }
+
+  return client_id;
+#else
+  return NULL;
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_restart_style (GnomeRestartStyle style)
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue val;
+  char c = (char) style;
+
+  if (! info)
+    return;
+
+  prop.name = SmRestartStyleHint;
+  prop.type = SmCARD8;
+  prop.num_vals = 1;
+  prop.vals = &val;
+  val.length = 1;
+  val.value = &style;
+  proplist[0] = &prop;
+  SmcSetProperties (info->connection, 1, proplist);
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_current_directory (char *dir)
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue val;
+  int len;
+
+  if (! info)
+    return;
+
+  prop.name = SmCurrentDirectory;
+  prop.type = SmARRAY8;
+  prop.num_vals = 1;
+  prop.vals = &val;
+  val.length = strlen (dir) + 1;
+  val.value = dir;
+  proplist[0] = &prop;
+  SmcSetProperties (info->connection, 1, proplist);
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_program (char *name)
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue val;
+  int len;
+
+  if (! info)
+    return;
+
+  prop.name = SmProgram;
+  prop.type = SmARRAY8;
+  prop.num_vals = 1;
+  prop.vals = &val;
+  val.length = strlen (name) + 1;
+  val.value = name;
+  proplist[0] = &prop;
+  SmcSetProperties (info->connection, 1, proplist);
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_discard_command (int argc, char *argv[])
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue *vals;
+  int i;
+
+  if (! info)
+    return;
+
+  prop.name = SmDiscardCommand;
+  prop.type = SmLISTofARRAY8;
+
+  vals = (SmPropValue *) malloc (argc * sizeof (SmPropValue));
+  for (i = 0; i < argc; ++i)
+    {
+      vals[i].length = strlen (argv[i]) + 1;
+      vals[i].value = argv[i];
+    }
+
+  prop.num_vals = argc;
+  prop.vals = vals;
+  proplist[0] = &prop;
+
+  SmcSetProperties (info->connection, 1, proplist);
+
+  free (vals);
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_restart_command (int argc, char *argv[])
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue *vals;
+  int i;
+
+  if (! info)
+    return;
+
+  prop.name = SmRestartCommand;
+  prop.type = SmLISTofARRAY8;
+
+  vals = (SmPropValue *) malloc (argc * sizeof (SmPropValue));
+  for (i = 0; i < argc; ++i)
+    {
+      vals[i].length = strlen (argv[i]) + 1;
+      vals[i].value = argv[i];
+    }
+
+  prop.num_vals = argc;
+  prop.vals = vals;
+  proplist[0] = &prop;
+
+  SmcSetProperties (info->connection, 1, proplist);
+
+  free (vals);
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_set_clone_command (int argc, char *argv[])
+{
+#ifdef HAVE_LIBSM
+  SmProp prop, *proplist[1];
+  SmPropValue *vals;
+  int i;
+
+  if (! info)
+    return;
+
+  prop.name = SmCloneCommand;
+  prop.type = SmLISTofARRAY8;
+
+  vals = (SmPropValue *) malloc (argc * sizeof (SmPropValue));
+  for (i = 0; i < argc; ++i)
+    {
+      vals[i].length = strlen (argv[i]) + 1;
+      vals[i].value = argv[i];
+    }
+
+  prop.num_vals = argc;
+  prop.vals = vals;
+  proplist[0] = &prop;
+
+  SmcSetProperties (info->connection, 1, proplist);
+
+  free (vals);
+#endif /* HAVE_LIBSM */
+}
+
+#ifdef HAVE_LIBSM
+
+static void
+interact (SmcConn connection, SmPointer client_data)
+{
+  assert (info->state == c_interact_request);
+  info->state = c_interact;
+}
+
+#endif /* HAVE_LIBSM */
+
+int
+gnome_request_interaction (GnomeDialogType type)
+{
+#ifdef HAVE_LIBSM
+  int status;
+
+  assert (info->state == c_save_yourself);
+  info->state = c_interact_request;
+  status = SmcInteractRequest (info->connection, type,
+			       interact, NULL);
+  if (! status)
+    return 0;
+
+  /* FIXME: Make it impossible for the user to interact.  */
+  while (info->state == c_interact_request
+	 && ! gtk_main_iteration ())
+    ;
+
+  return (info->state == c_interact);
+#else
+  return 1;
+#endif /* HAVE_LIBSM */
+}
+
+void
+gnome_interaction_done (int shutdown)
+{
+#ifdef HAVE_LIBSM
+  assert (info->state == c_interact);
+  info->state = c_save_yourself;
+  SmcInteractDone (info->connection, shutdown);
+#endif /* HAVE_LIBSM */
+}
diff --git a/libgnomeui/gnome-session.h b/libgnomeui/gnome-session.h
new file mode 100644
index 0000000..771387e
--- /dev/null
+++ b/libgnomeui/gnome-session.h
@@ -0,0 +1,115 @@
+/* gnome-session.h - Session management support for Gnome apps.  */
+
+#ifndef GNOME_SESSION_H
+#define GNOME_SESSION_H
+
+BEGIN_GNOME_DECLS
+
+/* If we don't have libSM, then we just define bogus values for the
+   things we need from SMlib.h.  The values don't matter because this
+   whole library is just stubbed out in this case.  */
+#ifdef HAVE_LIBSM
+#include <X11/SM/SMlib.h>
+#else /* HAVE_LIBSM */
+#define SmInteractStyleNone	0
+#define SmInteractStyleErrors	1
+#define SmInteractStyleAny	2
+#define SmDialogError		0
+#define SmDialogNormal		1
+#define SmSaveGlobal	0
+#define SmSaveLocal	1
+#define SmSaveBoth	2
+#define SmRestartIfRunning	0
+#define SmRestartAnyway		1
+#define SmRestartImmediately	2
+#define SmRestartNever		3
+#endif /* HAVE_LIBSM */
+
+/* Some redefinitions so we can use familiar names.  */
+typedef enum
+{
+  GNOME_INTERACT_NONE = SmInteractStyleNone,
+  GNOME_INTERACT_ERRORS = SmInteractStyleErrors,
+  GNOME_INTERACT_ANY = SmInteractStyleAny
+} GnomeInteractStyle;
+
+typedef enum
+{
+  GNOME_DIALOG_ERROR = SmDialogError,
+  GNOME_DIALOG_NORMAL = SmDialogNormal
+} GnomeDialogType;
+
+typedef enum
+{
+  GNOME_SAVE_GLOBAL = SmSaveGlobal,
+  GNOME_SAVE_LOCAL = SmSaveLocal,
+  GNOME_SAVE_BOTH = SmSaveBoth
+} GnomeSaveStyle;
+
+typedef enum
+{
+  GNOME_RESTART_IF_RUNNING = SmRestartIfRunning,
+  GNOME_RESTART_ANYWAY = SmRestartAnyway,
+  GNOME_RESTART_IMMEDIATELY = SmRestartImmediately,
+  GNOME_RESTART_NEVER = SmRestartNever
+} GnomeRestartStyle;
+
+
+/* A function of this type is called when the state should be saved.
+   The function should return 1 if the save was successful, 0
+   otherwise.  */
+typedef int GnomeSaveFunction (gpointer client_data,
+			       GnomeSaveStyle save_style,
+			       int /*bool*/ is_shutdown,
+			       GnomeInteractStyle interact_style,
+			       int /*bool*/ is_fast);
+
+/* A function of this type is called when the session manager requests
+   us to exit.  State will have already been saved.  If this function
+   returns, the handler will exit with status 0.  */
+typedef void GnomeDeathFunction (gpointer client_data);
+
+
+
+/* Initialize.  This returns the current client id (which should be
+   saved for restarting), or NULL on error.  If this client has been
+   restarted from a saved session, the old client id should be passed
+   as PREVIOUS_ID.  Otherwise NULL should be used.  */
+char *gnome_init_session (GnomeSaveFunction saver,
+			  GnomeDeathFunction death,
+			  gpointer client_data,
+			  char *previous_id);
+
+/* Set the restart style.  Default is GNOME_RESTART_IF_RUNNING.  */
+void gnome_set_restart_style (GnomeRestartStyle style);
+
+/* Set the current directory property.  */
+void gnome_set_current_directory (char *dir);
+
+/* Set the discard command.  This is a command that can clean up
+   after a local save.  */
+void gnome_set_discard_command (int argc, char *argv[]);
+
+/* Set the restart command.  */
+void gnome_set_restart_command (int argc, char *argv[]);
+
+/* Set the clone command.  This is like the restart command but
+   doesn't preserve session id info.  */
+void gnome_set_clone_command (int argc, char *argv[]);
+
+/* Set the program name.  The argument should just be ARGV[0].  */
+void gnome_set_program (char *name);
+
+/* Request the interaction token.  This will return 1 when this client
+   has the interaction token.  If it returns 0, then the shutdown has
+   been cancelled, and so the interaction should not take place.  */
+int gnome_request_interaction (GnomeDialogType dialog_type);
+
+/* Release the interaction token.  If SHUTDOWN is true, then the
+   shutdown will be cancelled.  */
+void gnome_interaction_done (int shutdown);
+
+
+END_GNOME_DECLS
+
+#endif /* GNOME_SESSION_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]