Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/accessibility/AccessibleBrowseBoxBase.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 <utility>
21
#include <vcl/accessibletableprovider.hxx>
22
#include <cppuhelper/supportsservice.hxx>
23
24
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
25
#include <com/sun/star/accessibility/AccessibleRole.hpp>
26
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
27
#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
28
#include <unotools/accessiblerelationsethelper.hxx>
29
#include <vcl/accessibility/AccessibleBrowseBoxBase.hxx>
30
#include <vcl/unohelp.hxx>
31
#include <vcl/window.hxx>
32
#include <vcl/svapp.hxx>
33
34
35
using ::com::sun::star::uno::Reference;
36
using ::com::sun::star::uno::Sequence;
37
using ::com::sun::star::uno::Any;
38
39
using namespace ::com::sun::star;
40
using namespace ::com::sun::star::accessibility;
41
using namespace ::comphelper;
42
43
using namespace com::sun::star::accessibility::AccessibleStateType;
44
45
46
// Ctor/Dtor/disposing
47
48
AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
49
    const css::uno::Reference<css::accessibility::XAccessible>& xParent,
50
    ::vcl::IAccessibleTableProvider& rBrowseBox,
51
    const css::uno::Reference<css::awt::XWindow>& xFocusWindow, AccessibleBrowseBoxObjType eObjType)
52
0
    : AccessibleBrowseBoxBase(xParent, rBrowseBox, xFocusWindow, eObjType,
53
0
                              rBrowseBox.GetAccessibleObjectName(eObjType),
54
0
                              rBrowseBox.GetAccessibleObjectDescription(eObjType))
55
0
{
56
0
}
57
58
AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
59
        css::uno::Reference< css::accessibility::XAccessible >  rxParent,
60
        ::vcl::IAccessibleTableProvider&                      rBrowseBox,
61
        css::uno::Reference< css::awt::XWindow >  _xFocusWindow,
62
        AccessibleBrowseBoxObjType      eObjType,
63
        OUString           rName,
64
        OUString           rDescription ) :
65
0
    ImplInheritanceHelper(),
66
0
    mxParent(std::move( rxParent )),
67
0
    mpBrowseBox( &rBrowseBox ),
68
0
    m_xFocusWindow(std::move(_xFocusWindow)),
69
0
    maName(std::move( rName )),
70
0
    maDescription(std::move( rDescription )),
71
0
    meObjType( eObjType )
