Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/outdev/nativecontrols.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 <sal/log.hxx>
21
22
#include <vcl/pdfextoutdevdata.hxx>
23
#include <vcl/salnativewidgets.hxx>
24
#include <vcl/virdev.hxx>
25
#include <vcl/window.hxx>
26
27
#include <salgdi.hxx>
28
#include <toolbarvalue.hxx>
29
#include <menubarvalue.hxx>
30
#include <scrollbarvalue.hxx>
31
32
#include <cassert>
33
34
ImplControlValue::~ImplControlValue()
35
0
{
36
0
}
37
38
ImplControlValue* ImplControlValue::clone() const
39
0
{
40
0
    assert( typeid( const ImplControlValue ) == typeid( *this ));
41
0
    return new ImplControlValue( *this );
42
0
}
43
44
ScrollbarValue::~ScrollbarValue()
45
{
46
}
47
48
ScrollbarValue* ScrollbarValue::clone() const
49
0
{
50
0
    assert( typeid( const ScrollbarValue ) == typeid( *this ));
51
0
    return new ScrollbarValue( *this );
52
0
}
53
54
SliderValue::~SliderValue()
55
{
56
}
57
58
SliderValue* SliderValue::clone() const
59
0
{
60
0
    assert( typeid( const SliderValue ) == typeid( *this ));
61
0
    return new SliderValue( *this );
62
0
}
63
64
int TabPaneValue::m_nOverlap = 0;
65
66
TabPaneValue* TabPaneValue::clone() const
67
0
{
68
0
    assert(typeid(const TabPaneValue) == typeid(*this));
69
0
    return new TabPaneValue(*this);
70
0
}
71
72
TabitemValue::~TabitemValue()
73
{
74
}
75
76
TabitemValue* TabitemValue::clone() const
77
0
{
78
0
    assert( typeid( const TabitemValue ) == typeid( *this ));
79
0
    return new TabitemValue( *this );
80
0
}
81
82
SpinbuttonValue::~SpinbuttonValue()
83
{
84
}
85
86
SpinbuttonValue* SpinbuttonValue::clone() const
87
0
{
88
0
    assert( typeid( const SpinbuttonValue ) == typeid( *this ));
89
0
    return new SpinbuttonValue( *this );
90
0
}
91
92
ToolbarValue::~ToolbarValue()
93
{
94
}
95
96
ToolbarValue* ToolbarValue::clone() const
97
0
{
98
0
    assert( typeid( const ToolbarValue ) == typeid( *this ));
99
0
    return new ToolbarValue( *this );
100
0
}
101
102
MenubarValue::~MenubarValue()
103
{
104
}
105
106
MenubarValue* MenubarValue::clone() const
107
0
{
108
0
    assert( typeid( const MenubarValue ) == typeid( *this ));
109
0
    return new MenubarValue( *this );
110
0
}
111
112
MenupopupValue::~MenupopupValue()
113
{
114
}
115
116
MenupopupValue* MenupopupValue::clone() const
117
0
{
118
0
    assert( typeid( const MenupopupValue ) == typeid( *this ));
119
0
    return new MenupopupValue( *this );
120
0
}
121
122
PushButtonValue::~PushButtonValue()
123
{
124
}
125
126
PushButtonValue* PushButtonValue::clone() const
127
0
{
128
0
    assert( typeid( const PushButtonValue ) == typeid( *this ));
129
0
    return new PushButtonValue( *this );
130
0
}
131
132
// These functions are mainly passthrough functions that allow access to
133
// the SalFrame behind a Window object for native widget rendering purposes.
134
135
bool OutputDevice::IsNativeControlSupported( ControlType nType, ControlPart nPart ) const
136
59.8k
{
137
59.8k
    if( !CanEnableNativeWidget() )
138
0
        return false;
139
140
59.8k
    if ( !mpGraphics && !AcquireGraphics() )
141
0
        return false;
142
59.8k
    assert(mpGraphics);
143
144
59.8k
    return mpGraphics->IsNativeControlSupported(nType, nPart);
145
59.8k
}
146
147
bool OutputDevice::HitTestNativeScrollbar(
148
                              ControlPart nPart,
149
                              const tools::Rectangle& rControlRegion,
150
                              const Point& aPos,
151
                              bool& rIsInside ) const
