Build fixes.
[platform/upstream/at-spi2-core.git] / registryd / registry-main.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <stdlib.h>
25 #include <config.h>
26 #include <string.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <stdio.h>
30 #include <dlfcn.h>
31
32 #include <dbus/dbus.h>
33
34 #include "paths.h"
35 #include "registry.h"
36 #include "deviceeventcontroller.h"
37 #include "atspi/atspi.h"
38
39 #define CORBA_GCONF_KEY  "/desktop/gnome/interface/at-spi-corba"
40
41 static gboolean need_to_quit ();
42
43 static GMainLoop *mainloop;
44 static gchar *dbus_name = NULL;
45 static gboolean use_gnome_session = FALSE;
46
47 static GOptionEntry optentries[] =
48 {
49   {"dbus-name", 0, 0, G_OPTION_ARG_STRING, &dbus_name, "Well-known name to register with D-Bus", NULL},
50   {"use-gnome-session", 0, 0, G_OPTION_ARG_NONE, &use_gnome_session, "Should register with gnome session manager", NULL},
51   {NULL}
52 };
53
54 static GDBusConnection *bus_connection = NULL;
55 static GDBusProxy      *sm_proxy = NULL;
56 static char            *client_id = NULL;
57 static GDBusProxy      *client_proxy = NULL;
58
59 #define SM_DBUS_NAME      "org.gnome.SessionManager"
60 #define SM_DBUS_PATH      "/org/gnome/SessionManager"
61 #define SM_DBUS_INTERFACE "org.gnome.SessionManager"
62
63 #define SM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
64
65 static void registry_session_init (const char *previous_client_id, const char *exe);
66
67 static void
68 on_session_over (GDBusProxy *proxy,
69                  gchar      *sender_name,
70                  gchar      *signal_name,
71                  GVariant   *parameters,
72                  gpointer    user_data)
73 {
74         if (g_strcmp0 (signal_name, "SessionOver") == 0) {
75                 g_main_loop_quit (mainloop);
76         }
77 }
78
79 static gboolean
80 session_manager_connect (void)
81 {
82
83         sm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, NULL,
84                                               SM_DBUS_NAME,
85                                               SM_DBUS_PATH,
86                                               SM_DBUS_INTERFACE, NULL, NULL);
87
88         g_signal_connect (G_OBJECT (sm_proxy), "g-signal",
89                           G_CALLBACK (on_session_over), NULL);
90
91         return (sm_proxy != NULL);
92 }
93
94 static void
95 stop_cb (gpointer data)
96 {
97         g_main_loop_quit (mainloop);
98 }
99
100 static gboolean
101 end_session_response (gboolean is_okay, const gchar *reason)
102 {
103   GVariant *ret;
104         GError *error = NULL;
105
106         if (!reason)
107                 reason = "";
108
109         ret = g_dbus_proxy_call_sync (client_proxy, "EndSessionResponse",
110                                       g_variant_new ("(bs)", is_okay, reason),
111                                       0, 1000, NULL, &error);
112
113         if (!ret) {
114                 g_warning ("Failed to send session response %s", error->message);
115                 g_error_free (error);
116                 return FALSE;
117         }
118         else
119                 g_variant_unref (ret);
120
121         return TRUE;
122 }
123
124 static void
125 client_proxy_signal_cb (GDBusProxy *proxy,
126                         gchar *sender_name,
127                         gchar *signal_name,
128                         GVariant *parameters,
129                         gpointer user_data)
130 {
131         if (g_strcmp0 (signal_name, "QueryEndSession") == 0) {
132                 g_debug ("Got QueryEndSession signal");
133                 end_session_response (TRUE, NULL);
134         } else if (g_strcmp0 (signal_name, "EndSession") == 0) {
135                 g_debug ("Got EndSession signal");
136                 end_session_response (TRUE, NULL);
137                 g_main_loop_quit (mainloop);
138         } else if (g_strcmp0 (signal_name, "Stop") == 0) {
139                 g_debug ("Got Stop signal");
140                 g_main_loop_quit (mainloop);
141         }
142 }
143
144 static gboolean
145 register_client (void)
146 {
147         GError     *error;
148   GVariant *res;
149         const char *startup_id;
150         const char *app_id;
151
152         startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
153         if (!startup_id)
154                 startup_id = "";
155         app_id = "at-spi-registryd.desktop";
156
157         error = NULL;
158         res = g_dbus_proxy_call_sync (sm_proxy,
159                                  "RegisterClient",
160                                       g_variant_new ("(ss)", app_id,
161                                                      startup_id),
162                                       0, 1000, NULL, &error);
163         if (! res) {
164                 g_warning ("Failed to register client: %s", error->message);
165                 g_error_free (error);
166                 return FALSE;
167         }
168         g_variant_get (res, "(o)", &client_id);
169         g_variant_unref (res);
170
171         client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, NULL,
172                                                   SM_DBUS_NAME,
173                                                   client_id,
174                                                   SM_CLIENT_DBUS_INTERFACE,
175                                                   NULL, NULL);
176
177         g_signal_connect (client_proxy, "g-signal",
178                           G_CALLBACK (client_proxy_signal_cb), NULL);
179
180         g_unsetenv ("DESKTOP_AUTOSTART_ID");
181
182         return TRUE;
183 }
184
185 /*---------------------------------------------------------------------------*/
186
187
188 /*---------------------------------------------------------------------------*/
189
190 typedef GObject *(*gconf_client_get_default_t) ();
191 typedef gboolean (*gconf_client_get_bool_t)(GObject *, const char *, void *);
192
193 int
194 main (int argc, char **argv)
195 {
196   SpiRegistry *registry;
197   SpiDEController *dec;
198
199   DBusConnection *bus = NULL;
200
201   GOptionContext *opt;
202
203   GError *err = NULL;
204   DBusError error;
205   int ret;
206
207   if (need_to_quit ())
208     return 0;
209
210   g_type_init();
211
212   /*Parse command options*/
213   opt = g_option_context_new(NULL);
214   g_option_context_add_main_entries(opt, optentries, NULL);
215
216   if (!g_option_context_parse(opt, &argc, &argv, &err))
217       g_error("Option parsing failed: %s\n", err->message);
218
219   if (dbus_name == NULL)
220       dbus_name = SPI_DBUS_NAME_REGISTRY;
221
222   dbus_error_init (&error);
223   bus = atspi_get_a11y_bus ();
224   if (!bus)
225   {
226     return 0;
227   }
228
229   mainloop = g_main_loop_new (NULL, FALSE);
230   atspi_dbus_connection_setup_with_g_main(bus, NULL);
231
232   ret = dbus_bus_request_name(bus, dbus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
233   if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
234     {
235       g_error("Could not obtain D-Bus name - %s\n", dbus_name);
236     }
237   else
238     {
239       g_print ("SpiRegistry daemon is running with well-known name - %s\n", dbus_name);
240     }
241
242   registry = spi_registry_new (bus);
243   dec = spi_registry_dec_new (registry, bus);
244
245   if (use_gnome_session)
246     {
247       if (!session_manager_connect ())
248           g_warning ("Unable to connect to session manager");
249
250       if (!register_client ())
251           g_warning ("Unable to register client with session manager");
252     }
253
254   g_main_loop_run (mainloop);
255   return 0;
256 }
257
258 static gboolean
259 need_to_quit ()
260 {
261   void *gconf = NULL;
262   gconf_client_get_default_t gconf_client_get_default = NULL;
263   gconf_client_get_bool_t gconf_client_get_bool = NULL;
264   GObject *gconf_client;        /* really a GConfClient */
265   gboolean ret;
266
267   g_type_init ();
268
269   gconf = dlopen ("libgconf-2.so", RTLD_LAZY);
270   if (gconf)
271     {
272       gconf_client_get_default = dlsym (gconf, "gconf_client_get_default");
273       gconf_client_get_bool = dlsym (gconf, "gconf_client_get_bool");
274   }
275
276   if (!gconf_client_get_default || !gconf_client_get_bool)
277     {
278       if (gconf)
279         dlclose (gconf);
280       return FALSE;
281     }
282
283   /* If we've been relocated, we will exit if the at-spi-corba gconf key
284  * has been set.  If we have not been relocated, we will only run if the
285  * at-spi-dbus gconf key has been set.
286    */
287   gconf_client = gconf_client_get_default ();
288   ret = gconf_client_get_bool (gconf_client, CORBA_GCONF_KEY, NULL);
289   g_object_unref (gconf_client);
290
291   return ret;
292 }