Update ooo320-m1
[ooovba.git] / vcl / unx / gtk / a11y / atkwrapper.cxx
blobcec4a2979f8340e92571a27daf36ca90d35b7d93
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: atkwrapper.cxx,v $
10 * $Revision: 1.11.52.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <com/sun/star/uno/Any.hxx>
35 #include <com/sun/star/uno/Type.hxx>
36 #include <com/sun/star/uno/Sequence.hxx>
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
39 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
40 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
41 #include <com/sun/star/accessibility/XAccessible.hpp>
42 #include <com/sun/star/accessibility/XAccessibleText.hpp>
43 #include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
44 #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
45 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
46 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
47 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
48 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
49 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
50 #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
51 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
52 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
53 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
54 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
55 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
56 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
57 #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
58 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
59 #include <com/sun/star/awt/XExtendedToolkit.hpp>
60 #include <com/sun/star/awt/XTopWindow.hpp>
61 #include <com/sun/star/awt/XTopWindowListener.hpp>
62 #include <com/sun/star/awt/XWindow.hpp>
63 #include <com/sun/star/lang/XComponent.hpp>
64 #include <com/sun/star/lang/XServiceInfo.hpp>
65 #include <com/sun/star/lang/XInitialization.hpp>
66 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
67 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
68 #include <com/sun/star/beans/Property.hpp>
70 #include <rtl/ref.hxx>
71 #include <cppuhelper/factory.hxx>
72 #include <cppuhelper/queryinterface.hxx>
74 #include "atkwrapper.hxx"
75 #include "atkregistry.hxx"
76 #include "atklistener.hxx"
78 #ifdef ENABLE_TRACING
79 #include <stdio.h>
80 #endif
82 #include <string.h>
84 using namespace ::com::sun::star;
86 static GObjectClass *parent_class = NULL;
88 static AtkRelationType mapRelationType( sal_Int16 nRelation )
90 AtkRelationType type = ATK_RELATION_NULL;
92 switch( nRelation )
94 case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
95 type = ATK_RELATION_FLOWS_FROM;
96 break;
98 case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
99 type = ATK_RELATION_FLOWS_TO;
100 break;
102 case accessibility::AccessibleRelationType::CONTROLLED_BY:
103 type = ATK_RELATION_CONTROLLED_BY;
104 break;
106 case accessibility::AccessibleRelationType::CONTROLLER_FOR:
107 type = ATK_RELATION_CONTROLLER_FOR;
108 break;
110 case accessibility::AccessibleRelationType::LABEL_FOR:
111 type = ATK_RELATION_LABEL_FOR;
112 break;
114 case accessibility::AccessibleRelationType::LABELED_BY:
115 type = ATK_RELATION_LABELLED_BY;
116 break;
118 case accessibility::AccessibleRelationType::MEMBER_OF:
119 type = ATK_RELATION_MEMBER_OF;
120 break;
122 case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
123 type = ATK_RELATION_SUBWINDOW_OF;
124 break;
126 case accessibility::AccessibleRelationType::NODE_CHILD_OF:
127 type = ATK_RELATION_NODE_CHILD_OF;
128 break;
130 default:
131 break;
133 #if 0
134 ATK_RELATION_NODE_CHILD_OF,
135 ATK_RELATION_EMBEDS,
136 ATK_RELATION_EMBEDDED_BY,
137 ATK_RELATION_POPUP_FOR,
138 #endif
139 return type;
143 AtkStateType mapAtkState( sal_Int16 nState )
145 AtkStateType type = ATK_STATE_INVALID;
147 // A perfect / complete mapping ...
148 switch( nState )
150 #define MAP_DIRECT( a ) \
151 case accessibility::AccessibleStateType::a: \
152 type = ATK_STATE_##a; break
154 MAP_DIRECT( INVALID );
155 MAP_DIRECT( ACTIVE );
156 MAP_DIRECT( ARMED );
157 MAP_DIRECT( BUSY );
158 MAP_DIRECT( CHECKED );
159 MAP_DIRECT( EDITABLE );
160 MAP_DIRECT( ENABLED );
161 MAP_DIRECT( EXPANDABLE );
162 MAP_DIRECT( EXPANDED );
163 MAP_DIRECT( FOCUSABLE );
164 MAP_DIRECT( FOCUSED );
165 MAP_DIRECT( HORIZONTAL );
166 MAP_DIRECT( ICONIFIED );
167 MAP_DIRECT( INDETERMINATE );
168 MAP_DIRECT( MANAGES_DESCENDANTS );
169 MAP_DIRECT( MODAL );
170 MAP_DIRECT( MULTI_LINE );
171 MAP_DIRECT( OPAQUE );
172 MAP_DIRECT( PRESSED );
173 MAP_DIRECT( RESIZABLE );
174 MAP_DIRECT( SELECTABLE );
175 MAP_DIRECT( SELECTED );
176 MAP_DIRECT( SENSITIVE );
177 MAP_DIRECT( SHOWING );
178 MAP_DIRECT( SINGLE_LINE );
179 MAP_DIRECT( STALE );
180 MAP_DIRECT( TRANSIENT );
181 MAP_DIRECT( VERTICAL );
182 MAP_DIRECT( VISIBLE );
183 // a spelling error ...
184 case accessibility::AccessibleStateType::DEFUNC:
185 type = ATK_STATE_DEFUNCT; break;
186 case accessibility::AccessibleStateType::MULTI_SELECTABLE:
187 type = ATK_STATE_MULTISELECTABLE; break;
188 default:
189 break;
192 return type;
195 static inline AtkRole registerRole( const gchar * name )
197 AtkRole ret = atk_role_for_name( name );
198 if( ATK_ROLE_INVALID == ret )
199 ret = atk_role_register( name );
201 return ret;
204 static AtkRole mapToAtkRole( sal_Int16 nRole )
206 AtkRole role = ATK_ROLE_UNKNOWN;
208 static AtkRole roleMap[] = {
209 ATK_ROLE_UNKNOWN,
210 ATK_ROLE_ALERT,
211 ATK_ROLE_COLUMN_HEADER,
212 ATK_ROLE_CANVAS,
213 ATK_ROLE_CHECK_BOX,
214 ATK_ROLE_CHECK_MENU_ITEM,
215 ATK_ROLE_COLOR_CHOOSER,
216 ATK_ROLE_COMBO_BOX,
217 ATK_ROLE_DATE_EDITOR,
218 ATK_ROLE_DESKTOP_ICON,
219 ATK_ROLE_DESKTOP_FRAME, // ? pane
220 ATK_ROLE_DIRECTORY_PANE,
221 ATK_ROLE_DIALOG,
222 ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
223 ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
224 ATK_ROLE_UNKNOWN, // END_NOTE - registered below
225 ATK_ROLE_FILE_CHOOSER,
226 ATK_ROLE_FILLER,
227 ATK_ROLE_FONT_CHOOSER,
228 ATK_ROLE_FOOTER,
229 ATK_ROLE_TEXT, // FOOTNOTE - registered below
230 ATK_ROLE_FRAME,
231 ATK_ROLE_GLASS_PANE,
232 ATK_ROLE_IMAGE, // GRAPHIC
233 ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
234 ATK_ROLE_HEADER,
235 ATK_ROLE_PARAGRAPH, // HEADING - registered below
236 ATK_ROLE_TEXT, // HYPER_LINK - registered below
237 ATK_ROLE_ICON,
238 ATK_ROLE_INTERNAL_FRAME,
239 ATK_ROLE_LABEL,
240 ATK_ROLE_LAYERED_PANE,
241 ATK_ROLE_LIST,
242 ATK_ROLE_LIST_ITEM,
243 ATK_ROLE_MENU,
244 ATK_ROLE_MENU_BAR,
245 ATK_ROLE_MENU_ITEM,
246 ATK_ROLE_OPTION_PANE,
247 ATK_ROLE_PAGE_TAB,
248 ATK_ROLE_PAGE_TAB_LIST,
249 ATK_ROLE_PANEL,
250 ATK_ROLE_PARAGRAPH,
251 ATK_ROLE_PASSWORD_TEXT,
252 ATK_ROLE_POPUP_MENU,
253 ATK_ROLE_PUSH_BUTTON,
254 ATK_ROLE_PROGRESS_BAR,
255 ATK_ROLE_RADIO_BUTTON,
256 ATK_ROLE_RADIO_MENU_ITEM,
257 ATK_ROLE_ROW_HEADER,
258 ATK_ROLE_ROOT_PANE,
259 ATK_ROLE_SCROLL_BAR,
260 ATK_ROLE_SCROLL_PANE,
261 ATK_ROLE_UNKNOWN, // SHAPE - registered below
262 ATK_ROLE_SEPARATOR,
263 ATK_ROLE_SLIDER,
264 ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
265 ATK_ROLE_SPLIT_PANE,
266 ATK_ROLE_STATUSBAR,
267 ATK_ROLE_TABLE,
268 ATK_ROLE_TABLE_CELL,
269 ATK_ROLE_TEXT,
270 ATK_ROLE_INTERNAL_FRAME, // TEXT_FRAME - registered below
271 ATK_ROLE_TOGGLE_BUTTON,
272 ATK_ROLE_TOOL_BAR,
273 ATK_ROLE_TOOL_TIP,
274 ATK_ROLE_TREE,
275 ATK_ROLE_VIEWPORT,
276 ATK_ROLE_WINDOW,
277 ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
278 ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
279 ATK_ROLE_UNKNOWN, // CAPTION - registered below
280 ATK_ROLE_UNKNOWN, // CHART - registered below
281 ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
282 ATK_ROLE_UNKNOWN, // FORM - registered below
283 ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
284 ATK_ROLE_UNKNOWN, // NOTE - registered below
285 ATK_ROLE_UNKNOWN, // PAGE - registered below
286 ATK_ROLE_RULER,
287 ATK_ROLE_UNKNOWN, // SECTION - registered below
288 ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
289 ATK_ROLE_TREE_TABLE
292 static bool initialized = false;
294 if( ! initialized )
296 // re-use strings from ATK library
297 roleMap[accessibility::AccessibleRole::EDIT_BAR] = registerRole("edit bar");
298 roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = registerRole("embedded component");
299 roleMap[accessibility::AccessibleRole::CHART] = registerRole("chart");
300 roleMap[accessibility::AccessibleRole::CAPTION] = registerRole("caption");
301 roleMap[accessibility::AccessibleRole::DOCUMENT] = registerRole("document frame");
302 roleMap[accessibility::AccessibleRole::HEADING] = registerRole("heading");
303 roleMap[accessibility::AccessibleRole::PAGE] = registerRole("page");
304 roleMap[accessibility::AccessibleRole::SECTION] = registerRole("section");
305 roleMap[accessibility::AccessibleRole::FORM] = registerRole("form");
307 // these don't exist in ATK yet
308 roleMap[accessibility::AccessibleRole::END_NOTE] = registerRole("end note");
309 roleMap[accessibility::AccessibleRole::FOOTNOTE] = registerRole("foot note");
310 roleMap[accessibility::AccessibleRole::GROUP_BOX] = registerRole("group box");
311 roleMap[accessibility::AccessibleRole::HYPER_LINK] = registerRole("hyper link");
312 roleMap[accessibility::AccessibleRole::SHAPE] = registerRole("shape");
313 roleMap[accessibility::AccessibleRole::TEXT_FRAME] = registerRole("text frame");
314 roleMap[accessibility::AccessibleRole::IMAGE_MAP] = registerRole("image map");
315 roleMap[accessibility::AccessibleRole::NOTE] = registerRole("note");
316 roleMap[accessibility::AccessibleRole::TREE_ITEM] = registerRole("tree item");
318 initialized = true;
321 static const sal_Int32 nMapSize = sizeof(roleMap)/sizeof(sal_Int16);
322 if( 0 <= nRole && nMapSize > nRole )
323 role = roleMap[nRole];
325 return role;
329 /*****************************************************************************/
331 extern "C" {
333 /*****************************************************************************/
335 static G_CONST_RETURN gchar*
336 wrapper_get_name( AtkObject *atk_obj )
338 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
340 if( obj->mpContext )
342 try {
343 rtl::OString aName =
344 rtl::OUStringToOString(
345 obj->mpContext->getAccessibleName(),
346 RTL_TEXTENCODING_UTF8);
348 int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
349 if( nCmp != 0 )
351 if( atk_obj->name )
352 g_free(atk_obj->name);
353 atk_obj->name = g_strdup(aName.getStr());
356 catch(const uno::Exception& e) {
357 g_warning( "Exception in getAccessibleName()" );
361 return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
364 /*****************************************************************************/
366 static G_CONST_RETURN gchar*
367 wrapper_get_description( AtkObject *atk_obj )
369 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
371 if( obj->mpContext )
373 try {
374 rtl::OString aDescription =
375 rtl::OUStringToOString(
376 obj->mpContext->getAccessibleDescription(),
377 RTL_TEXTENCODING_UTF8);
379 g_free(atk_obj->description);
380 atk_obj->description = g_strdup(aDescription.getStr());
382 catch(const uno::Exception& e) {
383 g_warning( "Exception in getAccessibleDescription()" );
387 return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
391 /*****************************************************************************/
393 static gint
394 wrapper_get_n_children( AtkObject *atk_obj )
396 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
397 gint n = 0;
399 if( obj->mpContext )
401 try {
402 n = obj->mpContext->getAccessibleChildCount();
404 catch(const uno::Exception& e) {
405 OSL_ENSURE(0, "Exception in getAccessibleChildCount()" );
409 return n;
412 /*****************************************************************************/
414 static AtkObject *
415 wrapper_ref_child( AtkObject *atk_obj,
416 gint i )
418 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
419 AtkObject* child = NULL;
421 // see comments above atk_object_wrapper_remove_child
422 if( -1 < i && obj->index_of_child_about_to_be_removed == i )
424 g_object_ref( obj->child_about_to_be_removed );
425 return obj->child_about_to_be_removed;
428 if( obj->mpContext )
430 try {
431 uno::Reference< accessibility::XAccessible > xAccessible =
432 obj->mpContext->getAccessibleChild( i );
434 child = atk_object_wrapper_ref( xAccessible );
436 catch(const uno::Exception& e) {
437 OSL_ENSURE(0, "Exception in getAccessibleChild");
441 return child;
444 /*****************************************************************************/
446 static gint
447 wrapper_get_index_in_parent( AtkObject *atk_obj )
449 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
450 gint i = -1;
452 if( obj->mpContext )
454 try {
455 i = obj->mpContext->getAccessibleIndexInParent();
457 #ifdef ENABLE_TRACING
458 fprintf(stderr, "%p->getAccessibleIndexInParent() returned: %u\n",
459 obj->mpAccessible, i);
460 #endif
462 catch(const uno::Exception& e) {
463 g_warning( "Exception in getAccessibleIndexInParent()" );
466 return i;
469 /*****************************************************************************/
471 static AtkRelationSet *
472 wrapper_ref_relation_set( AtkObject *atk_obj )
474 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
475 AtkRelationSet *pSet = atk_relation_set_new();
477 if( obj->mpContext )
479 try {
480 uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
481 obj->mpContext->getAccessibleRelationSet()
484 sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
485 for( sal_Int32 n = 0; n < nRelations; n++ )
487 accessibility::AccessibleRelation aRelation = xRelationSet->getRelation( n );
488 sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
489 AtkObject **pTargets = (AtkObject **) alloca( nTargetCount * sizeof(AtkObject *) );
491 for( sal_uInt32 i = 0; i < nTargetCount; i++ )
493 uno::Reference< accessibility::XAccessible > xAccessible(
494 aRelation.TargetSet[i], uno::UNO_QUERY );
495 pTargets[i] = atk_object_wrapper_ref( xAccessible );
498 AtkRelation *pRel =
499 atk_relation_new(
500 pTargets, nTargetCount,
501 mapRelationType( aRelation.RelationType )
503 atk_relation_set_add( pSet, pRel );
504 g_object_unref( G_OBJECT( pRel ) );
507 catch(const uno::Exception &e) {
508 g_object_unref( G_OBJECT( pSet ) );
509 pSet = NULL;
513 return pSet;
516 /*****************************************************************************/
518 #if 0
519 struct {
520 sal_Int16 value;
521 const sal_Char* name;
522 } aStateTypeTable[] = {
523 { accessibility::AccessibleStateType::INVALID, "INVALID" },
524 { accessibility::AccessibleStateType::ACTIVE, "ACTIVE" },
525 { accessibility::AccessibleStateType::ARMED, "ARMED" },
526 { accessibility::AccessibleStateType::BUSY, "BUSY" },
527 { accessibility::AccessibleStateType::CHECKED, "CHECKED" },
528 { accessibility::AccessibleStateType::DEFUNC, "DEFUNC" },
529 { accessibility::AccessibleStateType::EDITABLE, "EDITABLE" },
530 { accessibility::AccessibleStateType::ENABLED, "ENABLED" },
531 { accessibility::AccessibleStateType::EXPANDABLE, "EXPANDABLE" },
532 { accessibility::AccessibleStateType::EXPANDED, "EXPANDED" },
533 { accessibility::AccessibleStateType::FOCUSABLE, "FOCUSABLE" },
534 { accessibility::AccessibleStateType::FOCUSED, "FOCUSED" },
535 { accessibility::AccessibleStateType::HORIZONTAL, "HORIZONTAL" },
536 { accessibility::AccessibleStateType::ICONIFIED, "ICONIFIED" },
537 { accessibility::AccessibleStateType::INDETERMINATE, "INDETERMINATE" },
538 { accessibility::AccessibleStateType::MANAGES_DESCENDANTS, "MANAGES_DESCENDANTS" },
539 { accessibility::AccessibleStateType::MODAL, "MODAL" },
540 { accessibility::AccessibleStateType::MULTI_LINE, "MULTI_LINE" },
541 { accessibility::AccessibleStateType::MULTI_SELECTABLE, "MULTI_SELECTABLE" },
542 { accessibility::AccessibleStateType::OPAQUE, "OPAQUE" },
543 { accessibility::AccessibleStateType::PRESSED, "PRESSED" },
544 { accessibility::AccessibleStateType::RESIZABLE, "RESIZABLE" },
545 { accessibility::AccessibleStateType::SELECTABLE, "SELECTABLE" },
546 { accessibility::AccessibleStateType::SELECTED, "SELECTED" },
547 { accessibility::AccessibleStateType::SENSITIVE, "SENSITIVE" },
548 { accessibility::AccessibleStateType::SHOWING, "SHOWING" },
549 { accessibility::AccessibleStateType::SINGLE_LINE, "SINGLE_LINE" },
550 { accessibility::AccessibleStateType::STALE, "STALE" },
551 { accessibility::AccessibleStateType::TRANSIENT, "TRANSIENT" },
552 { accessibility::AccessibleStateType::VERTICAL, "VERTICAL" },
553 { accessibility::AccessibleStateType::VISIBLE, "VISIBLE" }
556 static void printStates(const uno::Sequence<sal_Int16>& rStates)
558 sal_Int32 n = rStates.getLength();
559 size_t nTypes = sizeof(aStateTypeTable)/sizeof(aStateTypeTable[0]);
560 for (sal_Int32 i = 0; i < n; ++i)
562 for (size_t j = 0; j < nTypes; ++j)
564 if (aStateTypeTable[j].value == rStates[i])
565 printf("%s ", aStateTypeTable[j].name);
568 printf("\n");
570 #endif
572 static AtkStateSet *
573 wrapper_ref_state_set( AtkObject *atk_obj )
575 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
576 AtkStateSet *pSet = atk_state_set_new();
578 if( obj->mpContext )
580 try {
581 uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
582 obj->mpContext->getAccessibleStateSet());
584 if( xStateSet.is() )
586 uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
588 for( sal_Int32 n = 0; n < aStates.getLength(); n++ )
589 atk_state_set_add_state( pSet, mapAtkState( aStates[n] ) );
591 // We need to emulate FOCUS state for menus, menu-items etc.
592 if( atk_obj == atk_get_focus_object() )
593 atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
594 /* FIXME - should we do this ?
595 else
596 atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
601 catch(const uno::Exception &e) {
602 g_warning( "Exception in wrapper_ref_state_set" );
603 atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
606 else
607 atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
609 return pSet;
612 /*****************************************************************************/
615 static void
616 atk_object_wrapper_finalize (GObject *obj)
618 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
620 if( pWrap->mpAccessible )
622 ooo_wrapper_registry_remove( pWrap->mpAccessible );
623 pWrap->mpAccessible->release();
624 pWrap->mpAccessible = NULL;
627 atk_object_wrapper_dispose( pWrap );
629 parent_class->finalize( obj );
632 static void
633 atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
635 GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
636 AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
638 parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
640 // GObject methods
641 gobject_class->finalize = atk_object_wrapper_finalize;
643 // AtkObject methods
644 atk_class->get_name = wrapper_get_name;
645 atk_class->get_description = wrapper_get_description;
646 atk_class->get_n_children = wrapper_get_n_children;
647 atk_class->ref_child = wrapper_ref_child;
648 atk_class->get_index_in_parent = wrapper_get_index_in_parent;
649 atk_class->ref_relation_set = wrapper_ref_relation_set;
650 atk_class->ref_state_set = wrapper_ref_state_set;
653 static void
654 atk_object_wrapper_init (AtkObjectWrapper *wrapper,
655 AtkObjectWrapperClass)
657 wrapper->mpAction = NULL;
658 wrapper->mpComponent = NULL;
659 wrapper->mpEditableText = NULL;
660 wrapper->mpHypertext = NULL;
661 wrapper->mpImage = NULL;
662 wrapper->mpSelection = NULL;
663 wrapper->mpTable = NULL;
664 wrapper->mpText = NULL;
665 wrapper->mpValue = NULL;
668 } // extern "C"
670 GType
671 atk_object_wrapper_get_type (void)
673 static GType type = 0;
675 if (!type)
677 static const GTypeInfo typeInfo =
679 sizeof (AtkObjectWrapperClass),
680 (GBaseInitFunc) NULL,
681 (GBaseFinalizeFunc) NULL,
682 (GClassInitFunc) atk_object_wrapper_class_init,
683 (GClassFinalizeFunc) NULL,
684 NULL,
685 sizeof (AtkObjectWrapper),
687 (GInstanceInitFunc) atk_object_wrapper_init,
688 NULL
690 type = g_type_register_static (ATK_TYPE_OBJECT,
691 "OOoAtkObj",
692 &typeInfo, (GTypeFlags)0) ;
694 return type;
697 static bool
698 isOfType( uno::XInterface *pInterface, const uno::Type & rType )
700 g_return_val_if_fail( pInterface != NULL, false );
702 bool bIs = false;
703 try {
704 uno::Any aRet = pInterface->queryInterface( rType );
706 bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
707 ( aRet.pReserved != NULL ) );
708 } catch( const uno::Exception &e) { }
710 return bIs;
713 extern "C" {
714 typedef GType (* GetGIfaceType ) (void);
716 const struct {
717 const char *name;
718 GInterfaceInitFunc aInit;
719 GetGIfaceType aGetGIfaceType;
720 const uno::Type & (*aGetUnoType) (void *);
721 } aTypeTable[] = {
722 // re-location heaven:
724 "Comp", (GInterfaceInitFunc) componentIfaceInit,
725 atk_component_get_type,
726 accessibility::XAccessibleComponent::static_type
729 "Act", (GInterfaceInitFunc) actionIfaceInit,
730 atk_action_get_type,
731 accessibility::XAccessibleAction::static_type
734 "Txt", (GInterfaceInitFunc) textIfaceInit,
735 atk_text_get_type,
736 accessibility::XAccessibleText::static_type
739 "Val", (GInterfaceInitFunc) valueIfaceInit,
740 atk_value_get_type,
741 accessibility::XAccessibleValue::static_type
744 "Tab", (GInterfaceInitFunc) tableIfaceInit,
745 atk_table_get_type,
746 accessibility::XAccessibleTable::static_type
749 "Edt", (GInterfaceInitFunc) editableTextIfaceInit,
750 atk_editable_text_get_type,
751 accessibility::XAccessibleEditableText::static_type
754 "Img", (GInterfaceInitFunc) imageIfaceInit,
755 atk_image_get_type,
756 accessibility::XAccessibleImage::static_type
759 "Hyp", (GInterfaceInitFunc) hypertextIfaceInit,
760 atk_hypertext_get_type,
761 accessibility::XAccessibleHypertext::static_type
764 "Sel", (GInterfaceInitFunc) selectionIfaceInit,
765 atk_selection_get_type,
766 accessibility::XAccessibleSelection::static_type
768 // AtkDocument is a nastily broken interface (so far)
769 // we could impl. get_document_type perhaps though.
772 const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
774 static GType
775 ensureTypeFor( uno::XInterface *pAccessible )
777 int i;
778 int bTypes[ aTypeTableSize ] = { 0, };
779 rtl::OString aTypeName( "OOoAtkObj" );
781 for( i = 0; i < aTypeTableSize; i++ )
783 if( isOfType( pAccessible, aTypeTable[i].aGetUnoType(0) ) )
785 aTypeName += aTypeTable[i].name;
786 bTypes[i] = TRUE;
788 // g_message( "Accessible %p has type '%s' (%d)",
789 // pAccessible, aTypeTable[i].name, bTypes[i] );
792 GType nType = g_type_from_name( aTypeName );
793 if( nType == G_TYPE_INVALID )
795 GTypeInfo aTypeInfo = {
796 sizeof( AtkObjectWrapperClass ),
797 NULL, NULL, NULL, NULL, NULL,
798 sizeof( AtkObjectWrapper ),
799 0, NULL, NULL
801 nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
802 aTypeName, &aTypeInfo, (GTypeFlags)0 ) ;
804 for( int j = 0; j < aTypeTableSize; j++ )
805 if( bTypes[j] )
807 GInterfaceInfo aIfaceInfo = { NULL, NULL, NULL };
808 aIfaceInfo.interface_init = aTypeTable[j].aInit;
809 g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
810 &aIfaceInfo);
813 return nType;
816 AtkObject *
817 atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
819 g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
821 AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
822 if( obj )
824 g_object_ref( obj );
825 return obj;
828 if( create )
829 return atk_object_wrapper_new( rxAccessible );
831 return NULL;
835 AtkObject *
836 atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
837 AtkObject* parent )
839 g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
841 AtkObjectWrapper *pWrap = NULL;
843 try {
844 uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
846 g_return_val_if_fail( xContext.get() != NULL, NULL );
848 GType nType = ensureTypeFor( xContext.get() );
849 gpointer obj = g_object_new( nType, NULL);
851 pWrap = ATK_OBJECT_WRAPPER( obj );
852 pWrap->mpAccessible = rxAccessible.get();
853 rxAccessible->acquire();
855 pWrap->index_of_child_about_to_be_removed = -1;
856 pWrap->child_about_to_be_removed = NULL;
858 xContext->acquire();
859 pWrap->mpContext = xContext.get();
861 AtkObject* atk_obj = ATK_OBJECT(pWrap);
862 atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
863 atk_obj->accessible_parent = parent;
865 ooo_wrapper_registry_add( rxAccessible, atk_obj );
867 if( parent )
868 g_object_ref( atk_obj->accessible_parent );
869 else
871 /* gail_focus_tracker remembers the focused object at the first
872 * parent in the hierachy that is a Gtk+ widget, but at the time the
873 * event gets processed (at idle), it may be too late to create the
874 * hierachy, so doing it now ..
876 uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
878 /* The top-level objects should never be of this class */
879 OSL_ASSERT( xParent.is() );
881 if( xParent.is() )
882 atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
885 // Attach a listener to the UNO object if it's not TRANSIENT
886 uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
887 if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
889 uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
890 if( xBroadcaster.is() )
891 xBroadcaster->addEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) );
892 else
893 OSL_ASSERT( false );
896 return ATK_OBJECT( pWrap );
898 catch (const uno::Exception &e)
900 if( pWrap )
901 g_object_unref( pWrap );
903 return NULL;
908 /*****************************************************************************/
910 void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
912 AtkObject *atk_obj = ATK_OBJECT( wrapper );
914 atk_object_set_parent( child, atk_obj );
915 g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, NULL );
918 /*****************************************************************************/
920 void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
923 * the atk-bridge GTK+ module get's back to the event source to ref the child just
924 * vanishing, so we keep this reference because the semantic on OOo side is different.
926 wrapper->child_about_to_be_removed = child;
927 wrapper->index_of_child_about_to_be_removed = index;
929 g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, NULL );
931 wrapper->index_of_child_about_to_be_removed = -1;
932 wrapper->child_about_to_be_removed = NULL;
935 /*****************************************************************************/
937 #define RELEASE(i) if( i ) { i->release(); i = NULL; }
939 void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
941 RELEASE( wrapper->mpContext )
942 RELEASE( wrapper->mpAction )
943 RELEASE( wrapper->mpComponent )
944 RELEASE( wrapper->mpEditableText )
945 RELEASE( wrapper->mpHypertext )
946 RELEASE( wrapper->mpImage )
947 RELEASE( wrapper->mpSelection )
948 RELEASE( wrapper->mpMultiLineText )
949 RELEASE( wrapper->mpTable )
950 RELEASE( wrapper->mpText )
951 RELEASE( wrapper->mpTextMarkup )
952 RELEASE( wrapper->mpTextAttributes )
953 RELEASE( wrapper->mpValue )