Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/uno/popupwindowcontroller.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 <cppuhelper/supportsservice.hxx>
21
#include <toolkit/helper/vclunohelper.hxx>
22
23
#include <vcl/svapp.hxx>
24
#include <vcl/toolbox.hxx>
25
26
#include <svtools/popupwindowcontroller.hxx>
27
#include <svtools/toolbarmenu.hxx>
28
29
using namespace ::com::sun::star;
30
using namespace css::uno;
31
using namespace css::lang;
32
33
34
namespace svt
35
{
36
37
class PopupWindowControllerImpl
38
{
39
public:
40
    PopupWindowControllerImpl();
41
    ~PopupWindowControllerImpl() COVERITY_NOEXCEPT_FALSE;
42
43
    void SetPopupWindow( vcl::Window* pPopupWindow, ToolBox* pToolBox );
44
    void SetFloatingWindow();
45
    DECL_LINK( WindowEventListener, VclWindowEvent&, void );
46
47
private:
48
    VclPtr<vcl::Window> mpPopupWindow, mpFloatingWindow;
49
    VclPtr<ToolBox>     mpToolBox;
50
};
51
52
PopupWindowControllerImpl::PopupWindowControllerImpl()
53
0
{
54
0
}
55
56
PopupWindowControllerImpl::~PopupWindowControllerImpl() COVERITY_NOEXCEPT_FALSE
57
0
{
58
0
    SetPopupWindow(nullptr,nullptr);
59
0
    SetFloatingWindow();
60
0
}
61
62
void PopupWindowControllerImpl::SetPopupWindow( vcl::Window* pPopupWindow, ToolBox* pToolBox )
63
0
{
64
0
    if( mpPopupWindow )
65
0
    {
66
0
        mpPopupWindow->RemoveEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ) );
67
0
        mpPopupWindow.disposeAndClear();
68
0
    }
69
0
    mpPopupWindow = pPopupWindow;
70
0
    mpToolBox = pToolBox;
71
72
0
    if( mpPopupWindow )
73
0
    {
74
0
        mpPopupWindow->AddEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ));
75
0
    }
76
0
}
77
78
void PopupWindowControllerImpl::SetFloatingWindow()
79
0
{
80
0
    if( mpFloatingWindow )
81
0
    {
82
0
        mpFloatingWindow->RemoveEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ) );
83
0
        mpFloatingWindow.disposeAndClear();
84
0
    }
85
0
    mpFloatingWindow = mpPopupWindow;
86
0
    mpPopupWindow.reset();
87
0
}
88
89
IMPL_LINK( PopupWindowControllerImpl, WindowEventListener, VclWindowEvent&, rWindowEvent, void )
90
0
{
91
0
    switch( rWindowEvent.GetId() )
92
0
    {
93
0
    case VclEventId::WindowEndPopupMode:
94
0
    {
95
0
        EndPopupModeData* pData = static_cast< EndPopupModeData* >( rWindowEvent.GetData() );
96
0
        if( pData && pData->mbTearoff )
97
0
        {
98
0
            vcl::Window::GetDockingManager()->SetFloatingMode( mpPopupWindow.get(), true );
99
0
            vcl::Window::GetDockingManager()->SetPosSizePixel( mpPopupWindow.get(),
100
0
                                                               pData->maFloatingPos.X(),
101
0
                                                               pData->maFloatingPos.Y(),
102
0
                                                               0, 0,
103
0
                                                               PosSizeFlags::Pos );
104
0
            SetFloatingWindow();
105
0
            mpFloatingWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
106
0
        }
107
0
        SetPopupWindow(nullptr,nullptr);
108
0
        break;
109
0
    }
110
0
    case VclEventId::WindowPrepareToggleFloating:
111
0
    {
112
0
        if ( mpFloatingWindow && rWindowEvent.GetWindow() == mpFloatingWindow.get() )
113
0
        {
114
0
            bool* pData = static_cast< bool* >( rWindowEvent.GetData() );
115
0
            *pData = false;
116
0
        }
117
0
        break;
118
0
    }
119
0
    case VclEventId::WindowClose:
120
0
    {
121
0
        SetPopupWindow(nullptr,nullptr);
122
0
        SetFloatingWindow();
123
0
        break;
124
0
    }
125
0
    case VclEventId::WindowShow:
126
0
    {
127
0
        if( mpPopupWindow )
128
0
        {
129
0
            if( mpToolBox )
130
0
                mpToolBox->CallEventListeners( VclEventId::DropdownOpen, static_cast<void*>(mpPopupWindow) );
131
0
            mpPopupWindow->CallEventListeners( VclEventId::WindowGetFocus );
132
0
            break;
133
0
        }
134
0
        break;
135
0
    }
136
0
    case VclEventId::WindowHide:
137
0
    {
138
0
        if( mpPopupWindow )
139
0
        {
140
0
            mpPopupWindow->CallEventListeners( VclEventId::WindowLoseFocus );
141
0
            if( mpToolBox )
142
0
                mpToolBox->CallEventListeners( VclEventId::DropdownClose, static_cast<void*>(mpPopupWindow) );
143
0
        }
144
0
        break;
145
0
    }
146
0
    default: break;
147
0
    }
148
0
}
149
150
151
152
153
PopupWindowController::PopupWindowController( const Reference< uno::XComponentContext >& rxContext,
154
                                              const Reference< frame::XFrame >& xFrame,
155
                                              const OUString& aCommandURL )
