xref: /aoo41x/main/vcl/unx/gtk/a11y/atkcomponent.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include "atkwrapper.hxx"
32 
33 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
34 
35 #ifdef ENABLE_TRACING
36 #include <stdio.h>
37 #endif
38 
39 using namespace ::com::sun::star;
40 
41 static accessibility::XAccessibleComponent*
42     getComponent( AtkComponent *pComponent ) throw (uno::RuntimeException)
43 {
44     AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pComponent );
45     if( pWrap )
46     {
47         if( !pWrap->mpComponent && pWrap->mpContext )
48         {
49             uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
50             pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
51             pWrap->mpComponent->acquire();
52         }
53 
54         return pWrap->mpComponent;
55     }
56 
57     return NULL;
58 }
59 
60 /*****************************************************************************/
61 
62 static awt::Point
63 translatePoint( accessibility::XAccessibleComponent *pComponent,
64                 gint x, gint y, AtkCoordType t)
65 {
66     awt::Point aOrigin( 0, 0 );
67     if( t == ATK_XY_SCREEN )
68         aOrigin = pComponent->getLocationOnScreen();
69 
70 #ifdef ENABLE_TRACING
71     fprintf(stderr, "coordinates ( %u, %u ) translated to: ( %u, %u )\n",
72         x, y, x - aOrigin.X, y - aOrigin.Y);
73 #endif
74 
75     return awt::Point( x - aOrigin.X, y - aOrigin.Y );
76 }
77 
78 /*****************************************************************************/
79 
80 extern "C" {
81 
82 static gboolean
83 component_wrapper_grab_focus (AtkComponent *component)
84 {
85     try
86     {
87         accessibility::XAccessibleComponent* pComponent = getComponent( component );
88         if( pComponent )
89         {
90             pComponent->grabFocus();
91             return TRUE;
92         }
93     }
94     catch( const uno::Exception &e )
95     {
96         g_warning( "Exception in grabFocus()" );
97     }
98 
99     return FALSE;
100 }
101 
102 /*****************************************************************************/
103 
104 static gboolean
105 component_wrapper_contains (AtkComponent *component,
106                             gint          x,
107                             gint          y,
108                             AtkCoordType  coord_type)
109 {
110     try
111     {
112         accessibility::XAccessibleComponent* pComponent = getComponent( component );
113         if( pComponent )
114             return pComponent->containsPoint( translatePoint( pComponent, x, y, coord_type ) );
115     }
116     catch( const uno::Exception &e )
117     {
118         g_warning( "Exception in containsPoint()" );
119     }
120 
121     return FALSE;
122 }
123 
124 /*****************************************************************************/
125 
126 static AtkObject *
127 component_wrapper_ref_accessible_at_point (AtkComponent *component,
128                                            gint          x,
129                                            gint          y,
130                                            AtkCoordType  coord_type)
131 {
132     try
133     {
134         accessibility::XAccessibleComponent* pComponent = getComponent( component );
135 
136         if( pComponent )
137         {
138             uno::Reference< accessibility::XAccessible > xAccessible;
139             xAccessible = pComponent->getAccessibleAtPoint(
140                 translatePoint( pComponent, x, y, coord_type ) );
141 
142 #ifdef ENABLE_TRACING
143             fprintf(stderr, "getAccessibleAtPoint( %u, %u ) returned %p\n",
144               x, y, xAccessible.get());
145 
146             uno::Reference< accessibility::XAccessibleComponent > xComponent(
147                 xAccessible->getAccessibleContext(), uno::UNO_QUERY );
148 
149             if( xComponent.is() )
150             {
151                 awt::Rectangle rect = xComponent->getBounds();
152                 fprintf(stderr, "%p->getBounds() returned: ( %u, %u, %u, %u )\n",
153                     xAccessible.get(), rect.X, rect.Y, rect.Width, rect.Height );
154             }
155 #endif
156 
157             return atk_object_wrapper_ref( xAccessible );
158         }
159     }
160     catch( const uno::Exception &e )
161     {
162         g_warning( "Exception in getAccessibleAtPoint()" );
163     }
164 
165     return NULL;
166 }
167 
168 /*****************************************************************************/
169 
170 static void
171 component_wrapper_get_position (AtkComponent   *component,
172                                 gint           *x,
173                                 gint           *y,
174                                 AtkCoordType   coord_type)
175 {
176     try
177     {
178         accessibility::XAccessibleComponent* pComponent = getComponent( component );
179         if( pComponent )
180         {
181             awt::Point aPos;
182 
183             if( coord_type == ATK_XY_SCREEN )
184                 aPos = pComponent->getLocationOnScreen();
185             else
186                 aPos = pComponent->getLocation();
187 
188             *x = aPos.X;
189             *y = aPos.Y;
190 
191 #ifdef ENABLE_TRACING
192             fprintf(stderr, "getLocation[OnScreen]() returned: ( %u, %u )\n", *x, *y );
193 #endif
194         }
195     }
196     catch( const uno::Exception &e )
197     {
198         g_warning( "Exception in getLocation[OnScreen]()" );
199     }
200 }
201 
202 /*****************************************************************************/
203 
204 static void
205 component_wrapper_get_size (AtkComponent   *component,
206                             gint           *width,
207                             gint           *height)
208 {
209     try
210     {
211         accessibility::XAccessibleComponent* pComponent = getComponent( component );
212         if( pComponent )
213         {
214             awt::Size aSize = pComponent->getSize();
215             *width = aSize.Width;
216             *height = aSize.Height;
217 
218 #ifdef ENABLE_TRACING
219             fprintf(stderr, "getSize() returned: ( %u, %u )\n", *width, *height );
220 #endif
221         }
222     }
223     catch( const uno::Exception &e )
224     {
225         g_warning( "Exception in getSize()" );
226     }
227 }
228 
229 /*****************************************************************************/
230 
231 static void
232 component_wrapper_get_extents (AtkComponent *component,
233                                gint         *x,
234                                gint         *y,
235                                gint         *width,
236                                gint         *height,
237                                AtkCoordType  coord_type)
238 {
239     component_wrapper_get_position( component, x, y, coord_type );
240     component_wrapper_get_size( component, width, height );
241 }
242 
243 /*****************************************************************************/
244 
245 static gboolean
246 component_wrapper_set_extents (AtkComponent *, gint, gint, gint, gint, AtkCoordType)
247 {
248     g_warning( "AtkComponent::set_extents unimplementable" );
249     return FALSE;
250 }
251 
252 /*****************************************************************************/
253 
254 static gboolean
255 component_wrapper_set_position (AtkComponent *, gint, gint, AtkCoordType)
256 {
257     g_warning( "AtkComponent::set_position unimplementable" );
258     return FALSE;
259 }
260 
261 /*****************************************************************************/
262 
263 static gboolean
264 component_wrapper_set_size (AtkComponent *, gint, gint)
265 {
266     g_warning( "AtkComponent::set_size unimplementable" );
267     return FALSE;
268 }
269 
270 /*****************************************************************************/
271 
272 static AtkLayer
273 component_wrapper_get_layer (AtkComponent   *component)
274 {
275     AtkRole role = atk_object_get_role( ATK_OBJECT( component ) );
276     AtkLayer layer = ATK_LAYER_WIDGET;
277 
278     switch (role)
279     {
280         case ATK_ROLE_POPUP_MENU:
281         case ATK_ROLE_MENU_ITEM:
282         case ATK_ROLE_CHECK_MENU_ITEM:
283         case ATK_ROLE_SEPARATOR:
284         case ATK_ROLE_LIST_ITEM:
285             layer = ATK_LAYER_POPUP;
286             break;
287         case ATK_ROLE_MENU:
288             {
289                 AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
290                 if( atk_object_get_role( parent ) != ATK_ROLE_MENU_BAR )
291                     layer = ATK_LAYER_POPUP;
292             }
293             break;
294 
295         case ATK_ROLE_LIST:
296             {
297                 AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
298                 if( atk_object_get_role( parent ) == ATK_ROLE_COMBO_BOX )
299                     layer = ATK_LAYER_POPUP;
300             }
301             break;
302 
303         default:
304             ;
305     }
306 
307     return layer;
308 }
309 
310 /*****************************************************************************/
311 
312 static gint
313 component_wrapper_get_mdi_zorder (AtkComponent   *)
314 {
315     // only needed for ATK_LAYER_MDI (not used) or ATK_LAYER_WINDOW (inherited from GAIL)
316     return G_MININT;
317 }
318 
319 /*****************************************************************************/
320 
321 // This code is mostly stolen from libgail ..
322 
323 static guint
324 component_wrapper_add_focus_handler (AtkComponent    *component,
325                                      AtkFocusHandler  handler)
326 {
327     GSignalMatchType match_type;
328     gulong ret;
329     guint signal_id;
330 
331     match_type = (GSignalMatchType) (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
332     signal_id = g_signal_lookup( "focus-event", ATK_TYPE_OBJECT );
333 
334     ret = g_signal_handler_find( component, match_type, signal_id, 0, NULL,
335                                  (gpointer) &handler, NULL);
336     if (!ret)
337     {
338         return g_signal_connect_closure_by_id (component,
339                                                signal_id, 0,
340                                                g_cclosure_new (
341                                                G_CALLBACK (handler), NULL,
342                                                (GClosureNotify) NULL),
343                                                FALSE);
344     }
345     else
346     {
347         return 0;
348     }
349 }
350 
351 /*****************************************************************************/
352 
353 static void
354 component_wrapper_remove_focus_handler (AtkComponent  *component,
355                                         guint         handler_id)
356 {
357     g_signal_handler_disconnect (component, handler_id);
358 }
359 
360 /*****************************************************************************/
361 
362 } // extern "C"
363 
364 void
365 componentIfaceInit (AtkComponentIface *iface)
366 {
367   g_return_if_fail (iface != NULL);
368 
369   iface->add_focus_handler = component_wrapper_add_focus_handler;
370   iface->contains = component_wrapper_contains;
371   iface->get_extents = component_wrapper_get_extents;
372   iface->get_layer = component_wrapper_get_layer;
373   iface->get_mdi_zorder = component_wrapper_get_mdi_zorder;
374   iface->get_position = component_wrapper_get_position;
375   iface->get_size = component_wrapper_get_size;
376   iface->grab_focus = component_wrapper_grab_focus;
377   iface->ref_accessible_at_point = component_wrapper_ref_accessible_at_point;
378   iface->remove_focus_handler = component_wrapper_remove_focus_handler;
379   iface->set_extents = component_wrapper_set_extents;
380   iface->set_position = component_wrapper_set_position;
381   iface->set_size = component_wrapper_set_size;
382 }
383