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