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