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/controls/accessiblecontrolcontext.hxx> 31 #include <unotools/accessiblestatesethelper.hxx> 32 #include <com/sun/star/awt/XControl.hpp> 33 #include <com/sun/star/awt/XWindow.hpp> 34 #include <vcl/svapp.hxx> 35 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 36 #include <com/sun/star/accessibility/AccessibleRole.hpp> 37 #include <toolkit/helper/vclunohelper.hxx> 38 #include <vcl/window.hxx> 39 40 //........................................................................ 41 namespace toolkit 42 { 43 //........................................................................ 44 45 using ::comphelper::OContextEntryGuard; 46 using namespace ::com::sun::star; 47 using namespace ::com::sun::star::uno; 48 using namespace ::com::sun::star::lang; 49 using namespace ::com::sun::star::beans; 50 using namespace ::com::sun::star::accessibility; 51 52 //==================================================================== 53 //= OAccessibleControlContext 54 //==================================================================== 55 //-------------------------------------------------------------------- 56 OAccessibleControlContext::OAccessibleControlContext() 57 :OAccessibleControlContext_Base( ) 58 { 59 // nothing to do here, we have a late ctor 60 } 61 62 //-------------------------------------------------------------------- 63 OAccessibleControlContext::~OAccessibleControlContext() 64 { 65 ensureDisposed(); 66 } 67 68 //-------------------------------------------------------------------- 69 IMPLEMENT_FORWARD_XINTERFACE3( OAccessibleControlContext, OAccessibleControlContext_Base, OAccessibleImplementationAccess, OAccessibleControlContext_IBase ) 70 IMPLEMENT_FORWARD_XTYPEPROVIDER3( OAccessibleControlContext, OAccessibleControlContext_Base, OAccessibleImplementationAccess, OAccessibleControlContext_IBase ) 71 // (order matters: the first is the class name, the second is the class doing the ref counting) 72 73 //-------------------------------------------------------------------- 74 void OAccessibleControlContext::Init( const Reference< XAccessible >& _rxCreator ) SAL_THROW( ( Exception ) ) 75 { 76 OContextEntryGuard aGuard( this ); 77 78 // retrieve the model of the control 79 OSL_ENSURE( !m_xControlModel.is(), "OAccessibleControlContext::Init: already know a control model....!???" ); 80 81 Reference< awt::XControl > xControl( _rxCreator, UNO_QUERY ); 82 if ( xControl.is() ) 83 m_xControlModel = m_xControlModel.query( xControl->getModel() ); 84 OSL_ENSURE( m_xControlModel.is(), "OAccessibleControlContext::Init: invalid creator (no control, or control without model!" ); 85 if ( !m_xControlModel.is() ) 86 throw DisposedException(); // caught by the caller (the create method) 87 88 // start listening at the model 89 startModelListening(); 90 91 // announce the XAccessible to our base class 92 OAccessibleControlContext_Base::lateInit( _rxCreator ); 93 } 94 95 //-------------------------------------------------------------------- 96 OAccessibleControlContext* OAccessibleControlContext::create( const Reference< XAccessible >& _rxCreator ) SAL_THROW( ( ) ) 97 { 98 OAccessibleControlContext* pNew = NULL; 99 try 100 { 101 pNew = new OAccessibleControlContext; 102 pNew->Init( _rxCreator ); 103 } 104 catch( const Exception& ) 105 { 106 OSL_ENSURE( sal_False, "OAccessibleControlContext::create: caught an exception from the late ctor!" ); 107 } 108 return pNew; 109 } 110 111 //-------------------------------------------------------------------- 112 void OAccessibleControlContext::startModelListening( ) SAL_THROW( ( Exception ) ) 113 { 114 Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY ); 115 OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::startModelListening: invalid model!" ); 116 if ( xModelComp.is() ) 117 xModelComp->addEventListener( this ); 118 } 119 120 //-------------------------------------------------------------------- 121 void OAccessibleControlContext::stopModelListening( ) SAL_THROW( ( Exception ) ) 122 { 123 Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY ); 124 OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::stopModelListening: invalid model!" ); 125 if ( xModelComp.is() ) 126 xModelComp->removeEventListener( this ); 127 } 128 129 //-------------------------------------------------------------------- 130 sal_Int32 SAL_CALL OAccessibleControlContext::getAccessibleChildCount( ) throw (RuntimeException) 131 { 132 // we do not have children 133 return 0; 134 } 135 136 //-------------------------------------------------------------------- 137 Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleChild( sal_Int32 ) throw (IndexOutOfBoundsException, RuntimeException) 138 { 139 // we do not have children 140 throw IndexOutOfBoundsException(); 141 } 142 143 //-------------------------------------------------------------------- 144 Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleParent( ) throw (RuntimeException) 145 { 146 OContextEntryGuard aGuard( this ); 147 OSL_ENSURE( implGetForeignControlledParent().is(), "OAccessibleControlContext::getAccessibleParent: somebody forgot to set a parent!" ); 148 // this parent of us is foreign controlled - somebody has to set it using the OAccessibleImplementationAccess 149 // class, before integrating our instance into an AccessibleDocumentModel 150 return implGetForeignControlledParent(); 151 } 152 153 //-------------------------------------------------------------------- 154 sal_Int16 SAL_CALL OAccessibleControlContext::getAccessibleRole( ) throw (RuntimeException) 155 { 156 return AccessibleRole::SHAPE; 157 } 158 159 //-------------------------------------------------------------------- 160 ::rtl::OUString SAL_CALL OAccessibleControlContext::getAccessibleDescription( ) throw (RuntimeException) 161 { 162 OContextEntryGuard aGuard( this ); 163 return getModelStringProperty( "HelpText" ); 164 } 165 166 //-------------------------------------------------------------------- 167 ::rtl::OUString SAL_CALL OAccessibleControlContext::getAccessibleName( ) throw (RuntimeException) 168 { 169 OContextEntryGuard aGuard( this ); 170 return getModelStringProperty( "Name" ); 171 } 172 173 //-------------------------------------------------------------------- 174 Reference< XAccessibleRelationSet > SAL_CALL OAccessibleControlContext::getAccessibleRelationSet( ) throw (RuntimeException) 175 { 176 return NULL; 177 } 178 179 //-------------------------------------------------------------------- 180 Reference< XAccessibleStateSet > SAL_CALL OAccessibleControlContext::getAccessibleStateSet( ) throw (RuntimeException) 181 { 182 ::osl::MutexGuard aGuard( GetMutex() ); 183 // no OContextEntryGuard here, as we do not want to throw an exception in case we're not alive anymore 184 185 ::utl::AccessibleStateSetHelper* pStateSet = NULL; 186 if ( isAlive() ) 187 { 188 // no own states, only the ones which are foreign controlled 189 pStateSet = new ::utl::AccessibleStateSetHelper( implGetForeignControlledStates() ); 190 } 191 else 192 { // only the DEFUNC state if we're already disposed 193 pStateSet = new ::utl::AccessibleStateSetHelper; 194 pStateSet->AddState( AccessibleStateType::DEFUNC ); 195 } 196 return pStateSet; 197 } 198 199 //-------------------------------------------------------------------- 200 void SAL_CALL OAccessibleControlContext::disposing( const EventObject& 201 #if OSL_DEBUG_LEVEL > 0 202 _rSource 203 #endif 204 ) throw ( RuntimeException ) 205 { 206 OSL_ENSURE( Reference< XPropertySet >( _rSource.Source, UNO_QUERY ).get() == m_xControlModel.get(), 207 "OAccessibleControlContext::disposing: where did this come from?" ); 208 209 stopModelListening( ); 210 m_xControlModel.clear(); 211 m_xModelPropsInfo.clear(); 212 213 OAccessibleControlContext_Base::disposing(); 214 } 215 216 //-------------------------------------------------------------------- 217 ::rtl::OUString OAccessibleControlContext::getModelStringProperty( const sal_Char* _pPropertyName ) 218 { 219 ::rtl::OUString sReturn; 220 try 221 { 222 if ( !m_xModelPropsInfo.is() && m_xControlModel.is() ) 223 m_xModelPropsInfo = m_xControlModel->getPropertySetInfo(); 224 225 ::rtl::OUString sPropertyName( ::rtl::OUString::createFromAscii( _pPropertyName ) ); 226 if ( m_xModelPropsInfo.is() && m_xModelPropsInfo->hasPropertyByName( sPropertyName ) ) 227 m_xControlModel->getPropertyValue( sPropertyName ) >>= sReturn; 228 } 229 catch( const Exception& ) 230 { 231 OSL_ENSURE( sal_False, "OAccessibleControlContext::getModelStringProperty: caught an exception!" ); 232 } 233 return sReturn; 234 } 235 236 //-------------------------------------------------------------------- 237 Window* OAccessibleControlContext::implGetWindow( Reference< awt::XWindow >* _pxUNOWindow ) const 238 { 239 Reference< awt::XControl > xControl( getAccessibleCreator(), UNO_QUERY ); 240 Reference< awt::XWindow > xWindow; 241 if ( xControl.is() ) 242 xWindow = xWindow.query( xControl->getPeer() ); 243 244 Window* pWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow ) : NULL; 245 246 if ( _pxUNOWindow ) 247 *_pxUNOWindow = xWindow; 248 return pWindow; 249 } 250 251 //-------------------------------------------------------------------- 252 awt::Rectangle SAL_CALL OAccessibleControlContext::implGetBounds( ) throw (RuntimeException) 253 { 254 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 255 // want to do some VCL stuff here ... 256 OContextEntryGuard aGuard( this ); 257 258 OSL_ENSURE( sal_False, "OAccessibleControlContext::implGetBounds: performance issue: forced to calc the size myself!" ); 259 // In design mode (and this is what this class is for), the surrounding shape (if any) should handle this call 260 // The problem is that in design mode, our size may not be correct (in the drawing layer, controls are 261 // positioned/sized for painting only), and that calculation of our position is expensive 262 263 // what we know (or can obtain from somewhere): 264 // * the PosSize of our peer, relative to it's parent window 265 // * the parent window which the PosSize is relative to 266 // * our foreign controlled accessible parent 267 // from this info, we can determine the the position of our peer relative to the foreign parent 268 269 // our control 270 Reference< awt::XWindow > xWindow; 271 Window* pVCLWindow = implGetWindow( &xWindow ); 272 273 awt::Rectangle aBounds( 0, 0, 0, 0 ); 274 if ( xWindow.is() ) 275 { 276 // ugly, but .... though the XWindow has a getPosSize, it is impossible to determine the 277 // parent which this position/size is relative to. This means we must tunnel UNO and ask the 278 // implementation 279 Window* pVCLParent = pVCLWindow ? pVCLWindow->GetParent() : NULL; 280 281 // the relative location of the window 282 ::Point aWindowRelativePos( 0, 0); 283 if ( pVCLWindow ) 284 aWindowRelativePos = pVCLWindow->GetPosPixel(); 285 286 // the screnn position of the "window parent" of the control 287 ::Point aVCLParentScreenPos( 0, 0 ); 288 if ( pVCLParent ) 289 aVCLParentScreenPos = pVCLParent->GetPosPixel(); 290 291 // the screen position of the "accessible parent" of the control 292 Reference< XAccessible > xParentAcc( implGetForeignControlledParent() ); 293 Reference< XAccessibleComponent > xParentAccComponent; 294 if ( xParentAcc.is() ) 295 xParentAccComponent = xParentAccComponent.query( xParentAcc->getAccessibleContext() ); 296 awt::Point aAccParentScreenPos( 0, 0 ); 297 if ( xParentAccComponent.is() ) 298 aAccParentScreenPos = xParentAccComponent->getLocationOnScreen(); 299 300 // now the size of the control 301 aBounds = xWindow->getPosSize(); 302 303 // correct the pos 304 aBounds.X = aWindowRelativePos.X() + aVCLParentScreenPos.X() - aAccParentScreenPos.X; 305 aBounds.Y = aWindowRelativePos.Y() + aVCLParentScreenPos.Y() - aAccParentScreenPos.Y; 306 } 307 308 return aBounds; 309 } 310 311 //-------------------------------------------------------------------- 312 Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleAtPoint( const awt::Point& /* _rPoint */ ) throw (RuntimeException) 313 { 314 // no children at all 315 return NULL; 316 } 317 318 //-------------------------------------------------------------------- 319 void SAL_CALL OAccessibleControlContext::grabFocus( ) throw (RuntimeException) 320 { 321 OSL_ENSURE( sal_False, "OAccessibleControlContext::grabFocus: !isFocusTraversable, but grabFocus!" ); 322 } 323 324 //-------------------------------------------------------------------- 325 Any SAL_CALL OAccessibleControlContext::getAccessibleKeyBinding( ) throw (RuntimeException) 326 { 327 // we do not have any key bindings to activate a UNO control in design mode 328 return Any(); 329 } 330 331 //-------------------------------------------------------------------- 332 sal_Int32 SAL_CALL OAccessibleControlContext::getForeground( ) throw (::com::sun::star::uno::RuntimeException) 333 { 334 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 335 // want to do some VCL stuff here ... 336 OContextEntryGuard aGuard( this ); 337 338 Window* pWindow = implGetWindow( ); 339 sal_Int32 nColor = 0; 340 if ( pWindow ) 341 { 342 if ( pWindow->IsControlForeground() ) 343 nColor = pWindow->GetControlForeground().GetColor(); 344 else 345 { 346 Font aFont; 347 if ( pWindow->IsControlFont() ) 348 aFont = pWindow->GetControlFont(); 349 else 350 aFont = pWindow->GetFont(); 351 nColor = aFont.GetColor().GetColor(); 352 } 353 } 354 return nColor; 355 } 356 357 //-------------------------------------------------------------------- 358 sal_Int32 SAL_CALL OAccessibleControlContext::getBackground( ) throw (::com::sun::star::uno::RuntimeException) 359 { 360 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 361 // want to do some VCL stuff here ... 362 OContextEntryGuard aGuard( this ); 363 364 Window* pWindow = implGetWindow( ); 365 sal_Int32 nColor = 0; 366 if ( pWindow ) 367 { 368 if ( pWindow->IsControlBackground() ) 369 nColor = pWindow->GetControlBackground().GetColor(); 370 else 371 nColor = pWindow->GetBackground().GetColor().GetColor(); 372 } 373 374 return nColor; 375 } 376 377 //........................................................................ 378 } //namespace toolkit 379 //........................................................................ 380 381