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