152
0
{
153
0
    if( !CanEnableNativeWidget() )
154
0
        return false;
155
156
0
    if ( !mpGraphics && !AcquireGraphics() )
157
0
        return false;
158
0
    assert(mpGraphics);
159
160
0
    Point aWinOffs( GetDeviceOriginX(), mnOutOffY );
161
0
    tools::Rectangle screenRegion( rControlRegion );
162
0
    screenRegion.Move( aWinOffs.X(), aWinOffs.Y());
163
164
0
    return mpGraphics->HitTestNativeScrollbar( nPart, screenRegion, Point( aPos.X() + GetDeviceOriginX(), aPos.Y() + mnOutOffY ),
165
0
        rIsInside, *this );
166
0
}
167
168
static std::unique_ptr< ImplControlValue > TransformControlValue( const ImplControlValue& rVal, const OutputDevice& rDev )
169
0
{
170
0
    std::unique_ptr< ImplControlValue > aResult;
171
0
    switch( rVal.getType() )
172
0
    {
173
0
    case ControlType::Slider:
174
0
        {
175
0
            const SliderValue* pSlVal = static_cast<const SliderValue*>(&rVal);
176
0
            SliderValue* pNew = new SliderValue( *pSlVal );
177
0
            aResult.reset( pNew );
178
0
            pNew->maThumbRect = rDev.LogicToDevicePixel(pSlVal->maThumbRect);
179
0
        }
180
0
        break;
181
0
    case ControlType::Scrollbar:
182
0
        {
183
0
            const ScrollbarValue* pScVal = static_cast<const ScrollbarValue*>(&rVal);
184
0
            ScrollbarValue* pNew = new ScrollbarValue( *pScVal );
185
0
            aResult.reset( pNew );
186
0
            pNew->maThumbRect = rDev.LogicToDevicePixel(pScVal->maThumbRect);
187
0
            pNew->maButton1Rect = rDev.LogicToDevicePixel(pScVal->maButton1Rect);
188
0
            pNew->maButton2Rect = rDev.LogicToDevicePixel(pScVal->maButton2Rect);
189
0
        }
190
0
        break;
191
0
    case ControlType::SpinButtons:
192
0
        {
193
0
            const SpinbuttonValue* pSpVal = static_cast<const SpinbuttonValue*>(&rVal);
194
0
            SpinbuttonValue* pNew = new SpinbuttonValue( *pSpVal );
195
0
            aResult.reset( pNew );
196
0
            pNew->maUpperRect = rDev.LogicToDevicePixel(pSpVal->maUpperRect);
197
0
            pNew->maLowerRect = rDev.LogicToDevicePixel(pSpVal->maLowerRect);
198
0
        }
199
0
        break;
200
0
    case ControlType::Toolbar:
201
0
        {
202
0
            const ToolbarValue* pTVal = static_cast<const ToolbarValue*>(&rVal);
203
0
            ToolbarValue* pNew = new ToolbarValue( *pTVal );
204
0
            aResult.reset( pNew );
205
0
            pNew->maGripRect = rDev.LogicToDevicePixel(pTVal->maGripRect);
206
0
        }
207
0
        break;
208
0
    case ControlType::TabPane:
209
0
        {
210
0
            const TabPaneValue* pTIVal = static_cast<const TabPaneValue*>(&rVal);
211
0
            TabPaneValue* pNew = new TabPaneValue(*pTIVal);
212
0
            pNew->m_aTabHeaderRect = rDev.LogicToDevicePixel(pTIVal->m_aTabHeaderRect);
213
0
            pNew->m_aSelectedTabRect = rDev.LogicToDevicePixel(pTIVal->m_aSelectedTabRect);
214
0
            aResult.reset(pNew);
215
0
        }
216
0
        break;
217
0
    case ControlType::TabItem:
218
0
        {
219
0
            const TabitemValue* pTIVal = static_cast<const TabitemValue*>(&rVal);
220
0
            TabitemValue* pNew = new TabitemValue( *pTIVal );
221
0
            pNew->maContentRect = rDev.LogicToDevicePixel(pTIVal->maContentRect);
222
0
            aResult.reset( pNew );
223
0
        }
224
0
        break;
225
0
    case ControlType::Menubar:
226
0
        {
227
0
            const MenubarValue* pMVal = static_cast<const MenubarValue*>(&rVal);
228
0
            MenubarValue* pNew = new MenubarValue( *pMVal );
229
0
            aResult.reset( pNew );
230
0
        }
231
0
        break;
232
0
    case ControlType::Pushbutton:
233
0
        {
234
0
            const PushButtonValue* pBVal = static_cast<const PushButtonValue*>(&rVal);
235
0
            PushButtonValue* pNew = new PushButtonValue( *pBVal );
236
0
            aResult.reset( pNew );
237
0
        }
238
0
        break;
239
0
    case ControlType::Generic:
240
0
            aResult = std::make_unique<ImplControlValue>( rVal );
241
0
            break;
242
0
    case ControlType::MenuPopup:
243
0
        {
244
0
            const MenupopupValue* pMVal = static_cast<const MenupopupValue*>(&rVal);
245
0
            MenupopupValue* pNew = new MenupopupValue( *pMVal );
246
0
            pNew->maItemRect = rDev.LogicToDevicePixel(pMVal->maItemRect);
247
0
            aResult.reset( pNew );
248
0
        }
249
0
        break;
250
0
    default:
251
0
        std::abort();
252
0
        break;
253
0
    }
254
0
    return aResult;
255
0
}
256
bool OutputDevice::DrawNativeControl( ControlType nType,
257
                            ControlPart nPart,
258
                            const tools::Rectangle& rControlRegion,
259
                            ControlState nState,
260
                            const ImplControlValue& aValue,
261
                            const OUString& aCaption,
262
                            const Color& rBackgroundColor )
