1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "atkwrapper.hxx"
21 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
22 #include <sal/log.hxx>
25 using namespace ::com::sun::star
;
27 static AtkObjectWrapper
* getObjectWrapper(AtkComponent
*pComponent
)
29 AtkObjectWrapper
*pWrap
= nullptr;
30 if (ATK_IS_OBJECT_WRAPPER(pComponent
))
31 pWrap
= ATK_OBJECT_WRAPPER(pComponent
);
32 else if (GTK_IS_DRAWING_AREA(pComponent
)) //when using a GtkDrawingArea as a custom widget in welded gtk3
34 GtkWidget
* pDrawingArea
= GTK_WIDGET(pComponent
);
35 AtkObject
* pAtkObject
= gtk_widget_get_accessible(pDrawingArea
);
36 pWrap
= ATK_IS_OBJECT_WRAPPER(pAtkObject
) ? ATK_OBJECT_WRAPPER(pAtkObject
) : nullptr;
41 /// @throws uno::RuntimeException
42 static css::uno::Reference
<css::accessibility::XAccessibleComponent
>
43 getComponent(AtkObjectWrapper
*pWrap
)
47 if (!pWrap
->mpComponent
.is())
48 pWrap
->mpComponent
.set(pWrap
->mpContext
, css::uno::UNO_QUERY
);
49 return pWrap
->mpComponent
;
52 return css::uno::Reference
<css::accessibility::XAccessibleComponent
>();
56 lcl_getLocationInWindow(AtkComponent
* pAtkComponent
,
57 css::uno::Reference
<accessibility::XAccessibleComponent
> const& xComponent
)
59 // calculate position in window by adding the component's position in the parent
60 // to the parent's position in the window (unless parent is a window itself)
61 awt::Point aPos
= xComponent
->getLocation();
62 AtkObject
* pParent
= atk_object_get_parent(ATK_OBJECT(pAtkComponent
));
63 if (ATK_IS_COMPONENT(pParent
) && pParent
->role
!= AtkRole::ATK_ROLE_DIALOG
64 && pParent
->role
!= AtkRole::ATK_ROLE_FILE_CHOOSER
65 && pParent
->role
!= AtkRole::ATK_ROLE_FRAME
66 && pParent
->role
!= AtkRole::ATK_ROLE_WINDOW
)
70 atk_component_get_extents(ATK_COMPONENT(pParent
), &nX
, &nY
, nullptr, nullptr, ATK_XY_WINDOW
);
78 /*****************************************************************************/
81 translatePoint( AtkComponent
* pAtkComponent
,
82 css::uno::Reference
<accessibility::XAccessibleComponent
> const & pComponent
,
83 gint x
, gint y
, AtkCoordType t
)
85 awt::Point
aOrigin( 0, 0 );
86 if( t
== ATK_XY_SCREEN
)
87 aOrigin
= pComponent
->getLocationOnScreen();
88 else if (t
== ATK_XY_WINDOW
)
89 aOrigin
= lcl_getLocationInWindow(pAtkComponent
, pComponent
);
90 return awt::Point( x
- aOrigin
.X
, y
- aOrigin
.Y
);
93 /*****************************************************************************/
98 component_wrapper_grab_focus (AtkComponent
*component
)
100 AtkObjectWrapper
* obj
= getObjectWrapper(component
);
101 //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
102 if (obj
&& obj
->mpOrig
)
103 return atk_component_grab_focus(ATK_COMPONENT(obj
->mpOrig
));
107 css::uno::Reference
<css::accessibility::XAccessibleComponent
> pComponent
109 if( pComponent
.is() )
111 pComponent
->grabFocus();
115 catch( const uno::Exception
& )
117 g_warning( "Exception in grabFocus()" );
123 /*****************************************************************************/
126 component_wrapper_contains (AtkComponent
*component
,
129 AtkCoordType coord_type
)
131 AtkObjectWrapper
* obj
= getObjectWrapper(component
);
132 //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
133 if (obj
&& obj
->mpOrig
)
134 return atk_component_contains(ATK_COMPONENT(obj
->mpOrig
), x
, y
, coord_type
);
138 css::uno::Reference
<css::accessibility::XAccessibleComponent
> pComponent
140 if( pComponent
.is() )
141 return pComponent
->containsPoint(
142 translatePoint(component
, pComponent
, x
, y
, coord_type
));
144 catch( const uno::Exception
& )
146 g_warning( "Exception in containsPoint()" );
152 /*****************************************************************************/
155 component_wrapper_ref_accessible_at_point (AtkComponent
*component
,
158 AtkCoordType coord_type
)
160 AtkObjectWrapper
* obj
= getObjectWrapper(component
);
161 //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
162 if (obj
&& obj
->mpOrig
)
163 return atk_component_ref_accessible_at_point(ATK_COMPONENT(obj
->mpOrig
), x
, y
, coord_type
);
167 css::uno::Reference
<css::accessibility::XAccessibleComponent
> pComponent
170 if( pComponent
.is() )
172 uno::Reference
< accessibility::XAccessible
> xAccessible
= pComponent
->getAccessibleAtPoint(
173 translatePoint(component
, pComponent
, x
, y
, coord_type
));
174 return atk_object_wrapper_ref( xAccessible
);
177 catch( const uno::Exception
& )
179 g_warning( "Exception in getAccessibleAtPoint()" );
185 /*****************************************************************************/
188 component_wrapper_get_position (AtkComponent
*component
,
191 AtkCoordType coord_type
)
193 AtkObjectWrapper
* obj
= getObjectWrapper(component
);
194 //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
195 if (obj
&& obj
->mpOrig
)
197 atk_component_get_extents(ATK_COMPONENT(obj
->mpOrig
), x
, y
, nullptr, nullptr, coord_type
);
205 css::uno::Reference
<css::accessibility::XAccessibleComponent
> pComponent
207 if( pComponent
.is() )
211 if( coord_type
== ATK_XY_SCREEN
)
212 aPos
= pComponent
->getLocationOnScreen();
213 else if (coord_type
== ATK_XY_WINDOW
)
214 aPos
= lcl_getLocationInWindow(component
, pComponent
);
215 #if ATK_CHECK_VERSION(2, 30, 0)
216 else if (coord_type
== ATK_XY_PARENT
)
218 // ATK_XY_PARENT added in ATK 2.30, so can't use the constant here
221 aPos
= pComponent
->getLocation();
222 #if ATK_CHECK_VERSION(2, 30, 0)
226 "component_wrapper_get_position called with unknown AtkCoordType "
236 catch( const uno::Exception
& )
238 g_warning( "Exception in getLocation[OnScreen]()" );
242 /*****************************************************************************/
245 component_wrapper_get_size (AtkComponent
*component
,
249 AtkObjectWrapper
* obj
= getObjectWrapper(component
);
250 //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
251 if (obj
&& obj
->mpOrig
)
253 atk_component_get_extents(ATK_COMPONENT(obj
->mpOrig
), nullptr, nullptr, width
, height
, ATK_XY_WINDOW
);
257 *width
= *height
= -1;
261 css::uno::Reference
<css::accessibility::XAccessibleComponent
> pComponent
263 if( pComponent
.is() )
265 awt::Size aSize
= pComponent
->getSize();
266 *width
= aSize
.Width
;
267 *height
= aSize
.Height
;
270 catch( const uno::Exception
& )
272 g_warning( "Exception in getSize()" );
276 /*****************************************************************************/
279 component_wrapper_get_extents (AtkComponent
*component
,
284 AtkCoordType coord_type
)
286 component_wrapper_get_position( component
, x
, y
, coord_type
);
287 component_wrapper_get_size( component
, width
, height
);
290 /*****************************************************************************/
293 component_wrapper_set_extents (AtkComponent
*, gint
, gint
, gint
, gint
, AtkCoordType
)
295 g_warning( "AtkComponent::set_extents unimplementable" );
299 /*****************************************************************************/
302 component_wrapper_set_position (AtkComponent
*, gint
, gint
, AtkCoordType
)
304 g_warning( "AtkComponent::set_position unimplementable" );
308 /*****************************************************************************/
311 component_wrapper_set_size (AtkComponent
*, gint
, gint
)
313 g_warning( "AtkComponent::set_size unimplementable" );
317 /*****************************************************************************/
320 component_wrapper_get_layer (AtkComponent
*component
)
322 AtkRole role
= atk_object_get_role( ATK_OBJECT( component
) );
323 AtkLayer layer
= ATK_LAYER_WIDGET
;
327 case ATK_ROLE_POPUP_MENU
:
328 case ATK_ROLE_MENU_ITEM
:
329 case ATK_ROLE_CHECK_MENU_ITEM
:
330 case ATK_ROLE_SEPARATOR
:
331 case ATK_ROLE_LIST_ITEM
:
332 layer
= ATK_LAYER_POPUP
;
336 AtkObject
* parent
= atk_object_get_parent( ATK_OBJECT( component
) );
337 if( atk_object_get_role( parent
) != ATK_ROLE_MENU_BAR
)
338 layer
= ATK_LAYER_POPUP
;
344 AtkObject
* parent
= atk_object_get_parent( ATK_OBJECT( component
) );
345 if( atk_object_get_role( parent
) == ATK_ROLE_COMBO_BOX
)
346 layer
= ATK_LAYER_POPUP
;
357 /*****************************************************************************/
360 component_wrapper_get_mdi_zorder (AtkComponent
*)
362 // only needed for ATK_LAYER_MDI (not used) or ATK_LAYER_WINDOW (inherited from GAIL)
366 /*****************************************************************************/
368 // This code is mostly stolen from libgail ..
371 component_wrapper_add_focus_handler (AtkComponent
*component
,
372 AtkFocusHandler handler
)
374 GSignalMatchType match_type
;
378 match_type
= GSignalMatchType(G_SIGNAL_MATCH_ID
| G_SIGNAL_MATCH_FUNC
);
379 signal_id
= g_signal_lookup( "focus-event", ATK_TYPE_OBJECT
);
381 ret
= g_signal_handler_find( component
, match_type
, signal_id
, 0, nullptr,
382 static_cast<gpointer
>(&handler
), nullptr);
385 return g_signal_connect_closure_by_id (component
,
388 G_CALLBACK (handler
), nullptr,
398 /*****************************************************************************/
401 component_wrapper_remove_focus_handler (AtkComponent
*component
,
404 g_signal_handler_disconnect (component
, handler_id
);
407 /*****************************************************************************/
412 componentIfaceInit (gpointer iface_
, gpointer
)
414 auto const iface
= static_cast<AtkComponentIface
*>(iface_
);
415 g_return_if_fail (iface
!= nullptr);
417 iface
->add_focus_handler
= component_wrapper_add_focus_handler
;
418 iface
->contains
= component_wrapper_contains
;
419 iface
->get_extents
= component_wrapper_get_extents
;
420 iface
->get_layer
= component_wrapper_get_layer
;
421 iface
->get_mdi_zorder
= component_wrapper_get_mdi_zorder
;
422 iface
->get_position
= component_wrapper_get_position
;
423 iface
->get_size
= component_wrapper_get_size
;
424 iface
->grab_focus
= component_wrapper_grab_focus
;
425 iface
->ref_accessible_at_point
= component_wrapper_ref_accessible_at_point
;
426 iface
->remove_focus_handler
= component_wrapper_remove_focus_handler
;
427 iface
->set_extents
= component_wrapper_set_extents
;
428 iface
->set_position
= component_wrapper_set_position
;
429 iface
->set_size
= component_wrapper_set_size
;
432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */