Add participation in gnome session management.
[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
29 #include <dbus/dbus.h>
30 #include <dbus/dbus-glib.h>
31
32 #include "paths.h"
33 #include "registry.h"
34 #include "deviceeventcontroller.h"
35
36 #if !defined ATSPI_INTROSPECTION_PATH
37     #error "No introspection XML directory defined"
38 #endif
39
40 static GMainLoop *mainloop;
41 static gchar *dbus_name = NULL;
42
43 static DBusGConnection *bus_connection = NULL;
44 static DBusGProxy      *sm_proxy = NULL;
45 static char            *client_id = NULL;
46 static DBusGProxy      *client_proxy = NULL;
47
48 static GOptionEntry optentries[] =
49 {
50   {"dbus-name", 0, 0, G_OPTION_ARG_STRING, &dbus_name, "Well-known name to register with D-Bus", NULL},
51   {NULL}
52 };
53
54 #define SM_DBUS_NAME      "org.gnome.SessionManager"
55 #define SM_DBUS_PATH      "/org/gnome/SessionManager"
56 #define SM_DBUS_INTERFACE "org.gnome.SessionManager"
57
58 #define SM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
59
60 static void registry_session_init (const char *previous_client_id, const char *exe);
61
62 static gboolean
63 session_manager_connect (void)
64 {
65
66         if (bus_connection == NULL) {
67                 GError *error;
68
69                 error = NULL;
70                 bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
71                 if (bus_connection == NULL) {
72                         g_message ("Failed to connect to the session bus: %s",
73                                    error->message);
74                         g_error_free (error);
75                         exit (1);
76                 }
77         }
78
79         sm_proxy = dbus_g_proxy_new_for_name (bus_connection,
80                                               SM_DBUS_NAME,
81                                               SM_DBUS_PATH,
82                                               SM_DBUS_INTERFACE);
83         return (sm_proxy != NULL);
84 }
85
86 static void
87 stop_cb (gpointer data)
88 {
89         g_main_loop_quit (mainloop);
90 }
91
92 static gboolean
93 end_session_response (gboolean is_okay, const gchar *reason)
94 {
95         gboolean ret;
96         GError *error = NULL;
97
98         ret = dbus_g_proxy_call (client_proxy, "EndSessionResponse",
99                                  &error,
100                                  G_TYPE_BOOLEAN, is_okay,
101                                  G_TYPE_STRING, reason,
102                                  G_TYPE_INVALID,
103                                  G_TYPE_INVALID);
104
105         if (!ret) {
106                 g_warning ("Failed to send session response %s", error->message);
107                 g_error_free (error);
108         }
109
110         return ret;
111 }
112
113 static void
114 query_end_session_cb (guint flags, gpointer data)
115 {
116         end_session_response (TRUE, NULL);
117 }
118
119 static void
120 end_session_cb (guint flags, gpointer data)
121 {
122         end_session_response (TRUE, NULL);
123         g_main_loop_quit (mainloop);
124 }
125 static gboolean
126 register_client (void)
127 {
128         GError     *error;
129         gboolean    res;
130         const char *startup_id;
131         const char *app_id;
132
133         startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
134         app_id = "at-spi-registryd.desktop";
135
136         error = NULL;
137         res = dbus_g_proxy_call (sm_proxy,
138                                  "RegisterClient",
139                                  &error,
140                                  G_TYPE_STRING, app_id,
141                                  G_TYPE_STRING, startup_id,
142                                  G_TYPE_INVALID,
143                                  DBUS_TYPE_G_OBJECT_PATH, &client_id,
144                                  G_TYPE_INVALID);
145         if (! res) {
146                 g_warning ("Failed to register client: %s", error->message);
147                 g_error_free (error);
148                 return FALSE;
149         }
150
151         client_proxy = dbus_g_proxy_new_for_name (bus_connection,
152                                                   SM_DBUS_NAME,
153                                                   client_id,
154                                                   SM_CLIENT_DBUS_INTERFACE);
155
156         dbus_g_proxy_add_signal (client_proxy, "Stop", G_TYPE_INVALID);
157         dbus_g_proxy_connect_signal (client_proxy, "Stop",
158                                      G_CALLBACK (stop_cb), NULL, NULL);
159
160         dbus_g_proxy_add_signal (client_proxy, "QueryEndSession", G_TYPE_UINT, G_TYPE_INVALID);
161         dbus_g_proxy_connect_signal (client_proxy, "QueryEndSession",
162                                      G_CALLBACK (query_end_session_cb), NULL, NULL);
163
164         dbus_g_proxy_add_signal (client_proxy, "EndSession", G_TYPE_UINT, G_TYPE_INVALID);
165         dbus_g_proxy_connect_signal (client_proxy, "EndSession",
166                                      G_CALLBACK (end_session_cb), NULL, NULL);
167
168         g_unsetenv ("DESKTOP_AUTOSTART_ID");
169
170         return TRUE;
171 }
172
173 int
174 main (int argc, char **argv)
175 {
176   SpiRegistry *registry;
177   SpiDEController *dec;
178   gchar *introspection_directory;
179
180   DBusConnection *bus;
181
182   GOptionContext *opt;
183
184   GError *err = NULL;
185   DBusError error;
186   int ret;
187
188   g_type_init();
189
190   /* We depend on GDK as well as XLib for device event processing */
191   gdk_init(&argc, &argv);
192
193   /*Parse command options*/
194   opt = g_option_context_new(NULL);
195   g_option_context_add_main_entries(opt, optentries, NULL);
196
197   if (!g_option_context_parse(opt, &argc, &argv, &err))
198       g_error("Option parsing failed: %s\n", err->message);
199
200   if (dbus_name == NULL)
201       dbus_name = SPI_DBUS_NAME_REGISTRY;
202
203   dbus_error_init (&error);
204   bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
205   if (!bus)
206   {
207     g_warning("Couldn't connect to dbus: %s\n", error.message);
208   }
209
210   mainloop = g_main_loop_new (NULL, FALSE);
211   dbus_connection_setup_with_g_main(bus, g_main_context_default());
212
213   ret = dbus_bus_request_name(bus, dbus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
214   if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
215     {
216       g_error("Could not obtain D-Bus name - %s\n", dbus_name);
217     }
218   else
219     {
220       g_print ("SpiRegistry daemon is running with well-known name - %s\n", dbus_name);
221     }
222
223   /* Get D-Bus introspection directory */
224   introspection_directory = (char *) g_getenv("ATSPI_INTROSPECTION_PATH");
225   if (introspection_directory == NULL)
226       introspection_directory = ATSPI_INTROSPECTION_PATH;
227
228   registry = spi_registry_new (bus);
229   dec = spi_registry_dec_new (registry, bus);
230
231   if (!session_manager_connect ())
232     {
233       g_warning ("Unable to connect to session manager");
234     }     
235
236   if (!register_client ())
237     {
238       g_warning ("Unable to register client with session manager");
239     }
240
241   g_main_loop_run (mainloop);
242   return 0;
243 }