Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/accessibility/vclxaccessiblecomponent.cxx
Line
Count
Source
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/AccessibleRelationType.hpp>
24
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25
#include <comphelper/accessiblecontexthelper.hxx>
26
#include <cppuhelper/supportsservice.hxx>
27
#include <i18nlangtag/languagetag.hxx>
28
#include <vcl/accessibility/vclxaccessiblecomponent.hxx>
29
#include <vcl/toolkit/dialog.hxx>
30
#include <vcl/vclevent.hxx>
31
#include <vcl/window.hxx>
32
#include <vcl/toolkit/edit.hxx>
33
#include <vcl/settings.hxx>
34
#include <vcl/unohelp.hxx>
35
#include <tools/debug.hxx>
36
#include <unotools/accessiblerelationsethelper.hxx>
37
#include <vcl/svapp.hxx>
38
#include <vcl/menu.hxx>
39
40
using namespace ::com::sun::star;
41
using namespace ::comphelper;
42
43
VCLXAccessibleComponent::VCLXAccessibleComponent(vcl::Window* pWindow)
44
0
    : m_xWindow(pWindow)
45
0
{
46
0
    assert(m_xWindow && "VCLXAccessibleComponent - no window!");
47
48
0
    m_xWindow->AddEventListener(LINK(this, VCLXAccessibleComponent, WindowEventListener));
49
0
    m_xWindow->AddChildEventListener(LINK(this, VCLXAccessibleComponent, WindowChildEventListener));
50
0
}
51
52
void VCLXAccessibleComponent::DisconnectEvents()
53
0
{
54
0
    if (m_xWindow)
55
0
    {
56
0
        m_xWindow->RemoveEventListener(LINK(this, VCLXAccessibleComponent, WindowEventListener));
57
0
        m_xWindow->RemoveChildEventListener(
58
0
            LINK(this, VCLXAccessibleComponent, WindowChildEventListener));
59
0
        m_xWindow.reset();
60
0
    }
61
0
}
62
63
VCLXAccessibleComponent::~VCLXAccessibleComponent()
64
0
{
65
0
    ensureDisposed();
66
0
    DisconnectEvents();
67
0
}
68
69
OUString VCLXAccessibleComponent::getImplementationName()
70
0
{
71
0
    return u"com.sun.star.comp.toolkit.AccessibleWindow"_ustr;
72
0
}
73
74
sal_Bool VCLXAccessibleComponent::supportsService( const OUString& rServiceName )
75
0
{
76
0
    return cppu::supportsService(this, rServiceName);
77
0
}
78
79
uno::Sequence< OUString > VCLXAccessibleComponent::getSupportedServiceNames()
80
0
{
81
0
    uno::Sequence< OUString > aNames { u"com.sun.star.awt.AccessibleWindow"_ustr };
82
0
    return aNames;
83
0
}
84
85
IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclWindowEvent&, rEvent, void )
86
0
{
87
    /* Ignore VclEventId::WindowEndPopupMode, because the UNO accessibility wrapper
88
     * might have been destroyed by the previous VCLEventListener (if no AT tool
89
     * is running), e.g. sub-toolbars in impress.
90
     */
91
0
    if (m_xWindow && (rEvent.GetId() != VclEventId::WindowEndPopupMode))
92
0
    {
93
0
        DBG_ASSERT( rEvent.GetWindow(), "Window???" );
94
0
        if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
95
0
        {
96
0
            ProcessWindowEvent( rEvent );
97
0
        }
98
0
    }
99
0
}
100
101
IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclWindowEvent&, rEvent, void )
102
0
{
103
0
    if (m_xWindow)
104
0
    {
105
0
        DBG_ASSERT( rEvent.GetWindow(), "Window???" );
106
0
        if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() )
107
0
        {
108
            // #103087# to prevent an early release of the component
109
0
            uno::Reference< accessibility::XAccessibleContext > xHoldAlive = this;
110
111
0
            ProcessWindowChildEvent( rEvent );
112
0
        }
113
0
    }
