1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_toolkit.hxx" 26 #include <toolkit/helper/accessibilityclient.hxx> 27 #include <toolkit/helper/accessiblefactory.hxx> 28 #include <osl/module.h> 29 #include <osl/diagnose.h> 30 #include <tools/solar.h> 31 32 // #define UNLOAD_ON_LAST_CLIENT_DYING 33 // this is not recommended currently. If enabled, the implementation will log 34 // the number of active clients, and unload the acc library when the last client 35 // goes away. 36 // Sounds like a good idea, unfortunately, there's no guarantee that all objects 37 // implemented in this library are already dead. 38 // Iow, just because an object implementing an XAccessible (implemented in this lib 39 // here) died, it's not said that everybody released all references to the 40 // XAccessibleContext used by this component, and implemented in the acc lib. 41 // So we cannot really unload the lib. 42 // 43 // Alternatively, if the lib would us own "usage counting", i.e. every component 44 // implemented therein would affect a static ref count, the acc lib could care 45 // for unloading itself. 46 47 //........................................................................ 48 namespace toolkit 49 { 50 //........................................................................ 51 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::accessibility; 54 55 namespace 56 { 57 #ifdef UNLOAD_ON_LAST_CLIENT_DYING 58 static oslInterlockedCount s_nAccessibilityClients = 0; 59 #endif // UNLOAD_ON_LAST_CLIENT_DYING 60 static oslModule s_hAccessibleImplementationModule = NULL; 61 static GetStandardAccComponentFactory s_pAccessibleFactoryFunc = NULL; 62 static ::rtl::Reference< IAccessibleFactory > s_pFactory; 63 } 64 65 //==================================================================== 66 //= AccessibleDummyFactory 67 //==================================================================== 68 class AccessibleDummyFactory : public IAccessibleFactory 69 { 70 public: 71 AccessibleDummyFactory(); 72 73 protected: 74 virtual ~AccessibleDummyFactory(); 75 76 private: 77 AccessibleDummyFactory( const AccessibleDummyFactory& ); // never implemented 78 AccessibleDummyFactory& operator=( const AccessibleDummyFactory& ); // never implemented 79 80 oslInterlockedCount m_refCount; 81 82 public: 83 // IReference 84 virtual oslInterlockedCount SAL_CALL acquire(); 85 virtual oslInterlockedCount SAL_CALL release(); 86 87 // IAccessibleFactory 88 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXButton *)89 createAccessibleContext( VCLXButton* /*_pXWindow*/ ) 90 { 91 return NULL; 92 } 93 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXCheckBox *)94 createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ ) 95 { 96 return NULL; 97 } 98 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXRadioButton *)99 createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ ) 100 { 101 return NULL; 102 } 103 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXListBox *)104 createAccessibleContext( VCLXListBox* /*_pXWindow*/ ) 105 { 106 return NULL; 107 } 108 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXFixedHyperlink *)109 createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ ) 110 { 111 return NULL; 112 } 113 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXFixedText *)114 createAccessibleContext( VCLXFixedText* /*_pXWindow*/ ) 115 { 116 return NULL; 117 } 118 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXScrollBar *)119 createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ ) 120 { 121 return NULL; 122 } 123 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXEdit *)124 createAccessibleContext( VCLXEdit* /*_pXWindow*/ ) 125 { 126 return NULL; 127 } 128 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXComboBox *)129 createAccessibleContext( VCLXComboBox* /*_pXWindow*/ ) 130 { 131 return NULL; 132 } 133 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXToolBox *)134 createAccessibleContext( VCLXToolBox* /*_pXWindow*/ ) 135 { 136 return NULL; 137 } 138 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > createAccessibleContext(VCLXWindow *)139 createAccessibleContext( VCLXWindow* /*_pXWindow*/ ) 140 { 141 return NULL; 142 } 143 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > createAccessible(Menu *,sal_Bool)144 createAccessible( Menu* /*_pMenu*/, sal_Bool /*_bIsMenuBar*/ ) 145 { 146 return NULL; 147 } 148 }; 149 150 //-------------------------------------------------------------------- AccessibleDummyFactory()151 AccessibleDummyFactory::AccessibleDummyFactory() 152 { 153 } 154 155 //-------------------------------------------------------------------- ~AccessibleDummyFactory()156 AccessibleDummyFactory::~AccessibleDummyFactory() 157 { 158 } 159 160 //-------------------------------------------------------------------- acquire()161 oslInterlockedCount SAL_CALL AccessibleDummyFactory::acquire() 162 { 163 return osl_incrementInterlockedCount( &m_refCount ); 164 } 165 166 //-------------------------------------------------------------------- release()167 oslInterlockedCount SAL_CALL AccessibleDummyFactory::release() 168 { 169 if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) 170 { 171 delete this; 172 return 0; 173 } 174 return m_refCount; 175 } 176 177 //==================================================================== 178 //= AccessibilityClient 179 //==================================================================== 180 //-------------------------------------------------------------------- AccessibilityClient()181 AccessibilityClient::AccessibilityClient() 182 :m_bInitialized( false ) 183 { 184 } 185 186 //-------------------------------------------------------------------- thisModule()187 extern "C" { static void SAL_CALL thisModule() {} } 188 ensureInitialized()189 void AccessibilityClient::ensureInitialized() 190 { 191 if ( m_bInitialized ) 192 return; 193 194 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 195 196 #ifdef UNLOAD_ON_LAST_CLIENT_DYING 197 if ( 1 == osl_incrementInterlockedCount( &s_nAccessibilityClients ) ) 198 { // the first client 199 #endif // UNLOAD_ON_LAST_CLIENT_DYING 200 // load the library implementing the factory 201 if ( !s_pFactory.get() ) 202 { 203 const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( 204 SVLIBRARY( "acc" ) 205 ); 206 s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 ); 207 if ( s_hAccessibleImplementationModule != NULL ) 208 { 209 const ::rtl::OUString sFactoryCreationFunc = 210 ::rtl::OUString::createFromAscii( "getStandardAccessibleFactory" ); 211 s_pAccessibleFactoryFunc = (GetStandardAccComponentFactory) 212 osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData ); 213 214 } 215 OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" ); 216 217 // get a factory instance 218 if ( s_pAccessibleFactoryFunc ) 219 { 220 IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() ); 221 OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" ); 222 if ( pFactory ) 223 { 224 s_pFactory = pFactory; 225 pFactory->release(); 226 } 227 } 228 } 229 230 if ( !s_pFactory.get() ) 231 // the attempt to load the lib, or to create the factory, failed 232 // -> fall back to a dummy factory 233 s_pFactory = new AccessibleDummyFactory; 234 #ifdef UNLOAD_ON_LAST_CLIENT_DYING 235 } 236 #endif 237 238 m_bInitialized = true; 239 } 240 241 //-------------------------------------------------------------------- ~AccessibilityClient()242 AccessibilityClient::~AccessibilityClient() 243 { 244 if ( m_bInitialized ) 245 { 246 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 247 248 #ifdef UNLOAD_ON_LAST_CLIENT_DYING 249 if( 0 == osl_decrementInterlockedCount( &s_nAccessibilityClients ) ) 250 { 251 s_pFactory = NULL; 252 s_pAccessibleFactoryFunc = NULL; 253 if ( s_hAccessibleImplementationModule ) 254 { 255 osl_unloadModule( s_hAccessibleImplementationModule ); 256 s_hAccessibleImplementationModule = NULL; 257 } 258 } 259 #endif // UNLOAD_ON_LAST_CLIENT_DYING 260 } 261 } 262 263 //-------------------------------------------------------------------- getFactory()264 IAccessibleFactory& AccessibilityClient::getFactory() 265 { 266 ensureInitialized(); 267 OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" ); 268 return *s_pFactory; 269 } 270 271 //........................................................................ 272 } // namespace toolkit 273 //........................................................................ 274