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