114
0
}
115
116
uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
117
0
{
118
    // checks if the data in the window event is our direct child
119
    // and returns its accessible
120
121
    // MT: Change this later, normally a show/hide event shouldn't have the vcl::Window* in pData.
122
0
    vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
123
    // tdf#141101/tdf#156561 Handle the event if this is either the a11y parent or the
124
    // vcl::Window parent, since child events are sent for the vcl::Window hierarchy
125
    // (s. Window::CallEventListeners) and e.g. DockingManager does manual partial reparenting
126
    // that would cause child events to not be forwarded to the a11y level when
127
    // not taking GetParent() into account here
128
0
    if (pChildWindow && (GetWindow() == pChildWindow->GetAccessibleParentWindow()
129
0
                         || GetWindow() == pChildWindow->GetParent()))
130
0
        return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VclEventId::WindowShow );
131
0
    else
132
0
        return uno::Reference< accessibility::XAccessible > ();
133
0
}
134
135
void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
136
0
{
137
0
    uno::Any aOldValue, aNewValue;
138
0
    uno::Reference< accessibility::XAccessible > xAcc;
139
140
0
    switch ( rVclWindowEvent.GetId() )
141
0
    {
142
0
        case VclEventId::WindowShow:  // send create on show for direct accessible children
143
0
        {
144
0
            xAcc = GetChildAccessible( rVclWindowEvent );
145
0
            if( xAcc.is() )
146
0
            {
147
0
                aNewValue <<= xAcc;
148
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
149
150
                // CHILD event above results in a11y event listeners getting registered,
151
                // so send state change event for SHOWING event after that
152
0
                uno::Reference<XAccessibleContext> xChildContext = xAcc->getAccessibleContext();
153
0
                if (xChildContext.is())
154
0
                {
155
0
                    VCLXAccessibleComponent* pChildComponent = dynamic_cast<VCLXAccessibleComponent*>(xChildContext.get());
156
0
                    if (pChildComponent)
157
0
                    {
158
0
                        css::uno::Any aNewStateValue;
159
0
                        aNewStateValue <<= accessibility::AccessibleStateType::SHOWING;
160
0
                        pChildComponent->NotifyAccessibleEvent(accessibility::AccessibleEventId::STATE_CHANGED, css::uno::Any(), aNewStateValue);
161
0
                    }
162
0
                }
163
0
            }
164
0
        }
165
0
        break;
166
0
        case VclEventId::WindowHide:  // send destroy on hide for direct accessible children
167
0
        {
168
0
            xAcc = GetChildAccessible( rVclWindowEvent );
169
0
            if( xAcc.is() )
170
0
            {
171
                // send state change event for SHOWING before sending the CHILD event below,
172
                // since that one results in a11y event listeners getting removed
173
0
                uno::Reference<XAccessibleContext> xChildContext = xAcc->getAccessibleContext();
174
0
                if (xChildContext.is())
175
0
                {
176
0
                    VCLXAccessibleComponent* pChildComponent = dynamic_cast<VCLXAccessibleComponent*>(xChildContext.get());
177
0
                    if (pChildComponent)
178
0
                    {
179
0
                        css::uno::Any aOldStateValue;
180
0
                        aOldStateValue <<= accessibility::AccessibleStateType::SHOWING;
181
0
                        pChildComponent->NotifyAccessibleEvent(accessibility::AccessibleEventId::STATE_CHANGED, aOldStateValue, css::uno::Any());
182
0
                    }
183
0
                }
184
185
0
                aOldValue <<= xAcc;
186
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
187
0
            }
188
0
        }
189
0
        break;
190
0
        default: break;
191
0
    }
192
0
}
193
194
void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
195
0
{
196
0
    uno::Any aOldValue, aNewValue;
197
198
0
    vcl::Window* pAccWindow = rVclWindowEvent.GetWindow();
199
0
    assert(pAccWindow && "VCLXAccessibleComponent::ProcessWindowEvent - Window?");
200
201
0
    switch ( rVclWindowEvent.GetId() )
202
0
    {
203
0
        case VclEventId::ObjectDying:
204
0
        {
205
0
            DisconnectEvents();
206
0
        }
207
0
        break;
208
0
        case VclEventId::WindowChildDestroyed:
209
0
        {
210
0
            vcl::Window* pWindow = static_cast<vcl::Window*>(rVclWindowEvent.GetData());
211
0
            DBG_ASSERT( pWindow, "VclEventId::WindowChildDestroyed - Window=?" );
212
0
            if ( pWindow->GetAccessible( false ).is() )
213
0
            {
214
0
                aOldValue <<= css::uno::Reference<accessibility::XAccessible>(
215
0
                    pWindow->GetAccessible(false));
216
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
217
0
            }
218
0
        }
219
0
        break;
220
0
        case VclEventId::WindowActivate:
221
0
        {
222
0
            sal_Int16 aAccessibleRole = getAccessibleRole();
223
            // avoid notification if a child frame is already active
224
            // only one frame may be active at a given time
225
0
            if ( !pAccWindow->HasActiveChildFrame() &&
226
0
                 ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
227
0
                   aAccessibleRole == accessibility::AccessibleRole::ALERT ||
228
0
                   aAccessibleRole == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
229
0
            {
230
0
                aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
231
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
232
0
            }
233
0
        }
234
0
        break;
235
0
        case VclEventId::WindowDeactivate:
236
0
        {
237
0
            sal_Int16 aAccessibleRole = getAccessibleRole();
238
0
            if ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
239
0
                 aAccessibleRole == accessibility::AccessibleRole::ALERT ||
240
0
                 aAccessibleRole == accessibility::AccessibleRole::DIALOG )  // #i18891#
241
0
            {
242
0
                aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
243
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
244
0
            }
245
0
        }
246
0
        break;
247
0
        case VclEventId::WindowGetFocus:
248
0
        case VclEventId::ControlGetFocus:
249
0
        {
250
0
            if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlGetFocus) ||
251
0
                (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowGetFocus) )
252
0
            {
253
                // if multiple listeners were registered it is possible that the
254
                // focus was changed during event processing (eg SfxTopWindow )
255
                // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
256
0
                if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
257
0
                    (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
258
0
                {
259
0
                    aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
260
0
                    NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
261
0
                }
262
0
            }
263
0
        }
264
0
        break;
265
0
        case VclEventId::WindowLoseFocus:
266
0
        case VclEventId::ControlLoseFocus:
267
0
        {
268
0
            if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlLoseFocus) ||
269
0
                (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowLoseFocus) )
