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 0 : VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow )
46 : : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
47 0 : , OAccessibleImplementationAccess( )
48 : {
49 0 : mpVCLXindow = pVCLXindow;
50 0 : mxWindow = pVCLXindow;
51 :
52 0 : m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
53 :
54 : DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
55 0 : if ( pVCLXindow->GetWindow() )
56 : {
57 0 : pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
58 0 : pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
59 : }
60 :
61 : // announce the XAccessible of our creator to the base class
62 0 : lateInit( pVCLXindow );
63 0 : }
64 :
65 0 : VCLXAccessibleComponent::~VCLXAccessibleComponent()
66 : {
67 0 : ensureDisposed();
68 :
69 0 : 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 0 : delete m_pSolarLock;
76 0 : 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 0 : }
84 :
85 0 : IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
86 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
87 :
88 0 : OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException, std::exception)
89 : {
90 0 : 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 0 : 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 0 : if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
114 : {
115 : DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
116 0 : if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
117 : {
118 0 : ProcessWindowEvent( *(VclWindowEvent*)pEvent );
119 : }
120 : }
121 0 : return 0;
122 : }
123 :
124 0 : IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent )
125 : {
126 : DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
127 0 : if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ )
128 : {
129 : DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
130 0 : if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() )
131 : {
132 : // #103087# to prevent an early release of the component
133 0 : uno::Reference< accessibility::XAccessibleContext > xTmp = this;
134 :
135 0 : ProcessWindowChildEvent( *(VclWindowEvent*)pEvent );
136 : }
137 : }
138 0 : return 0;
139 : }
140 :
141 0 : 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 0 : Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
148 0 : if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
149 0 : return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
150 : else
151 0 : return uno::Reference< accessibility::XAccessible > ();
152 : }
153 :
154 0 : void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
155 : {
156 0 : uno::Any aOldValue, aNewValue;
157 0 : uno::Reference< accessibility::XAccessible > xAcc;
158 :
159 0 : switch ( rVclWindowEvent.GetId() )
160 : {
161 : case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
162 : {
163 0 : xAcc = GetChildAccessible( rVclWindowEvent );
164 0 : if( xAcc.is() )
165 : {
166 0 : aNewValue <<= xAcc;
167 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
168 : }
169 : }
170 0 : break;
171 : case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
172 : {
173 0 : xAcc = GetChildAccessible( rVclWindowEvent );
174 0 : if( xAcc.is() )
175 : {
176 0 : aOldValue <<= xAcc;
177 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
178 : }
179 : }
180 0 : break;
181 0 : }
182 0 : }
183 :
184 0 : void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
185 : {
186 0 : uno::Any aOldValue, aNewValue;
187 :
188 0 : Window* pAccWindow = rVclWindowEvent.GetWindow();
189 : DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" );
190 :
191 0 : switch ( rVclWindowEvent.GetId() )
192 : {
193 : case VCLEVENT_OBJECT_DYING:
194 : {
195 0 : pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
196 0 : pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
197 0 : mxWindow.clear();
198 0 : mpVCLXindow = NULL;
199 : }
200 0 : break;
201 : case VCLEVENT_WINDOW_CHILDDESTROYED:
202 : {
203 0 : Window* pWindow = (Window*) rVclWindowEvent.GetData();
204 : DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" );
205 0 : if ( pWindow->GetAccessible( false ).is() )
206 : {
207 0 : aOldValue <<= pWindow->GetAccessible( false );
208 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
209 : }
210 : }
211 0 : 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 0 : if ( !pAccWindow->HasActiveChildFrame() &&
217 0 : ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
218 0 : getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
219 0 : getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
220 : {
221 0 : aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
222 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
223 : }
224 : }
225 0 : break;
226 : case VCLEVENT_WINDOW_DEACTIVATE:
227 : {
228 0 : if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
229 0 : getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
230 0 : getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891#
231 : {
232 0 : aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
233 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
234 : }
235 : }
236 0 : break;
237 : case VCLEVENT_WINDOW_GETFOCUS:
238 : case VCLEVENT_CONTROL_GETFOCUS:
239 : {
240 0 : if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) ||
241 0 : (!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 0 : if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
247 0 : (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
248 : {
249 0 : aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
250 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
251 : }
252 : }
253 : }
254 0 : break;
255 : case VCLEVENT_WINDOW_LOSEFOCUS:
256 : case VCLEVENT_CONTROL_LOSEFOCUS:
257 : {
258 0 : if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) ||
259 0 : (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) )
260 : {
261 0 : aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
262 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
263 : }
264 : }
265 0 : break;
266 : case VCLEVENT_WINDOW_FRAMETITLECHANGED:
267 : {
268 0 : OUString aOldName( *((OUString*) rVclWindowEvent.GetData()) );
269 0 : OUString aNewName( getAccessibleName() );
270 0 : aOldValue <<= aOldName;
271 0 : aNewValue <<= aNewName;
272 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
273 : }
274 0 : break;
275 : case VCLEVENT_WINDOW_ENABLED:
276 : {
277 0 : aNewValue <<= accessibility::AccessibleStateType::ENABLED;
278 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
279 0 : aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
280 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
281 : }
282 0 : break;
283 : case VCLEVENT_WINDOW_DISABLED:
284 : {
285 0 : aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
286 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
287 :
288 0 : aOldValue <<= accessibility::AccessibleStateType::ENABLED;
289 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
290 : }
291 0 : break;
292 : case VCLEVENT_WINDOW_MOVE:
293 : case VCLEVENT_WINDOW_RESIZE:
294 : {
295 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
296 : }
297 0 : 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 0 : MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
315 0 : if ( pMenuBar )
316 : {
317 0 : uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
318 0 : if ( xChild.is() )
319 : {
320 0 : aOldValue <<= xChild;
321 0 : NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
322 0 : }
323 : }
324 : }
325 0 : 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 0 : break;
342 0 : }
343 0 : }
344 :
345 0 : void VCLXAccessibleComponent::disposing()
346 : {
347 0 : if ( mpVCLXindow && mpVCLXindow->GetWindow() )
348 : {
349 0 : mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
350 0 : mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
351 : }
352 :
353 0 : AccessibleExtendedComponentHelper_BASE::disposing();
354 :
355 0 : mxWindow.clear();
356 0 : mpVCLXindow = NULL;
357 0 : }
358 :
359 0 : Window* VCLXAccessibleComponent::GetWindow() const
360 : {
361 0 : return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL;
362 : }
363 :
364 0 : void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
365 : {
366 0 : Window* pWindow = GetWindow();
367 0 : if ( pWindow )
368 : {
369 0 : Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
370 0 : 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 0 : Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
378 0 : 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 0 : Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
386 0 : 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 0 : }
394 :
395 0 : void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
396 : {
397 0 : Window* pWindow = GetWindow();
398 0 : if ( pWindow )
399 : {
400 0 : if ( pWindow->IsVisible() )
401 : {
402 0 : rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
403 0 : rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
404 : }
405 : else
406 : {
407 0 : rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
408 : }
409 :
410 0 : if ( pWindow->IsEnabled() )
411 : {
412 0 : rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
413 0 : rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
414 : }
415 :
416 0 : if ( pWindow->HasChildPathFocus() &&
417 0 : ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
418 0 : getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
419 0 : getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
420 0 : rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
421 :
422 0 : if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
423 0 : rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
424 :
425 0 : if ( pWindow->IsWait() )
426 0 : rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
427 :
428 0 : if ( pWindow->GetStyle() & WB_SIZEABLE )
429 0 : rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
430 : // 6. frame doesn't have MOVABLE state
431 : // 10. for password text, where is the sensitive state?
432 0 : if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
433 0 : rStateSet.AddState( accessibility::AccessibleStateType::MOVEABLE );
434 0 : if( pWindow->IsDialog() )
435 : {
436 0 : Dialog *pDlg = static_cast< Dialog* >( pWindow );
437 0 : 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 0 : if( pWindow && pWindow->GetType() == WINDOW_COMBOBOX )
443 : {
444 0 : if( !( pWindow->GetStyle() & WB_READONLY) ||
445 0 : !((Edit*)pWindow)->IsReadOnly() )
446 0 : rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
447 : }
448 :
449 0 : Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
450 :
451 0 : while( pWindow && pChild )
452 : {
453 0 : Window* pWinTemp = pChild->GetWindow( WINDOW_FIRSTCHILD );
454 0 : 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 0 : if( pChild->GetType() == WINDOW_EDIT )
462 : {
463 0 : if( !( pChild->GetStyle() & WB_READONLY) ||
464 0 : !((Edit*)pChild)->IsReadOnly())
465 0 : rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
466 0 : break;
467 : }
468 0 : 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 0 : }
499 :
500 :
501 : // accessibility::XAccessibleContext
502 0 : sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException, std::exception)
503 : {
504 0 : OExternalLockGuard aGuard( this );
505 :
506 0 : sal_Int32 nChildren = 0;
507 0 : if ( GetWindow() )
508 0 : nChildren = GetWindow()->GetAccessibleChildWindowCount();
509 :
510 0 : return nChildren;
511 : }
512 :
513 0 : uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
514 : {
515 0 : OExternalLockGuard aGuard( this );
516 :
517 0 : if ( i >= getAccessibleChildCount() )
518 0 : throw lang::IndexOutOfBoundsException();
519 :
520 0 : uno::Reference< accessibility::XAccessible > xAcc;
521 0 : if ( GetWindow() )
522 : {
523 0 : Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i );
524 0 : if ( pChild )
525 0 : xAcc = pChild->GetAccessible();
526 : }
527 :
528 0 : return xAcc;
529 : }
530 :
531 0 : uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
532 : {
533 0 : uno::Reference< accessibility::XAccessible > xAcc;
534 0 : if ( GetWindow() )
535 : {
536 0 : Window* pParent = GetWindow()->GetAccessibleParentWindow();
537 0 : if ( pParent )
538 0 : xAcc = pParent->GetAccessible();
539 : }
540 0 : return xAcc;
541 : }
542 :
543 0 : uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( ) throw (uno::RuntimeException, std::exception)
544 : {
545 0 : OExternalLockGuard aGuard( this );
546 :
547 0 : uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
548 0 : if ( !xAcc.is() )
549 : // we do _not_ have a foreign-controlled parent -> default to our VCL parent
550 0 : xAcc = getVclParent();
551 :
552 0 : return xAcc;
553 : }
554 :
555 0 : sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( ) throw (uno::RuntimeException, std::exception)
556 : {
557 0 : OExternalLockGuard aGuard( this );
558 :
559 0 : sal_Int32 nIndex = -1;
560 :
561 0 : uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
562 0 : 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 0 : if ( GetWindow() )
570 : {
571 0 : Window* pParent = GetWindow()->GetAccessibleParentWindow();
572 0 : 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 0 : uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
577 0 : if ( xParentAcc.is() )
578 : {
579 0 : uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
580 0 : if ( xParentContext.is() )
581 : {
582 0 : sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
583 0 : for ( sal_Int32 i=0; i<nChildCount; i++ )
584 : {
585 0 : uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
586 0 : if ( xChild.is() )
587 : {
588 0 : uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
589 0 : if ( xChildContext == (accessibility::XAccessibleContext*) this )
590 : {
591 0 : nIndex = i;
592 0 : break;
593 0 : }
594 : }
595 0 : }
596 0 : }
597 0 : }
598 : }
599 : }
600 : }
601 0 : return nIndex;
602 : }
603 :
604 0 : sal_Int16 VCLXAccessibleComponent::getAccessibleRole( ) throw (uno::RuntimeException, std::exception)
605 : {
606 0 : OExternalLockGuard aGuard( this );
607 :
608 0 : sal_Int16 nRole = 0;
609 :
610 0 : if ( GetWindow() )
611 0 : nRole = GetWindow()->GetAccessibleRole();
612 :
613 0 : return nRole;
614 : }
615 :
616 0 : OUString VCLXAccessibleComponent::getAccessibleDescription( ) throw (uno::RuntimeException, std::exception)
617 : {
618 0 : OExternalLockGuard aGuard( this );
619 :
620 0 : OUString aDescription;
621 :
622 0 : if ( GetWindow() )
623 0 : aDescription = GetWindow()->GetAccessibleDescription();
624 :
625 0 : return aDescription;
626 : }
627 :
628 0 : OUString VCLXAccessibleComponent::getAccessibleName( ) throw (uno::RuntimeException, std::exception)
629 : {
630 0 : OExternalLockGuard aGuard( this );
631 :
632 0 : OUString aName;
633 0 : if ( GetWindow() )
634 : {
635 0 : 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 0 : return aName;
643 : }
644 :
645 0 : uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( ) throw (uno::RuntimeException, std::exception)
646 : {
647 0 : OExternalLockGuard aGuard( this );
648 :
649 0 : utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
650 0 : uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
651 0 : FillAccessibleRelationSet( *pRelationSetHelper );
652 0 : return xSet;
653 : }
654 :
655 0 : uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( ) throw (uno::RuntimeException, std::exception)
656 : {
657 0 : OExternalLockGuard aGuard( this );
658 :
659 0 : utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
660 0 : uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
661 0 : FillAccessibleStateSet( *pStateSetHelper );
662 0 : return xSet;
663 : }
664 :
665 0 : lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException, std::exception)
666 : {
667 0 : OExternalLockGuard aGuard( this );
668 :
669 0 : return Application::GetSettings().GetLanguageTag().getLocale();
670 : }
671 :
672 0 : uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException, std::exception)
673 : {
674 0 : OExternalLockGuard aGuard( this );
675 :
676 0 : uno::Reference< accessibility::XAccessible > xChild;
677 0 : for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
678 : {
679 0 : uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
680 0 : if ( xAcc.is() )
681 : {
682 0 : uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
683 0 : if ( xComp.is() )
684 : {
685 0 : Rectangle aRect = VCLRectangle( xComp->getBounds() );
686 0 : Point aPos = VCLPoint( rPoint );
687 0 : if ( aRect.IsInside( aPos ) )
688 : {
689 0 : xChild = xAcc;
690 0 : break;
691 : }
692 0 : }
693 : }
694 0 : }
695 :
696 0 : return xChild;
697 : }
698 :
699 : // accessibility::XAccessibleComponent
700 0 : awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException)
701 : {
702 0 : awt::Rectangle aBounds ( 0, 0, 0, 0 );
703 :
704 0 : Window* pWindow = GetWindow();
705 0 : if ( pWindow )
706 : {
707 0 : Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
708 0 : aBounds = AWTRectangle( aRect );
709 0 : Window* pParent = pWindow->GetAccessibleParentWindow();
710 0 : if ( pParent )
711 : {
712 0 : Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
713 0 : awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
714 0 : aBounds.X -= aParentScreenLoc.X;
715 0 : aBounds.Y -= aParentScreenLoc.Y;
716 : }
717 : }
718 :
719 0 : uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
720 0 : 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 0 : return aBounds;
750 : }
751 :
752 0 : awt::Point VCLXAccessibleComponent::getLocationOnScreen( ) throw (uno::RuntimeException, std::exception)
753 : {
754 0 : OExternalLockGuard aGuard( this );
755 :
756 0 : awt::Point aPos;
757 0 : if ( GetWindow() )
758 : {
759 0 : Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL );
760 0 : aPos.X = aRect.Left();
761 0 : aPos.Y = aRect.Top();
762 : }
763 :
764 0 : return aPos;
765 : }
766 :
767 0 : void VCLXAccessibleComponent::grabFocus( ) throw (uno::RuntimeException, std::exception)
768 : {
769 0 : OExternalLockGuard aGuard( this );
770 :
771 0 : uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
772 0 : if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
773 0 : mxWindow->setFocus();
774 0 : }
775 :
776 0 : sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( ) throw (uno::RuntimeException, std::exception)
777 : {
778 0 : OExternalLockGuard aGuard( this );
779 :
780 0 : sal_Int32 nColor = 0;
781 0 : Window* pWindow = GetWindow();
782 0 : if ( pWindow )
783 : {
784 0 : if ( pWindow->IsControlForeground() )
785 0 : nColor = pWindow->GetControlForeground().GetColor();
786 : else
787 : {
788 0 : Font aFont;
789 0 : if ( pWindow->IsControlFont() )
790 0 : aFont = pWindow->GetControlFont();
791 : else
792 0 : aFont = pWindow->GetFont();
793 0 : nColor = aFont.GetColor().GetColor();
794 : // COL_AUTO is not very meaningful for AT
795 0 : if ( nColor == (sal_Int32)COL_AUTO)
796 0 : nColor = pWindow->GetTextColor().GetColor();
797 : }
798 : }
799 :
800 0 : return nColor;
801 : }
802 :
803 0 : sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( ) throw (uno::RuntimeException, std::exception)
804 : {
805 0 : OExternalLockGuard aGuard( this );
806 :
807 0 : sal_Int32 nColor = 0;
808 0 : Window* pWindow = GetWindow();
809 0 : if ( pWindow )
810 : {
811 0 : if ( pWindow->IsControlBackground() )
812 0 : nColor = pWindow->GetControlBackground().GetColor();
813 : else
814 0 : nColor = pWindow->GetBackground().GetColor().GetColor();
815 : }
816 :
817 0 : return nColor;
818 : }
819 :
820 : // XAccessibleExtendedComponent
821 :
822 0 : uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( ) throw (uno::RuntimeException, std::exception)
823 : {
824 0 : OExternalLockGuard aGuard( this );
825 :
826 0 : uno::Reference< awt::XFont > xFont;
827 0 : Window* pWindow = GetWindow();
828 0 : if ( pWindow )
829 : {
830 0 : uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
831 0 : if ( xDev.is() )
832 : {
833 0 : Font aFont;
834 0 : if ( pWindow->IsControlFont() )
835 0 : aFont = pWindow->GetControlFont();
836 : else
837 0 : aFont = pWindow->GetFont();
838 0 : VCLXFont* pVCLXFont = new VCLXFont;
839 0 : pVCLXFont->Init( *xDev.get(), aFont );
840 0 : xFont = pVCLXFont;
841 0 : }
842 : }
843 :
844 0 : return xFont;
845 : }
846 :
847 0 : OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( ) throw (uno::RuntimeException, std::exception)
848 : {
849 0 : OExternalLockGuard aGuard( this );
850 :
851 0 : OUString sRet;
852 0 : if ( GetWindow() )
853 0 : sRet = GetWindow()->GetText();
854 :
855 0 : return sRet;
856 : }
857 :
858 0 : OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( ) throw (uno::RuntimeException, std::exception)
859 : {
860 0 : OExternalLockGuard aGuard( this );
861 :
862 0 : OUString sRet;
863 0 : if ( GetWindow() )
864 0 : sRet = GetWindow()->GetQuickHelpText();
865 :
866 0 : return sRet;
867 : }
868 :
869 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|