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