270
0
            {
271
0
                aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
272
0
                NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
273
0
            }
274
0
        }
275
0
        break;
276
0
        case VclEventId::WindowFrameTitleChanged:
277
0
        {
278
0
            OUString aOldName( *static_cast<OUString*>(rVclWindowEvent.GetData()) );
279
0
            OUString aNewName( getAccessibleName() );
280
0
            aOldValue <<= aOldName;
281
0
            aNewValue <<= aNewName;
282
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
283
0
        }
284
0
        break;
285
0
        case VclEventId::WindowEnabled:
286
0
        {
287
0
            aNewValue <<= accessibility::AccessibleStateType::ENABLED;
288
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
289
0
            aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
290
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
291
0
        }
292
0
        break;
293
0
        case VclEventId::WindowDisabled:
294
0
        {
295
0
            aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
296
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
297
298
0
            aOldValue <<= accessibility::AccessibleStateType::ENABLED;
299
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
300
0
        }
301
0
        break;
302
0
        case VclEventId::WindowMove:
303
0
        case VclEventId::WindowResize:
304
0
        {
305
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
306
0
        }
307
0
        break;
308
0
        case VclEventId::WindowMenubarAdded:
309
0
        {
310
0
            MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
311
0
            if ( pMenuBar )
312
0
            {
313
0
                uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
314
0
                if ( xChild.is() )
315
0
                {
316
0
                    aNewValue <<= xChild;
317
0
                    NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
318
0
                }
319
0
            }
320
0
        }
321
0
        break;
322
0
        case VclEventId::WindowMenubarRemoved:
323
0
        {
324
0
            MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
325
0
            if ( pMenuBar )
326
0
            {
327
0
                uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
328
0
                if ( xChild.is() )
329
0
                {
330
0
                    aOldValue <<= xChild;
331
0
                    NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
332
0
                }
333
0
            }
334
0
        }
