9258398ae813a04bb66dafd1b7cb80474b01029b
[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 <libspi/desktop.h>
29
30 /* Our parent Gtk object type */
31 #define PARENT_TYPE SPI_ACCESSIBLE_TYPE
32
33 typedef struct {
34         SpiDesktop *desktop;
35         Accessibility_Application ref;
36 } Application;
37
38 /* A pointer to our parent object class */
39 static SpiAccessibleClass *parent_class;
40
41 static void
42 spi_desktop_init (SpiDesktop *desktop)
43 {
44   spi_base_construct_default (SPI_BASE (desktop));
45
46   desktop->applications = NULL;
47
48   atk_object_set_name (SPI_BASE (desktop)->atko, "main");
49 }
50
51 static void
52 spi_desktop_dispose (GObject *object)
53 {
54   SpiDesktop *desktop = (SpiDesktop *) object;
55
56   while (desktop->applications)
57     {
58       Application *app = (Application *) desktop->applications;
59       spi_desktop_remove_application (desktop, app->ref);
60     }
61
62   G_OBJECT_CLASS (parent_class)->dispose (object); 
63 }
64
65 static CORBA_long
66 impl_desktop_get_child_count (PortableServer_Servant servant,
67                               CORBA_Environment     *ev)
68 {
69   SpiDesktop *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
70
71   if (desktop->applications)
72     {
73       return g_list_length (desktop->applications);
74     }
75   else
76     {
77       return 0;
78     }
79 }
80
81 static Accessibility_Accessible
82 impl_desktop_get_child_at_index (PortableServer_Servant servant,
83                                  const CORBA_long       index,
84                                  CORBA_Environment     *ev)
85 {
86   SpiDesktop  *desktop = SPI_DESKTOP (bonobo_object_from_servant (servant));
87   CORBA_Object retval;
88   Application *app;
89
90   app = g_list_nth_data (desktop->applications, index);
91
92   if (app)
93     {
94       retval = bonobo_object_dup_ref (app->ref, ev);
95       if (BONOBO_EX (ev))
96         {
97           CORBA_exception_free (ev);
98           CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
99                                ex_Accessibility_ChildGone, NULL);
100           retval = CORBA_OBJECT_NIL;
101         }
102     }
103   else
104     {
105       retval = CORBA_OBJECT_NIL;
106     }
107
108   return (Accessibility_Accessible) retval;
109 }
110
111 static void
112 spi_desktop_class_init (SpiDesktopClass *klass)
113 {
114   GObjectClass * object_class = (GObjectClass *) klass;
115   SpiAccessibleClass * spi_accessible_class = (SpiAccessibleClass *) klass;
116   POA_Accessibility_Accessible__epv *epv = &spi_accessible_class->epv;
117
118   object_class->dispose = spi_desktop_dispose;
119   
120   parent_class = g_type_class_ref (SPI_ACCESSIBLE_TYPE);
121
122   epv->_get_childCount = impl_desktop_get_child_count;
123   epv->getChildAtIndex = impl_desktop_get_child_at_index;
124 }
125
126 BONOBO_TYPE_FUNC_FULL (SpiDesktop,
127                        Accessibility_Desktop,
128                        PARENT_TYPE,
129                        spi_desktop);
130
131 SpiDesktop *
132 spi_desktop_new (void)
133 {
134   SpiDesktop *retval = g_object_new (SPI_DESKTOP_TYPE, NULL);
135
136   return retval;
137 }
138
139 static void
140 abnormal_application_termination (gpointer object, Application *app)
141 {
142   g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
143
144   spi_desktop_remove_application (app->desktop, app->ref);
145 }
146
147 void
148 spi_desktop_add_application (SpiDesktop *desktop,
149                              const Accessibility_Application application)
150 {
151   CORBA_Environment ev;
152   Application       *app;
153   Accessibility_Application ref;
154
155   g_return_if_fail (SPI_IS_DESKTOP (desktop));
156
157   spi_desktop_remove_application (desktop, application);
158
159   CORBA_exception_init (&ev);
160
161   ref = bonobo_object_dup_ref (application, &ev);
162
163   if (!BONOBO_EX (&ev))
164     {
165       app = g_new (Application, 1);
166       app->desktop = desktop;
167       app->ref = ref;
168
169       desktop->applications = g_list_append (desktop->applications, app);
170
171       ORBit_small_listen_for_broken (app->ref, G_CALLBACK (abnormal_application_termination), app);
172     }
173
174   CORBA_exception_free (&ev);
175 }
176
177 void
178 spi_desktop_remove_application (SpiDesktop *desktop,
179                                 const Accessibility_Application app_ref)
180 {
181   GList *l;
182   CORBA_Environment ev;
183
184   g_return_if_fail (SPI_IS_DESKTOP (desktop));
185
186   CORBA_exception_init (&ev);
187
188   for (l = desktop->applications; l; l = l->next)
189     {
190       Application *app = (Application *) l->data;
191
192       if (CORBA_Object_is_equivalent (app->ref, app_ref, &ev))
193         {
194           break;
195         }
196     }
197
198   CORBA_exception_free (&ev);
199
200   if (l)
201     {
202       Application *app = (Application *) l->data;
203
204       desktop->applications = g_list_delete_link (desktop->applications, l);
205
206       ORBit_small_unlisten_for_broken (app->ref, G_CALLBACK (abnormal_application_termination));
207       bonobo_object_release_unref (app->ref, NULL);
208       g_free (app);
209     }
210 }