Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/toolkit/source/helper/unowrapper.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 <toolkit/helper/vclunohelper.hxx>
21
#include <toolkit/awt/vclxwindow.hxx>
22
#include <toolkit/awt/vclxwindows.hxx>
23
#include <toolkit/awt/vclxmenu.hxx>
24
#include <awt/vclxcontainer.hxx>
25
#include <awt/vclxgraphics.hxx>
26
#include <awt/vclxtopwindow.hxx>
27
#include <awt/vclxwindows.hxx>
28
29
#include <toolkit/dllapi.h>
30
#include <vcl/menu.hxx>
31
32
#include <helper/unowrapper.hxx>
33
34
using namespace ::com::sun::star;
35
36
static rtl::Reference<VCLXWindow> CreateXWindow( vcl::Window const * pWindow )
37
58.3k
{
38
58.3k
    switch ( pWindow->GetType() )
39
58.3k
    {
40
0
        case WindowType::IMAGEBUTTON:
41
0
        case WindowType::SPINBUTTON:
42
0
        case WindowType::MENUBUTTON:
43
0
        case WindowType::MOREBUTTON:
44
0
        case WindowType::PUSHBUTTON:
45
0
        case WindowType::HELPBUTTON:
46
0
        case WindowType::OKBUTTON:
47
0
        case WindowType::CANCELBUTTON:   return new VCLXButton;
48
0
        case WindowType::CHECKBOX:       return new VCLXCheckBox;
49
        // #i95042#
50
        // A Window of type <MetricBox> is inherited from type <ComboBox>.
51
        // Thus, it does make more sense to return a <VCLXComboBox> instance
52
        // instead of only a <VCLXWindow> instance, especially regarding its
53
        // corresponding accessibility API.
54
0
        case WindowType::METRICBOX:
55
0
        case WindowType::COMBOBOX:       return new VCLXComboBox;
56
0
        case WindowType::FORMATTEDFIELD: return new SVTXNumericField;
57
0
        case WindowType::SPINFIELD:
58
0
        case WindowType::CURRENCYFIELD:  return new VCLXNumericField;
59
0
        case WindowType::DATEFIELD:      return new VCLXDateField;
60
0
        case WindowType::MULTILINEEDIT:
61
0
        case WindowType::EDIT:           return new VCLXEdit;
62
0
        case WindowType::METRICFIELD:    return new VCLXSpinField;
63
0
        case WindowType::MESSBOX:
64
0
        case WindowType::INFOBOX:
65
0
        case WindowType::WARNINGBOX:
66
0
        case WindowType::QUERYBOX:
67
0
        case WindowType::ERRORBOX:       return new VCLXMessageBox;
68
0
        case WindowType::FIXEDIMAGE:     return new VCLXImageControl;
69
0
        case WindowType::FIXEDTEXT:      return new VCLXFixedText;
70
0
        case WindowType::MULTILISTBOX:
71
0
        case WindowType::LISTBOX:        return new VCLXListBox;
72
0
        case WindowType::DIALOG:
73
0
        case WindowType::TABDIALOG:
74
0
        case WindowType::BUTTONDIALOG:
75
0
        case WindowType::MODELESSDIALOG: return new VCLXDialog;
76
0
        case WindowType::PATTERNFIELD:   return new VCLXPatternField;
77
0
        case WindowType::RADIOBUTTON:    return new VCLXRadioButton;
78
0
        case WindowType::SCROLLBAR:      return new VCLXScrollBar;
79
0
        case WindowType::TIMEFIELD:      return new VCLXTimeField;
80
81
30
        case WindowType::WORKWINDOW:
82
30
        case WindowType::DOCKINGWINDOW:
83
30
        case WindowType::FLOATINGWINDOW:
84
30
        case WindowType::HELPTEXTWINDOW: return new VCLXTopWindow;
85
86
3.68k
        case WindowType::WINDOW:
87
3.68k
        case WindowType::TABPAGE:        return new VCLXContainer;
88
0
        case WindowType::TABCONTROL:     return new VCLXMultiPage;
89
90
3.70k
        case WindowType::BORDERWINDOW:
91
3.70k
        {
92
3.70k
            if (pWindow->IsNativeFrame())
93
3.67k
                return new VCLXTopWindow;
94
30
            return new VCLXWindow(true);
95
3.70k
        }
96
97
        // case WindowType::FIXEDLINE:
98
        // case WindowType::FIXEDBITMAP:
99
        // case WindowType::DATEBOX:
100
        // case WindowType::GROUPBOX:
101
        // case WindowType::LONGCURRENCYBOX:
102
        // case WindowType::SPLITTER:
103
        // case WindowType::STATUSBAR:
104
        // case WindowType::TABCONTROL:
105
        // case WindowType::NUMERICBOX:
106
        // case WindowType::TRISTATEBOX:
107
        // case WindowType::TIMEBOX:
108
        // case WindowType::SPLITWINDOW:
109
        // case WindowType::SCROLLBARBOX:
110
        // case WindowType::PATTERNBOX:
111
        // case WindowType::CURRENCYBOX:
112
0
        case WindowType::HEADERBAR:
113
0
        case WindowType::TOOLBOX:
114
50.9k
        default:                    return new VCLXWindow( true );
115
58.3k
    }
116
58.3k
}
117
118
119
120
121
extern "C" {
122
123
TOOLKIT_DLLPUBLIC UnoWrapperBase* CreateUnoWrapper()
124
30
{
125
30
    return new UnoWrapper( nullptr );
126
30
}
127
128
}   // extern "C"
129
130
131
UnoWrapper::UnoWrapper( const css::uno::Reference< css::awt::XToolkit>& rxToolkit )
132
30
{
133
30
    mxToolkit = rxToolkit;
134
30
}
135
136
void UnoWrapper::Destroy()
137
0
{
138
0
    delete this;
139
0
}
140
141
UnoWrapper::~UnoWrapper()
142
0
{
143
0
}
144
145
css::uno::Reference< css::awt::XToolkit> UnoWrapper::GetVCLToolkit()
146
0
{
147
0
    if ( !mxToolkit.is() )
148
0
        mxToolkit = VCLUnoHelper::CreateToolkit();
149
0
    return mxToolkit;
150
0
}
151
152
css::uno::Reference< css::awt::XVclWindowPeer> UnoWrapper::GetWindowInterface( vcl::Window* pWindow )
153
58.3k
{
154
58.3k
    css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer();
155
58.3k
    if ( xPeer )
156
0
        return xPeer;
157
158
58.3k
    rtl::Reference<VCLXWindow> xVCLXWindow = CreateXWindow( pWindow );
159
58.3k
    xVCLXWindow->SetWindow( pWindow );
160
58.3k
    pWindow->SetWindowPeer( xVCLXWindow, xVCLXWindow.get() );
161
58.3k
    return xVCLXWindow;
162
58.3k
}
163
164
VclPtr<vcl::Window> UnoWrapper::GetWindow(const css::uno::Reference<css::awt::XWindow>& rWindow)
165
0
{
166
0
    return VCLUnoHelper::GetWindow(rWindow);
167
0
}
168
169
void UnoWrapper::SetWindowInterface( vcl::Window* pWindow, const css::uno::Reference< css::awt::XVclWindowPeer> & xIFace )
170
44.0k
{
171
44.0k
    VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( xIFace.get() );
172
173
44.0k
    assert( pVCLXWindow && "must be a VCLXWindow subclass" );
174
44.0k
    if ( !pVCLXWindow )
175
0
        return;
176
177
44.0k
    if (!pWindow)
178
36.7k
    {
179
        // we are disconnecting a peer from a window
180
36.7k
        pVCLXWindow->SetWindow( nullptr );
181
36.7k
    }
182
7.24k
    else
183
7.24k
    {
184
7.24k
        css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer();
185
7.24k
        if( xPeer.is() )
186
0
        {
187
0
            bool bSameInstance( pVCLXWindow == dynamic_cast< VCLXWindow* >( xPeer.get() ));
188
0
            SAL_WARN_IF( !bSameInstance, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" );
189
0
            if ( bSameInstance )
190
0
                return;
191
0
        }
192
7.24k
        pVCLXWindow->SetWindow( pWindow );
193
7.24k
        pWindow->SetWindowPeer( xIFace, pVCLXWindow );
194
7.24k
    }
195
44.0k
}
196
197
css::uno::Reference<css::awt::XPopupMenu> UnoWrapper::CreateMenuInterface( PopupMenu* pPopupMenu )
198
0
{
199
0
    return new VCLXPopupMenu(pPopupMenu);
200
0
}
201
202
css::uno::Reference< css::awt::XGraphics> UnoWrapper::CreateGraphics( OutputDevice* pOutDev )
203
0
{
204
0
    rtl::Reference<VCLXGraphics> pGrf = new VCLXGraphics;
205
0
    pGrf->Init( pOutDev );
206
0
    return pGrf;
207
0
}
208
209
void UnoWrapper::ReleaseAllGraphics( OutputDevice* pOutDev )
210
0
{
211
0
    std::vector< VCLXGraphics* > *pLst = pOutDev->GetUnoGraphicsList();
212
0
    if ( pLst )
213
0
    {
214
0
        for (VCLXGraphics* pGrf : *pLst)
215
0
        {
216
0
            pGrf->SetOutputDevice( nullptr );
217
0
        }
218
0
    }
219
220
0
}
221
222
static bool lcl_ImplIsParent( vcl::Window const * pParentWindow, vcl::Window* pPossibleChild )
223
0
{
224
0
    vcl::Window* pWindow = ( pPossibleChild != pParentWindow ) ? pPossibleChild : nullptr;
225
0
    while ( pWindow && ( pWindow != pParentWindow ) )
226
0
        pWindow = pWindow->GetParent();
227
228
0
    return pWindow != nullptr;
229
0
}
230
231
void UnoWrapper::WindowDestroyed( vcl::Window* pWindow )
232
91.9k
{
233
    // their still might be some children created with css::loader::Java
234
    // that would otherwise not be destroyed until the garbage collector cleans up
235
91.9k
    VclPtr< vcl::Window > pChild = pWindow->GetWindow( GetWindowType::FirstChild );
236
121k
    while ( pChild )
237
29.4k
    {
238
29.4k
        VclPtr< vcl::Window > pNextChild = pChild->GetWindow( GetWindowType::Next );
239
240
29.4k
        VclPtr< vcl::Window > pClient = pChild->GetWindow( GetWindowType::Client );
241
29.4k
        if ( pClient && pClient->GetWindowPeer() )
242
29.4k
        {
243
29.4k
            css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false );
244
29.4k
            xComp->dispose();
245
29.4k
        }
246
0
        else
247
0
        {
248
            // We need it to dispose the child windows properly (even without window peer),
249
            // otherwise the vcl::Window will be leaked.
250
0
            pClient.disposeAndClear();
251
0
        }
252
253
29.4k
        pChild = std::move(pNextChild);
254
29.4k
    }
255
256
    // find system windows...
257
91.9k
    VclPtr< vcl::Window > pOverlap = pWindow->GetWindow( GetWindowType::Overlap );
258
91.9k
    if ( pOverlap )
259
91.9k
    {
260
91.9k
        pOverlap = pOverlap->GetWindow( GetWindowType::FirstOverlap );
261
91.9k
        while ( pOverlap )
262
0
        {
263
0
            VclPtr< vcl::Window > pNextOverlap = pOverlap->GetWindow( GetWindowType::Next );
264
0
            VclPtr< vcl::Window > pClient = pOverlap->GetWindow( GetWindowType::Client );
265
266
0
            if ( pClient && pClient->GetWindowPeer() && lcl_ImplIsParent( pWindow, pClient ) )
267
0
            {
268
0
                css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false );
269
0
                xComp->dispose();
270
0
            }
271
272
0
            pOverlap = std::move(pNextOverlap);
273
0
        }
274
91.9k
    }
