Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <com/sun/star/uno/Any.hxx>
31 : : #include <com/sun/star/uno/Type.hxx>
32 : : #include <com/sun/star/uno/Sequence.hxx>
33 : : #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 : : #include <com/sun/star/accessibility/AccessibleRelation.hpp>
35 : : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
36 : : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 : : #include <com/sun/star/accessibility/XAccessible.hpp>
38 : : #include <com/sun/star/accessibility/XAccessibleText.hpp>
39 : : #include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
40 : : #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
41 : : #include <com/sun/star/accessibility/XAccessibleValue.hpp>
42 : : #include <com/sun/star/accessibility/XAccessibleAction.hpp>
43 : : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
44 : : #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
45 : : #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
46 : : #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
47 : : #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
48 : : #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
49 : : #include <com/sun/star/accessibility/XAccessibleTable.hpp>
50 : : #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
51 : : #include <com/sun/star/accessibility/XAccessibleImage.hpp>
52 : : #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
53 : : #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
54 : : #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
55 : : #include <com/sun/star/awt/XExtendedToolkit.hpp>
56 : : #include <com/sun/star/awt/XTopWindow.hpp>
57 : : #include <com/sun/star/awt/XTopWindowListener.hpp>
58 : : #include <com/sun/star/awt/XWindow.hpp>
59 : : #include <com/sun/star/lang/XComponent.hpp>
60 : : #include <com/sun/star/lang/XServiceInfo.hpp>
61 : : #include <com/sun/star/lang/XInitialization.hpp>
62 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 : : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
64 : : #include <com/sun/star/beans/Property.hpp>
65 : :
66 : : #include <rtl/ref.hxx>
67 : : #include <cppuhelper/factory.hxx>
68 : : #include <cppuhelper/queryinterface.hxx>
69 : :
70 : : #include "atkwrapper.hxx"
71 : : #include "atkregistry.hxx"
72 : : #include "atklistener.hxx"
73 : :
74 : : #ifdef ENABLE_TRACING
75 : : #include <stdio.h>
76 : : #endif
77 : :
78 : : #include <string.h>
79 : :
80 : : using namespace ::com::sun::star;
81 : :
82 : : static GObjectClass *parent_class = NULL;
83 : :
84 : 0 : static AtkRelationType mapRelationType( sal_Int16 nRelation )
85 : : {
86 : 0 : AtkRelationType type = ATK_RELATION_NULL;
87 : :
88 : 0 : switch( nRelation )
89 : : {
90 : : case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
91 : 0 : type = ATK_RELATION_FLOWS_FROM;
92 : 0 : break;
93 : :
94 : : case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
95 : 0 : type = ATK_RELATION_FLOWS_TO;
96 : 0 : break;
97 : :
98 : : case accessibility::AccessibleRelationType::CONTROLLED_BY:
99 : 0 : type = ATK_RELATION_CONTROLLED_BY;
100 : 0 : break;
101 : :
102 : : case accessibility::AccessibleRelationType::CONTROLLER_FOR:
103 : 0 : type = ATK_RELATION_CONTROLLER_FOR;
104 : 0 : break;
105 : :
106 : : case accessibility::AccessibleRelationType::LABEL_FOR:
107 : 0 : type = ATK_RELATION_LABEL_FOR;
108 : 0 : break;
109 : :
110 : : case accessibility::AccessibleRelationType::LABELED_BY:
111 : 0 : type = ATK_RELATION_LABELLED_BY;
112 : 0 : break;
113 : :
114 : : case accessibility::AccessibleRelationType::MEMBER_OF:
115 : 0 : type = ATK_RELATION_MEMBER_OF;
116 : 0 : break;
117 : :
118 : : case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
119 : 0 : type = ATK_RELATION_SUBWINDOW_OF;
120 : 0 : break;
121 : :
122 : : case accessibility::AccessibleRelationType::NODE_CHILD_OF:
123 : 0 : type = ATK_RELATION_NODE_CHILD_OF;
124 : 0 : break;
125 : :
126 : : default:
127 : 0 : break;
128 : : }
129 : :
130 : 0 : return type;
131 : : }
132 : :
133 : :
134 : 0 : AtkStateType mapAtkState( sal_Int16 nState )
135 : : {
136 : 0 : AtkStateType type = ATK_STATE_INVALID;
137 : :
138 : : // A perfect / complete mapping ...
139 : 0 : switch( nState )
140 : : {
141 : : #define MAP_DIRECT( a ) \
142 : : case accessibility::AccessibleStateType::a: \
143 : : type = ATK_STATE_##a; break
144 : :
145 : 0 : MAP_DIRECT( INVALID );
146 : 0 : MAP_DIRECT( ACTIVE );
147 : 0 : MAP_DIRECT( ARMED );
148 : 0 : MAP_DIRECT( BUSY );
149 : 0 : MAP_DIRECT( CHECKED );
150 : 0 : MAP_DIRECT( EDITABLE );
151 : 0 : MAP_DIRECT( ENABLED );
152 : 0 : MAP_DIRECT( EXPANDABLE );
153 : 0 : MAP_DIRECT( EXPANDED );
154 : 0 : MAP_DIRECT( FOCUSABLE );
155 : 0 : MAP_DIRECT( FOCUSED );
156 : 0 : MAP_DIRECT( HORIZONTAL );
157 : 0 : MAP_DIRECT( ICONIFIED );
158 : 0 : MAP_DIRECT( INDETERMINATE );
159 : 0 : MAP_DIRECT( MANAGES_DESCENDANTS );
160 : 0 : MAP_DIRECT( MODAL );
161 : 0 : MAP_DIRECT( MULTI_LINE );
162 : 0 : MAP_DIRECT( OPAQUE );
163 : 0 : MAP_DIRECT( PRESSED );
164 : 0 : MAP_DIRECT( RESIZABLE );
165 : 0 : MAP_DIRECT( SELECTABLE );
166 : 0 : MAP_DIRECT( SELECTED );
167 : 0 : MAP_DIRECT( SENSITIVE );
168 : 0 : MAP_DIRECT( SHOWING );
169 : 0 : MAP_DIRECT( SINGLE_LINE );
170 : 0 : MAP_DIRECT( STALE );
171 : 0 : MAP_DIRECT( TRANSIENT );
172 : 0 : MAP_DIRECT( VERTICAL );
173 : 0 : MAP_DIRECT( VISIBLE );
174 : : // a spelling error ...
175 : : case accessibility::AccessibleStateType::DEFUNC:
176 : 0 : type = ATK_STATE_DEFUNCT; break;
177 : : case accessibility::AccessibleStateType::MULTI_SELECTABLE:
178 : 0 : type = ATK_STATE_MULTISELECTABLE; break;
179 : : default:
180 : 0 : break;
181 : : }
182 : :
183 : 0 : return type;
184 : : }
185 : :
186 : 0 : static inline AtkRole registerRole( const gchar * name )
187 : : {
188 : 0 : AtkRole ret = atk_role_for_name( name );
189 : 0 : if( ATK_ROLE_INVALID == ret )
190 : 0 : ret = atk_role_register( name );
191 : :
192 : 0 : return ret;
193 : : }
194 : :
195 : 0 : static AtkRole mapToAtkRole( sal_Int16 nRole )
196 : : {
197 : 0 : AtkRole role = ATK_ROLE_UNKNOWN;
198 : :
199 : : static AtkRole roleMap[] = {
200 : : ATK_ROLE_UNKNOWN,
201 : : ATK_ROLE_ALERT,
202 : : ATK_ROLE_COLUMN_HEADER,
203 : : ATK_ROLE_CANVAS,
204 : : ATK_ROLE_CHECK_BOX,
205 : : ATK_ROLE_CHECK_MENU_ITEM,
206 : : ATK_ROLE_COLOR_CHOOSER,
207 : : ATK_ROLE_COMBO_BOX,
208 : : ATK_ROLE_DATE_EDITOR,
209 : : ATK_ROLE_DESKTOP_ICON,
210 : : ATK_ROLE_DESKTOP_FRAME, // ? pane
211 : : ATK_ROLE_DIRECTORY_PANE,
212 : : ATK_ROLE_DIALOG,
213 : : ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
214 : : ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
215 : : ATK_ROLE_UNKNOWN, // END_NOTE - registered below
216 : : ATK_ROLE_FILE_CHOOSER,
217 : : ATK_ROLE_FILLER,
218 : : ATK_ROLE_FONT_CHOOSER,
219 : : ATK_ROLE_FOOTER,
220 : : ATK_ROLE_TEXT, // FOOTNOTE - registered below
221 : : ATK_ROLE_FRAME,
222 : : ATK_ROLE_GLASS_PANE,
223 : : ATK_ROLE_IMAGE, // GRAPHIC
224 : : ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
225 : : ATK_ROLE_HEADER,
226 : : ATK_ROLE_PARAGRAPH, // HEADING - registered below
227 : : ATK_ROLE_TEXT, // HYPER_LINK - registered below
228 : : ATK_ROLE_ICON,
229 : : ATK_ROLE_INTERNAL_FRAME,
230 : : ATK_ROLE_LABEL,
231 : : ATK_ROLE_LAYERED_PANE,
232 : : ATK_ROLE_LIST,
233 : : ATK_ROLE_LIST_ITEM,
234 : : ATK_ROLE_MENU,
235 : : ATK_ROLE_MENU_BAR,
236 : : ATK_ROLE_MENU_ITEM,
237 : : ATK_ROLE_OPTION_PANE,
238 : : ATK_ROLE_PAGE_TAB,
239 : : ATK_ROLE_PAGE_TAB_LIST,
240 : : ATK_ROLE_PANEL,
241 : : ATK_ROLE_PARAGRAPH,
242 : : ATK_ROLE_PASSWORD_TEXT,
243 : : ATK_ROLE_POPUP_MENU,
244 : : ATK_ROLE_PUSH_BUTTON,
245 : : ATK_ROLE_PROGRESS_BAR,
246 : : ATK_ROLE_RADIO_BUTTON,
247 : : ATK_ROLE_RADIO_MENU_ITEM,
248 : : ATK_ROLE_ROW_HEADER,
249 : : ATK_ROLE_ROOT_PANE,
250 : : ATK_ROLE_SCROLL_BAR,
251 : : ATK_ROLE_SCROLL_PANE,
252 : : ATK_ROLE_UNKNOWN, // SHAPE - registered below
253 : : ATK_ROLE_SEPARATOR,
254 : : ATK_ROLE_SLIDER,
255 : : ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
256 : : ATK_ROLE_SPLIT_PANE,
257 : : ATK_ROLE_STATUSBAR,
258 : : ATK_ROLE_TABLE,
259 : : ATK_ROLE_TABLE_CELL,
260 : : ATK_ROLE_TEXT,
261 : : ATK_ROLE_INTERNAL_FRAME, // TEXT_FRAME - registered below
262 : : ATK_ROLE_TOGGLE_BUTTON,
263 : : ATK_ROLE_TOOL_BAR,
264 : : ATK_ROLE_TOOL_TIP,
265 : : ATK_ROLE_TREE,
266 : : ATK_ROLE_VIEWPORT,
267 : : ATK_ROLE_WINDOW,
268 : : ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
269 : : ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
270 : : ATK_ROLE_UNKNOWN, // CAPTION - registered below
271 : : ATK_ROLE_UNKNOWN, // CHART - registered below
272 : : ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
273 : : ATK_ROLE_UNKNOWN, // FORM - registered below
274 : : ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
275 : : ATK_ROLE_UNKNOWN, // NOTE - registered below
276 : : ATK_ROLE_UNKNOWN, // PAGE - registered below
277 : : ATK_ROLE_RULER,
278 : : ATK_ROLE_UNKNOWN, // SECTION - registered below
279 : : ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
280 : : ATK_ROLE_TREE_TABLE,
281 : : ATK_ROLE_SCROLL_PANE, // COMMENT - mapped to atk_role_scroll_pane
282 : : ATK_ROLE_UNKNOWN // COMMENT_END - mapped to atk_role_unknown
283 : : };
284 : :
285 : : static bool initialized = false;
286 : :
287 : 0 : if( ! initialized )
288 : : {
289 : : // re-use strings from ATK library
290 : 0 : roleMap[accessibility::AccessibleRole::EDIT_BAR] = registerRole("edit bar");
291 : 0 : roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = registerRole("embedded component");
292 : 0 : roleMap[accessibility::AccessibleRole::CHART] = registerRole("chart");
293 : 0 : roleMap[accessibility::AccessibleRole::CAPTION] = registerRole("caption");
294 : 0 : roleMap[accessibility::AccessibleRole::DOCUMENT] = registerRole("document frame");
295 : 0 : roleMap[accessibility::AccessibleRole::HEADING] = registerRole("heading");
296 : 0 : roleMap[accessibility::AccessibleRole::PAGE] = registerRole("page");
297 : 0 : roleMap[accessibility::AccessibleRole::SECTION] = registerRole("section");
298 : 0 : roleMap[accessibility::AccessibleRole::FORM] = registerRole("form");
299 : :
300 : : // these don't exist in ATK yet
301 : 0 : roleMap[accessibility::AccessibleRole::END_NOTE] = registerRole("end note");
302 : 0 : roleMap[accessibility::AccessibleRole::FOOTNOTE] = registerRole("foot note");
303 : 0 : roleMap[accessibility::AccessibleRole::GROUP_BOX] = registerRole("group box");
304 : 0 : roleMap[accessibility::AccessibleRole::HYPER_LINK] = registerRole("hyper link");
305 : 0 : roleMap[accessibility::AccessibleRole::SHAPE] = registerRole("shape");
306 : 0 : roleMap[accessibility::AccessibleRole::TEXT_FRAME] = registerRole("text frame");
307 : 0 : roleMap[accessibility::AccessibleRole::IMAGE_MAP] = registerRole("image map");
308 : 0 : roleMap[accessibility::AccessibleRole::NOTE] = registerRole("note");
309 : 0 : roleMap[accessibility::AccessibleRole::TREE_ITEM] = registerRole("tree item");
310 : :
311 : 0 : initialized = true;
312 : : }
313 : :
314 : : static const sal_Int32 nMapSize = SAL_N_ELEMENTS(roleMap);
315 : 0 : if( 0 <= nRole && nMapSize > nRole )
316 : 0 : role = roleMap[nRole];
317 : :
318 : 0 : return role;
319 : : }
320 : :
321 : :
322 : : /*****************************************************************************/
323 : :
324 : : extern "C" {
325 : :
326 : : /*****************************************************************************/
327 : :
328 : : static G_CONST_RETURN gchar*
329 : 0 : wrapper_get_name( AtkObject *atk_obj )
330 : : {
331 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
332 : :
333 : 0 : if( obj->mpContext )
334 : : {
335 : : try {
336 : : rtl::OString aName =
337 : : rtl::OUStringToOString(
338 : 0 : obj->mpContext->getAccessibleName(),
339 : 0 : RTL_TEXTENCODING_UTF8);
340 : :
341 : 0 : int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
342 : 0 : if( nCmp != 0 )
343 : : {
344 : 0 : if( atk_obj->name )
345 : 0 : g_free(atk_obj->name);
346 : 0 : atk_obj->name = g_strdup(aName.getStr());
347 : 0 : }
348 : : }
349 : 0 : catch(const uno::Exception& e) {
350 : 0 : g_warning( "Exception in getAccessibleName()" );
351 : : }
352 : : }
353 : :
354 : 0 : return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
355 : : }
356 : :
357 : : /*****************************************************************************/
358 : :
359 : : static G_CONST_RETURN gchar*
360 : 0 : wrapper_get_description( AtkObject *atk_obj )
361 : : {
362 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
363 : :
364 : 0 : if( obj->mpContext )
365 : : {
366 : : try {
367 : : rtl::OString aDescription =
368 : : rtl::OUStringToOString(
369 : 0 : obj->mpContext->getAccessibleDescription(),
370 : 0 : RTL_TEXTENCODING_UTF8);
371 : :
372 : 0 : g_free(atk_obj->description);
373 : 0 : atk_obj->description = g_strdup(aDescription.getStr());
374 : : }
375 : 0 : catch(const uno::Exception& e) {
376 : 0 : g_warning( "Exception in getAccessibleDescription()" );
377 : : }
378 : : }
379 : :
380 : 0 : return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
381 : :
382 : : }
383 : :
384 : : /*****************************************************************************/
385 : :
386 : : static gint
387 : 0 : wrapper_get_n_children( AtkObject *atk_obj )
388 : : {
389 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
390 : 0 : gint n = 0;
391 : :
392 : 0 : if( obj->mpContext )
393 : : {
394 : : try {
395 : 0 : n = obj->mpContext->getAccessibleChildCount();
396 : : }
397 : 0 : catch(const uno::Exception& e) {
398 : : OSL_FAIL("Exception in getAccessibleChildCount()" );
399 : : }
400 : : }
401 : :
402 : 0 : return n;
403 : : }
404 : :
405 : : /*****************************************************************************/
406 : :
407 : : static AtkObject *
408 : 0 : wrapper_ref_child( AtkObject *atk_obj,
409 : : gint i )
410 : : {
411 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
412 : 0 : AtkObject* child = NULL;
413 : :
414 : : // see comments above atk_object_wrapper_remove_child
415 : 0 : if( -1 < i && obj->index_of_child_about_to_be_removed == i )
416 : : {
417 : 0 : g_object_ref( obj->child_about_to_be_removed );
418 : 0 : return obj->child_about_to_be_removed;
419 : : }
420 : :
421 : 0 : if( obj->mpContext )
422 : : {
423 : : try {
424 : : uno::Reference< accessibility::XAccessible > xAccessible =
425 : 0 : obj->mpContext->getAccessibleChild( i );
426 : :
427 : 0 : child = atk_object_wrapper_ref( xAccessible );
428 : : }
429 : 0 : catch(const uno::Exception& e) {
430 : : OSL_FAIL("Exception in getAccessibleChild");
431 : : }
432 : : }
433 : :
434 : 0 : return child;
435 : : }
436 : :
437 : : /*****************************************************************************/
438 : :
439 : : static gint
440 : 0 : wrapper_get_index_in_parent( AtkObject *atk_obj )
441 : : {
442 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
443 : 0 : gint i = -1;
444 : :
445 : 0 : if( obj->mpContext )
446 : : {
447 : : try {
448 : 0 : i = obj->mpContext->getAccessibleIndexInParent();
449 : :
450 : : #ifdef ENABLE_TRACING
451 : : fprintf(stderr, "%p->getAccessibleIndexInParent() returned: %u\n",
452 : : obj->mpAccessible, i);
453 : : #endif
454 : : }
455 : 0 : catch(const uno::Exception& e) {
456 : 0 : g_warning( "Exception in getAccessibleIndexInParent()" );
457 : : }
458 : : }
459 : 0 : return i;
460 : : }
461 : :
462 : : /*****************************************************************************/
463 : :
464 : : static AtkRelationSet *
465 : 0 : wrapper_ref_relation_set( AtkObject *atk_obj )
466 : : {
467 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
468 : 0 : AtkRelationSet *pSet = atk_relation_set_new();
469 : :
470 : 0 : if( obj->mpContext )
471 : : {
472 : : try {
473 : : uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
474 : 0 : obj->mpContext->getAccessibleRelationSet()
475 : 0 : );
476 : :
477 : 0 : sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
478 : 0 : for( sal_Int32 n = 0; n < nRelations; n++ )
479 : : {
480 : 0 : accessibility::AccessibleRelation aRelation = xRelationSet->getRelation( n );
481 : 0 : sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
482 : 0 : AtkObject **pTargets = (AtkObject **) alloca( nTargetCount * sizeof(AtkObject *) );
483 : :
484 : 0 : for( sal_uInt32 i = 0; i < nTargetCount; i++ )
485 : : {
486 : : uno::Reference< accessibility::XAccessible > xAccessible(
487 : 0 : aRelation.TargetSet[i], uno::UNO_QUERY );
488 : 0 : pTargets[i] = atk_object_wrapper_ref( xAccessible );
489 : 0 : }
490 : :
491 : : AtkRelation *pRel =
492 : : atk_relation_new(
493 : : pTargets, nTargetCount,
494 : : mapRelationType( aRelation.RelationType )
495 : 0 : );
496 : 0 : atk_relation_set_add( pSet, pRel );
497 : 0 : g_object_unref( G_OBJECT( pRel ) );
498 : 0 : }
499 : : }
500 : 0 : catch(const uno::Exception &e) {
501 : 0 : g_object_unref( G_OBJECT( pSet ) );
502 : 0 : pSet = NULL;
503 : : }
504 : : }
505 : :
506 : 0 : return pSet;
507 : : }
508 : :
509 : : static AtkStateSet *
510 : 0 : wrapper_ref_state_set( AtkObject *atk_obj )
511 : : {
512 : 0 : AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
513 : 0 : AtkStateSet *pSet = atk_state_set_new();
514 : :
515 : 0 : if( obj->mpContext )
516 : : {
517 : : try {
518 : : uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
519 : 0 : obj->mpContext->getAccessibleStateSet());
520 : :
521 : 0 : if( xStateSet.is() )
522 : : {
523 : 0 : uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
524 : :
525 : 0 : for( sal_Int32 n = 0; n < aStates.getLength(); n++ )
526 : 0 : atk_state_set_add_state( pSet, mapAtkState( aStates[n] ) );
527 : :
528 : : // We need to emulate FOCUS state for menus, menu-items etc.
529 : 0 : if( atk_obj == atk_get_focus_object() )
530 : 0 : atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
531 : : /* FIXME - should we do this ?
532 : : else
533 : : atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
534 : : */
535 : 0 : }
536 : : }
537 : :
538 : 0 : catch(const uno::Exception &e) {
539 : 0 : g_warning( "Exception in wrapper_ref_state_set" );
540 : 0 : atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
541 : : }
542 : : }
543 : : else
544 : 0 : atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
545 : :
546 : 0 : return pSet;
547 : : }
548 : :
549 : : /*****************************************************************************/
550 : :
551 : :
552 : : static void
553 : 0 : atk_object_wrapper_finalize (GObject *obj)
554 : : {
555 : 0 : AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
556 : :
557 : 0 : if( pWrap->mpAccessible )
558 : : {
559 : 0 : ooo_wrapper_registry_remove( pWrap->mpAccessible );
560 : 0 : pWrap->mpAccessible->release();
561 : 0 : pWrap->mpAccessible = NULL;
562 : : }
563 : :
564 : 0 : atk_object_wrapper_dispose( pWrap );
565 : :
566 : 0 : parent_class->finalize( obj );
567 : 0 : }
568 : :
569 : : static void
570 : 0 : atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
571 : : {
572 : 0 : GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
573 : 0 : AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
574 : :
575 : 0 : parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
576 : :
577 : : // GObject methods
578 : 0 : gobject_class->finalize = atk_object_wrapper_finalize;
579 : :
580 : : // AtkObject methods
581 : 0 : atk_class->get_name = wrapper_get_name;
582 : 0 : atk_class->get_description = wrapper_get_description;
583 : 0 : atk_class->get_n_children = wrapper_get_n_children;
584 : 0 : atk_class->ref_child = wrapper_ref_child;
585 : 0 : atk_class->get_index_in_parent = wrapper_get_index_in_parent;
586 : 0 : atk_class->ref_relation_set = wrapper_ref_relation_set;
587 : 0 : atk_class->ref_state_set = wrapper_ref_state_set;
588 : 0 : }
589 : :
590 : : static void
591 : 0 : atk_object_wrapper_init (AtkObjectWrapper *wrapper,
592 : : AtkObjectWrapperClass)
593 : : {
594 : 0 : wrapper->mpAction = NULL;
595 : 0 : wrapper->mpComponent = NULL;
596 : 0 : wrapper->mpEditableText = NULL;
597 : 0 : wrapper->mpHypertext = NULL;
598 : 0 : wrapper->mpImage = NULL;
599 : 0 : wrapper->mpSelection = NULL;
600 : 0 : wrapper->mpTable = NULL;
601 : 0 : wrapper->mpText = NULL;
602 : 0 : wrapper->mpValue = NULL;
603 : 0 : }
604 : :
605 : : } // extern "C"
606 : :
607 : : GType
608 : 0 : atk_object_wrapper_get_type (void)
609 : : {
610 : : static GType type = 0;
611 : :
612 : 0 : if (!type)
613 : : {
614 : : static const GTypeInfo typeInfo =
615 : : {
616 : : sizeof (AtkObjectWrapperClass),
617 : : (GBaseInitFunc) NULL,
618 : : (GBaseFinalizeFunc) NULL,
619 : : (GClassInitFunc) atk_object_wrapper_class_init,
620 : : (GClassFinalizeFunc) NULL,
621 : : NULL,
622 : : sizeof (AtkObjectWrapper),
623 : : 0,
624 : : (GInstanceInitFunc) atk_object_wrapper_init,
625 : : NULL
626 : : } ;
627 : : type = g_type_register_static (ATK_TYPE_OBJECT,
628 : : "OOoAtkObj",
629 : 0 : &typeInfo, (GTypeFlags)0) ;
630 : : }
631 : 0 : return type;
632 : : }
633 : :
634 : : static bool
635 : 0 : isOfType( uno::XInterface *pInterface, const uno::Type & rType )
636 : : {
637 : 0 : g_return_val_if_fail( pInterface != NULL, false );
638 : :
639 : 0 : bool bIs = false;
640 : : try {
641 : 0 : uno::Any aRet = pInterface->queryInterface( rType );
642 : :
643 : : bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
644 : 0 : ( aRet.pReserved != NULL ) );
645 : 0 : } catch( const uno::Exception &e) { }
646 : :
647 : 0 : return bIs;
648 : : }
649 : :
650 : : extern "C" {
651 : : typedef GType (* GetGIfaceType ) (void);
652 : : }
653 : : const struct {
654 : : const char *name;
655 : : GInterfaceInitFunc aInit;
656 : : GetGIfaceType aGetGIfaceType;
657 : : const uno::Type & (*aGetUnoType) (void *);
658 : : } aTypeTable[] = {
659 : : // re-location heaven:
660 : : {
661 : : "Comp", (GInterfaceInitFunc) componentIfaceInit,
662 : : atk_component_get_type,
663 : : accessibility::XAccessibleComponent::static_type
664 : : },
665 : : {
666 : : "Act", (GInterfaceInitFunc) actionIfaceInit,
667 : : atk_action_get_type,
668 : : accessibility::XAccessibleAction::static_type
669 : : },
670 : : {
671 : : "Txt", (GInterfaceInitFunc) textIfaceInit,
672 : : atk_text_get_type,
673 : : accessibility::XAccessibleText::static_type
674 : : },
675 : : {
676 : : "Val", (GInterfaceInitFunc) valueIfaceInit,
677 : : atk_value_get_type,
678 : : accessibility::XAccessibleValue::static_type
679 : : },
680 : : {
681 : : "Tab", (GInterfaceInitFunc) tableIfaceInit,
682 : : atk_table_get_type,
683 : : accessibility::XAccessibleTable::static_type
684 : : },
685 : : {
686 : : "Edt", (GInterfaceInitFunc) editableTextIfaceInit,
687 : : atk_editable_text_get_type,
688 : : accessibility::XAccessibleEditableText::static_type
689 : : },
690 : : {
691 : : "Img", (GInterfaceInitFunc) imageIfaceInit,
692 : : atk_image_get_type,
693 : : accessibility::XAccessibleImage::static_type
694 : : },
695 : : {
696 : : "Hyp", (GInterfaceInitFunc) hypertextIfaceInit,
697 : : atk_hypertext_get_type,
698 : : accessibility::XAccessibleHypertext::static_type
699 : : },
700 : : {
701 : : "Sel", (GInterfaceInitFunc) selectionIfaceInit,
702 : : atk_selection_get_type,
703 : : accessibility::XAccessibleSelection::static_type
704 : : }
705 : : // AtkDocument is a nastily broken interface (so far)
706 : : // we could impl. get_document_type perhaps though.
707 : : };
708 : :
709 : : const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
710 : :
711 : : static GType
712 : 0 : ensureTypeFor( uno::XInterface *pAccessible )
713 : : {
714 : : int i;
715 : 0 : int bTypes[ aTypeTableSize ] = { 0, };
716 : 0 : rtl::OString aTypeName( "OOoAtkObj" );
717 : :
718 : 0 : for( i = 0; i < aTypeTableSize; i++ )
719 : : {
720 : 0 : if( isOfType( pAccessible, aTypeTable[i].aGetUnoType(0) ) )
721 : : {
722 : 0 : aTypeName += aTypeTable[i].name;
723 : 0 : bTypes[i] = TRUE;
724 : : }
725 : : }
726 : :
727 : 0 : GType nType = g_type_from_name( aTypeName.getStr() );
728 : 0 : if( nType == G_TYPE_INVALID )
729 : : {
730 : : GTypeInfo aTypeInfo = {
731 : : sizeof( AtkObjectWrapperClass ),
732 : : NULL, NULL, NULL, NULL, NULL,
733 : : sizeof( AtkObjectWrapper ),
734 : : 0, NULL, NULL
735 : 0 : } ;
736 : : nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
737 : : aTypeName.getStr(), &aTypeInfo,
738 : 0 : (GTypeFlags)0 ) ;
739 : :
740 : 0 : for( int j = 0; j < aTypeTableSize; j++ )
741 : 0 : if( bTypes[j] )
742 : : {
743 : 0 : GInterfaceInfo aIfaceInfo = { NULL, NULL, NULL };
744 : 0 : aIfaceInfo.interface_init = aTypeTable[j].aInit;
745 : : g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
746 : 0 : &aIfaceInfo);
747 : : }
748 : : }
749 : 0 : return nType;
750 : : }
751 : :
752 : : AtkObject *
753 : 0 : atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
754 : : {
755 : 0 : g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
756 : :
757 : 0 : AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
758 : 0 : if( obj )
759 : : {
760 : 0 : g_object_ref( obj );
761 : 0 : return obj;
762 : : }
763 : :
764 : 0 : if( create )
765 : 0 : return atk_object_wrapper_new( rxAccessible );
766 : :
767 : 0 : return NULL;
768 : : }
769 : :
770 : :
771 : : AtkObject *
772 : 0 : atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
773 : : AtkObject* parent )
774 : : {
775 : 0 : g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
776 : :
777 : 0 : AtkObjectWrapper *pWrap = NULL;
778 : :
779 : : try {
780 : 0 : uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
781 : :
782 : 0 : g_return_val_if_fail( xContext.get() != NULL, NULL );
783 : :
784 : 0 : GType nType = ensureTypeFor( xContext.get() );
785 : 0 : gpointer obj = g_object_new( nType, NULL);
786 : :
787 : 0 : pWrap = ATK_OBJECT_WRAPPER( obj );
788 : 0 : pWrap->mpAccessible = rxAccessible.get();
789 : 0 : rxAccessible->acquire();
790 : :
791 : 0 : pWrap->index_of_child_about_to_be_removed = -1;
792 : 0 : pWrap->child_about_to_be_removed = NULL;
793 : :
794 : 0 : xContext->acquire();
795 : 0 : pWrap->mpContext = xContext.get();
796 : :
797 : 0 : AtkObject* atk_obj = ATK_OBJECT(pWrap);
798 : 0 : atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
799 : 0 : atk_obj->accessible_parent = parent;
800 : :
801 : 0 : ooo_wrapper_registry_add( rxAccessible, atk_obj );
802 : :
803 : 0 : if( parent )
804 : 0 : g_object_ref( atk_obj->accessible_parent );
805 : : else
806 : : {
807 : : /* gail_focus_tracker remembers the focused object at the first
808 : : * parent in the hierachy that is a Gtk+ widget, but at the time the
809 : : * event gets processed (at idle), it may be too late to create the
810 : : * hierachy, so doing it now ..
811 : : */
812 : 0 : uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
813 : :
814 : : /* The top-level objects should never be of this class */
815 : : OSL_ASSERT( xParent.is() );
816 : :
817 : 0 : if( xParent.is() )
818 : 0 : atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
819 : : }
820 : :
821 : : // Attach a listener to the UNO object if it's not TRANSIENT
822 : 0 : uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
823 : 0 : if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
824 : : {
825 : 0 : uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
826 : 0 : if( xBroadcaster.is() )
827 : 0 : xBroadcaster->addEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) );
828 : : else
829 : 0 : OSL_ASSERT( false );
830 : : }
831 : :
832 : 0 : return ATK_OBJECT( pWrap );
833 : : }
834 : 0 : catch (const uno::Exception &e)
835 : : {
836 : 0 : if( pWrap )
837 : 0 : g_object_unref( pWrap );
838 : :
839 : 0 : return NULL;
840 : : }
841 : : }
842 : :
843 : :
844 : : /*****************************************************************************/
845 : :
846 : 0 : void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
847 : : {
848 : 0 : AtkObject *atk_obj = ATK_OBJECT( wrapper );
849 : :
850 : 0 : atk_object_set_parent( child, atk_obj );
851 : 0 : g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, NULL );
852 : 0 : }
853 : :
854 : : /*****************************************************************************/
855 : :
856 : 0 : void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
857 : : {
858 : : /*
859 : : * the atk-bridge GTK+ module get's back to the event source to ref the child just
860 : : * vanishing, so we keep this reference because the semantic on OOo side is different.
861 : : */
862 : 0 : wrapper->child_about_to_be_removed = child;
863 : 0 : wrapper->index_of_child_about_to_be_removed = index;
864 : :
865 : 0 : g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, NULL );
866 : :
867 : 0 : wrapper->index_of_child_about_to_be_removed = -1;
868 : 0 : wrapper->child_about_to_be_removed = NULL;
869 : 0 : }
870 : :
871 : : /*****************************************************************************/
872 : :
873 : : #define RELEASE(i) if( i ) { i->release(); i = NULL; }
874 : :
875 : 0 : void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
876 : : {
877 : 0 : RELEASE( wrapper->mpContext )
878 : 0 : RELEASE( wrapper->mpAction )
879 : 0 : RELEASE( wrapper->mpComponent )
880 : 0 : RELEASE( wrapper->mpEditableText )
881 : 0 : RELEASE( wrapper->mpHypertext )
882 : 0 : RELEASE( wrapper->mpImage )
883 : 0 : RELEASE( wrapper->mpSelection )
884 : 0 : RELEASE( wrapper->mpMultiLineText )
885 : 0 : RELEASE( wrapper->mpTable )
886 : 0 : RELEASE( wrapper->mpText )
887 : 0 : RELEASE( wrapper->mpTextMarkup )
888 : 0 : RELEASE( wrapper->mpTextAttributes )
889 : 0 : RELEASE( wrapper->mpValue )
890 : 0 : }
891 : :
892 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|