19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
59f62ea84SAndrew Rist * distributed with this work for additional information
69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
109f62ea84SAndrew Rist *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist *
139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist * software distributed under the License is distributed on an
159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
179f62ea84SAndrew Rist * specific language governing permissions and limitations
189f62ea84SAndrew Rist * under the License.
199f62ea84SAndrew Rist *
209f62ea84SAndrew Rist *************************************************************/
219f62ea84SAndrew Rist
229f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include "atkwrapper.hxx"
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleAction.hpp>
30cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
31cdf0e10cSrcweir
32cdf0e10cSrcweir #include <com/sun/star/awt/Key.hpp>
33cdf0e10cSrcweir #include <com/sun/star/awt/KeyModifier.hpp>
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include <rtl/strbuf.hxx>
36cdf0e10cSrcweir #include <algorithm>
37cdf0e10cSrcweir #include <map>
38cdf0e10cSrcweir
39cdf0e10cSrcweir #include <stdio.h>
40cdf0e10cSrcweir
41cdf0e10cSrcweir using namespace ::com::sun::star;
42cdf0e10cSrcweir
43cdf0e10cSrcweir // FIXME
44cdf0e10cSrcweir static G_CONST_RETURN gchar *
getAsConst(const rtl::OString & rString)45cdf0e10cSrcweir getAsConst( const rtl::OString& rString )
46cdf0e10cSrcweir {
47cdf0e10cSrcweir static const int nMax = 10;
48cdf0e10cSrcweir static rtl::OString aUgly[nMax];
49cdf0e10cSrcweir static int nIdx = 0;
50cdf0e10cSrcweir nIdx = (nIdx + 1) % nMax;
51cdf0e10cSrcweir aUgly[nIdx] = rString;
52*24c56ab9SHerbert Dürr return aUgly[ nIdx ].getStr();
53cdf0e10cSrcweir }
54cdf0e10cSrcweir
55cdf0e10cSrcweir static accessibility::XAccessibleAction*
getAction(AtkAction * action)56cdf0e10cSrcweir getAction( AtkAction *action ) throw (uno::RuntimeException)
57cdf0e10cSrcweir {
58cdf0e10cSrcweir AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( action );
59cdf0e10cSrcweir
60cdf0e10cSrcweir if( pWrap )
61cdf0e10cSrcweir {
62cdf0e10cSrcweir if( !pWrap->mpAction && pWrap->mpContext )
63cdf0e10cSrcweir {
64cdf0e10cSrcweir uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleAction::static_type(NULL) );
65cdf0e10cSrcweir pWrap->mpAction = reinterpret_cast< accessibility::XAccessibleAction * > (any.pReserved);
66cdf0e10cSrcweir pWrap->mpAction->acquire();
67cdf0e10cSrcweir }
68cdf0e10cSrcweir
69cdf0e10cSrcweir return pWrap->mpAction;
70cdf0e10cSrcweir }
71cdf0e10cSrcweir
72cdf0e10cSrcweir return NULL;
73cdf0e10cSrcweir }
74cdf0e10cSrcweir
75cdf0e10cSrcweir extern "C" {
76cdf0e10cSrcweir
77cdf0e10cSrcweir static gboolean
action_wrapper_do_action(AtkAction * action,gint i)78cdf0e10cSrcweir action_wrapper_do_action (AtkAction *action,
79cdf0e10cSrcweir gint i)
80cdf0e10cSrcweir {
81cdf0e10cSrcweir try {
82cdf0e10cSrcweir accessibility::XAccessibleAction* pAction = getAction( action );
83cdf0e10cSrcweir if( pAction )
84cdf0e10cSrcweir return pAction->doAccessibleAction( i );
85cdf0e10cSrcweir }
86cdf0e10cSrcweir catch(const uno::Exception& e) {
87cdf0e10cSrcweir g_warning( "Exception in doAccessibleAction()" );
88cdf0e10cSrcweir }
89cdf0e10cSrcweir
90cdf0e10cSrcweir return FALSE;
91cdf0e10cSrcweir }
92cdf0e10cSrcweir
93cdf0e10cSrcweir static gint
action_wrapper_get_n_actions(AtkAction * action)94cdf0e10cSrcweir action_wrapper_get_n_actions (AtkAction *action)
95cdf0e10cSrcweir {
96cdf0e10cSrcweir try {
97cdf0e10cSrcweir accessibility::XAccessibleAction* pAction = getAction( action );
98cdf0e10cSrcweir if( pAction )
99cdf0e10cSrcweir return pAction->getAccessibleActionCount();
100cdf0e10cSrcweir }
101cdf0e10cSrcweir catch(const uno::Exception& e) {
102cdf0e10cSrcweir g_warning( "Exception in getAccessibleActionCount()" );
103cdf0e10cSrcweir }
104cdf0e10cSrcweir
105cdf0e10cSrcweir return 0;
106cdf0e10cSrcweir }
107cdf0e10cSrcweir
108cdf0e10cSrcweir static G_CONST_RETURN gchar *
action_wrapper_get_description(AtkAction *,gint)109cdf0e10cSrcweir action_wrapper_get_description (AtkAction *, gint)
110cdf0e10cSrcweir {
111cdf0e10cSrcweir // GAIL implement this only for cells
112cdf0e10cSrcweir g_warning( "Not implemented: get_description()" );
113cdf0e10cSrcweir return "";
114cdf0e10cSrcweir }
115cdf0e10cSrcweir
116cdf0e10cSrcweir static G_CONST_RETURN gchar *
action_wrapper_get_localized_name(AtkAction *,gint)117cdf0e10cSrcweir action_wrapper_get_localized_name (AtkAction *, gint)
118cdf0e10cSrcweir {
119cdf0e10cSrcweir // GAIL doesn't implement this as well
120cdf0e10cSrcweir g_warning( "Not implemented: get_localized_name()" );
121cdf0e10cSrcweir return "";
122cdf0e10cSrcweir }
123cdf0e10cSrcweir
124cdf0e10cSrcweir #define ACTION_NAME_PAIR( OOoName, AtkName ) \
125cdf0e10cSrcweir std::pair< const rtl::OUString, const gchar * > ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OOoName ) ), AtkName )
126cdf0e10cSrcweir
127cdf0e10cSrcweir static G_CONST_RETURN gchar *
action_wrapper_get_name(AtkAction * action,gint i)128cdf0e10cSrcweir action_wrapper_get_name (AtkAction *action,
129cdf0e10cSrcweir gint i)
130cdf0e10cSrcweir {
131cdf0e10cSrcweir static std::map< rtl::OUString, const gchar * > aNameMap;
132cdf0e10cSrcweir
133cdf0e10cSrcweir if( aNameMap.empty() )
134cdf0e10cSrcweir {
135cdf0e10cSrcweir aNameMap.insert( ACTION_NAME_PAIR( "click", "click" ) );
136cdf0e10cSrcweir aNameMap.insert( ACTION_NAME_PAIR( "select", "click" ) );
137cdf0e10cSrcweir aNameMap.insert( ACTION_NAME_PAIR( "togglePopup", "push" ) );
138cdf0e10cSrcweir }
139cdf0e10cSrcweir
140cdf0e10cSrcweir try {
141cdf0e10cSrcweir accessibility::XAccessibleAction* pAction = getAction( action );
142cdf0e10cSrcweir if( pAction )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir std::map< rtl::OUString, const gchar * >::iterator iter;
145cdf0e10cSrcweir
146cdf0e10cSrcweir rtl::OUString aDesc( pAction->getAccessibleActionDescription( i ) );
147cdf0e10cSrcweir
148cdf0e10cSrcweir iter = aNameMap.find( aDesc );
149cdf0e10cSrcweir if( iter != aNameMap.end() )
150cdf0e10cSrcweir return iter->second;
151cdf0e10cSrcweir
152cdf0e10cSrcweir std::pair< const rtl::OUString, const gchar * > aNewVal( aDesc,
153cdf0e10cSrcweir g_strdup( OUStringToConstGChar(aDesc) ) );
154cdf0e10cSrcweir
155cdf0e10cSrcweir if( aNameMap.insert( aNewVal ).second )
156cdf0e10cSrcweir return aNewVal.second;
157cdf0e10cSrcweir }
158cdf0e10cSrcweir }
159cdf0e10cSrcweir catch(const uno::Exception& e) {
160cdf0e10cSrcweir g_warning( "Exception in getAccessibleActionDescription()" );
161cdf0e10cSrcweir }
162cdf0e10cSrcweir
163cdf0e10cSrcweir return "";
164cdf0e10cSrcweir }
165cdf0e10cSrcweir
166cdf0e10cSrcweir /*
167cdf0e10cSrcweir * GNOME Expects a string in the format:
168cdf0e10cSrcweir *
169cdf0e10cSrcweir * <nmemonic>;<full-path>;<accelerator>
170cdf0e10cSrcweir *
171cdf0e10cSrcweir * The keybindings in <full-path> should be separated by ":"
172cdf0e10cSrcweir */
173cdf0e10cSrcweir
174cdf0e10cSrcweir static inline void
appendKeyStrokes(rtl::OStringBuffer & rBuffer,const uno::Sequence<awt::KeyStroke> & rKeyStrokes)175cdf0e10cSrcweir appendKeyStrokes(rtl::OStringBuffer& rBuffer, const uno::Sequence< awt::KeyStroke >& rKeyStrokes)
176cdf0e10cSrcweir {
177cdf0e10cSrcweir for( sal_Int32 i = 0; i < rKeyStrokes.getLength(); i++ )
178cdf0e10cSrcweir {
179cdf0e10cSrcweir if( rKeyStrokes[i].Modifiers & awt::KeyModifier::SHIFT )
180cdf0e10cSrcweir rBuffer.append("<Shift>");
181cdf0e10cSrcweir if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD1 )
182cdf0e10cSrcweir rBuffer.append("<Control>");
183cdf0e10cSrcweir if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD2 )
184cdf0e10cSrcweir rBuffer.append("<Alt>");
185cdf0e10cSrcweir
186cdf0e10cSrcweir if( ( rKeyStrokes[i].KeyCode >= awt::Key::A ) && ( rKeyStrokes[i].KeyCode <= awt::Key::Z ) )
187cdf0e10cSrcweir rBuffer.append( (sal_Char) ( 'a' + ( rKeyStrokes[i].KeyCode - awt::Key::A ) ) );
188cdf0e10cSrcweir else
189cdf0e10cSrcweir {
190cdf0e10cSrcweir sal_Char c = '\0';
191cdf0e10cSrcweir
192cdf0e10cSrcweir switch( rKeyStrokes[i].KeyCode )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir case awt::Key::TAB: c = '\t'; break;
195cdf0e10cSrcweir case awt::Key::SPACE: c = ' '; break;
196cdf0e10cSrcweir case awt::Key::ADD: c = '+'; break;
197cdf0e10cSrcweir case awt::Key::SUBTRACT: c = '-'; break;
198cdf0e10cSrcweir case awt::Key::MULTIPLY: c = '*'; break;
199cdf0e10cSrcweir case awt::Key::DIVIDE: c = '/'; break;
200cdf0e10cSrcweir case awt::Key::POINT: c = '.'; break;
201cdf0e10cSrcweir case awt::Key::COMMA: c = ','; break;
202cdf0e10cSrcweir case awt::Key::LESS: c = '<'; break;
203cdf0e10cSrcweir case awt::Key::GREATER: c = '>'; break;
204cdf0e10cSrcweir case awt::Key::EQUAL: c = '='; break;
205cdf0e10cSrcweir case 0:
206cdf0e10cSrcweir break;
207cdf0e10cSrcweir default:
208cdf0e10cSrcweir g_warning( "Unmapped KeyCode: %d", rKeyStrokes[i].KeyCode );
209cdf0e10cSrcweir break;
210cdf0e10cSrcweir }
211cdf0e10cSrcweir
212cdf0e10cSrcweir if( c != '\0' )
213cdf0e10cSrcweir rBuffer.append( c );
214cdf0e10cSrcweir }
215cdf0e10cSrcweir }
216cdf0e10cSrcweir }
217cdf0e10cSrcweir
218cdf0e10cSrcweir
219cdf0e10cSrcweir static G_CONST_RETURN gchar *
action_wrapper_get_keybinding(AtkAction * action,gint i)220cdf0e10cSrcweir action_wrapper_get_keybinding (AtkAction *action,
221cdf0e10cSrcweir gint i)
222cdf0e10cSrcweir {
223cdf0e10cSrcweir try {
224cdf0e10cSrcweir accessibility::XAccessibleAction* pAction = getAction( action );
225cdf0e10cSrcweir if( pAction )
226cdf0e10cSrcweir {
227cdf0e10cSrcweir uno::Reference< accessibility::XAccessibleKeyBinding > xBinding( pAction->getAccessibleActionKeyBinding( i ));
228cdf0e10cSrcweir
229cdf0e10cSrcweir if( xBinding.is() )
230cdf0e10cSrcweir {
231cdf0e10cSrcweir rtl::OStringBuffer aRet;
232cdf0e10cSrcweir
233cdf0e10cSrcweir sal_Int32 nmax = std::min( xBinding->getAccessibleKeyBindingCount(), (sal_Int32) 3 );
234cdf0e10cSrcweir for( sal_Int32 n = 0; n < nmax; n++ )
235cdf0e10cSrcweir {
236cdf0e10cSrcweir appendKeyStrokes( aRet, xBinding->getAccessibleKeyBinding( n ) );
237cdf0e10cSrcweir
238cdf0e10cSrcweir if( n < 2 )
239cdf0e10cSrcweir aRet.append( (sal_Char) ';' );
240cdf0e10cSrcweir }
241cdf0e10cSrcweir
242cdf0e10cSrcweir // !! FIXME !! remember keystroke in wrapper object ?
243cdf0e10cSrcweir return getAsConst( aRet.makeStringAndClear() );
244cdf0e10cSrcweir }
245cdf0e10cSrcweir }
246cdf0e10cSrcweir }
247cdf0e10cSrcweir catch(const uno::Exception& e) {
248cdf0e10cSrcweir g_warning( "Exception in get_keybinding()" );
249cdf0e10cSrcweir }
250cdf0e10cSrcweir
251cdf0e10cSrcweir return "";
252cdf0e10cSrcweir }
253cdf0e10cSrcweir
254cdf0e10cSrcweir static gboolean
action_wrapper_set_description(AtkAction *,gint,const gchar *)255cdf0e10cSrcweir action_wrapper_set_description (AtkAction *, gint, const gchar *)
256cdf0e10cSrcweir {
257cdf0e10cSrcweir return FALSE;
258cdf0e10cSrcweir }
259cdf0e10cSrcweir
260cdf0e10cSrcweir } // extern "C"
261cdf0e10cSrcweir
262cdf0e10cSrcweir void
actionIfaceInit(AtkActionIface * iface)263cdf0e10cSrcweir actionIfaceInit (AtkActionIface *iface)
264cdf0e10cSrcweir {
265cdf0e10cSrcweir g_return_if_fail (iface != NULL);
266cdf0e10cSrcweir
267cdf0e10cSrcweir iface->do_action = action_wrapper_do_action;
268cdf0e10cSrcweir iface->get_n_actions = action_wrapper_get_n_actions;
269cdf0e10cSrcweir iface->get_description = action_wrapper_get_description;
270cdf0e10cSrcweir iface->get_keybinding = action_wrapper_get_keybinding;
271cdf0e10cSrcweir iface->get_name = action_wrapper_get_name;
272cdf0e10cSrcweir iface->get_localized_name = action_wrapper_get_localized_name;
273cdf0e10cSrcweir iface->set_description = action_wrapper_set_description;
274cdf0e10cSrcweir }
275