fe52c70ff1b133346da39a9fd114495be30db36a
[platform/core/uifw/at-spi2-atk.git] / registryd / desktop.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., 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 /* desktop.c: implements SpiDesktop.idl */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <libbonobo.h>
29 #include "desktop.h"
30
31 /* SpiDesktop signals */
32 enum {
33   APPLICATION_ADDED,
34   APPLICATION_REMOVED,  
35 LAST_SIGNAL
36 };
37 static guint spi_desktop_signals[LAST_SIGNAL];
38
39
40 /* Our parent Gtk object type */
41 #define PARENT_TYPE SPI_ACCESSIBLE_TYPE
42
43 typedef struct {
44         SpiDesktop *desktop;
45         Accessibility_Application ref;
46 } Application;
47
48 /* A pointer to our parent object class */
49 static SpiAccessibleClass *parent_class;
50
51 static void
52 spi_desktop_init (SpiDesktop *desktop)
53 {
54   spi_base_construct (SPI_BASE (desktop), g_object_new (ATK_TYPE_OBJECT, NULL));
55
56   desktop->applications = NULL;
57   bonobo_object_set_immortal (BONOBO_OBJECT (desktop), TRUE);
58
59   atk_object_set_name (ATK_OBJECT (SPI_BASE (desktop)->gobj), "main");
60 }
61
62 static void
63 spi_desktop_dispose (GObject *object)
64 {
65   SpiDesktop *desktop = (SpiDesktop *) object;
66
67   while (desktop->applications)
68     {
69       Application *app = desktop->applications->data;
70       g_assert (app->ref != CORBA_OBJECT_NIL);
71       spi_desktop_remove_application (desktop, app->ref);
72     }
73
74   G_OBJECT_CLASS (parent_class)->dispose (object); 
75 }
76
77 static CORBA_long
78 impl_desktop_get_child_count (PortableServer_Servant servant,
79                               CORBA_Environment     *ev)
80 {
81   SpiDesktop *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
82
83   if (desktop->applications)
84     {
85       return g_list_length (desktop->applications);
86     }
87   else
88     {
89       return 0;
90     }
91 }
92
93 static Accessibility_Accessible
94 impl_desktop_get_child_at_index (PortableServer_Servant servant,
95                                  const CORBA_long       index,
96                                  CORBA_Environment     *ev)
97 {
98   SpiDesktop  *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
99   CORBA_Object retval;
100   Application *app;
101
102   app = g_list_nth_data (desktop->applications, index);
103
104   if (app)
105     {
106       retval = bonobo_object_dup_ref (app->ref, ev);
107       if (BONOBO_EX (ev))
108         {
109           retval = CORBA_OBJECT_NIL;
110         }
111     }
112   else
113     {
114       retval = CORBA_OBJECT_NIL;
115     }
116
117   return (Accessibility_Accessible) retval;
118 }
119
120 static void
121 spi_desktop_class_init (SpiDesktopClass *klass)
122 {
123   GObjectClass * object_class = (GObjectClass *) klass;
124   SpiAccessibleClass * spi_accessible_class = (SpiAccessibleClass *) klass;
125   POA_Accessibility_Accessible__epv *epv = &spi_accessible_class->epv;
126
127   object_class->dispose = spi_desktop_dispose;
128   
129   parent_class = g_type_class_ref (SPI_ACCESSIBLE_TYPE);
130
131   spi_desktop_signals[APPLICATION_ADDED] =
132     g_signal_new ("application_added",
133                   G_TYPE_FROM_CLASS (klass),
134                   G_SIGNAL_RUN_LAST,
135                   G_STRUCT_OFFSET (SpiDesktopClass, application_added),
136                   NULL, NULL,
137                   g_cclosure_marshal_VOID__UINT,
138                   G_TYPE_NONE,
139                   1, G_TYPE_UINT);
140   spi_desktop_signals[APPLICATION_REMOVED] =
141     g_signal_new ("application_removed",
142                   G_TYPE_FROM_CLASS (klass),
143                   G_SIGNAL_RUN_LAST,
144                   G_STRUCT_OFFSET (SpiDesktopClass, application_removed),
145                   NULL, NULL,
146                   g_cclosure_marshal_VOID__UINT,
147                   G_TYPE_NONE,
148                   1, G_TYPE_UINT);
149   epv->_get_childCount = impl_desktop_get_child_count;
150   epv->getChildAtIndex = impl_desktop_get_child_at_index;
151 }
152
153 BONOBO_TYPE_FUNC_FULL (SpiDesktop,
154                        Accessibility_Desktop,
155                        PARENT_TYPE,
156                        spi_desktop);
157
158 SpiDesktop *
159 spi_desktop_new (void)
160 {
161   SpiDesktop *retval = g_object_new (SPI_DESKTOP_TYPE, NULL);
162
163   return retval;
164 }
165
166 static void
167 abnormal_application_termination (gpointer object, Application *app)
168 {
169   g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
170
171   spi_desktop_remove_application (app->desktop, app->ref);
172 }
173
174 void
175 spi_desktop_add_application (SpiDesktop *desktop,
176                              const Accessibility_Application application)
177 {
178   CORBA_Environment ev;
179   Application       *app;
180   Accessibility_Application ref;
181
182   g_return_if_fail (SPI_IS_DESKTOP (desktop));
183
184   spi_desktop_remove_application (desktop, application);
185
186   CORBA_exception_init (&ev);
187
188   ref = bonobo_object_dup_ref (application, &ev);
189
190   if (!BONOBO_EX (&ev))
191     {
192       app = g_new (Application, 1);
193       app->desktop = desktop;
194       app->ref = ref;
195
196       desktop->applications = g_list_append (desktop->applications, app);
197
198       ORBit_small_listen_for_broken (
199               app->ref, G_CALLBACK (abnormal_application_termination), app);
200
201       g_signal_emit (G_OBJECT (desktop),
202                      spi_desktop_signals[APPLICATION_ADDED], 0,
203                      g_list_index (desktop->applications, app));
204     }
205
206   CORBA_exception_free (&ev);
207 }
208
209 void
210 spi_desktop_remove_application (SpiDesktop *desktop,
211                                 const Accessibility_Application app_ref)
212 {
213   guint idx;
214   GList *l;
215   CORBA_Environment ev;
216
217   g_return_if_fail (app_ref != CORBA_OBJECT_NIL);
218   g_return_if_fail (SPI_IS_DESKTOP (desktop));
219
220   CORBA_exception_init (&ev);
221
222   idx = 0;
223   for (l = desktop->applications; l; l = l->next)
224     {
225       Application *app = (Application *) l->data;
226
227       if (CORBA_Object_is_equivalent (app->ref, app_ref, &ev))
228         {
229           break;
230         }
231       idx++;
232     }
233
234   CORBA_exception_free (&ev);
235
236   if (l)
237     {
238       Application *app = (Application *) l->data;
239
240       desktop->applications = g_list_delete_link (desktop->applications, l);
241
242       ORBit_small_unlisten_for_broken (app->ref, G_CALLBACK (abnormal_application_termination));
243       bonobo_object_release_unref (app->ref, NULL);
244       g_free (app);
245       
246       g_signal_emit (G_OBJECT (desktop), spi_desktop_signals[APPLICATION_REMOVED], 0, idx);
247     }
248 }