275
276
91.9k
    {
277
91.9k
        VclPtr< vcl::Window > pParent = pWindow->GetParent();
278
91.9k
        if ( pParent && pParent->GetWindowPeer() )
279
47.8k
            pParent->GetWindowPeer()->notifyWindowRemoved( *pWindow );
280
91.9k
    }
281
282
91.9k
    VCLXWindow* pWindowPeer = pWindow->GetWindowPeer();
283
91.9k
    uno::Reference< lang::XComponent > xWindowPeerComp = pWindow->GetComponentInterface( false );
284
91.9k
    OSL_ENSURE( ( pWindowPeer != nullptr ) == xWindowPeerComp.is(),
285
91.9k
        "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" );
286
91.9k
    if ( pWindowPeer )
287
7.36k
    {
288
7.36k
        pWindowPeer->SetWindow( nullptr );
289
7.36k
        pWindow->SetWindowPeer( nullptr, nullptr );
290
7.36k
    }
291
91.9k
    if ( xWindowPeerComp.is() )
292
7.36k
        xWindowPeerComp->dispose();
293
294
    // #102132# Iterate over frames after setting Window peer to NULL,
295
    // because while destroying other frames, we get into the method again and try
296
    // to destroy this window again...
297
    // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children
298
    // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme
299
    // performance penalties)
300
91.9k
    VclPtr< vcl::Window > pTopWindowChild = pWindow->GetWindow( GetWindowType::FirstTopWindowChild );
301
91.9k
    while ( pTopWindowChild )
302
0
    {
303
0
        OSL_ENSURE( pTopWindowChild->GetParent() == pWindow,
304
0
                    "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" );
305
306
0
        VclPtr< vcl::Window > pNextTopChild = pTopWindowChild->GetWindow( GetWindowType::NextTopWindowSibling );
307
308
0
        pTopWindowChild.disposeAndClear();
309
0
        pTopWindowChild = std::move(pNextTopChild);
310
0
    }
311
91.9k
}
312
313
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */