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