Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/control/InterimItemWindow.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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
10
#include <vcl/InterimItemWindow.hxx>
11
#include <vcl/layout.hxx>
12
#include <vcl/rendercontext/SystemTextColorFlags.hxx>
13
#include <vcl/weld/Builder.hxx>
14
#include <vcl/weld/Container.hxx>
15
16
#include <salobj.hxx>
17
#include <svdata.hxx>
18
#include <window.h>
19
20
InterimItemWindow::InterimItemWindow(vcl::Window* pParent, const OUString& rUIXMLDescription,
21
                                     const OUString& rID, bool bAllowCycleFocusOut)
22
0
    : Control(pParent, WB_TABSTOP)
23
0
    , m_pWidget(nullptr) // inheritors are expected to call InitControlBase
24
0
    , m_aLayoutIdle("InterimItemWindow m_aLayoutIdle")
25
0
{
26
0
    m_aLayoutIdle.SetPriority(TaskPriority::RESIZE);
27
0
    m_aLayoutIdle.SetInvokeHandler(LINK(this, InterimItemWindow, DoLayout));
28
29
0
    m_xVclContentArea = VclPtr<VclVBox>::Create(this);
30
0
    m_xVclContentArea->Show();
31
0
    m_xBuilder = Application::CreateInterimBuilder(m_xVclContentArea, rUIXMLDescription,
32
0
                                                   bAllowCycleFocusOut);
33
0
    m_xContainer = m_xBuilder->weld_container(rID);
34
35
0
    SetBackground();
36
0
    SetPaintTransparent(true);
37
0
}
Unexecuted instantiation: InterimItemWindow::InterimItemWindow(vcl::Window*, rtl::OUString const&, rtl::OUString const&, bool)
Unexecuted instantiation: InterimItemWindow::InterimItemWindow(vcl::Window*, rtl::OUString const&, rtl::OUString const&, bool)
38
39
void InterimItemWindow::StateChanged(StateChangedType nStateChange)
40
0
{
41
0
    if (nStateChange == StateChangedType::Enable)
42
0
        m_xContainer->set_sensitive(IsEnabled());
43
0
    Control::StateChanged(nStateChange);
44
0
}
45
46
0
InterimItemWindow::~InterimItemWindow() { disposeOnce(); }
47
48
void InterimItemWindow::dispose()
49
0
{
50
0
    m_pWidget = nullptr;
51
52
0
    m_xContainer.reset();
53
0
    m_xBuilder.reset();
54
0
    m_xVclContentArea.disposeAndClear();
55
56
0
    m_aLayoutIdle.Stop();
57
58
0
    Control::dispose();
59
0
}
60
61
void InterimItemWindow::StartIdleLayout()
62
0
{
63
0
    if (!m_xVclContentArea)
64
0
        return;
65
0
    if (m_aLayoutIdle.IsActive())
66
0
        return;
67
0
    m_aLayoutIdle.Start();
68
0
}
69
70
void InterimItemWindow::queue_resize(StateChangedType eReason)
71
0
{
72
0
    Control::queue_resize(eReason);
73
0
    StartIdleLayout();
74
0
}
75
76
0
void InterimItemWindow::Resize() { Layout(); }
77
78
void InterimItemWindow::UnclipVisibleSysObj()
79
0
{
80
0
    if (!IsVisible())
81
0
        return;
82
0
    vcl::Window* pChild = m_xVclContentArea->GetWindow(GetWindowType::FirstChild);
83
0
    if (!pChild)
84
0
        return;
85
0
    WindowImpl* pWindowImpl = pChild->ImplGetWindowImpl();
86
0
    if (!pWindowImpl)
87
0
        return;
88
0
    if (!pWindowImpl->mpSysObj)
89
0
        return;
90
0
    pWindowImpl->mpSysObj->Show(true);
91
0
    pWindowImpl->mpSysObj->ResetClipRegion();
92
    // flag that sysobj clip is dirty and needs to be recalculated on next use
93
0
    pWindowImpl->mbInitWinClipRegion = true;
94
0
}
95
96
0
IMPL_LINK_NOARG(InterimItemWindow, DoLayout, Timer*, void) { Layout(); }
97
98
void InterimItemWindow::Layout()
99
0
{
100
0
    m_aLayoutIdle.Stop();
101
0
    vcl::Window* pChild = GetWindow(GetWindowType::FirstChild);
102
0
    assert(pChild);
103
0
    VclContainer::setLayoutAllocation(*pChild, Point(0, 0), GetSizePixel());
104
0
    Control::Resize();
105
0
}
106
107
Size InterimItemWindow::GetOptimalSize() const
108
0
{
109
0
    return VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
110
0
}
111
112
void InterimItemWindow::InvalidateChildSizeCache()
113
0
{
114
    // find the bottom vcl::Window of the hierarchy and queue_resize on that
115
    // one will invalidate all the size caches upwards
116
0
    vcl::Window* pChild = GetWindow(GetWindowType::FirstChild);
117
0
    while (true)
118
0
    {
119
0
        vcl::Window* pSubChild = pChild->GetWindow(GetWindowType::FirstChild);
120
0
        if (!pSubChild)
121
0
            break;
122
0
        pChild = pSubChild;
123
0
    }
124
0
    pChild->queue_resize();
125
0
}
126
127
bool InterimItemWindow::ControlHasFocus() const
128
0
{
129
0
    if (!m_pWidget)
130
0
        return false;
131
0
    return m_pWidget->has_focus();
132
0
}
133
134
0
void InterimItemWindow::InitControlBase(weld::Widget* pWidget) { m_pWidget = pWidget; }
135
136
void InterimItemWindow::GetFocus()
137
0
{
138
    // tdf#157738 Don't grab focus to the other widget hierarchy if the parent has
139
    // captured the mouse in order to avoid breaking the capture.
140
0
    ImplSVWinData* pWinData = ImplGetSVData()->mpWinData;
141
0
    const bool bParentHasCapturedMouse
142
0
        = pWinData->mpCaptureWin && pWinData->mpCaptureWin->ImplIsChild(this);
143
0
    if (m_pWidget && !bParentHasCapturedMouse)
144
0
        m_pWidget->grab_focus();
145
146
    /* let toolbox know this item window has focus so it updates its mnHighItemId to point
147
       to this toolitem in case tab means to move to another toolitem within
148
       the toolbox
149
    */
150
0
    vcl::Window* pToolBox = GetParent();
151
0
    NotifyEvent aNEvt(NotifyEventType::GETFOCUS, this);
152
0
    pToolBox->EventNotify(aNEvt);
153
0
}
154
155
bool InterimItemWindow::ChildKeyInput(const KeyEvent& rKEvt)
156
0
{
157
0
    sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
158
0
    if (nCode != KEY_TAB)
159
0
        return false;
160
161
    /* if the native widget has focus, then no vcl window has focus.
162
163
       We want to grab focus to this vcl widget so that pressing tab will traverse
164
       to the next vcl widget.
165
166
       But just using GrabFocus will, because no vcl widget has focus, trigger
167
       bringing the toplevel to front with the expectation that a suitable widget
168
       will be picked for focus when that happen, which is no use to us here.
169
170
       SetFakeFocus avoids the problem, allowing GrabFocus to do the expected thing
171
       then sending the Tab to our parent will do the right traversal
172
    */
173
0
    SetFakeFocus(true);
174
0
    GrabFocus();
175
176
    /* now give focus to our toolbox parent */
177
0
    vcl::Window* pToolBox = GetParent();
178
0
    pToolBox->GrabFocus();
179
180
    /* let toolbox know this item window has focus so it updates its mnHighItemId to point
181
       to this toolitem in case tab means to move to another toolitem within
182
       the toolbox
183
    */
184
0
    NotifyEvent aNEvt(NotifyEventType::GETFOCUS, this);
185
0
    pToolBox->EventNotify(aNEvt);
186
187
    /* send parent the tab */
188
0
    pToolBox->KeyInput(rKEvt);
189
190
0
    return true;
191
0
}
192
193
void InterimItemWindow::Draw(OutputDevice& rDevice, const Point& rPos,
194
                             SystemTextColorFlags /*nFlags*/)
195
0
{
196
0
    m_xContainer->draw(rDevice, rPos, GetSizePixel());
197
0
}
198
199
void InterimItemWindow::SetPriority(TaskPriority nPriority)
200
0
{
201
    // Eliminate warning when changing timer's priority
202
    // Task::SetPriority() expects the timer to be stopped while
203
    // changing the timer's priority.
204
0
    bool bActive = m_aLayoutIdle.IsActive();
205
0
    if (bActive)
206
0
        m_aLayoutIdle.Stop();
207
0
    m_aLayoutIdle.SetPriority(nPriority);
208
0
    if (bActive)
209
0
        m_aLayoutIdle.Start();
210
0
}
211
212
void InterimItemWindow::ImplPaintToDevice(OutputDevice& rTargetOutDev, const Point& rPos)
213
0
{
214
0
    Draw(rTargetOutDev, rPos, SystemTextColorFlags::NONE);
215
0
}
216
217
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */