* atk-bridge/bridge.c:
[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 Sun Microsystems Inc., Ximian Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /* desktop.c: implements SpiDesktop.idl */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <libbonobo.h>
28 #include "desktop.h"
29
30 /* SpiDesktop signals */
31 enum {
32   APPLICATION_ADDED,
33   APPLICATION_REMOVED,  
34 LAST_SIGNAL
35 };
36 static guint spi_desktop_signals[LAST_SIGNAL];
37
38
39 /* Our parent Gtk object type */
40 #define PARENT_TYPE SPI_ACCESSIBLE_TYPE
41
42 typedef struct {
43         SpiDesktop *desktop;
44         Accessibility_Application ref;
45 } Application;
46
47 /* A pointer to our parent object class */
48 static SpiAccessibleClass *parent_class;
49
50 static void
51 spi_desktop_init (SpiDesktop *desktop)
52 {
53   spi_base_construct (SPI_BASE (desktop), g_object_new (ATK_TYPE_OBJECT, NULL));
54
55   desktop->applications = NULL;
56   bonobo_object_set_immortal (BONOBO_OBJECT (desktop), TRUE);
57
58   atk_object_set_name (ATK_OBJECT (SPI_BASE (desktop)->gobj), "main");
59 }
60
61 static void
62 spi_desktop_dispose (GObject *object)
63 {
64   SpiDesktop *desktop = (SpiDesktop *) object;
65
66   while (desktop->applications)
67     {
68       Application *app = desktop->applications->data;
69       g_assert (app->ref != CORBA_OBJECT_NIL);
70       spi_desktop_remove_application (desktop, app->ref);
71     }
72
73   G_OBJECT_CLASS (parent_class)->dispose (object); 
74 }
75
76 static CORBA_long
77 impl_desktop_get_child_count (PortableServer_Servant servant,
78                               CORBA_Environment     *ev)
79 {
80   SpiDesktop *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
81
82   if (desktop->applications)
83     {
84       return g_list_length (desktop->applications);
85     }
86   else
87     {
88       return 0;
89     }
90 }
91
92 static Accessibility_Accessible
93 impl_desktop_get_child_at_index (PortableServer_Servant servant,
94                                  const CORBA_long       index,
95                                  CORBA_Environment     *ev)
96 {
97   SpiDesktop  *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
98   CORBA_Object retval;
99   Application *app;
100
101   app = g_list_nth_data (desktop->applications, index);
102
103   if (app)
104     {
105       retval = bonobo_object_dup_ref (app->ref, ev);
106       if (BONOBO_EX (ev))
107         {
108           retval = CORBA_OBJECT_NIL;
109         }
110     }
111   else
112     {
113       retval = CORBA_OBJECT_NIL;
114     }
115
116   return (Accessibility_Accessible) retval;
117 }
118
119 static void
120 spi_desktop_class_init (SpiDesktopClass *klass)
121 {
122   GObjectClass * object_class = (GObjectClass *) klass;
123   SpiAccessibleClass * spi_accessible_class = (SpiAccessibleClass *) klass;
124   POA_Accessibility_Accessible__epv *epv = &spi_accessible_class->epv;
125
126   object_class->dispose = spi_desktop_dispose;
127   
128   parent_class = g_type_class_ref (SPI_ACCESSIBLE_TYPE);
129
130   spi_desktop_signals[APPLICATION_ADDED] =
131     g_signal_new ("application_added",
132                   G_TYPE_FROM_CLASS (klass),
133                   G_SIGNAL_RUN_LAST,
134                   G_STRUCT_OFFSET (SpiDesktopClass, application_added),
135                   NULL, NULL,
136                   g_cclosure_marshal_VOID__UINT,
137                   G_TYPE_NONE,
138                   1, G_TYPE_UINT);
139   spi_desktop_signals[APPLICATION_REMOVED] =
140     g_signal_new ("application_removed",
141                   G_TYPE_FROM_CLASS (klass),
142                   G_SIGNAL_RUN_LAST,
143                   G_STRUCT_OFFSET (SpiDesktopClass, application_removed),
144                   NULL, NULL,
145                   g_cclosure_marshal_VOID__UINT,
146                   G_TYPE_NONE,
147                   1, G_TYPE_UINT);
148   epv->_get_childCount = impl_desktop_get_child_count;
149   epv->getChildAtIndex = impl_desktop_get_child_at_index;
150 }
151
152 BONOBO_TYPE_FUNC_FULL (SpiDesktop,
153                        Accessibility_Desktop,
154                        PARENT_TYPE,
155                        spi_desktop);
156
157 SpiDesktop *
158 spi_desktop_new (void)
159 {
160   SpiDesktop *retval = g_object_new (SPI_DESKTOP_TYPE, NULL);
161
162   return retval;
163 }
164
165 static void
166 abnormal_application_termination (gpointer object, Application *app)
167 {
168   g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
169
170   spi_desktop_remove_application (app->desktop, app->ref);
171 }
172
173 void
174 spi_desktop_add_application (SpiDesktop *desktop,
175                              const Accessibility_Application application)
176 {
177   CORBA_Environment ev;
178   Application       *app;
179   Accessibility_Application ref;
180
181   g_return_if_fail (SPI_IS_DESKTOP (desktop));
182
183   spi_desktop_remove_application (desktop, application);
184
185   CORBA_exception_init (&ev);
186
187   ref = bonobo_object_dup_ref (application, &ev);
188
189   if (!BONOBO_EX (&ev))
190     {
191       app = g_new (Application, 1);
192       app->desktop = desktop;
193       app->ref = ref;
194
195       desktop->applications = g_list_append (desktop->applications, app);
196
197       ORBit_small_listen_for_broken (
198               app->ref, G_CALLBACK (abnormal_application_termination), app);
199
200       g_signal_emit (G_OBJECT (desktop),
201                      spi_desktop_signals[APPLICATION_ADDED], 0,
202                      g_list_index (desktop->applications, app));
203     }
204
205   CORBA_exception_free (&ev);
206 }
207
208 void
209 spi_desktop_remove_application (SpiDesktop *desktop,
210                                 const Accessibility_Application app_ref)
211 {
212   guint idx;
213   GList *l;
214   CORBA_Environment ev;
215
216   g_return_if_fail (app_ref != CORBA_OBJECT_NIL);
217   g_return_if_fail (SPI_IS_DESKTOP (desktop));
218
219   CORBA_exception_init (&ev);
220
221   idx = 0;
222   for (l = desktop->applications; l; l = l->next)
223     {
224       Application *app = (Application *) l->data;
225
226       if (CORBA_Object_is_equivalent (app->ref, app_ref, &ev))
227         {
228           break;
229         }
230       idx++;
231     }
232
233   CORBA_exception_free (&ev);
234
235   if (l)
236     {
237       Application *app = (Application *) l->data;
238
239       desktop->applications = g_list_delete_link (desktop->applications, l);
240
241       ORBit_small_unlisten_for_broken (app->ref, G_CALLBACK (abnormal_application_termination));
242       bonobo_object_release_unref (app->ref, NULL);
243       g_free (app);
244       
245       g_signal_emit (G_OBJECT (desktop), spi_desktop_signals[APPLICATION_REMOVED], 0, idx);
246     }
247 }