xref: /aoo41x/main/vcl/unx/gtk/a11y/atkaction.cxx (revision 24c56ab9)
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