diff -up at-spi-1.28.0/registryd/registry-main.c.fixed-sm at-spi-1.28.0/registryd/registry-main.c --- at-spi-1.28.0/registryd/registry-main.c.fixed-sm 2009-09-22 02:50:10.000000000 -0400 +++ at-spi-1.28.0/registryd/registry-main.c 2009-09-27 16:36:17.805030309 -0400 @@ -33,28 +33,133 @@ #include "registry.h" #include -#ifdef HAVE_SM -#include -#include -#include -#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); static void set_gtk_modules (DBusGProxy *gsm); -#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 +#define SM_DBUS_NAME "org.gnome.SessionManager" +#define SM_DBUS_PATH "/org/gnome/SessionManager" +#define SM_DBUS_INTERFACE "org.gnome.SessionManager" + +#define SM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate" + +static DBusGConnection *bus_connection = NULL; +static DBusGProxy *sm_proxy = NULL; +static char *client_id = NULL; +static DBusGProxy *client_proxy = NULL; + +static gboolean +session_manager_connect (void) +{ + + if (bus_connection == NULL) { + GError *error; + + error = NULL; + bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (bus_connection == NULL) { + g_message ("Failed to connect to the session bus: %s", + error->message); + g_error_free (error); + exit (1); + } + } + + sm_proxy = dbus_g_proxy_new_for_name (bus_connection, + SM_DBUS_NAME, + SM_DBUS_PATH, + SM_DBUS_INTERFACE); + return (sm_proxy != NULL); +} + +static void +stop_cb (gpointer data) +{ + gtk_main_quit (); +} + +static gboolean +end_session_response (gboolean is_okay, const gchar *reason) +{ + gboolean ret; + GError *error = NULL; + + ret = dbus_g_proxy_call (client_proxy, "EndSessionResponse", + &error, + G_TYPE_BOOLEAN, is_okay, + G_TYPE_STRING, reason, + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (!ret) { + g_warning ("Failed to send session response %s", error->message); + g_error_free (error); + } + + return ret; +} + +static void +query_end_session_cb (guint flags, gpointer data) +{ + end_session_response (TRUE, NULL); +} + +static void +end_session_cb (guint flags, gpointer data) +{ + end_session_response (TRUE, NULL); + gtk_main_quit (); +} +static gboolean +register_client (void) +{ + GError *error; + gboolean res; + const char *startup_id; + const char *app_id; + + startup_id = g_getenv ("DESKTOP_AUTOSTART_ID"); + app_id = "at-spi-registryd.desktop"; + + error = NULL; + res = dbus_g_proxy_call (sm_proxy, + "RegisterClient", + &error, + G_TYPE_STRING, app_id, + G_TYPE_STRING, startup_id, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &client_id, + G_TYPE_INVALID); + if (! res) { + g_warning ("Failed to register client: %s", error->message); + g_error_free (error); + return FALSE; + } + + g_debug ("Client registered with session manager: %s", client_id); + client_proxy = dbus_g_proxy_new_for_name (bus_connection, + SM_DBUS_NAME, + client_id, + SM_CLIENT_DBUS_INTERFACE); + + dbus_g_proxy_add_signal (client_proxy, "Stop", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (client_proxy, "Stop", + G_CALLBACK (stop_cb), NULL, NULL); + + dbus_g_proxy_add_signal (client_proxy, "QueryEndSession", G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (client_proxy, "QueryEndSession", + G_CALLBACK (query_end_session_cb), NULL, NULL); + + dbus_g_proxy_add_signal (client_proxy, "EndSession", G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (client_proxy, "EndSession", + G_CALLBACK (end_session_cb), NULL, NULL); + + g_unsetenv ("DESKTOP_AUTOSTART_ID"); + + return TRUE; +} int main (int argc, char **argv) @@ -116,17 +221,15 @@ main (int argc, char **argv) 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); - } + if (!session_manager_connect ()) + { + g_warning ("Unable to connect to session manager"); + } + + if (!register_client ()) + { + g_warning ("Unable to register client with session manager"); + } bonobo_main (); } @@ -164,224 +267,6 @@ registry_set_ior (SpiRegistry *registry) } -#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 - static void set_gtk_modules (DBusGProxy *gsm) {