156
0
: PopupWindowController_Base( rxContext, xFrame, aCommandURL )
157
0
, mxImpl( new PopupWindowControllerImpl() )
158
0
{
159
0
}
160
161
PopupWindowController::~PopupWindowController()
162
0
{
163
0
}
164
165
// XServiceInfo
166
sal_Bool SAL_CALL PopupWindowController::supportsService( const OUString& ServiceName )
167
0
{
168
0
    return cppu::supportsService(this, ServiceName);
169
0
}
170
171
// XComponent
172
void SAL_CALL PopupWindowController::dispose()
173
0
{
174
0
    mxInterimPopover.reset();
175
0
    mxPopoverContainer.reset();
176
0
    mxImpl.reset();
177
0
    svt::ToolboxController::dispose();
178
0
}
179
180
// XStatusListener
181
void SAL_CALL PopupWindowController::statusChanged( const frame::FeatureStateEvent& rEvent )
182
0
{
183
0
    SolarMutexGuard aSolarLock;
184
185
0
    bool bValue = false;
186
0
    rEvent.State >>= bValue;
187
188
0
    if (m_pToolbar)
189
0
    {
190
0
        m_pToolbar->set_item_active(m_aCommandURL, bValue);
191
0
        m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled);
192
0
        return;
193
0
    }
194
195
0
    ToolBox* pToolBox = nullptr;
196
0
    ToolBoxItemId nItemId;
197
0
    if ( getToolboxId( nItemId, &pToolBox ) )
198
0
    {
199
0
        pToolBox->CheckItem( nItemId, bValue );
200
0
        pToolBox->EnableItem( nItemId, rEvent.IsEnabled );
201
0
    }
202
0
}
203
204
VclPtr<vcl::Window> PopupWindowController::createVclPopupWindow(vcl::Window* /*pParent*/)
205
0
{
206
0
    return nullptr;
207
0
}
208
209
Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow()
210
0
{
211
0
    if (m_pToolbar)
212
0
    {
213
0
        mxPopoverContainer->unsetPopover();
214
0
        mxPopoverContainer->setPopover(weldPopupWindow());
215
216
        // tdf#141577 setPopover might GrabFocus, which may cause the ActiveFrame to be
217
        // unset. So explicitly set this frame as the active frame of its parent when
218
        // this popup is created.
219
0
        if (uno::Reference<frame::XFrame> xFrame = getFrameInterface())
220
0
        {
221
0
            if (uno::Reference<frame::XFramesSupplier> xParentFrame = xFrame->getCreator())
222
0
                xParentFrame->setActiveFrame(xFrame);
223
0
        }
224
225
0
        return Reference<awt::XWindow>();
226
0
    }
227
228
0
    VclPtr< ToolBox > pToolBox = dynamic_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) );
229
0
    if( pToolBox )
230
0
    {
231
0
        vcl::Window* pItemWindow = pToolBox->GetItemWindow( pToolBox->GetDownItemId() );
232
0
        VclPtr<vcl::Window> pWin = createVclPopupWindow( pItemWindow ? pItemWindow : pToolBox );
233
0
        if( pWin )
234
0
        {
235
0
            FloatWinPopupFlags eFloatFlags = FloatWinPopupFlags::GrabFocus |
236
0
                                             FloatWinPopupFlags::AllMouseButtonClose |
237
0
                                             FloatWinPopupFlags::NoMouseUpClose;
238
239
0
            WinBits nWinBits;
240
0
            if ( pWin->GetType() == WindowType::DOCKINGWINDOW )
241
0
                nWinBits = static_cast< DockingWindow* >( pWin.get() )->GetFloatStyle();
242
0
            else
243
0
                nWinBits = pWin->GetStyle();
244
245
0
            if ( nWinBits & ( WB_SIZEABLE | WB_CLOSEABLE ) )
246
0
                eFloatFlags |= FloatWinPopupFlags::AllowTearOff;
247
248
0
            pWin->EnableDocking();
249
0
            mxImpl->SetPopupWindow(pWin,pToolBox);
250
0
            vcl::Window::GetDockingManager()->StartPopupMode( pToolBox, pWin, eFloatFlags );
251
0
            return VCLUnoHelper::GetInterface(pWin.get());
252
0
        }
253
0
    }
254
0
    return Reference< awt::XWindow >();
255
0
}
256
257
void SAL_CALL PopupWindowController::click()
258
0
{
259
0
    if (m_pToolbar)
260
0
    {
261
0
        if (m_pToolbar->get_menu_item_active(m_aCommandURL))
262
0
            createPopupWindow();
263
0
        else
264
0
            mxPopoverContainer->unsetPopover();
265
0
    }
266
267
0
    svt::ToolboxController::click();
268
0
}
269
270
void PopupWindowController::EndPopupMode()
271
0
{
272
0
    if (m_pToolbar)
273
0
        m_pToolbar->set_menu_item_active(m_aCommandURL, false);
274
0
    else if (mxInterimPopover)
275
0
        mxInterimPopover->EndPopupMode();
276
0
}
277
278
}
279
280
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */