[at-spi] Make at-spi-registryd managed by gnome-session.



commit 22a0d9a3caa235dad52d6cab467d2146bed5dd62
Author: Li Yuan <li yuan sun com>
Date:   Fri Aug 21 15:49:43 2009 +0800

    Make at-spi-registryd managed by gnome-session.
    
    Bug #578334. Original patch from Tomislav Vujec.

 configure.in                                |   14 ++
 po/POTFILES.in                              |    1 +
 po/POTFILES.skip                            |    2 +
 registryd/Makefile.am                       |   25 +++-
 registryd/at-spi-registryd.desktop.in.in.in |   12 ++
 registryd/registry-main.c                   |  251 ++++++++++++++++++++++++++-
 6 files changed, 302 insertions(+), 3 deletions(-)
---
diff --git a/configure.in b/configure.in
index b174904..844cee8 100644
--- a/configure.in
+++ b/configure.in
@@ -194,6 +194,19 @@ if test x$enable_xevie = xyes ; then
 	AC_SUBST(XEVIE_LIBS)
 fi
 
+dnl Allow disabling SMlib
+AC_ARG_ENABLE(sm, [  --enable-sm  Enable session management support [default=yes]], enable_sm="$enableval", enable_sm=yes)
+
+if test x$enable_sm = xyes ; then
+	have_sm=
+	AC_CHECK_LIB(SM, SmcSaveYourselfDone, have_sm="yes")
+	if test x$have_sm = xyes ; then
+		SM_LIBS="-lSM -lICE"
+		AC_DEFINE(HAVE_SM, , [Building with SM support])
+	fi
+	AC_SUBST(SM_LIBS)
+fi
+
 dnl CFLAGS="$CFLAGS -Wall"
 AC_SUBST(CFLAGS)
 AC_SUBST(CPPFLAGS)
@@ -243,6 +256,7 @@ docs/reference/idl/Makefile
 idl/Makefile
 libspi/Makefile
 registryd/Makefile
+registryd/at-spi-registryd.desktop.in.in
 atk-bridge/Makefile
 login-helper/Makefile
 test/Makefile
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 482d3f2..4db7f22 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,3 +2,4 @@
 # Please keep this file sorted alphabetically.
 at-spi.schemas.in
 registryd/Accessibility_Registry.server.in.in
+registryd/at-spi-registryd-wrapper.desktop.in.in.in
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 0357969..3ac70be 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -2,3 +2,5 @@
 # Please keep this file sorted alphabetically.
 atk-bridge/bridge.c
 registryd/Accessibility_Registry.server.in
+registryd/at-spi-registryd-wrapper.desktop.in
+registryd/at-spi-registryd-wrapper.desktop.in.in
diff --git a/registryd/Makefile.am b/registryd/Makefile.am
index 0495b5d..68828db 100644
--- a/registryd/Makefile.am
+++ b/registryd/Makefile.am
@@ -22,12 +22,33 @@ at_spi_registryd_SOURCES =		\
 	registry.h		\
 	ucs2keysym.c
 
-LDADD = $(top_builddir)/libspi/libspi.la $(X_LIBS) $(XTST_LIBS) $(XEVIE_LIBS) $(REGISTRYD_LIBS) 
+LDADD = $(top_builddir)/libspi/libspi.la $(X_LIBS) $(SM_LIBS) $(XTST_LIBS) $(XEVIE_LIBS) $(REGISTRYD_LIBS) 
 
 serverinfodir = $(libdir)/bonobo/servers
 serverinfo_DATA = Accessibility_Registry.server
 
+default_sessiondir = $(sysconfdir)/xdg/autostart
+default_session_in_in_files = 				\
+	at-spi-registryd.desktop.in.in
+default_session_in_files = $(default_session_in_in_files:.desktop.in.in=.desktop.in)
+default_session_DATA = $(default_session_in_files:.desktop.in=.desktop)
+
+ INTLTOOL_DESKTOP_RULE@
+
+%.desktop.in: %.desktop.in.in Makefile.am
+	sed -e "s,\ registryddir\@,$(libexecdir)," \
+		< $< > $@
+
 @INTLTOOL_SERVER_RULE@
 
 EXTRA_DIST = Accessibility_Registry.server.in.in
-CLEANFILES = $(serverinfo_DATA) $(server_dot_in)
+CLEANFILES = 			\
+	$(serverinfo_DATA)	\
+	$(server_dot_in)	\
+	$(default_session_DATA)	\
+	$(default_session_in_files)
+	
+DISTCLEANFILES =					\
+	$(default_session_in_in_files)
+
+
diff --git a/registryd/at-spi-registryd.desktop.in.in.in b/registryd/at-spi-registryd.desktop.in.in.in
new file mode 100644
index 0000000..0e414a7
--- /dev/null
+++ b/registryd/at-spi-registryd.desktop.in.in.in
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Type=Application
+_Name=AT SPI Registry Wrapper
+Exec= registryddir@/at-spi-registryd
+OnlyShowIn=GNOME;
+NoDisplay=true
+AutostartCondition=GNOME /desktop/gnome/interface/accessibility
+X-GNOME-Autostart-Phase=Initialization
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=at-spi
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-Version= VERSION@
diff --git a/registryd/registry-main.c b/registryd/registry-main.c
index 1be5b69..bd98740 100644
--- a/registryd/registry-main.c
+++ b/registryd/registry-main.c
@@ -32,9 +32,27 @@
 #include <glib.h>
 #include "registry.h"
 
+#ifdef HAVE_SM
+#include <X11/SM/SMlib.h>
+#include <X11/ICE/ICElib.h>
+#include <fcntl.h>
+#endif
+
 #define spi_get_display() GDK_DISPLAY()
 
 static void registry_set_ior (SpiRegistry *registry);
+static void registry_session_init (const char *previous_client_id, const char *exe);
+#ifdef HAVE_SM
+static void die_callback (SmcConn smc_conn, SmPointer client_data);
+static void save_yourself_callback      (SmcConn   smc_conn,
+                                         SmPointer client_data,
+                                         int       save_style,
+                                         Bool      shutdown,
+                                         int       interact_style,
+                                         Bool      fast);
+
+static SmcConn session_connection;
+#endif
 
 int
 main (int argc, char **argv)
@@ -62,7 +80,6 @@ main (int argc, char **argv)
       dp = strrchr (display_name, ':');
       if (cp && dp && (cp > dp)) *cp = '\0';
   }
-
   ret = bonobo_activation_register_active_server (
 	  obj_id,
 	  bonobo_object_corba_objref (bonobo_object (registry)),
@@ -80,6 +97,19 @@ main (int argc, char **argv)
       fprintf (stderr, "SpiRegistry Message: SpiRegistry daemon is running.\n");
 #endif
       registry_set_ior (registry);
+
+      /* If DESKTOP_AUTOSTART_ID exists, assume we're started by session
+       * manager and connect to it. */
+      const char *desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+      if (desktop_autostart_id != NULL) {
+        char *client_id = g_strdup (desktop_autostart_id);
+        /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+         * use the same client id. */
+        g_unsetenv ("DESKTOP_AUTOSTART_ID");
+        registry_session_init (client_id, argv[0]);
+        g_free (client_id);
+      }
+
       bonobo_main ();
     }
 
@@ -115,3 +145,222 @@ registry_set_ior (SpiRegistry *registry){
   CORBA_exception_free (&ev);
 
 }
+
+#ifdef HAVE_SM
+/* This is called when data is available on an ICE connection.  */
+static gboolean
+process_ice_messages (GIOChannel *channel,
+                      GIOCondition condition,
+                      gpointer client_data)
+{
+  IceConn connection = (IceConn) client_data;
+  IceProcessMessagesStatus status;
+
+  /* This blocks infinitely sometimes. I don't know what
+   * to do about it. Checking "condition" just breaks
+   * session management.
+   */
+  status = IceProcessMessages (connection, NULL, NULL);
+
+  if (status == IceProcessMessagesIOError)
+    {
+#if 0
+      IcePointer context = IceGetConnectionContext (connection);
+#endif
+
+      /* We were disconnected */
+      IceSetShutdownNegotiation (connection, False);
+      IceCloseConnection (connection);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* 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)
+{
+  guint input_id;
+
+  if (opening)
+    {
+      /* Make sure we don't pass on these file descriptors to any
+       * exec'ed children
+       */
+      GIOChannel *channel;
+
+      fcntl (IceConnectionNumber (connection), F_SETFD,
+             fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC);
+
+      channel = g_io_channel_unix_new (IceConnectionNumber (connection));
+
+      input_id = g_io_add_watch (channel,
+                                 G_IO_IN | G_IO_ERR,
+                                 process_ice_messages,
+                                 connection);
+
+      g_io_channel_unref (channel);
+
+      *watch_data = (IcePointer) GUINT_TO_POINTER (input_id);
+    }
+  else
+    {
+      input_id = GPOINTER_TO_UINT ((gpointer) *watch_data);
+
+      g_source_remove (input_id);
+    }
+}
+
+static IceIOErrorHandler ice_installed_handler;
+
+/* We call any handler installed before (or after) gnome_ice_init but 
+   avoid calling the default libICE handler which does an exit() */
+static void
+ice_io_error_handler (IceConn connection)
+{
+    if (ice_installed_handler)
+      (*ice_installed_handler) (connection);
+}
+
+static void
+ice_init (void)
+{
+  static gboolean ice_initted = FALSE;
+
+  if (! ice_initted)
+    {
+      IceIOErrorHandler default_handler;
+
+      ice_installed_handler = IceSetIOErrorHandler (NULL);
+      default_handler = IceSetIOErrorHandler (ice_io_error_handler);
+
+      if (ice_installed_handler == default_handler)
+        ice_installed_handler = NULL;
+
+      IceAddConnectionWatch (new_ice_connection, NULL);
+
+      ice_initted = TRUE;
+    }
+}
+#endif
+
+void
+registry_session_init (const char *previous_client_id, const char *exe)
+{
+#ifdef HAVE_SM
+  char buf[256];
+  char *client_id;
+  unsigned long mask;
+  SmcCallbacks callbacks;
+
+  ice_init();
+
+  callbacks.save_yourself.callback = save_yourself_callback;
+  callbacks.save_yourself.client_data = NULL;
+  callbacks.die.callback = die_callback;
+  callbacks.die.client_data = NULL;
+
+  mask = SmcSaveYourselfProcMask | SmcDieProcMask;
+
+  session_connection =
+    SmcOpenConnection (NULL, /* use SESSION_MANAGER env */
+                       NULL, /* means use existing ICE connection */
+                       SmProtoMajor,
+                       SmProtoMinor,
+                       mask,
+                       &callbacks,
+                       (char*) previous_client_id,
+                       &client_id,
+                       255, buf);
+
+  if (session_connection != NULL) {
+    SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6];
+    SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val;
+    char pid[32];
+    char hint = SmRestartImmediately;
+    char priority = 1; /* low to run before other apps */
+
+    prop1.name = SmProgram;
+    prop1.type = SmARRAY8;
+    prop1.num_vals = 1;
+    prop1.vals = &prop1val;
+    prop1val.value = exe;
+    prop1val.length = strlen (exe);
+
+    /* twm sets getuid() for this, but the SM spec plainly
+     * says pw_name, twm is on crack
+     */
+    prop2.name = SmUserID;
+    prop2.type = SmARRAY8;
+    prop2.num_vals = 1;
+    prop2.vals = &prop2val;
+    prop2val.value = (char*) g_get_user_name ();
+    prop2val.length = strlen (prop2val.value);
+
+    prop3.name = SmRestartStyleHint;
+    prop3.type = SmCARD8;
+    prop3.num_vals = 1;
+    prop3.vals = &prop3val;
+    prop3val.value = &hint;
+    prop3val.length = 1;
+
+    sprintf (pid, "%d", getpid ());
+    prop4.name = SmProcessID;
+    prop4.type = SmARRAY8;
+    prop4.num_vals = 1;
+    prop4.vals = &prop4val;
+    prop4val.value = pid;
+    prop4val.length = strlen (prop4val.value);
+
+    /* Always start in home directory */
+    prop5.name = SmCurrentDirectory;
+    prop5.type = SmARRAY8;
+    prop5.num_vals = 1;
+    prop5.vals = &prop5val;
+    prop5val.value = (char*) g_get_home_dir ();
+    prop5val.length = strlen (prop5val.value);
+
+    prop6.name = "_GSM_Priority";
+    prop6.type = SmCARD8;
+    prop6.num_vals = 1;
+    prop6.vals = &prop6val;
+    prop6val.value = &priority;
+    prop6val.length = 1;
+
+    props[0] = &prop1;
+    props[1] = &prop2;
+    props[2] = &prop3;
+    props[3] = &prop4;
+    props[4] = &prop5;
+    props[5] = &prop6;
+
+    SmcSetProperties (session_connection, 6, props);
+  }
+
+#endif
+}
+
+#ifdef HAVE_SM
+static void
+die_callback (SmcConn smc_conn, SmPointer client_data)
+{
+  SmcCloseConnection (session_connection, 0, NULL);
+  bonobo_main_quit ();
+}
+
+static void
+save_yourself_callback      (SmcConn   smc_conn,
+                             SmPointer client_data,
+                             int       save_style,
+                             Bool      shutdown,
+                             int       interact_style,
+                             Bool      fast)
+{
+  SmcSaveYourselfDone (session_connection, TRUE);
+}
+#endif
+



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