Merged Michael's branch back into HEAD, and fixed a number of reference counting...
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_main.c
1 /*
2  *
3  * Basic SPI initialization and event loop function prototypes
4  *
5  */
6 #include <string.h>
7 #include <stdlib.h>
8 #include <cspi/spi-private.h>
9
10 static CORBA_Environment ev = { 0 };
11 static Accessibility_Registry registry = CORBA_OBJECT_NIL;
12 static boolean is_gnome_app = FALSE;
13 static GSList *live_refs = NULL;
14
15 CORBA_Environment *
16 cspi_ev (void)
17 {
18   /* This method is an ugly hack */
19   return &ev;
20 }
21
22 Accessibility_Registry
23 cspi_registry (void)
24 {
25   return registry;
26 }
27
28 boolean
29 cspi_is_gnome_app (void)
30 {
31   return is_gnome_app;  
32 }
33
34 boolean
35 cspi_exception (void)
36 {
37   boolean retval;
38
39   if (BONOBO_EX (&ev))
40     {
41       CORBA_exception_free (&ev);
42       retval = TRUE;
43     }
44   else
45     {
46       retval = FALSE;
47     }
48
49   return retval;
50 }
51
52 Accessible *
53 cspi_object_add (CORBA_Object corba_object)
54 {
55   Accessible *ref;
56
57   if (corba_object != CORBA_OBJECT_NIL)
58     {
59       ref = g_new (Accessible, 1);
60
61       ref->objref = CORBA_Object_duplicate (corba_object, cspi_ev());
62       ref->ref_count = 1;
63
64       live_refs = g_slist_prepend (live_refs, ref);
65     }
66   else
67    {
68      ref = NULL;
69    }
70
71   return ref;
72 }
73
74 void
75 cspi_object_ref (Accessible *accessible)
76 {
77   g_return_if_fail (accessible != NULL);
78
79   accessible->ref_count++;
80 }
81
82 void
83 cspi_object_unref (Accessible *accessible)
84 {
85   g_return_if_fail (accessible != NULL);
86         
87   if (--accessible->ref_count == 0)
88     {
89       live_refs = g_slist_remove (live_refs, accessible);
90
91       bonobo_object_release_unref (accessible->objref, cspi_ev ());
92
93       cspi_check_ev (cspi_ev (), "unref");
94
95       memset (accessible, 0xaa, sizeof (Accessible));
96
97       g_free (accessible);
98     }
99 }
100
101 static void
102 cspi_cleanup (void)
103 {
104   GSList *l, *refs;
105
106   refs = live_refs;
107   live_refs = NULL;
108
109   for (l = refs; l; l = l->next)
110     {
111       Accessible *a = l->data;
112
113       g_print ("releasing %p\n", l->data);
114       bonobo_object_release_unref (a->objref, NULL);
115
116       g_free (a);
117     }
118
119   g_slist_free (refs);
120
121   if (registry != CORBA_OBJECT_NIL)
122     {
123       bonobo_object_release_unref (registry, NULL);
124       registry = CORBA_OBJECT_NIL;
125     }
126 }
127
128 /**
129  * SPI_init:
130  *
131  * Connects to the accessibility registry and initializes the SPI.
132  *
133  * Returns: 0 on success, otherwise an integer error code.
134  **/
135 int
136 SPI_init (void)
137 {
138   int argc = 0;
139   char *obj_id;
140   static gboolean inited = FALSE;
141
142   if (inited)
143     {
144       return 1;
145     }
146
147   inited = TRUE;
148
149   CORBA_exception_init (&ev);
150
151   if (!bonobo_init (&argc, NULL))
152     {
153       g_error ("Could not initialize Bonobo");
154     }
155
156   obj_id = "OAFIID:Accessibility_Registry:proto0.1";
157
158   registry = bonobo_activation_activate_from_id (
159           obj_id, 0, NULL, cspi_ev ());
160
161   if (ev._major != CORBA_NO_EXCEPTION)
162     {
163       g_error ("AT-SPI error: during registry activation: %s\n",
164                bonobo_exception_get_text (cspi_ev ()));
165     }
166
167   if (registry == CORBA_OBJECT_NIL)
168     {
169       g_error ("Could not locate registry");
170     }
171
172   Accessibility_Registry_ref (registry, &ev);
173   
174   bonobo_activate ();
175   
176   return 0;
177 }
178
179 /**
180  * SPI_event_main:
181  * @isGNOMEApp: a #boolean indicating whether the client of the SPI
182  *              will use the Gnome event loop or not.  Clients that have
183  *              their own GUIS will usually specify #TRUE here, and must
184  *              do so if they use Gnome GUI components.
185  *
186  * Starts/enters the main event loop for the SPI services.
187  *
188  * (NOTE: This method does not return control, it is exited via a call to SPI_exit()
189  * from within an event handler).
190  *
191  **/
192 void
193 SPI_event_main (boolean isGNOMEApp)
194 {
195   is_gnome_app = isGNOMEApp;
196   if (isGNOMEApp)
197     {
198       g_atexit (cspi_cleanup);
199       bonobo_main ();
200     }
201   else
202     {
203       /* TODO: install signal handlers to do cleanup */
204       CORBA_ORB_run (bonobo_orb (), cspi_ev ());
205       fprintf (stderr, "orb loop exited...\n");
206     }
207 }
208
209 /**
210  * SPI_eventIsReady:
211  *
212  * Checks to see if an SPI event is waiting in the event queue.
213  * Used by clients that don't wish to use SPI_event_main().
214  *
215  * Not Yet Implemented.
216  *
217  * Returns: #TRUE if an event is waiting, otherwise #FALSE.
218  *
219  **/
220 boolean
221 SPI_eventIsReady ()
222 {
223   return FALSE;
224 }
225
226 /**
227  * SPI_nextEvent:
228  * @waitForEvent: a #boolean indicating whether to block or not.
229  *
230  * Gets the next event in the SPI event queue; blocks if no event
231  * is pending and @waitForEvent is #TRUE.
232  * Used by clients that don't wish to use SPI_event_main().
233  *
234  * Not Yet Implemented.
235  *
236  * Returns: the next #AccessibleEvent in the SPI event queue.
237  **/
238 AccessibleEvent *
239 SPI_nextEvent (boolean waitForEvent)
240 {
241   return NULL;
242 }
243
244 /**
245  * SPI_exit:
246  *
247  * Disconnects from the Accessibility Registry and releases 
248  * any floating resources.
249  **/
250 void
251 SPI_exit (void)
252 {
253   cspi_cleanup();
254   if (cspi_is_gnome_app ())
255     {
256       bonobo_main_quit ();
257     }
258   else
259     {
260       CORBA_ORB_shutdown (bonobo_orb (), TRUE, cspi_ev ());         
261     }
262   fprintf (stderr, "bye-bye!\n");
263 }
264