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
27
28 #include <com/sun/star/accessibility/AccessibleRole.hpp>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
32 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
33 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
34 #include <toolkit/helper/externallock.hxx>
35 #include <toolkit/awt/vclxwindow.hxx>
36 #include <toolkit/helper/convert.hxx>
37 #include <toolkit/awt/vclxfont.hxx>
38 #include <vcl/dialog.hxx>
39 #include <vcl/window.hxx>
40 //Solution:Need methods in Edit.
41 #include <vcl/edit.hxx>
42 #include <tools/debug.hxx>
43 #include <unotools/accessiblestatesethelper.hxx>
44 #include <unotools/accessiblerelationsethelper.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/menu.hxx>
47
48 #ifndef VCLEVENT_WINDOW_FRAMETITLECHANGED
49 #define VCLEVENT_WINDOW_FRAMETITLECHANGED 1018 // pData = XubString* = oldTitle
50 #endif
51
52 using namespace ::com::sun::star;
53 using namespace ::comphelper;
54
55
DBG_NAME(VCLXAccessibleComponent)56 DBG_NAME(VCLXAccessibleComponent)
57
58
59 // ----------------------------------------------------
60 // class VCLXAccessibleComponent
61 // ----------------------------------------------------
62 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow )
63 : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
64 , OAccessibleImplementationAccess( )
65 {
66 DBG_CTOR( VCLXAccessibleComponent, 0 );
67 mpVCLXindow = pVCLXindow;
68 mxWindow = pVCLXindow;
69
70 m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
71
72 DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
73 if ( pVCLXindow->GetWindow() )
74 {
75 pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
76 pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
77 }
78
79 // announce the XAccessible of our creator to the base class
80 lateInit( pVCLXindow );
81 }
82
~VCLXAccessibleComponent()83 VCLXAccessibleComponent::~VCLXAccessibleComponent()
84 {
85 DBG_DTOR( VCLXAccessibleComponent, 0 );
86
87 ensureDisposed();
88
89 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
90 {
91 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
92 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
93 }
94
95 delete m_pSolarLock;
96 m_pSolarLock = NULL;
97 // This is not completely safe. If we assume that the base class dtor calls some method which
98 // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_
99 // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external
100 // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so
101 // let's assume it keeps this way.
102 // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* )
103 }
104
IMPLEMENT_FORWARD_XINTERFACE3(VCLXAccessibleComponent,AccessibleExtendedComponentHelper_BASE,OAccessibleImplementationAccess,VCLXAccessibleComponent_BASE)105 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
106 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
107
108 ::rtl::OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException)
109 {
110 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleWindow" );
111 }
112
supportsService(const::rtl::OUString & rServiceName)113 sal_Bool VCLXAccessibleComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (uno::RuntimeException)
114 {
115 uno::Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
116 const ::rtl::OUString* pNames = aNames.getConstArray();
117 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
118 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
119 ;
120
121 return pNames != pEnd;
122 }
123
getSupportedServiceNames()124 uno::Sequence< ::rtl::OUString > VCLXAccessibleComponent::getSupportedServiceNames() throw (uno::RuntimeException)
125 {
126 uno::Sequence< ::rtl::OUString > aNames(1);
127 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleWindow" );
128 return aNames;
129 }
130
IMPL_LINK(VCLXAccessibleComponent,WindowEventListener,VclSimpleEvent *,pEvent)131 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclSimpleEvent*, pEvent )
132 {
133 DBG_CHKTHIS(VCLXAccessibleComponent,0);
134
135 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
136
137 /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper
138 * might have been destroyed by the previous VCLEventListener (if no AT tool
139 * is running), e.g. sub-toolbars in impress.
140 */
141 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
142 {
143 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
144 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
145 {
146 ProcessWindowEvent( *(VclWindowEvent*)pEvent );
147 }
148 }
149 return 0;
150 }
151
IMPL_LINK(VCLXAccessibleComponent,WindowChildEventListener,VclSimpleEvent *,pEvent)152 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent )
153 {
154 DBG_CHKTHIS(VCLXAccessibleComponent,0);
155
156 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
157 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ )
158 {
159 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
160 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() )
161 {
162 // #103087# to prevent an early release of the component
163 uno::Reference< accessibility::XAccessibleContext > xTmp = this;
164
165 ProcessWindowChildEvent( *(VclWindowEvent*)pEvent );
166 }
167 }
168 return 0;
169 }
170
GetChildAccessible(const VclWindowEvent & rVclWindowEvent)171 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
172 {
173 // checks if the data in the window event is our direct child
174 // and returns its accessible
175
176 // MT: Change this later, normaly a show/hide event shouldn't have the Window* in pData.
177 Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
178 if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
179 return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
180 else
181 return uno::Reference< accessibility::XAccessible > ();
182 }
183
ProcessWindowChildEvent(const VclWindowEvent & rVclWindowEvent)184 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
185 {
186 uno::Any aOldValue, aNewValue;
187 uno::Reference< accessibility::XAccessible > xAcc;
188
189 switch ( rVclWindowEvent.GetId() )
190 {
191 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
192 {
193 xAcc = GetChildAccessible( rVclWindowEvent );
194 if( xAcc.is() )
195 {
196 aNewValue <<= xAcc;
197 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
198 }
199 }
200 break;
201 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
202 {
203 xAcc = GetChildAccessible( rVclWindowEvent );
204 if( xAcc.is() )
205 {
206 aOldValue <<= xAcc;
207 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
208 }
209 }
210 break;
211 }
212 }
213
ProcessWindowEvent(const VclWindowEvent & rVclWindowEvent)214 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
215 {
216 uno::Any aOldValue, aNewValue;
217
218 Window* pAccWindow = rVclWindowEvent.GetWindow();
219 DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" );
220
221 switch ( rVclWindowEvent.GetId() )
222 {
223 case VCLEVENT_OBJECT_DYING:
224 {
225 pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
226 pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
227 mxWindow.clear();
228 mpVCLXindow = NULL;
229 }
230 break;
231 //
232 // dont handle CHILDCREATED events here
233 // they are handled separately as child events, see ProcessWindowChildEvent above
234 //
235 /*
236 case VCLEVENT_WINDOW_CHILDCREATED:
237 {
238 Window* pWindow = (Window*) rVclWindowEvent.GetData();
239 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDCREATED - Window=?" );
240 aNewValue <<= pWindow->GetAccessible();
241 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
242 }
243 break;
244 */
245 case VCLEVENT_WINDOW_CHILDDESTROYED:
246 {
247 Window* pWindow = (Window*) rVclWindowEvent.GetData();
248 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" );
249 if ( pWindow->GetAccessible( sal_False ).is() )
250 {
251 aOldValue <<= pWindow->GetAccessible( sal_False );
252 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
253 }
254 }
255 break;
256
257 //
258 // show and hide will be handled as child events only and are
259 // responsible for sending create/destroy events, see ProcessWindowChildEvent above
260 //
261 /*
262 case VCLEVENT_WINDOW_SHOW:
263 {
264 aNewValue <<= accessibility::AccessibleStateType::VISIBLE;
265 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
266
267 aNewValue <<= accessibility::AccessibleStateType::SHOWING;
268 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
269
270 aNewValue.clear();
271 aOldValue <<= accessibility::AccessibleStateType::INVALID;
272 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
273 }
274 break;
275 case VCLEVENT_WINDOW_HIDE:
276 {
277 aOldValue <<= accessibility::AccessibleStateType::VISIBLE;
278 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
279
280 aOldValue <<= accessibility::AccessibleStateType::SHOWING;
281 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
282
283 aOldValue.clear();
284 aNewValue <<= accessibility::AccessibleStateType::INVALID;
285 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
286 }
287 break;
288 */
289 case VCLEVENT_WINDOW_ACTIVATE:
290 {
291 // avoid notification if a child frame is already active
292 // only one frame may be active at a given time
293 if ( !pAccWindow->HasActiveChildFrame() &&
294 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
295 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
296 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
297 {
298 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
299 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
300 }
301 }
302 break;
303 case VCLEVENT_WINDOW_DEACTIVATE:
304 {
305 if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
306 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
307 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891#
308 {
309 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
310 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
311 }
312 }
313 break;
314 case VCLEVENT_WINDOW_GETFOCUS:
315 case VCLEVENT_CONTROL_GETFOCUS:
316 {
317 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) ||
318 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_GETFOCUS) )
319 {
320 // if multiple listeners were registered it is possible that the
321 // focus was changed during event processing (eg SfxTopWindow )
322 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
323 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
324 (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
325 {
326 aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
327 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
328 }
329 }
330 }
331 break;
332 case VCLEVENT_WINDOW_LOSEFOCUS:
333 case VCLEVENT_CONTROL_LOSEFOCUS:
334 {
335 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) ||
336 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) )
337 {
338 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
339 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
340 }
341 }
342 break;
343 case VCLEVENT_WINDOW_FRAMETITLECHANGED:
344 {
345 ::rtl::OUString aOldName( *((::rtl::OUString*) rVclWindowEvent.GetData()) );
346 ::rtl::OUString aNewName( getAccessibleName() );
347 aOldValue <<= aOldName;
348 aNewValue <<= aNewName;
349 NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
350 }
351 break;
352 case VCLEVENT_WINDOW_ENABLED:
353 {
354 aNewValue <<= accessibility::AccessibleStateType::ENABLED;
355 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
356 aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
357 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
358 }
359 break;
360 case VCLEVENT_WINDOW_DISABLED:
361 {
362 aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
363 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
364
365 aOldValue <<= accessibility::AccessibleStateType::ENABLED;
366 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
367 }
368 break;
369 case VCLEVENT_WINDOW_MOVE:
370 case VCLEVENT_WINDOW_RESIZE:
371 {
372 NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
373 }
374 break;
375 case VCLEVENT_WINDOW_MENUBARADDED:
376 {
377 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
378 if ( pMenuBar )
379 {
380 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
381 if ( xChild.is() )
382 {
383 aNewValue <<= xChild;
384 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
385 }
386 }
387 }
388 break;
389 case VCLEVENT_WINDOW_MENUBARREMOVED:
390 {
391 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
392 if ( pMenuBar )
393 {
394 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
395 if ( xChild.is() )
396 {
397 aOldValue <<= xChild;
398 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
399 }
400 }
401 }
402 break;
403 case VCLEVENT_WINDOW_MINIMIZE:
404 {
405 aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
406 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
407 }
408 break;
409 case VCLEVENT_WINDOW_NORMALIZE:
410 {
411 aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
412 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
413 }
414 break;
415 default:
416 {
417 }
418 break;
419 }
420 }
421
disposing()422 void VCLXAccessibleComponent::disposing()
423 {
424 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
425 {
426 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
427 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
428 }
429
430 AccessibleExtendedComponentHelper_BASE::disposing();
431
432 mxWindow.clear();
433 mpVCLXindow = NULL;
434 }
435
GetWindow() const436 Window* VCLXAccessibleComponent::GetWindow() const
437 {
438 return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL;
439 }
440
FillAccessibleRelationSet(utl::AccessibleRelationSetHelper & rRelationSet)441 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
442 {
443 Window* pWindow = GetWindow();
444 if ( pWindow )
445 {
446 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
447 if ( pLabeledBy && pLabeledBy != pWindow )
448 {
449 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
450 aSequence[0] = pLabeledBy->GetAccessible();
451 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
452 }
453
454 Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
455 if ( pLabelFor && pLabelFor != pWindow )
456 {
457 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
458 aSequence[0] = pLabelFor->GetAccessible();
459 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
460 }
461 Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
462 if ( pMemberOf && pMemberOf != pWindow )
463 {
464 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
465 aSequence[0] = pMemberOf->GetAccessible();
466 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
467 }
468 uno::Sequence< uno::Reference< uno::XInterface > > aFlowToSequence = pWindow->GetAccFlowToSequence();
469 if( aFlowToSequence.getLength() > 0 )
470 {
471 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::CONTENT_FLOWS_TO, aFlowToSequence ) );
472 }
473 }
474 }
475
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)476 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
477 {
478 Window* pWindow = GetWindow();
479 if ( pWindow )
480 {
481 if ( pWindow->IsVisible() )
482 {
483 rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
484 rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
485 }
486 else
487 {
488 rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
489 }
490
491 if ( pWindow->IsEnabled() )
492 {
493 rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
494 rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
495 }
496
497 if ( pWindow->HasChildPathFocus() &&
498 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
499 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
500 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
501 rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
502
503 // #104290# MT: This way, a ComboBox doesn't get state FOCUSED.
504 // I also don't understand
505 // a) why WINDOW_FIRSTCHILD is used here (which btw is a border window in the case of a combo box)
506 // b) why HasFocus() is nout "enough" for a compound control
507 /*
508 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
509 if ( ( !pWindow->IsCompoundControl() && pWindow->HasFocus() ) ||
510 ( pWindow->IsCompoundControl() && pChild && pChild->HasFocus() ) )
511 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
512 */
513 if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
514 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
515
516 if ( pWindow->IsWait() )
517 rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
518
519 if ( pWindow->GetStyle() & WB_SIZEABLE )
520 rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
521 // 6. frame doesn't have MOVABLE state
522 // 10. for password text, where is the sensitive state?
523 if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
524 rStateSet.AddState( accessibility::AccessibleStateType::MOVEABLE );
525 if( pWindow->IsDialog() )
526 {
527 Dialog *pDlg = static_cast< Dialog* >( pWindow );
528 if( pDlg->IsInExecute() )
529 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
530 }
531 //Solution:If a combobox or list's edit child isn't read-only,EDITABLE state
532 // should be set.
533 if( pWindow && pWindow->GetType() == WINDOW_COMBOBOX )
534 {
535 if( !( pWindow->GetStyle() & WB_READONLY) ||
536 !((Edit*)pWindow)->IsReadOnly() )
537 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
538 }
539
540 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
541
542 while( pWindow && pChild )
543 {
544 Window* pWinTemp = pChild->GetWindow( WINDOW_FIRSTCHILD );
545 if( pWinTemp && pWinTemp->GetType() == WINDOW_EDIT )
546 {
547 if( !( pWinTemp->GetStyle() & WB_READONLY) ||
548 !((Edit*)pWinTemp)->IsReadOnly() )
549 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
550 break;
551 }
552 if( pChild->GetType() == WINDOW_EDIT )
553 {
554 if( !( pChild->GetStyle() & WB_READONLY) ||
555 !((Edit*)pChild)->IsReadOnly())
556 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
557 break;
558 }
559 pChild = pChild->GetWindow( WINDOW_NEXT );
560 }
561 }
562 else
563 {
564 rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
565 }
566
567 /*
568
569 MUST BE SET FROM DERIVED CLASSES:
570
571 CHECKED
572 COLLAPSED
573 EXPANDED
574 EXPANDABLE
575 EDITABLE
576 FOCUSABLE
577 HORIZONTAL
578 VERTICAL
579 ICONIFIED
580 MULTILINE
581 MULTI_SELECTABLE
582 PRESSED
583 SELECTABLE
584 SELECTED
585 SINGLE_LINE
586 TRANSIENT
587
588 */
589 }
590
591
592 // accessibility::XAccessibleContext
getAccessibleChildCount()593 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException)
594 {
595 OExternalLockGuard aGuard( this );
596
597 sal_Int32 nChildren = 0;
598 if ( GetWindow() )
599 nChildren = GetWindow()->GetAccessibleChildWindowCount();
600
601 return nChildren;
602 }
603
getAccessibleChild(sal_Int32 i)604 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
605 {
606 OExternalLockGuard aGuard( this );
607
608 if ( i >= getAccessibleChildCount() )
609 throw lang::IndexOutOfBoundsException();
610
611 uno::Reference< accessibility::XAccessible > xAcc;
612 if ( GetWindow() )
613 {
614 Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i );
615 if ( pChild )
616 xAcc = pChild->GetAccessible();
617 }
618
619 return xAcc;
620 }
621
getVclParent() const622 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
623 {
624 uno::Reference< accessibility::XAccessible > xAcc;
625 if ( GetWindow() )
626 {
627 Window* pParent = GetWindow()->GetAccessibleParentWindow();
628 if ( pParent )
629 xAcc = pParent->GetAccessible();
630 }
631 return xAcc;
632 }
633
getAccessibleParent()634 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( ) throw (uno::RuntimeException)
635 {
636 OExternalLockGuard aGuard( this );
637
638 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
639 if ( !xAcc.is() )
640 // we do _not_ have a foreign-controlled parent -> default to our VCL parent
641 xAcc = getVclParent();
642
643 return xAcc;
644 }
645
getAccessibleIndexInParent()646 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( ) throw (uno::RuntimeException)
647 {
648 OExternalLockGuard aGuard( this );
649
650 sal_Int32 nIndex = -1;
651
652 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
653 if ( xAcc.is() )
654 { // we _do_ have a foreign-controlled parent -> use the base class' implementation,
655 // which goes the UNO way
656 nIndex = AccessibleExtendedComponentHelper_BASE::getAccessibleIndexInParent( );
657 }
658 else
659 {
660 if ( GetWindow() )
661 {
662 Window* pParent = GetWindow()->GetAccessibleParentWindow();
663 if ( pParent )
664 {
665 /*
666 for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; )
667 {
668 Window* pChild = pParent->GetAccessibleChildWindow( --n );
669 if ( pChild == GetWindow() )
670 {
671 nIndex = n;
672 break;
673 }
674 }
675 */
676 // Iterate over all the parent's children and search for this object.
677 // this should be compatible with the code in SVX
678 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
679 if ( xParentAcc.is() )
680 {
681 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
682 if ( xParentContext.is() )
683 {
684 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
685 for ( sal_Int32 i=0; i<nChildCount; i++ )
686 {
687 uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
688 if ( xChild.is() )
689 {
690 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
691 if ( xChildContext == (accessibility::XAccessibleContext*) this )
692 {
693 nIndex = i;
694 break;
695 }
696 }
697 }
698 }
699 }
700 }
701 }
702 }
703 return nIndex;
704 }
705
getAccessibleRole()706 sal_Int16 VCLXAccessibleComponent::getAccessibleRole( ) throw (uno::RuntimeException)
707 {
708 OExternalLockGuard aGuard( this );
709
710 sal_Int16 nRole = 0;
711
712 if ( GetWindow() )
713 nRole = GetWindow()->GetAccessibleRole();
714
715 return nRole;
716 }
717
getAccessibleDescription()718 ::rtl::OUString VCLXAccessibleComponent::getAccessibleDescription( ) throw (uno::RuntimeException)
719 {
720 OExternalLockGuard aGuard( this );
721
722 ::rtl::OUString aDescription;
723
724 if ( GetWindow() )
725 aDescription = GetWindow()->GetAccessibleDescription();
726
727 return aDescription;
728 }
729
getAccessibleName()730 ::rtl::OUString VCLXAccessibleComponent::getAccessibleName( ) throw (uno::RuntimeException)
731 {
732 OExternalLockGuard aGuard( this );
733
734 ::rtl::OUString aName;
735 if ( GetWindow() )
736 {
737 aName = GetWindow()->GetAccessibleName();
738 #if OSL_DEBUG_LEVEL > 1
739 aName += String( RTL_CONSTASCII_USTRINGPARAM( " (Type = " ) );
740 aName += String::CreateFromInt32( GetWindow()->GetType() );
741 aName += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
742 #endif
743 }
744 return aName;
745 }
746
getAccessibleRelationSet()747 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( ) throw (uno::RuntimeException)
748 {
749 OExternalLockGuard aGuard( this );
750
751 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
752 uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
753 FillAccessibleRelationSet( *pRelationSetHelper );
754 return xSet;
755 }
756
getAccessibleStateSet()757 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( ) throw (uno::RuntimeException)
758 {
759 OExternalLockGuard aGuard( this );
760
761 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
762 uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
763 FillAccessibleStateSet( *pStateSetHelper );
764 return xSet;
765 }
766
getLocale()767 lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
768 {
769 OExternalLockGuard aGuard( this );
770
771 return Application::GetSettings().GetLocale();
772 }
773
getAccessibleAtPoint(const awt::Point & rPoint)774 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException)
775 {
776 OExternalLockGuard aGuard( this );
777
778 uno::Reference< accessibility::XAccessible > xChild;
779 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
780 {
781 uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
782 if ( xAcc.is() )
783 {
784 uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
785 if ( xComp.is() )
786 {
787 Rectangle aRect = VCLRectangle( xComp->getBounds() );
788 Point aPos = VCLPoint( rPoint );
789 if ( aRect.IsInside( aPos ) )
790 {
791 xChild = xAcc;
792 break;
793 }
794 }
795 }
796 }
797
798 return xChild;
799 }
800
801 // accessibility::XAccessibleComponent
implGetBounds()802 awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException)
803 {
804 awt::Rectangle aBounds ( 0, 0, 0, 0 );
805
806 Window* pWindow = GetWindow();
807 if ( pWindow )
808 {
809 Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
810 aBounds = AWTRectangle( aRect );
811 Window* pParent = pWindow->GetAccessibleParentWindow();
812 if ( pParent )
813 {
814 Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
815 awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
816 aBounds.X -= aParentScreenLoc.X;
817 aBounds.Y -= aParentScreenLoc.Y;
818 }
819 }
820
821 uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
822 if ( xParent.is() )
823 { // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave
824 // us a parent which is different from our VCL parent
825 // (actually, we did not check if it's really different ...)
826
827 // the screen location of the foreign parent
828 uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
829 DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" );
830
831 awt::Point aScreenLocForeign( 0, 0 );
832 if ( xParentComponent.is() )
833 aScreenLocForeign = xParentComponent->getLocationOnScreen();
834
835 // the screen location of the VCL parent
836 xParent = getVclParent();
837 if ( xParent.is() )
838 xParentComponent = xParentComponent.query( xParent->getAccessibleContext() );
839
840 awt::Point aScreenLocVCL( 0, 0 );
841 if ( xParentComponent.is() )
842 aScreenLocVCL = xParentComponent->getLocationOnScreen();
843
844 // the difference between them
845 awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y );
846 // move the bounds
847 aBounds.X += aOffset.Width;
848 aBounds.Y += aOffset.Height;
849 }
850
851 return aBounds;
852 }
853
getLocationOnScreen()854 awt::Point VCLXAccessibleComponent::getLocationOnScreen( ) throw (uno::RuntimeException)
855 {
856 OExternalLockGuard aGuard( this );
857
858 awt::Point aPos;
859 if ( GetWindow() )
860 {
861 Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL );
862 aPos.X = aRect.Left();
863 aPos.Y = aRect.Top();
864 }
865
866 return aPos;
867 }
868
grabFocus()869 void VCLXAccessibleComponent::grabFocus( ) throw (uno::RuntimeException)
870 {
871 OExternalLockGuard aGuard( this );
872
873 uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
874 if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
875 mxWindow->setFocus();
876 }
877
getForeground()878 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( ) throw (uno::RuntimeException)
879 {
880 OExternalLockGuard aGuard( this );
881
882 sal_Int32 nColor = 0;
883 Window* pWindow = GetWindow();
884 if ( pWindow )
885 {
886 if ( pWindow->IsControlForeground() )
887 nColor = pWindow->GetControlForeground().GetColor();
888 else
889 {
890 Font aFont;
891 if ( pWindow->IsControlFont() )
892 aFont = pWindow->GetControlFont();
893 else
894 aFont = pWindow->GetFont();
895 nColor = aFont.GetColor().GetColor();
896 // COL_AUTO is not very meaningful for AT
897 if ( nColor == (sal_Int32)COL_AUTO)
898 nColor = pWindow->GetTextColor().GetColor();
899 }
900 }
901
902 return nColor;
903 }
904
getBackground()905 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( ) throw (uno::RuntimeException)
906 {
907 OExternalLockGuard aGuard( this );
908
909 sal_Int32 nColor = 0;
910 Window* pWindow = GetWindow();
911 if ( pWindow )
912 {
913 if ( pWindow->IsControlBackground() )
914 nColor = pWindow->GetControlBackground().GetColor();
915 else
916 nColor = pWindow->GetBackground().GetColor().GetColor();
917 }
918
919 return nColor;
920 }
921
922 // XAccessibleExtendedComponent
923
getFont()924 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( ) throw (uno::RuntimeException)
925 {
926 OExternalLockGuard aGuard( this );
927
928 uno::Reference< awt::XFont > xFont;
929 Window* pWindow = GetWindow();
930 if ( pWindow )
931 {
932 uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
933 if ( xDev.is() )
934 {
935 Font aFont;
936 if ( pWindow->IsControlFont() )
937 aFont = pWindow->GetControlFont();
938 else
939 aFont = pWindow->GetFont();
940 VCLXFont* pVCLXFont = new VCLXFont;
941 pVCLXFont->Init( *xDev.get(), aFont );
942 xFont = pVCLXFont;
943 }
944 }
945
946 return xFont;
947 }
948
getTitledBorderText()949 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( ) throw (uno::RuntimeException)
950 {
951 OExternalLockGuard aGuard( this );
952
953 ::rtl::OUString sRet;
954 if ( GetWindow() )
955 sRet = GetWindow()->GetText();
956
957 return sRet;
958 }
959
getToolTipText()960 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( ) throw (uno::RuntimeException)
961 {
962 OExternalLockGuard aGuard( this );
963
964 ::rtl::OUString sRet;
965 if ( GetWindow() )
966 sRet = GetWindow()->GetQuickHelpText();
967
968 return sRet;
969 }
970
971