update dev300-m58
[ooovba.git] / vcl / unx / gtk / a11y / atkwrapper.cxx
blobac508bdf85cc80ca20b0b9f9b5f84009b87d57ea
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/XAccessibleTextAttributes.hpp>
44 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
45 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
46 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
47 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
48 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
49 #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
50 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
51 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
52 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
53 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
54 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
55 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
56 #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
57 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
58 #include <com/sun/star/awt/XExtendedToolkit.hpp>
59 #include <com/sun/star/awt/XTopWindow.hpp>
60 #include <com/sun/star/awt/XTopWindowListener.hpp>
61 #include <com/sun/star/awt/XWindow.hpp>
62 #include <com/sun/star/lang/XComponent.hpp>
63 #include <com/sun/star/lang/XServiceInfo.hpp>
64 #include <com/sun/star/lang/XInitialization.hpp>
65 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
66 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
67 #include <com/sun/star/beans/Property.hpp>
69 #include <rtl/ref.hxx>
70 #include <cppuhelper/factory.hxx>
71 #include <cppuhelper/queryinterface.hxx>
73 #include "atkwrapper.hxx"
74 #include "atkregistry.hxx"
75 #include "atklistener.hxx"
77 #ifdef ENABLE_TRACING
78 #include <stdio.h>
79 #endif
81 #include <string.h>
83 using namespace ::com::sun::star;
85 static GObjectClass *parent_class = NULL;
87 static AtkRelationType mapRelationType( sal_Int16 nRelation )
89 AtkRelationType type = ATK_RELATION_NULL;
91 switch( nRelation )
93 case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
94 type = ATK_RELATION_FLOWS_FROM;
95 break;
97 case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
98 type = ATK_RELATION_FLOWS_TO;
99 break;
101 case accessibility::AccessibleRelationType::CONTROLLED_BY:
102 type = ATK_RELATION_CONTROLLED_BY;
103 break;
105 case accessibility::AccessibleRelationType::CONTROLLER_FOR:
106 type = ATK_RELATION_CONTROLLER_FOR;
107 break;
109 case accessibility::AccessibleRelationType::LABEL_FOR:
110 type = ATK_RELATION_LABEL_FOR;
111 break;
113 case accessibility::AccessibleRelationType::LABELED_BY:
114 type = ATK_RELATION_LABELLED_BY;
115 break;
117 case accessibility::AccessibleRelationType::MEMBER_OF:
118 type = ATK_RELATION_MEMBER_OF;
119 break;
121 case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
122 type = ATK_RELATION_SUBWINDOW_OF;
123 break;
125 case accessibility::AccessibleRelationType::NODE_CHILD_OF:
126 type = ATK_RELATION_NODE_CHILD_OF;
127 break;
129 default:
130 break;
132 #if 0
133 ATK_RELATION_NODE_CHILD_OF,
134 ATK_RELATION_EMBEDS,
135 ATK_RELATION_EMBEDDED_BY,
136 ATK_RELATION_POPUP_FOR,
137 #endif
138 return type;
142 AtkStateType mapAtkState( sal_Int16 nState )
144 AtkStateType type = ATK_STATE_INVALID;
146 // A perfect / complete mapping ...
147 switch( nState )
149 #define MAP_DIRECT( a ) \
150 case accessibility::AccessibleStateType::a: \
151 type = ATK_STATE_##a; break
153 MAP_DIRECT( INVALID );
154 MAP_DIRECT( ACTIVE );
155 MAP_DIRECT( ARMED );
156 MAP_DIRECT( BUSY );
157 MAP_DIRECT( CHECKED );
158 MAP_DIRECT( EDITABLE );
159 MAP_DIRECT( ENABLED );
160 MAP_DIRECT( EXPANDABLE );
161 MAP_DIRECT( EXPANDED );
162 MAP_DIRECT( FOCUSABLE );
163 MAP_DIRECT( FOCUSED );
164 MAP_DIRECT( HORIZONTAL );
165 MAP_DIRECT( ICONIFIED );
166 MAP_DIRECT( INDETERMINATE );
167 MAP_DIRECT( MANAGES_DESCENDANTS );
168 MAP_DIRECT( MODAL );
169 MAP_DIRECT( MULTI_LINE );
170 MAP_DIRECT( OPAQUE );
171 MAP_DIRECT( PRESSED );
172 MAP_DIRECT( RESIZABLE );
173 MAP_DIRECT( SELECTABLE );
174 MAP_DIRECT( SELECTED );
175 MAP_DIRECT( SENSITIVE );
176 MAP_DIRECT( SHOWING );
177 MAP_DIRECT( SINGLE_LINE );
178 MAP_DIRECT( STALE );
179 MAP_DIRECT( TRANSIENT );
180 MAP_DIRECT( VERTICAL );
181 MAP_DIRECT( VISIBLE );
182 // a spelling error ...
183 case accessibility::AccessibleStateType::DEFUNC:
184 type = ATK_STATE_DEFUNCT; break;
185 case accessibility::AccessibleStateType::MULTI_SELECTABLE:
186 type = ATK_STATE_MULTISELECTABLE; break;
187 default:
188 break;
191 return type;
194 static inline AtkRole registerRole( const gchar * name )
196 AtkRole ret = atk_role_for_name( name );
197 if( ATK_ROLE_INVALID == ret )
198 ret = atk_role_register( name );
200 return ret;
203 static AtkRole mapToAtkRole( sal_Int16 nRole )
205 AtkRole role = ATK_ROLE_UNKNOWN;
207 static AtkRole roleMap[] = {
208 ATK_ROLE_UNKNOWN,
209 ATK_ROLE_ALERT,
210 ATK_ROLE_COLUMN_HEADER,
211 ATK_ROLE_CANVAS,
212 ATK_ROLE_CHECK_BOX,
213 ATK_ROLE_CHECK_MENU_ITEM,
214 ATK_ROLE_COLOR_CHOOSER,
215 ATK_ROLE_COMBO_BOX,
216 ATK_ROLE_DATE_EDITOR,
217 ATK_ROLE_DESKTOP_ICON,
218 ATK_ROLE_DESKTOP_FRAME, // ? pane
219 ATK_ROLE_DIRECTORY_PANE,
220 ATK_ROLE_DIALOG,
221 ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
222 ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
223 ATK_ROLE_UNKNOWN, // END_NOTE - registered below
224 ATK_ROLE_FILE_CHOOSER,
225 ATK_ROLE_FILLER,
226 ATK_ROLE_FONT_CHOOSER,
227 ATK_ROLE_FOOTER,
228 ATK_ROLE_TEXT, // FOOTNOTE - registered below
229 ATK_ROLE_FRAME,
230 ATK_ROLE_GLASS_PANE,
231 ATK_ROLE_IMAGE, // GRAPHIC
232 ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
233 ATK_ROLE_HEADER,
234 ATK_ROLE_PARAGRAPH, // HEADING - registered below
235 ATK_ROLE_TEXT, // HYPER_LINK - registered below
236 ATK_ROLE_ICON,
237 ATK_ROLE_INTERNAL_FRAME,
238 ATK_ROLE_LABEL,
239 ATK_ROLE_LAYERED_PANE,
240 ATK_ROLE_LIST,
241 ATK_ROLE_LIST_ITEM,
242 ATK_ROLE_MENU,
243 ATK_ROLE_MENU_BAR,
244 ATK_ROLE_MENU_ITEM,
245 ATK_ROLE_OPTION_PANE,
246 ATK_ROLE_PAGE_TAB,
247 ATK_ROLE_PAGE_TAB_LIST,
248 ATK_ROLE_PANEL,
249 ATK_ROLE_PARAGRAPH,
250 ATK_ROLE_PASSWORD_TEXT,
251 ATK_ROLE_POPUP_MENU,
252 ATK_ROLE_PUSH_BUTTON,
253 ATK_ROLE_PROGRESS_BAR,
254 ATK_ROLE_RADIO_BUTTON,
255 ATK_ROLE_RADIO_MENU_ITEM,
256 ATK_ROLE_ROW_HEADER,
257 ATK_ROLE_ROOT_PANE,
258 ATK_ROLE_SCROLL_BAR,
259 ATK_ROLE_SCROLL_PANE,
260 ATK_ROLE_UNKNOWN, // SHAPE - registered below
261 ATK_ROLE_SEPARATOR,
262 ATK_ROLE_SLIDER,
263 ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
264 ATK_ROLE_SPLIT_PANE,
265 ATK_ROLE_STATUSBAR,
266 ATK_ROLE_TABLE,
267 ATK_ROLE_TABLE_CELL,
268 ATK_ROLE_TEXT,
269 ATK_ROLE_INTERNAL_FRAME, // TEXT_FRAME - registered below
270 ATK_ROLE_TOGGLE_BUTTON,
271 ATK_ROLE_TOOL_BAR,
272 ATK_ROLE_TOOL_TIP,
273 ATK_ROLE_TREE,
274 ATK_ROLE_VIEWPORT,
275 ATK_ROLE_WINDOW,
276 ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
277 ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
278 ATK_ROLE_UNKNOWN, // CAPTION - registered below
279 ATK_ROLE_UNKNOWN, // CHART - registered below
280 ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
281 ATK_ROLE_UNKNOWN, // FORM - registered below
282 ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
283 ATK_ROLE_UNKNOWN, // NOTE - registered below
284 ATK_ROLE_UNKNOWN, // PAGE - registered below
285 ATK_ROLE_RULER,
286 ATK_ROLE_UNKNOWN, // SECTION - registered below
287 ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
288 ATK_ROLE_TREE_TABLE
291 static bool initialized = false;
293 if( ! initialized )
295 // re-use strings from ATK library
296 roleMap[accessibility::AccessibleRole::EDIT_BAR] = registerRole("edit bar");
297 roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = registerRole("embedded component");
298 roleMap[accessibility::AccessibleRole::CHART] = registerRole("chart");
299 roleMap[accessibility::AccessibleRole::CAPTION] = registerRole("caption");
300 roleMap[accessibility::AccessibleRole::DOCUMENT] = registerRole("document frame");
301 roleMap[accessibility::AccessibleRole::HEADING] = registerRole("heading");
302 roleMap[accessibility::AccessibleRole::PAGE] = registerRole("page");
303 roleMap[accessibility::AccessibleRole::SECTION] = registerRole("section");
304 roleMap[accessibility::AccessibleRole::FORM] = registerRole("form");
306 // these don't exist in ATK yet
307 roleMap[accessibility::AccessibleRole::END_NOTE] = registerRole("end note");
308 roleMap[accessibility::AccessibleRole::FOOTNOTE] = registerRole("foot note");
309 roleMap[accessibility::AccessibleRole::GROUP_BOX] = registerRole("group box");
310 roleMap[accessibility::AccessibleRole::HYPER_LINK] = registerRole("hyper link");
311 roleMap[accessibility::AccessibleRole::SHAPE] = registerRole("shape");
312 roleMap[accessibility::AccessibleRole::TEXT_FRAME] = registerRole("text frame");
313 roleMap[accessibility::AccessibleRole::IMAGE_MAP] = registerRole("image map");
314 roleMap[accessibility::AccessibleRole::NOTE] = registerRole("note");
315 roleMap[accessibility::AccessibleRole::TREE_ITEM] = registerRole("tree item");
317 initialized = true;
320 static const sal_Int32 nMapSize = sizeof(roleMap)/sizeof(sal_Int16);
321 if( 0 <= nRole && nMapSize > nRole )
322 role = roleMap[nRole];
324 return role;
328 /*****************************************************************************/
330 extern "C" {
332 /*****************************************************************************/
334 static G_CONST_RETURN gchar*
335 wrapper_get_name( AtkObject *atk_obj )
337 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
339 if( obj->mpContext )
341 try {
342 rtl::OString aName =
343 rtl::OUStringToOString(
344 obj->mpContext->getAccessibleName(),
345 RTL_TEXTENCODING_UTF8);
347 int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
348 if( nCmp != 0 )
350 if( atk_obj->name )
351 g_free(atk_obj->name);
352 atk_obj->name = g_strdup(aName.getStr());
355 catch(const uno::Exception& e) {
356 g_warning( "Exception in getAccessibleName()" );
360 return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
363 /*****************************************************************************/
365 static G_CONST_RETURN gchar*
366 wrapper_get_description( AtkObject *atk_obj )
368 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
370 if( obj->mpContext )
372 try {
373 rtl::OString aDescription =
374 rtl::OUStringToOString(
375 obj->mpContext->getAccessibleDescription(),
376 RTL_TEXTENCODING_UTF8);
378 g_free(atk_obj->description);
379 atk_obj->description = g_strdup(aDescription.getStr());
381 catch(const uno::Exception& e) {
382 g_warning( "Exception in getAccessibleDescription()" );
386 return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
390 /*****************************************************************************/
392 static gint
393 wrapper_get_n_children( AtkObject *atk_obj )
395 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
396 gint n = 0;
398 if( obj->mpContext )
400 try {
401 n = obj->mpContext->getAccessibleChildCount();
403 catch(const uno::Exception& e) {
404 OSL_ENSURE(0, "Exception in getAccessibleChildCount()" );
408 return n;
411 /*****************************************************************************/
413 static AtkObject *
414 wrapper_ref_child( AtkObject *atk_obj,
415 gint i )
417 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
418 AtkObject* child = NULL;
420 // see comments above atk_object_wrapper_remove_child
421 if( -1 < i && obj->index_of_child_about_to_be_removed == i )
423 g_object_ref( obj->child_about_to_be_removed );
424 return obj->child_about_to_be_removed;
427 if( obj->mpContext )
429 try {
430 uno::Reference< accessibility::XAccessible > xAccessible =
431 obj->mpContext->getAccessibleChild( i );
433 child = atk_object_wrapper_ref( xAccessible );
435 catch(const uno::Exception& e) {
436 OSL_ENSURE(0, "Exception in getAccessibleChild");
440 return child;
443 /*****************************************************************************/
445 static gint
446 wrapper_get_index_in_parent( AtkObject *atk_obj )
448 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
449 gint i = -1;
451 if( obj->mpContext )
453 try {
454 i = obj->mpContext->getAccessibleIndexInParent();
456 #ifdef ENABLE_TRACING
457 fprintf(stderr, "%p->getAccessibleIndexInParent() returned: %u\n",
458 obj->mpAccessible, i);
459 #endif
461 catch(const uno::Exception& e) {
462 g_warning( "Exception in getAccessibleIndexInParent()" );
465 return i;
468 /*****************************************************************************/
470 static AtkRelationSet *
471 wrapper_ref_relation_set( AtkObject *atk_obj )
473 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
474 AtkRelationSet *pSet = atk_relation_set_new();
476 if( obj->mpContext )
478 try {
479 uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
480 obj->mpContext->getAccessibleRelationSet()
483 sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
484 for( sal_Int32 n = 0; n < nRelations; n++ )
486 accessibility::AccessibleRelation aRelation = xRelationSet->getRelation( n );
487 sal_uInt32 nTargetCount = aRelation.TargetSet.getLength();
488 AtkObject **pTargets = (AtkObject **) alloca( nTargetCount * sizeof(AtkObject *) );
490 for( sal_uInt32 i = 0; i < nTargetCount; i++ )
492 uno::Reference< accessibility::XAccessible > xAccessible(
493 aRelation.TargetSet[i], uno::UNO_QUERY );
494 pTargets[i] = atk_object_wrapper_ref( xAccessible );
497 AtkRelation *pRel =
498 atk_relation_new(
499 pTargets, nTargetCount,
500 mapRelationType( aRelation.RelationType )
502 atk_relation_set_add( pSet, pRel );
503 g_object_unref( G_OBJECT( pRel ) );
506 catch(const uno::Exception &e) {
507 g_object_unref( G_OBJECT( pSet ) );
508 pSet = NULL;
512 return pSet;
515 /*****************************************************************************/
517 #if 0
518 struct {
519 sal_Int16 value;
520 const sal_Char* name;
521 } aStateTypeTable[] = {
522 { accessibility::AccessibleStateType::INVALID, "INVALID" },
523 { accessibility::AccessibleStateType::ACTIVE, "ACTIVE" },
524 { accessibility::AccessibleStateType::ARMED, "ARMED" },
525 { accessibility::AccessibleStateType::BUSY, "BUSY" },
526 { accessibility::AccessibleStateType::CHECKED, "CHECKED" },
527 { accessibility::AccessibleStateType::DEFUNC, "DEFUNC" },
528 { accessibility::AccessibleStateType::EDITABLE, "EDITABLE" },
529 { accessibility::AccessibleStateType::ENABLED, "ENABLED" },
530 { accessibility::AccessibleStateType::EXPANDABLE, "EXPANDABLE" },
531 { accessibility::AccessibleStateType::EXPANDED, "EXPANDED" },
532 { accessibility::AccessibleStateType::FOCUSABLE, "FOCUSABLE" },
533 { accessibility::AccessibleStateType::FOCUSED, "FOCUSED" },
534 { accessibility::AccessibleStateType::HORIZONTAL, "HORIZONTAL" },
535 { accessibility::AccessibleStateType::ICONIFIED, "ICONIFIED" },
536 { accessibility::AccessibleStateType::INDETERMINATE, "INDETERMINATE" },
537 { accessibility::AccessibleStateType::MANAGES_DESCENDANTS, "MANAGES_DESCENDANTS" },
538 { accessibility::AccessibleStateType::MODAL, "MODAL" },
539 { accessibility::AccessibleStateType::MULTI_LINE, "MULTI_LINE" },
540 { accessibility::AccessibleStateType::MULTI_SELECTABLE, "MULTI_SELECTABLE" },
541 { accessibility::AccessibleStateType::OPAQUE, "OPAQUE" },
542 { accessibility::AccessibleStateType::PRESSED, "PRESSED" },
543 { accessibility::AccessibleStateType::RESIZABLE, "RESIZABLE" },
544 { accessibility::AccessibleStateType::SELECTABLE, "SELECTABLE" },
545 { accessibility::AccessibleStateType::SELECTED, "SELECTED" },
546 { accessibility::AccessibleStateType::SENSITIVE, "SENSITIVE" },
547 { accessibility::AccessibleStateType::SHOWING, "SHOWING" },
548 { accessibility::AccessibleStateType::SINGLE_LINE, "SINGLE_LINE" },
549 { accessibility::AccessibleStateType::STALE, "STALE" },
550 { accessibility::AccessibleStateType::TRANSIENT, "TRANSIENT" },
551 { accessibility::AccessibleStateType::VERTICAL, "VERTICAL" },
552 { accessibility::AccessibleStateType::VISIBLE, "VISIBLE" }
555 static void printStates(const uno::Sequence<sal_Int16>& rStates)
557 sal_Int32 n = rStates.getLength();
558 size_t nTypes = sizeof(aStateTypeTable)/sizeof(aStateTypeTable[0]);
559 for (sal_Int32 i = 0; i < n; ++i)
561 for (size_t j = 0; j < nTypes; ++j)
563 if (aStateTypeTable[j].value == rStates[i])
564 printf("%s ", aStateTypeTable[j].name);
567 printf("\n");
569 #endif
571 static AtkStateSet *
572 wrapper_ref_state_set( AtkObject *atk_obj )
574 AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
575 AtkStateSet *pSet = atk_state_set_new();
577 if( obj->mpContext )
579 try {
580 uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
581 obj->mpContext->getAccessibleStateSet());
583 if( xStateSet.is() )
585 uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
587 for( sal_Int32 n = 0; n < aStates.getLength(); n++ )
588 atk_state_set_add_state( pSet, mapAtkState( aStates[n] ) );
590 // We need to emulate FOCUS state for menus, menu-items etc.
591 if( atk_obj == atk_get_focus_object() )
592 atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
593 /* FIXME - should we do this ?
594 else
595 atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
600 catch(const uno::Exception &e) {
601 g_warning( "Exception in wrapper_ref_state_set" );
602 atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
605 else
606 atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
608 return pSet;
611 /*****************************************************************************/
614 static void
615 atk_object_wrapper_finalize (GObject *obj)
617 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
619 if( pWrap->mpAccessible )
621 ooo_wrapper_registry_remove( pWrap->mpAccessible );
622 pWrap->mpAccessible->release();
623 pWrap->mpAccessible = NULL;
626 atk_object_wrapper_dispose( pWrap );
628 parent_class->finalize( obj );
631 static void
632 atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
634 GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
635 AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
637 parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
639 // GObject methods
640 gobject_class->finalize = atk_object_wrapper_finalize;
642 // AtkObject methods
643 atk_class->get_name = wrapper_get_name;
644 atk_class->get_description = wrapper_get_description;
645 atk_class->get_n_children = wrapper_get_n_children;
646 atk_class->ref_child = wrapper_ref_child;
647 atk_class->get_index_in_parent = wrapper_get_index_in_parent;
648 atk_class->ref_relation_set = wrapper_ref_relation_set;
649 atk_class->ref_state_set = wrapper_ref_state_set;
652 static void
653 atk_object_wrapper_init (AtkObjectWrapper *wrapper,
654 AtkObjectWrapperClass)
656 wrapper->mpAction = NULL;
657 wrapper->mpComponent = NULL;
658 wrapper->mpEditableText = NULL;
659 wrapper->mpHypertext = NULL;
660 wrapper->mpImage = NULL;
661 wrapper->mpSelection = NULL;
662 wrapper->mpTable = NULL;
663 wrapper->mpText = NULL;
664 wrapper->mpValue = NULL;
667 } // extern "C"
669 GType
670 atk_object_wrapper_get_type (void)
672 static GType type = 0;
674 if (!type)
676 static const GTypeInfo typeInfo =
678 sizeof (AtkObjectWrapperClass),
679 (GBaseInitFunc) NULL,
680 (GBaseFinalizeFunc) NULL,
681 (GClassInitFunc) atk_object_wrapper_class_init,
682 (GClassFinalizeFunc) NULL,
683 NULL,
684 sizeof (AtkObjectWrapper),
686 (GInstanceInitFunc) atk_object_wrapper_init,
687 NULL
689 type = g_type_register_static (ATK_TYPE_OBJECT,
690 "OOoAtkObj",
691 &typeInfo, (GTypeFlags)0) ;
693 return type;
696 static bool
697 isOfType( uno::XInterface *pInterface, const uno::Type & rType )
699 g_return_val_if_fail( pInterface != NULL, false );
701 bool bIs = false;
702 try {
703 uno::Any aRet = pInterface->queryInterface( rType );
705 bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
706 ( aRet.pReserved != NULL ) );
707 } catch( const uno::Exception &e) { }
709 return bIs;
712 extern "C" {
713 typedef GType (* GetGIfaceType ) (void);
715 const struct {
716 const char *name;
717 GInterfaceInitFunc aInit;
718 GetGIfaceType aGetGIfaceType;
719 const uno::Type & (*aGetUnoType) (void *);
720 } aTypeTable[] = {
721 // re-location heaven:
723 "Comp", (GInterfaceInitFunc) componentIfaceInit,
724 atk_component_get_type,
725 accessibility::XAccessibleComponent::static_type
728 "Act", (GInterfaceInitFunc) actionIfaceInit,
729 atk_action_get_type,
730 accessibility::XAccessibleAction::static_type
733 "Txt", (GInterfaceInitFunc) textIfaceInit,
734 atk_text_get_type,
735 accessibility::XAccessibleText::static_type
738 "Val", (GInterfaceInitFunc) valueIfaceInit,
739 atk_value_get_type,
740 accessibility::XAccessibleValue::static_type
743 "Tab", (GInterfaceInitFunc) tableIfaceInit,
744 atk_table_get_type,
745 accessibility::XAccessibleTable::static_type
748 "Edt", (GInterfaceInitFunc) editableTextIfaceInit,
749 atk_editable_text_get_type,
750 accessibility::XAccessibleEditableText::static_type
753 "Img", (GInterfaceInitFunc) imageIfaceInit,
754 atk_image_get_type,
755 accessibility::XAccessibleImage::static_type
758 "Hyp", (GInterfaceInitFunc) hypertextIfaceInit,
759 atk_hypertext_get_type,
760 accessibility::XAccessibleHypertext::static_type
763 "Sel", (GInterfaceInitFunc) selectionIfaceInit,
764 atk_selection_get_type,
765 accessibility::XAccessibleSelection::static_type
767 // AtkDocument is a nastily broken interface (so far)
768 // we could impl. get_document_type perhaps though.
771 const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
773 static GType
774 ensureTypeFor( uno::XInterface *pAccessible )
776 int i;
777 int bTypes[ aTypeTableSize ] = { 0, };
778 rtl::OString aTypeName( "OOoAtkObj" );
780 for( i = 0; i < aTypeTableSize; i++ )
782 if( isOfType( pAccessible, aTypeTable[i].aGetUnoType(0) ) )
784 aTypeName += aTypeTable[i].name;
785 bTypes[i] = TRUE;
787 // g_message( "Accessible %p has type '%s' (%d)",
788 // pAccessible, aTypeTable[i].name, bTypes[i] );
791 GType nType = g_type_from_name( aTypeName );
792 if( nType == G_TYPE_INVALID )
794 GTypeInfo aTypeInfo = {
795 sizeof( AtkObjectWrapperClass ),
796 NULL, NULL, NULL, NULL, NULL,
797 sizeof( AtkObjectWrapper ),
798 0, NULL, NULL
800 nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
801 aTypeName, &aTypeInfo, (GTypeFlags)0 ) ;
803 for( int j = 0; j < aTypeTableSize; j++ )
804 if( bTypes[j] )
806 GInterfaceInfo aIfaceInfo = { NULL, NULL, NULL };
807 aIfaceInfo.interface_init = aTypeTable[j].aInit;
808 g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
809 &aIfaceInfo);
812 return nType;
815 AtkObject *
816 atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
818 g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
820 AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
821 if( obj )
823 g_object_ref( obj );
824 return obj;
827 if( create )
828 return atk_object_wrapper_new( rxAccessible );
830 return NULL;
834 AtkObject *
835 atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
836 AtkObject* parent )
838 g_return_val_if_fail( rxAccessible.get() != NULL, NULL );
840 AtkObjectWrapper *pWrap = NULL;
842 try {
843 uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
845 g_return_val_if_fail( xContext.get() != NULL, NULL );
847 GType nType = ensureTypeFor( xContext.get() );
848 gpointer obj = g_object_new( nType, NULL);
850 pWrap = ATK_OBJECT_WRAPPER( obj );
851 pWrap->mpAccessible = rxAccessible.get();
852 rxAccessible->acquire();
854 pWrap->index_of_child_about_to_be_removed = -1;
855 pWrap->child_about_to_be_removed = NULL;
857 xContext->acquire();
858 pWrap->mpContext = xContext.get();
860 AtkObject* atk_obj = ATK_OBJECT(pWrap);
861 atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
862 atk_obj->accessible_parent = parent;
864 ooo_wrapper_registry_add( rxAccessible, atk_obj );
866 if( parent )
867 g_object_ref( atk_obj->accessible_parent );
868 else
870 /* gail_focus_tracker remembers the focused object at the first
871 * parent in the hierachy that is a Gtk+ widget, but at the time the
872 * event gets processed (at idle), it may be too late to create the
873 * hierachy, so doing it now ..
875 uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
877 /* The top-level objects should never be of this class */
878 OSL_ASSERT( xParent.is() );
880 if( xParent.is() )
881 atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
884 // Attach a listener to the UNO object if it's not TRANSIENT
885 uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
886 if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
888 uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
889 if( xBroadcaster.is() )
890 xBroadcaster->addEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) );
891 else
892 OSL_ASSERT( false );
895 return ATK_OBJECT( pWrap );
897 catch (const uno::Exception &e)
899 if( pWrap )
900 g_object_unref( pWrap );
902 return NULL;
907 /*****************************************************************************/
909 void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
911 AtkObject *atk_obj = ATK_OBJECT( wrapper );
913 atk_object_set_parent( child, atk_obj );
914 g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, NULL );
917 /*****************************************************************************/
919 void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
922 * the atk-bridge GTK+ module get's back to the event source to ref the child just
923 * vanishing, so we keep this reference because the semantic on OOo side is different.
925 wrapper->child_about_to_be_removed = child;
926 wrapper->index_of_child_about_to_be_removed = index;
928 g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, NULL );
930 wrapper->index_of_child_about_to_be_removed = -1;
931 wrapper->child_about_to_be_removed = NULL;
934 /*****************************************************************************/
936 #define RELEASE(i) if( i ) { i->release(); i = NULL; }
938 void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
940 RELEASE( wrapper->mpContext )
941 RELEASE( wrapper->mpAction )
942 RELEASE( wrapper->mpComponent )
943 RELEASE( wrapper->mpEditableText )
944 RELEASE( wrapper->mpHypertext )
945 RELEASE( wrapper->mpImage )
946 RELEASE( wrapper->mpSelection )
947 RELEASE( wrapper->mpMultiLineText )
948 RELEASE( wrapper->mpTable )
949 RELEASE( wrapper->mpText )
950 RELEASE( wrapper->mpTextAttributes )
951 RELEASE( wrapper->mpValue )