X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=registryd%2Fregistry-main.c;h=083de1986f4a1f4d4b365879b15bc6f4ba21d3ab;hb=56640b9fc89be31ec6d44278c6f2ef0b69a9d74a;hp=246270c6c16aabde8fdc617436a62fa749e48ae6;hpb=fe57252569727cafcf3228f261403303f1acd9fb;p=platform%2Fupstream%2Fat-spi2-core.git diff --git a/registryd/registry-main.c b/registryd/registry-main.c index 246270c..083de19 100644 --- a/registryd/registry-main.c +++ b/registryd/registry-main.c @@ -21,79 +21,393 @@ * Boston, MA 02111-1307, USA. */ -#ifdef AT_SPI_DEBUG #include -#endif - #include #include -#include -#include +#include +#include +#include + +#include +#include + +#include "paths.h" #include "registry.h" +#include "deviceeventcontroller.h" + +#define CORBA_GCONF_KEY "/desktop/gnome/interface/at-spi-corba" + +static gboolean need_to_quit (); + +static GMainLoop *mainloop; +static gchar *dbus_name = NULL; +static gboolean use_gnome_session = FALSE; + +static GOptionEntry optentries[] = +{ + {"dbus-name", 0, 0, G_OPTION_ARG_STRING, &dbus_name, "Well-known name to register with D-Bus", NULL}, + {"use-gnome-session", 0, 0, G_OPTION_ARG_NONE, &use_gnome_session, "Should register with gnome session manager", NULL}, + {NULL} +}; + +static DBusGConnection *bus_connection = NULL; +static DBusGProxy *sm_proxy = NULL; +static char *client_id = NULL; +static DBusGProxy *client_proxy = NULL; + +#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 void registry_session_init (const char *previous_client_id, const char *exe); + +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 +kill_accessibility_bus () +{ + FILE *fp; + const char *home; + char *name; + int pid; + + home = getenv ("HOME"); + if (!home) + return; + name = g_strconcat (home, "/", ".atspi-dbus-bus.pid", NULL); + if (!name) + return; + + fp = fopen (name, "r"); + if (fp) + { + if (fscanf (fp, "%d", &pid) == 1) + { + kill (&pid, SIGTERM); + } + fclose (fp); + } + g_free (name); +} + +static void +stop_cb (gpointer data) +{ + kill_accessibility_bus (); + g_main_loop_quit (mainloop); +} + +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) +{ + kill_accessibility_bus (); + end_session_response (TRUE, NULL); + g_main_loop_quit (mainloop); +} +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; + } + + client_proxy = dbus_g_proxy_new_for_name (bus_connection, + SM_DBUS_NAME, + client_id, + SM_CLIENT_DBUS_INTERFACE); -#define spi_get_display() GDK_DISPLAY() + 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); -static void registry_set_ior (SpiRegistry *registry); + 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; +} + +/*---------------------------------------------------------------------------*/ + +/* + * Returns a 'canonicalized' value for DISPLAY, + * with the screen number stripped off if present. + * + */ +static const gchar* +spi_display_name (void) +{ + static const char *canonical_display_name = NULL; + if (!canonical_display_name) + { + const gchar *display_env = g_getenv ("AT_SPI_DISPLAY"); + if (!display_env) + { + display_env = g_getenv ("DISPLAY"); + if (!display_env || !display_env[0]) + canonical_display_name = ":0"; + else + { + gchar *display_p, *screen_p; + canonical_display_name = g_strdup (display_env); + display_p = strrchr (canonical_display_name, ':'); + screen_p = strrchr (canonical_display_name, '.'); + if (screen_p && display_p && (screen_p > display_p)) + { + *screen_p = '\0'; + } + } + } + else + { + canonical_display_name = display_env; + } + } + return canonical_display_name; +} + +/*---------------------------------------------------------------------------*/ + +/* + * Gets the IOR from the XDisplay. + * Not currently used in D-Bus version, but something similar + * may be employed in the future for accessing the registry daemon + * bus name. + */ + +static DBusConnection * +spi_get_bus (void) +{ + Atom AT_SPI_BUS; + Atom actual_type; + Display *bridge_display; + int actual_format; + unsigned char *data = NULL; + unsigned long nitems; + unsigned long leftover; + + DBusConnection *bus = NULL; + DBusError error; + + bridge_display = XOpenDisplay (spi_display_name ()); + if (!bridge_display) + g_error ("AT_SPI: Could not get the display"); + + AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", FALSE); + XGetWindowProperty(bridge_display, + XDefaultRootWindow (bridge_display), + AT_SPI_BUS, 0L, + (long)BUFSIZ, False, + (Atom) 31, &actual_type, &actual_format, + &nitems, &leftover, &data); + + dbus_error_init (&error); + + if (data == NULL) + { + g_warning ("AT-SPI: Accessibility bus bus not found - Using session bus.\n"); + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) + g_error ("AT-SPI: Couldn't connect to bus: %s\n", error.message); + } + else + { + bus = dbus_connection_open (data, &error); + XFree (data); + if (!bus) + { + g_error ("AT-SPI: Couldn't connect to bus: %s\n", error.message); + } + else + { + if (!dbus_bus_register (bus, &error)) + g_error ("AT-SPI: Couldn't register with bus: %s\n", error.message); + } + } + + XCloseDisplay (bridge_display); + return bus; +} + +/*---------------------------------------------------------------------------*/ + +typedef GObject *(*gconf_client_get_default_t) (); +typedef gboolean (*gconf_client_get_bool_t)(GObject *, const char *, void *); int main (int argc, char **argv) { - int ret; - char *obj_id; - const char *display_name; - char *cp, *dp; SpiRegistry *registry; + SpiDEController *dec; + + DBusConnection *bus = NULL; + + GOptionContext *opt; + + GError *err = NULL; DBusError error; - GMainLoop *mainloop; + int ret; + + if (need_to_quit ()) + return 0; g_type_init(); - obj_id = "OAFIID:Accessibility_Registry:1.0"; + /*Parse command options*/ + opt = g_option_context_new(NULL); + g_option_context_add_main_entries(opt, optentries, NULL); + + if (!g_option_context_parse(opt, &argc, &argv, &err)) + g_error("Option parsing failed: %s\n", err->message); - registry = spi_registry_new (); + if (dbus_name == NULL) + dbus_name = SPI_DBUS_NAME_REGISTRY; - display_name = g_getenv ("AT_SPI_DISPLAY"); - if (!display_name) + dbus_error_init (&error); + bus = dbus_bus_get(DBUS_BUS_SESSION, &error); + bus = spi_get_bus (); + if (!bus) { - display_name = g_getenv ("DISPLAY"); - cp = strrchr (display_name, '.'); - dp = strrchr (display_name, ':'); - if (cp && dp && (cp > dp)) *cp = '\0'; + return 0; } - dbus_error_init (&error); mainloop = g_main_loop_new (NULL, FALSE); - ret= dbus_bus_request_name(registry->droute.bus, SPI_DBUS_NAME_REGISTRY, 0, &error); + dbus_connection_setup_with_g_main(bus, NULL); - if (!ret) + ret = dbus_bus_request_name(bus, dbus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error); + if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) { -#ifdef AT_SPI_DEBUG - fprintf (stderr, "SpiRegistry Message: SpiRegistry daemon was already running.\n"); -#endif + g_error("Could not obtain D-Bus name - %s\n", dbus_name); } else { -#ifdef AT_SPI_DEBUG - fprintf (stderr, "SpiRegistry Message: SpiRegistry daemon is running.\n"); -#endif - registry_set_ior (registry); - g_main_loop_run (mainloop); + g_print ("SpiRegistry daemon is running with well-known name - %s\n", dbus_name); + } + + registry = spi_registry_new (bus); + dec = spi_registry_dec_new (registry, bus); + + if (use_gnome_session) + { + if (!session_manager_connect ()) + g_warning ("Unable to connect to session manager"); + + if (!register_client ()) + g_warning ("Unable to register client with session manager"); } + g_main_loop_run (mainloop); return 0; } -static void -registry_set_ior (SpiRegistry *registry){ - Atom AT_SPI_IOR = XInternAtom (spi_get_display (), "AT_SPI_IOR", FALSE); - char *iorstring = NULL; - - iorstring = SPI_DBUS_NAME_REGISTRY; - - XChangeProperty (spi_get_display(), - XDefaultRootWindow (spi_get_display ()), - AT_SPI_IOR, (Atom) 31, 8, - PropModeReplace, - (unsigned char *) iorstring, - iorstring ? strlen (iorstring) : 0); +static gboolean +need_to_quit () +{ + void *gconf = NULL; + gconf_client_get_default_t gconf_client_get_default = NULL; + gconf_client_get_bool_t gconf_client_get_bool = NULL; + GObject *gconf_client; /* really a GConfClient */ + gboolean ret; + + g_type_init (); + + gconf = dlopen ("libgconf-2.so", RTLD_LAZY); + if (gconf) + { + gconf_client_get_default = dlsym (gconf, "gconf_client_get_default"); + gconf_client_get_bool = dlsym (gconf, "gconf_client_get_bool"); + } + + if (!gconf_client_get_default || !gconf_client_get_bool) + { + if (gconf) + dlclose (gconf); + return FALSE; + } + + /* If we've been relocated, we will exit if the at-spi-corba gconf key + * has been set. If we have not been relocated, we will only run if the + * at-spi-dbus gconf key has been set. + */ + gconf_client = gconf_client_get_default (); + ret = gconf_client_get_bool (gconf_client, CORBA_GCONF_KEY, NULL); + g_object_unref (gconf_client); + + return ret; }