72
0
{
73
0
    if ( m_xFocusWindow.is() )
74
0
        m_xFocusWindow->addFocusListener( this );
75
0
}
76
77
void SAL_CALL AccessibleBrowseBoxBase::disposing()
78
0
{
79
0
    ::osl::MutexGuard aGuard( getMutex() );
80
0
    if ( m_xFocusWindow.is() )
81
0
    {
82
0
        SolarMutexGuard aSolarGuard;
83
0
        m_xFocusWindow->removeFocusListener( this );
84
0
    }
85
86
0
    OAccessible::disposing();
87
88
0
    mxParent = nullptr;
89
0
    mpBrowseBox = nullptr;
90
0
}
91
92
css::awt::Rectangle AccessibleBrowseBoxBase::implGetBounds()
93
0
{
94
0
    return vcl::unohelper::ConvertToAWTRect(implGetBoundingBox());
95
0
}
96
97
// css::accessibility::XAccessibleContext
98
99
Reference< css::accessibility::XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleParent()
100
0
{
101
0
    ::osl::MutexGuard aGuard( getMutex() );
102
0
    ensureIsAlive();
103
0
    return mxParent;
104
0
}
105
106
OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleDescription()
107
0
{
108
0
    ::osl::MutexGuard aGuard( getMutex() );
109
0
    ensureIsAlive();
110
0
    return maDescription;
111
0
}
112
113
OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleName()
114
0
{
115
0
    ::osl::MutexGuard aGuard( getMutex() );
116
0
    ensureIsAlive();
117
0
    return maName;
118
0
}
119
120
Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL
121
AccessibleBrowseBoxBase::getAccessibleRelationSet()
122
0
{
123
0
    ::osl::MutexGuard aGuard( getMutex() );
124
0
    ensureIsAlive();
125
    // BrowseBox does not have relations.
126
0
    return new utl::AccessibleRelationSetHelper;
127
0
}
128
129
sal_Int64 SAL_CALL
130
AccessibleBrowseBoxBase::getAccessibleStateSet()
131
0
{
132
0
    SolarMethodGuard aGuard( getMutex() );
133
    // don't check whether alive -> StateSet may contain DEFUNC
134
0
    return implCreateStateSet();
135
0
}
136
137
lang::Locale SAL_CALL AccessibleBrowseBoxBase::getLocale()
138
0
{
139
0
    ::osl::MutexGuard aGuard( getMutex() );
140
0
    ensureIsAlive();
141
0
    if( mxParent.is() )
142
0
    {
143
0
        css::uno::Reference< css::accessibility::XAccessibleContext >
144
0
            xParentContext( mxParent->getAccessibleContext() );
145
0
        if( xParentContext.is() )
146
0
            return xParentContext->getLocale();
147
0
    }
148
0
    throw IllegalAccessibleComponentStateException();
149
0
}
150
151
// css::accessibility::XAccessibleComponent
152
153
void SAL_CALL AccessibleBrowseBoxBase::focusGained( const css::awt::FocusEvent& )
154
0
{
155
0
    css::uno::Any aFocused;
156
0
    css::uno::Any aEmpty;
157
0
    aFocused <<= FOCUSED;
158
159
0
    commitEvent(AccessibleEventId::STATE_CHANGED,aFocused,aEmpty);
160
0
}
161
162
163
void SAL_CALL AccessibleBrowseBoxBase::focusLost( const css::awt::FocusEvent& )
164
0
{
165
0
    css::uno::Any aFocused;
166
0
    css::uno::Any aEmpty;
167
0
    aFocused <<= FOCUSED;
168
169
0
    commitEvent(AccessibleEventId::STATE_CHANGED,aEmpty,aFocused);
170
0
}
171
172
// XServiceInfo
173
174
sal_Bool SAL_CALL AccessibleBrowseBoxBase::supportsService(
175
        const OUString& rServiceName )
176
0
{
177
0
    return cppu::supportsService(this, rServiceName);
178
0
}
179
180
Sequence< OUString > SAL_CALL AccessibleBrowseBoxBase::getSupportedServiceNames()
181
0
{
182
0
    return { u"com.sun.star.accessibility.AccessibleContext"_ustr };
183
0
}
184
185
// other public methods
186
187
void AccessibleBrowseBoxBase::setAccessibleName( const OUString& rName )
188
0
{
189
0
    ::osl::ClearableMutexGuard aGuard( getMutex() );
190
0
    Any aOld;
191
0
    aOld <<= maName;
192
0
    maName = rName;
193
194
0
    aGuard.clear();
195
196
0
    commitEvent(
197
0
        AccessibleEventId::NAME_CHANGED,
198
0
        uno::Any( maName ),
199
0
        aOld );
200
0
}
201
202
void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString& rDescription )
203
0
{
204
0
    ::osl::ClearableMutexGuard aGuard( getMutex() );
205
0
    Any aOld;
206
0
    aOld <<= maDescription;
207
0
    maDescription = rDescription;
208
209
0
    aGuard.clear();
210
211
0
    commitEvent(
212
0
        AccessibleEventId::DESCRIPTION_CHANGED,
213
0
        uno::Any( maDescription ),
214
0
        aOld );
215
0
}
216
217
// internal virtual methods
218
219
bool AccessibleBrowseBoxBase::implIsShowing()
220
0
{
221
0
    bool bShowing = false;
222
0
    if( mxParent.is() )
223
0
    {
224
0
        css::uno::Reference< css::accessibility::XAccessibleComponent >
225
0
            xParentComp( mxParent->getAccessibleContext(), uno::UNO_QUERY );
226
0
        if( xParentComp.is() )
227
0
            bShowing = implGetBoundingBox().Overlaps(
228
0
                vcl::unohelper::ConvertToVCLRect(xParentComp->getBounds()));
229
0
    }
230
0
    return bShowing;
231
0
}
232
233
sal_Int64 AccessibleBrowseBoxBase::implCreateStateSet()
234
0
{
235
0
    sal_Int64 nStateSet = 0;
236
237
0
    if( isAlive() )
238
0
    {
239
        // SHOWING done with mxParent
240
0
        if( implIsShowing() )
241
0
            nStateSet |= AccessibleStateType::SHOWING;
242
        // BrowseBox fills StateSet with states depending on object type
243
0
        mpBrowseBox->FillAccessibleStateSet( nStateSet, getType() );
244
0
    }
245
0
    else
246
0
        nStateSet |= AccessibleStateType::DEFUNC;
247
248
0
    return nStateSet;
249
0
}
250
251
// internal helper methods
252
253
bool AccessibleBrowseBoxBase::isAlive() const
254
0
{
255
0
    return OAccessible::isAlive() && mpBrowseBox;
256
0
}
257
258
void AccessibleBrowseBoxBase::ensureIsAlive() const
259
0
{
260
0
    if( !isAlive() )
261
0
        throw lang::DisposedException();
262
0
}
263
264
void AccessibleBrowseBoxBase::commitEvent(
265
        sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
266
0
{
267
0
    NotifyAccessibleEvent(_nEventId, _rOldValue, _rNewValue);
268
0
}
269
270
sal_Int16 SAL_CALL AccessibleBrowseBoxBase::getAccessibleRole()
271
0
{
272
0
    osl::MutexGuard aGuard( getMutex() );
273
0
    ensureIsAlive();
274
0
    sal_Int16 nRole = AccessibleRole::UNKNOWN;
275
0
    switch ( meObjType )
276
0
    {
277
0
        case AccessibleBrowseBoxObjType::RowHeaderCell:
278
0
            nRole = AccessibleRole::ROW_HEADER;
279
0
            break;
280
0
        case AccessibleBrowseBoxObjType::ColumnHeaderCell:
281
0
            nRole = AccessibleRole::COLUMN_HEADER;
282
0
            break;
283
0
        case AccessibleBrowseBoxObjType::ColumnHeaderBar:
284
0
        case AccessibleBrowseBoxObjType::RowHeaderBar:
285
0
        case AccessibleBrowseBoxObjType::Table:
286
0
            nRole = AccessibleRole::TABLE;
287
0
            break;
288
0
        case AccessibleBrowseBoxObjType::TableCell:
289
0
            nRole = AccessibleRole::TABLE_CELL;
290
0
            break;
291
0
        case AccessibleBrowseBoxObjType::BrowseBox:
292
0
            nRole = AccessibleRole::PANEL;
293
0
            break;
294
0
        case AccessibleBrowseBoxObjType::CheckBoxCell:
295
0
            nRole = AccessibleRole::CHECK_BOX;
296
0
            break;
297
0
    }
298
0
    return nRole;
299
0
}
300
301
Reference<XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleAtPoint( const css::awt::Point& )
302
0
{
303
0
    return nullptr;
304
0
}
305
306
void SAL_CALL AccessibleBrowseBoxBase::disposing( const css::lang::EventObject& )
307
0
{
308
0
    m_xFocusWindow = nullptr;
309
0
}
310
311
sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getForeground(  )
312
0
{
313
0
    SolarMethodGuard aGuard(getMutex());
314
0
    ensureIsAlive();
315
316
0
    Color nColor;
317
0
    vcl::Window* pInst = mpBrowseBox->GetWindowInstance();
318
0
    if ( pInst )
319
0
    {
320
0
        if ( pInst->IsControlForeground() )
321
0
            nColor = pInst->GetControlForeground();
322
0
        else
323
0
        {
324
0
            vcl::Font aFont;
325
0
            if ( pInst->IsControlFont() )
326
0
                aFont = pInst->GetControlFont();
327
0
            else
328
0
                aFont = pInst->GetFont();
329
0
            nColor = aFont.GetColor();
330
0
        }
331
0
    }
332
333
0
    return sal_Int32(nColor);
334
0
}
335
336
sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getBackground(  )
337
0
{
338
0
    SolarMethodGuard aGuard(getMutex());
339
0
    ensureIsAlive();
340
341
0
    Color nColor;
342
0
    vcl::Window* pInst = mpBrowseBox->GetWindowInstance();
343
0
    if ( pInst )
344
0
    {
345
0
        if ( pInst->IsControlBackground() )
346
0
            nColor = pInst->GetControlBackground();
347
0
        else
348
0
            nColor = pInst->GetBackground().GetColor();
349
0
    }
350
351
0
    return sal_Int32(nColor);
352
0
}
353
354
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */