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_accessibility.hxx" 26 #include <accessibility/standard/vclxaccessiblemenuitem.hxx> 27 #include <accessibility/helper/accresmgr.hxx> 28 #include <accessibility/helper/accessiblestrings.hrc> 29 #include <toolkit/helper/convert.hxx> 30 #include <accessibility/helper/characterattributeshelper.hxx> 31 #include <comphelper/accessiblekeybindinghelper.hxx> 32 #include <com/sun/star/awt/KeyModifier.hpp> 33 34 #include <com/sun/star/accessibility/AccessibleRole.hpp> 35 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 36 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> 37 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> 38 #include <unotools/accessiblestatesethelper.hxx> 39 #include <comphelper/sequence.hxx> 40 #include <vcl/svapp.hxx> 41 #include <vcl/window.hxx> 42 #include <vcl/menu.hxx> 43 #include <vcl/unohelp2.hxx> 44 45 #include <memory> 46 47 48 using namespace ::com::sun::star::accessibility; 49 using namespace ::com::sun::star::uno; 50 using namespace ::com::sun::star::beans; 51 using namespace ::com::sun::star::lang; 52 using namespace ::com::sun::star; 53 using namespace ::comphelper; 54 55 56 // ----------------------------------------------------------------------------- 57 // class VCLXAccessibleMenuItem 58 // ----------------------------------------------------------------------------- 59 60 VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu ) 61 :OAccessibleMenuItemComponent( pParent, nItemPos, pMenu ) 62 { 63 } 64 65 // ----------------------------------------------------------------------------- 66 67 VCLXAccessibleMenuItem::~VCLXAccessibleMenuItem() 68 { 69 } 70 71 // ----------------------------------------------------------------------------- 72 73 sal_Bool VCLXAccessibleMenuItem::IsFocused() 74 { 75 return IsHighlighted(); 76 } 77 78 // ----------------------------------------------------------------------------- 79 80 sal_Bool VCLXAccessibleMenuItem::IsSelected() 81 { 82 return IsHighlighted(); 83 } 84 85 // ----------------------------------------------------------------------------- 86 87 sal_Bool VCLXAccessibleMenuItem::IsChecked() 88 { 89 sal_Bool bChecked = sal_False; 90 91 if ( m_pParent ) 92 { 93 sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos ); 94 if ( m_pParent->IsItemChecked( nItemId ) ) 95 bChecked = sal_True; 96 } 97 98 return bChecked; 99 } 100 101 // ----------------------------------------------------------------------------- 102 103 sal_Bool VCLXAccessibleMenuItem::IsHighlighted() 104 { 105 sal_Bool bHighlighted = sal_False; 106 107 if ( m_pParent && m_pParent->IsHighlighted( m_nItemPos ) ) 108 bHighlighted = sal_True; 109 110 return bHighlighted; 111 } 112 113 // ----------------------------------------------------------------------------- 114 115 void VCLXAccessibleMenuItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) 116 { 117 OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet ); 118 119 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 120 121 if ( IsFocused() ) 122 rStateSet.AddState( AccessibleStateType::FOCUSED ); 123 124 rStateSet.AddState( AccessibleStateType::SELECTABLE ); 125 126 if ( IsSelected() ) 127 rStateSet.AddState( AccessibleStateType::SELECTED ); 128 129 if ( IsChecked() ) 130 rStateSet.AddState( AccessibleStateType::CHECKED ); 131 } 132 133 // ----------------------------------------------------------------------------- 134 // OCommonAccessibleText 135 // ----------------------------------------------------------------------------- 136 137 ::rtl::OUString VCLXAccessibleMenuItem::implGetText() 138 { 139 return m_sItemText; 140 } 141 142 // ----------------------------------------------------------------------------- 143 144 Locale VCLXAccessibleMenuItem::implGetLocale() 145 { 146 return Application::GetSettings().GetLocale(); 147 } 148 149 // ----------------------------------------------------------------------------- 150 151 void VCLXAccessibleMenuItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) 152 { 153 nStartIndex = 0; 154 nEndIndex = 0; 155 } 156 157 // ----------------------------------------------------------------------------- 158 // XInterface 159 // ----------------------------------------------------------------------------- 160 161 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE ) 162 163 // ----------------------------------------------------------------------------- 164 // XTypeProvider 165 // ----------------------------------------------------------------------------- 166 167 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE ) 168 169 // ----------------------------------------------------------------------------- 170 // XServiceInfo 171 // ----------------------------------------------------------------------------- 172 173 ::rtl::OUString VCLXAccessibleMenuItem::getImplementationName() throw (RuntimeException) 174 { 175 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleMenuItem" ); 176 } 177 178 // ----------------------------------------------------------------------------- 179 180 Sequence< ::rtl::OUString > VCLXAccessibleMenuItem::getSupportedServiceNames() throw (RuntimeException) 181 { 182 Sequence< ::rtl::OUString > aNames(1); 183 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleMenuItem" ); 184 return aNames; 185 } 186 187 // ----------------------------------------------------------------------------- 188 // XAccessibleContext 189 // ----------------------------------------------------------------------------- 190 191 sal_Int16 VCLXAccessibleMenuItem::getAccessibleRole( ) throw (RuntimeException) 192 { 193 OExternalLockGuard aGuard( this ); 194 195 return AccessibleRole::MENU_ITEM; 196 } 197 198 // ----------------------------------------------------------------------------- 199 // XAccessibleText 200 // ----------------------------------------------------------------------------- 201 202 sal_Int32 VCLXAccessibleMenuItem::getCaretPosition() throw (RuntimeException) 203 { 204 OExternalLockGuard aGuard( this ); 205 206 return -1; 207 } 208 209 // ----------------------------------------------------------------------------- 210 211 sal_Bool VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 212 { 213 214 OExternalLockGuard aGuard( this ); 215 216 if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) ) 217 throw IndexOutOfBoundsException(); 218 219 return sal_False; 220 } 221 222 // ----------------------------------------------------------------------------- 223 224 sal_Unicode VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 225 { 226 OExternalLockGuard aGuard( this ); 227 228 return OCommonAccessibleText::getCharacter( nIndex ); 229 } 230 231 // ----------------------------------------------------------------------------- 232 233 Sequence< PropertyValue > VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (IndexOutOfBoundsException, RuntimeException) 234 { 235 OExternalLockGuard aGuard( this ); 236 237 Sequence< PropertyValue > aValues; 238 ::rtl::OUString sText( implGetText() ); 239 240 if ( !implIsValidIndex( nIndex, sText.getLength() ) ) 241 throw IndexOutOfBoundsException(); 242 243 Font aFont = Application::GetSettings().GetStyleSettings().GetMenuFont(); 244 sal_Int32 nBackColor = getBackground(); 245 sal_Int32 nColor = getForeground(); 246 ::std::auto_ptr< CharacterAttributesHelper > pHelper( new CharacterAttributesHelper( aFont, nBackColor, nColor ) ); 247 aValues = pHelper->GetCharacterAttributes( aRequestedAttributes ); 248 249 return aValues; 250 } 251 252 // ----------------------------------------------------------------------------- 253 254 awt::Rectangle VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 255 { 256 OExternalLockGuard aGuard( this ); 257 258 if ( !implIsValidIndex( nIndex, implGetText().getLength() ) ) 259 throw IndexOutOfBoundsException(); 260 261 awt::Rectangle aBounds( 0, 0, 0, 0 ); 262 if ( m_pParent ) 263 { 264 sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos ); 265 Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos ); 266 Rectangle aCharRect = m_pParent->GetCharacterBounds( nItemId, nIndex ); 267 aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() ); 268 aBounds = AWTRectangle( aCharRect ); 269 } 270 271 return aBounds; 272 } 273 274 // ----------------------------------------------------------------------------- 275 276 sal_Int32 VCLXAccessibleMenuItem::getCharacterCount() throw (RuntimeException) 277 { 278 OExternalLockGuard aGuard( this ); 279 280 return OCommonAccessibleText::getCharacterCount(); 281 } 282 283 // ----------------------------------------------------------------------------- 284 285 sal_Int32 VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException) 286 { 287 OExternalLockGuard aGuard( this ); 288 289 sal_Int32 nIndex = -1; 290 if ( m_pParent ) 291 { 292 sal_uInt16 nItemId = 0; 293 Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos ); 294 Point aPnt( VCLPoint( aPoint ) ); 295 aPnt += aItemRect.TopLeft(); 296 sal_Int32 nI = m_pParent->GetIndexForPoint( aPnt, nItemId ); 297 if ( nI != -1 && m_pParent->GetItemId( m_nItemPos ) == nItemId ) 298 nIndex = nI; 299 } 300 301 return nIndex; 302 } 303 304 // ----------------------------------------------------------------------------- 305 306 ::rtl::OUString VCLXAccessibleMenuItem::getSelectedText() throw (RuntimeException) 307 { 308 OExternalLockGuard aGuard( this ); 309 310 return OCommonAccessibleText::getSelectedText(); 311 } 312 313 // ----------------------------------------------------------------------------- 314 315 sal_Int32 VCLXAccessibleMenuItem::getSelectionStart() throw (RuntimeException) 316 { 317 OExternalLockGuard aGuard( this ); 318 319 return OCommonAccessibleText::getSelectionStart(); 320 } 321 322 // ----------------------------------------------------------------------------- 323 324 sal_Int32 VCLXAccessibleMenuItem::getSelectionEnd() throw (RuntimeException) 325 { 326 OExternalLockGuard aGuard( this ); 327 328 return OCommonAccessibleText::getSelectionEnd(); 329 } 330 331 // ----------------------------------------------------------------------------- 332 333 sal_Bool VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 334 { 335 OExternalLockGuard aGuard( this ); 336 337 if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) ) 338 throw IndexOutOfBoundsException(); 339 340 return sal_False; 341 } 342 343 // ----------------------------------------------------------------------------- 344 345 ::rtl::OUString VCLXAccessibleMenuItem::getText() throw (RuntimeException) 346 { 347 OExternalLockGuard aGuard( this ); 348 349 return OCommonAccessibleText::getText(); 350 } 351 352 // ----------------------------------------------------------------------------- 353 354 ::rtl::OUString VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 355 { 356 OExternalLockGuard aGuard( this ); 357 358 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex ); 359 } 360 361 // ----------------------------------------------------------------------------- 362 363 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 364 { 365 OExternalLockGuard aGuard( this ); 366 367 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); 368 } 369 370 // ----------------------------------------------------------------------------- 371 372 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 373 { 374 OExternalLockGuard aGuard( this ); 375 376 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); 377 } 378 379 // ----------------------------------------------------------------------------- 380 381 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 382 { 383 OExternalLockGuard aGuard( this ); 384 385 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); 386 } 387 388 // ----------------------------------------------------------------------------- 389 390 sal_Bool VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 391 { 392 OExternalLockGuard aGuard( this ); 393 394 sal_Bool bReturn = sal_False; 395 396 if ( m_pParent ) 397 { 398 Window* pWindow = m_pParent->GetWindow(); 399 if ( pWindow ) 400 { 401 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard(); 402 if ( xClipboard.is() ) 403 { 404 ::rtl::OUString sText( getTextRange( nStartIndex, nEndIndex ) ); 405 406 ::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( sText ); 407 const sal_uInt32 nRef = Application::ReleaseSolarMutex(); 408 xClipboard->setContents( pDataObj, NULL ); 409 410 Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY ); 411 if( xFlushableClipboard.is() ) 412 xFlushableClipboard->flushClipboard(); 413 414 Application::AcquireSolarMutex( nRef ); 415 416 bReturn = sal_True; 417 } 418 } 419 } 420 421 return bReturn; 422 } 423 424 // ----------------------------------------------------------------------------- 425 // XAccessibleAction 426 // ----------------------------------------------------------------------------- 427 428 sal_Int32 VCLXAccessibleMenuItem::getAccessibleActionCount( ) throw (RuntimeException) 429 { 430 OExternalLockGuard aGuard( this ); 431 432 return 1; 433 } 434 435 // ----------------------------------------------------------------------------- 436 437 sal_Bool VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 438 { 439 OExternalLockGuard aGuard( this ); 440 441 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 442 throw IndexOutOfBoundsException(); 443 444 Click(); 445 446 return sal_True; 447 } 448 449 // ----------------------------------------------------------------------------- 450 451 ::rtl::OUString VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 452 { 453 OExternalLockGuard aGuard( this ); 454 455 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 456 throw IndexOutOfBoundsException(); 457 458 return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) ); 459 } 460 461 // ----------------------------------------------------------------------------- 462 463 Reference< XAccessibleKeyBinding > VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 464 { 465 OExternalLockGuard aGuard( this ); 466 467 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 468 throw IndexOutOfBoundsException(); 469 470 OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper(); 471 Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper; 472 473 if ( m_pParent ) 474 { 475 // create auto mnemonics 476 if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( m_pParent->GetMenuFlags() & MENU_FLAG_NOAUTOMNEMONICS ) ) 477 m_pParent->CreateAutoMnemonics(); 478 479 // activation key 480 KeyEvent aKeyEvent = m_pParent->GetActivationKey( m_pParent->GetItemId( m_nItemPos ) ); 481 KeyCode aKeyCode = aKeyEvent.GetKeyCode(); 482 Sequence< awt::KeyStroke > aSeq1(1); 483 aSeq1[0].Modifiers = 0; 484 Reference< XAccessible > xParent( getAccessibleParent() ); 485 if ( xParent.is() ) 486 { 487 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); 488 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU_BAR ) 489 aSeq1[0].Modifiers |= awt::KeyModifier::MOD2; 490 } 491 aSeq1[0].KeyCode = aKeyCode.GetCode(); 492 aSeq1[0].KeyChar = aKeyEvent.GetCharCode(); 493 aSeq1[0].KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() ); 494 pKeyBindingHelper->AddKeyBinding( aSeq1 ); 495 496 // complete menu activation key sequence 497 Sequence< awt::KeyStroke > aSeq; 498 if ( xParent.is() ) 499 { 500 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); 501 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU ) 502 { 503 Reference< XAccessibleAction > xAction( xParentContext, UNO_QUERY ); 504 if ( xAction.is() && xAction->getAccessibleActionCount() > 0 ) 505 { 506 Reference< XAccessibleKeyBinding > xKeyB( xAction->getAccessibleActionKeyBinding( 0 ) ); 507 if ( xKeyB.is() && xKeyB->getAccessibleKeyBindingCount() > 1 ) 508 aSeq = xKeyB->getAccessibleKeyBinding( 1 ); 509 } 510 } 511 } 512 Sequence< awt::KeyStroke > aSeq2 = ::comphelper::concatSequences( aSeq, aSeq1 ); 513 pKeyBindingHelper->AddKeyBinding( aSeq2 ); 514 515 // accelerator key 516 KeyCode aAccelKeyCode = m_pParent->GetAccelKey( m_pParent->GetItemId( m_nItemPos ) ); 517 if ( aAccelKeyCode.GetCode() != 0 ) 518 { 519 Sequence< awt::KeyStroke > aSeq3(1); 520 aSeq3[0].Modifiers = 0; 521 if ( aAccelKeyCode.IsShift() ) 522 aSeq3[0].Modifiers |= awt::KeyModifier::SHIFT; 523 if ( aAccelKeyCode.IsMod1() ) 524 aSeq3[0].Modifiers |= awt::KeyModifier::MOD1; 525 if ( aAccelKeyCode.IsMod2() ) 526 aSeq3[0].Modifiers |= awt::KeyModifier::MOD2; 527 if ( aAccelKeyCode.IsMod3() ) 528 aSeq3[0].Modifiers |= awt::KeyModifier::MOD3; 529 aSeq3[0].KeyCode = aAccelKeyCode.GetCode(); 530 aSeq3[0].KeyFunc = static_cast< sal_Int16 >( aAccelKeyCode.GetFunction() ); 531 pKeyBindingHelper->AddKeyBinding( aSeq3 ); 532 } 533 } 534 535 return xKeyBinding; 536 } 537 538 // ----------------------------------------------------------------------------- 539 // XAccessibleValue 540 // ----------------------------------------------------------------------------- 541 542 Any VCLXAccessibleMenuItem::getCurrentValue( ) throw (RuntimeException) 543 { 544 OExternalLockGuard aGuard( this ); 545 546 Any aValue; 547 if ( IsSelected() ) 548 aValue <<= (sal_Int32) 1; 549 else 550 aValue <<= (sal_Int32) 0; 551 552 return aValue; 553 } 554 555 // ----------------------------------------------------------------------------- 556 557 sal_Bool VCLXAccessibleMenuItem::setCurrentValue( const Any& aNumber ) throw (RuntimeException) 558 { 559 OExternalLockGuard aGuard( this ); 560 561 sal_Bool bReturn = sal_False; 562 sal_Int32 nValue = 0; 563 OSL_VERIFY( aNumber >>= nValue ); 564 565 if ( nValue <= 0 ) 566 { 567 DeSelect(); 568 bReturn = sal_True; 569 } 570 else if ( nValue >= 1 ) 571 { 572 Select(); 573 bReturn = sal_True; 574 } 575 576 return bReturn; 577 } 578 579 // ----------------------------------------------------------------------------- 580 581 Any VCLXAccessibleMenuItem::getMaximumValue( ) throw (RuntimeException) 582 { 583 OExternalLockGuard aGuard( this ); 584 585 Any aValue; 586 aValue <<= (sal_Int32) 1; 587 588 return aValue; 589 } 590 591 // ----------------------------------------------------------------------------- 592 593 Any VCLXAccessibleMenuItem::getMinimumValue( ) throw (RuntimeException) 594 { 595 OExternalLockGuard aGuard( this ); 596 597 Any aValue; 598 aValue <<= (sal_Int32) 0; 599 600 return aValue; 601 } 602 603 // ----------------------------------------------------------------------------- 604