263
0
{
264
0
    assert(!is_double_buffered_window());
265
266
0
    if( !CanEnableNativeWidget() )
267
0
        return false;
268
269
    // make sure the current clip region is initialized correctly
270
0
    if ( !mpGraphics && !AcquireGraphics() )
271
0
        return false;
272
0
    assert(mpGraphics);
273
274
0
    if ( mbInitClipRegion )
275
0
        InitClipRegion();
276
0
    if ( mbOutputClipped )
277
0
        return true;
278
279
0
    if ( mbInitLineColor )
280
0
        InitLineColor();
281
0
    if ( mbInitFillColor )
282
0
        InitFillColor();
283
284
    // Convert the coordinates from relative to Window-absolute, so we draw
285
    // in the correct place in platform code
286
0
    std::unique_ptr< ImplControlValue > aScreenCtrlValue( TransformControlValue( aValue, *this ) );
287
0
    tools::Rectangle screenRegion(LogicToDevicePixel(rControlRegion));
288
289
0
    bool bRet = mpGraphics->DrawNativeControl(nType, nPart, screenRegion, nState, *aScreenCtrlValue, aCaption, *this, rBackgroundColor);
290
291
0
    return bRet;
292
0
}
293
294
bool OutputDevice::GetNativeControlRegion(  ControlType nType,
295
                                ControlPart nPart,
296
                                const tools::Rectangle& rControlRegion,
297
                                ControlState nState,
298
                                const ImplControlValue& aValue,
299
                                tools::Rectangle &rNativeBoundingRegion,
300
                                tools::Rectangle &rNativeContentRegion ) const
301
0
{
302
0
    if( !CanEnableNativeWidget() )
303
0
        return false;
304
305
0
    if ( !mpGraphics && !AcquireGraphics() )
306
0
        return false;
307
0
    assert(mpGraphics);
308
309
    // Convert the coordinates from relative to Window-absolute, so we draw
310
    // in the correct place in platform code
311
0
    std::unique_ptr< ImplControlValue > aScreenCtrlValue( TransformControlValue( aValue, *this ) );
312
0
    tools::Rectangle screenRegion(LogicToDevicePixel(rControlRegion));
313
314
0
    bool bRet = mpGraphics->GetNativeControlRegion(nType, nPart, screenRegion, nState, *aScreenCtrlValue,
315
0
                                rNativeBoundingRegion,
316
0
                                rNativeContentRegion, *this );
317
0
    if( bRet )
318
0
    {
319
        // transform back native regions
320
0
        rNativeBoundingRegion = ImplDevicePixelToLogic( rNativeBoundingRegion );
321
0
        rNativeContentRegion = ImplDevicePixelToLogic( rNativeContentRegion );
322
0
    }
323
324
0
    return bRet;
325
0
}
326
327
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */