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