335
0
        break;
336
0
        case VclEventId::WindowMinimize:
337
0
        {
338
0
            aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
339
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
340
0
        }
341
0
        break;
342
0
        case VclEventId::WindowNormalize:
343
0
        {
344
0
            aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
345
0
            NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
346
0
        }
347
0
        break;
348
0
        case VclEventId::WindowHide:
349
0
        case VclEventId::WindowShow:
350
        // WindowHide and WindowShow are handled in ProcessWindowChildEvent so the right order
351
        // regarding the CHILD event can be taken into account
352
0
        default:
353
0
        {
354
0
        }
355
0
        break;
356
0
    }
357
0
}
358
359
void VCLXAccessibleComponent::disposing()
360
0
{
361
0
    DisconnectEvents();
362
363
0
    OAccessible::disposing();
364
0
}
365
366
0
vcl::Window* VCLXAccessibleComponent::GetWindow() const { return m_xWindow; }
367
368
void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
369
0
{
370
0
    VclPtr<vcl::Window> pWindow = GetWindow();
371
0
    if ( !pWindow )
372
0
        return;
373
374
0
    vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
375
0
    if ( pLabeledBy && pLabeledBy != pWindow )
376
0
    {
377
0
        uno::Sequence<uno::Reference<css::accessibility::XAccessible>> aSequence { pLabeledBy->GetAccessible() };
378
0
        rRelationSet.AddRelation(accessibility::AccessibleRelation(accessibility::AccessibleRelationType_LABELED_BY, aSequence));
379
0
    }
380
381
0
    vcl::Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
382
0
    if ( pLabelFor && pLabelFor != pWindow )
383
0
    {
384
0
        uno::Sequence<uno::Reference<css::accessibility::XAccessible>> aSequence { pLabelFor->GetAccessible() };
385
0
        rRelationSet.AddRelation(accessibility::AccessibleRelation(accessibility::AccessibleRelationType_LABEL_FOR, aSequence));
386
0
    }
387
388
0
    vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
389
0
    if ( pMemberOf && pMemberOf != pWindow )
390
0
    {
391
0
        uno::Sequence<uno::Reference<css::accessibility::XAccessible>> aSequence { pMemberOf->GetAccessible() };
392
0
        rRelationSet.AddRelation(accessibility::AccessibleRelation(accessibility::AccessibleRelationType_MEMBER_OF, aSequence));
393
0
    }
394
0
}
395
396
void VCLXAccessibleComponent::FillAccessibleStateSet( sal_Int64& rStateSet )
397
0
{
398
0
    VclPtr<vcl::Window> pWindow = GetWindow();
399
0
    if ( pWindow )
400
0
    {
401
0
        if ( pWindow->IsVisible() )
402
0
        {
403
0
            rStateSet |= accessibility::AccessibleStateType::VISIBLE;
404
0
            rStateSet |= accessibility::AccessibleStateType::SHOWING;
405
0
        }
406
0
        else
407
0
        {
408
0
            rStateSet |= accessibility::AccessibleStateType::INVALID;
409
0
        }
410
411
0
        if ( pWindow->IsEnabled() )
412
0
        {
413
0
            rStateSet |= accessibility::AccessibleStateType::ENABLED;
414
0
            rStateSet |= accessibility::AccessibleStateType::SENSITIVE;
415
0
        }
416
417
0
        if ( pWindow->HasChildPathFocus() &&
418
0
             ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
419
0
               getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
420
0
               getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
421
0
            rStateSet |= accessibility::AccessibleStateType::ACTIVE;
422
423
0
        if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
424
0
            rStateSet |= accessibility::AccessibleStateType::FOCUSED;
425
426
0
        if ( pWindow->IsWait() )
427
0
            rStateSet |= accessibility::AccessibleStateType::BUSY;
428
429
0
        if ( pWindow->GetStyle() & WB_SIZEABLE )
430
0
            rStateSet |= accessibility::AccessibleStateType::RESIZABLE;
431
        // 6. frame doesn't have MOVABLE state
432
        // 10. for password text, where is the sensitive state?
433
0
        if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
434
0
            rStateSet |= accessibility::AccessibleStateType::MOVEABLE;
435
0
        if( pWindow->IsDialog() )
436
0
        {
437
0
            Dialog *pDlg = static_cast< Dialog* >( pWindow.get() );
438
0
            if( pDlg->IsInExecute() )
439
0
                rStateSet |= accessibility::AccessibleStateType::MODAL;
440
0
        }
441
        //If a combobox or list's edit child isn't read-only,EDITABLE state
442
        //should be set.
443
0
        if( pWindow && pWindow->GetType() == WindowType::COMBOBOX )
444
0
        {
445
0
            if( !( pWindow->GetStyle() & WB_READONLY) ||
446
0
                !static_cast<Edit*>(pWindow.get())->IsReadOnly() )
447
0
                    rStateSet |= accessibility::AccessibleStateType::EDITABLE;
448
0
        }
449
450
0
        VclPtr<vcl::Window> pChild = pWindow->GetWindow( GetWindowType::FirstChild );
451
452
0
        while( pWindow && pChild )
453
0
        {
454
0
            VclPtr<vcl::Window> pWinTemp = pChild->GetWindow( GetWindowType::FirstChild );
455
0
            if( pWinTemp && pWinTemp->GetType() == WindowType::EDIT )
456
0
            {
457
0
                if( !( pWinTemp->GetStyle() & WB_READONLY) ||
458
0
                    !static_cast<Edit*>(pWinTemp.get())->IsReadOnly() )
459
0
                    rStateSet |= accessibility::AccessibleStateType::EDITABLE;
460
0
                break;
461
0
            }
462
0
            if( pChild->GetType() == WindowType::EDIT )
463
0
            {
464
0
                if( !( pChild->GetStyle() & WB_READONLY) ||
465
0
                    !static_cast<Edit*>(pChild.get())->IsReadOnly())
466
0
                    rStateSet |= accessibility::AccessibleStateType::EDITABLE;
467
0
                break;
468
0
            }
469
0
            pChild = pChild->GetWindow( GetWindowType::Next );
470
0
        }
471
0
    }
472
0
    else
473
0
    {
474
0
        rStateSet |= accessibility::AccessibleStateType::DEFUNC;
475
0
    }
476
477
/*
478
479
MUST BE SET FROM DERIVED CLASSES:
480
481
CHECKABLE
482
CHECKED
483
COLLAPSED
484
EXPANDED
485
EXPANDABLE
486
EDITABLE
487
FOCUSABLE
488
HORIZONTAL
489
VERTICAL
490
ICONIFIED
491
MULTILINE
492
MULTI_SELECTABLE
493
PRESSED
494
SELECTABLE
495
SELECTED
496
SINGLE_LINE
497
TRANSIENT
498
499
    */
500
0
}
501
502
// accessibility::XAccessibleContext
503
sal_Int64 VCLXAccessibleComponent::getAccessibleChildCount()
504
0
{
505
0
    OExternalLockGuard aGuard( this );
506
507
0
    sal_Int64 nChildren = 0;
508
0
    if ( GetWindow() )
509
0
        nChildren = GetWindow()->GetAccessibleChildWindowCount();
510
511
0
    return nChildren;
512
0
}
513
514
uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int64 i )
515
0
{
516
0
    OExternalLockGuard aGuard( this );
517
518
0
    if ( i >= getAccessibleChildCount() )
519
0
        throw lang::IndexOutOfBoundsException();
520
521
0
    uno::Reference< accessibility::XAccessible > xAcc;
522
0
    if ( GetWindow() )
523
0
    {
524
0
        vcl::Window* pChild = GetWindow()->GetAccessibleChildWindow( static_cast<sal_uInt16>(i) );
525
0
        if ( pChild )
526
0
            xAcc = pChild->GetAccessible();
527
0
    }
528
529
0
    return xAcc;
530
0
}
531
532
uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent(  )
533
0
{
534
0
    OExternalLockGuard aGuard( this );
535
536
0
    uno::Reference< accessibility::XAccessible > xAcc;
537
0
    if ( GetWindow() )
538
0
        xAcc = GetWindow()->GetAccessibleParent();
539
0
    return xAcc;
540
0
}
541
542
sal_Int16 VCLXAccessibleComponent::getAccessibleRole(  )
543
0
{
544
0
    OExternalLockGuard aGuard( this );
545
546
0
    sal_Int16 nRole = 0;
547
548
0
    if ( GetWindow() )
549
0
        nRole = GetWindow()->GetAccessibleRole();
550
551
0
    return nRole;
552
0
}
553
554
OUString VCLXAccessibleComponent::getAccessibleDescription(  )
555
0
{
556
0
    OExternalLockGuard aGuard( this );
557
558
0
    OUString aDescription;
559
560
0
    if ( GetWindow() )
561
0
        aDescription = GetWindow()->GetAccessibleDescription();
562
563
0
    return aDescription;
564
0
}
565
566
OUString VCLXAccessibleComponent::getAccessibleName(  )
567
0
{
568
0
    OExternalLockGuard aGuard( this );
569
570
0
    OUString aName;
571
0
    if ( GetWindow() )
572
0
    {
573
0
        aName = GetWindow()->GetAccessibleName();
574
#if OSL_DEBUG_LEVEL > 0
575
        // append window type to accessible name for debugging purposes
576
        // if LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME environment variable is set
577
        static const char* pEnvAppendType = getenv("LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME");
578
        if (pEnvAppendType && OUString::createFromAscii(pEnvAppendType) != u"0")
579
            aName += " (Type = " + OUString::number(static_cast<sal_Int32>(GetWindow()->GetType())) + ")";
580
#endif
581
0
    }
582
0
    return aName;
583
0
}
584
585
OUString VCLXAccessibleComponent::getAccessibleId(  )
586
0
{
587
0
    OExternalLockGuard aGuard( this );
588
589
0
    OUString aId;
590
0
    if ( GetWindow() )
591
0
    {
592
0
        const OUString &aWindowId = GetWindow()->get_id();
593
0
        aId = aWindowId;
594
0
    }
595
0
    return aId;
596
0
}
597
598
uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet(  )
599
0
{
600
0
    OExternalLockGuard aGuard( this );
601
602
0
    rtl::Reference<utl::AccessibleRelationSetHelper> pRelationSetHelper = new utl::AccessibleRelationSetHelper;
603
0
    FillAccessibleRelationSet( *pRelationSetHelper );
604
0
    return pRelationSetHelper;
605
0
}
606
607
sal_Int64 VCLXAccessibleComponent::getAccessibleStateSet(  )
608
0
{
609
0
    OExternalLockGuard aGuard( this );
610
611
0
    sal_Int64 nStateSet = 0;
612
0
    FillAccessibleStateSet( nStateSet );
613
0
    return nStateSet;
614
0
}
615
616
lang::Locale VCLXAccessibleComponent::getLocale()
617
0
{
618
0
    OExternalLockGuard aGuard( this );
619
620
0
    return Application::GetSettings().GetLanguageTag().getLocale();
621
0
}
622
623
uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint )
624
0
{
625
0
    OExternalLockGuard aGuard( this );
626
627
0
    uno::Reference< accessibility::XAccessible > xChild;
628
0
    for ( sal_Int64 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
629
0
    {
630
0
        uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
631
0
        if ( xAcc.is() )
632
0
        {
633
0
            uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
634
0
            if ( xComp.is() )
635
0
            {
636
0
                tools::Rectangle aRect = vcl::unohelper::ConvertToVCLRect(xComp->getBounds());
637
0
                Point aPos = vcl::unohelper::ConvertToVCLPoint(rPoint);
638
0
                if ( aRect.Contains( aPos ) )
639
0
                {
640
0
                    xChild = std::move(xAcc);
641
0
                    break;
642
0
                }
643
0
            }
644
0
        }
645
0
    }
646
647
0
    return xChild;
648
0
}
649
650
// accessibility::XAccessibleComponent
651
awt::Rectangle VCLXAccessibleComponent::implGetBounds()
652
0
{
653
0
    VclPtr<vcl::Window> pWindow = GetWindow();
654
0
    if (!pWindow)
655
0
        return awt::Rectangle();
656
657
0
    AbsoluteScreenPixelRectangle aRect = pWindow->GetWindowExtentsAbsolute();
658
0
    awt::Rectangle aBounds = vcl::unohelper::ConvertToAWTRect(aRect);
659
660
0
    css::uno::Reference<css::accessibility::XAccessible> xParent = pWindow->GetAccessibleParent();
661
0
    if (!xParent.is())
662
0
        return aBounds;
663
664
0
    css::uno::Reference<css::accessibility::XAccessibleComponent> xParentComponent(
665
0
        xParent->getAccessibleContext(), css::uno::UNO_QUERY);
666
0
    if (!xParentComponent)
667
0
        return aBounds;
668
669
0
    awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
670
0
    aBounds.X -= aParentScreenLoc.X;
671
0
    aBounds.Y -= aParentScreenLoc.Y;
672
673
0
    return aBounds;
674
0
}
675
676
awt::Point VCLXAccessibleComponent::getLocationOnScreen(  )
677
0
{
678
0
    OExternalLockGuard aGuard( this );
679
680
0
    awt::Point aPos;
681
0
    if ( GetWindow() )
682
0
    {
683
0
        AbsoluteScreenPixelRectangle aRect = GetWindow()->GetWindowExtentsAbsolute();
684
0
        aPos.X = aRect.Left();
685
0
        aPos.Y = aRect.Top();
686
0
    }
687
688
0
    return aPos;
689
0
}
690
691
void VCLXAccessibleComponent::grabFocus(  )
692
0
{
693
0
    OExternalLockGuard aGuard( this );
694
695
0
    sal_Int64 nStates = getAccessibleStateSet();
696
0
    if (m_xWindow && (nStates & accessibility::AccessibleStateType::FOCUSABLE))
697
0
        m_xWindow->GrabFocus();
698
0
}
699
700
sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground(  )
701
0
{
702
0
    OExternalLockGuard aGuard( this );
703
704
0
    Color nColor;
705
0
    VclPtr<vcl::Window> pWindow = GetWindow();
706
0
    if ( pWindow )
707
0
    {
708
0
        if ( pWindow->IsControlForeground() )
709
0
            nColor = pWindow->GetControlForeground();
710
0
        else
711
0
        {
712
0
            vcl::Font aFont;
713
0
            if ( pWindow->IsControlFont() )
714
0
                aFont = pWindow->GetControlFont();
715
0
            else
716
0
                aFont = pWindow->GetFont();
717
0
            nColor = aFont.GetColor();
718
            // COL_AUTO is not very meaningful for AT
719
0
            if ( nColor == COL_AUTO)
720
0
                nColor = pWindow->GetTextColor();
721
0
        }
722
0
    }
723
724
0
    return sal_Int32(nColor);
725
0
}
726
727
sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground(  )
728
0
{
729
0
    OExternalLockGuard aGuard( this );
730
731
0
    Color nColor;
732
0
    VclPtr<vcl::Window> pWindow = GetWindow();
733
0
    if ( pWindow )
734
0
    {
735
0
        if ( pWindow->IsControlBackground() )
736
0
            nColor = pWindow->GetControlBackground();
737
0
        else
738
0
            nColor = pWindow->GetBackground().GetColor();
739
0
    }
740
741
0
    return sal_Int32(nColor);
742
0
}
743
744
// XAccessibleExtendedComponent
745
746
OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText(  )
747
0
{
748
0
    OExternalLockGuard aGuard( this );
749
750
0
    OUString sRet;
751
0
    if ( GetWindow() )
752
0
        sRet = GetWindow()->GetText();
753
754
0
    return sRet;
755
0
}
756
757
OUString SAL_CALL VCLXAccessibleComponent::getToolTipText(  )
758
0
{
759
0
    OExternalLockGuard aGuard( this );
760
761
0
    OUString sRet;
762
0
    if ( GetWindow() )
763
0
        sRet = GetWindow()->GetQuickHelpText();
764
765
0
    return sRet;
766
0
}
767
768
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */