Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name floatwin.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx

/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx

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 <svdata.hxx>
21#include <brdwin.hxx>
22#include <window.h>
23#include <salframe.hxx>
24#include <helpwin.hxx>
25
26#include <comphelper/lok.hxx>
27#include <sal/log.hxx>
28#include <vcl/layout.hxx>
29#include <vcl/svapp.hxx>
30#include <vcl/wrkwin.hxx>
31#include <vcl/event.hxx>
32#include <vcl/toolbox.hxx>
33#include <vcl/floatwin.hxx>
34#include <vcl/settings.hxx>
35#include <vcl/IDialogRenderable.hxx>
36
37class FloatingWindow::ImplData
38{
39public:
40 ImplData();
41
42 VclPtr<ToolBox> mpBox;
43 tools::Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
44 Point maPos; // position of the floating window wrt. parent
45 Point maLOKTwipsPos; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows).
46};
47
48FloatingWindow::ImplData::ImplData()
49{
50 mpBox = nullptr;
51}
52
53tools::Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
54{
55 return mpImplData->maItemEdgeClipRect;
56}
57
58void FloatingWindow::ImplInitFloating( vcl::Window* pParent, WinBits nStyle )
59{
60 mpImplData.reset(new ImplData);
61
62 mpWindowImpl->mbFloatWin = true;
63 mbInCleanUp = false;
64 mbGrabFocus = false;
65
66 SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!")do { if (true && (!pParent)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "66" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FloatWindow::FloatingWindow(): - pParent == NULL!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "66" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FloatWindow::FloatingWindow(): - pParent == NULL!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "66" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FloatWindow::FloatingWindow(): - pParent == NULL!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "66" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
67
68 if (!pParent)
69 pParent = ImplGetSVData()->maFrameData.mpAppWin;
70
71 SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists")do { if (true && (!pParent)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "71" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "71" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "71" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"),
("/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
":" "71" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
72
73 // no Border, then we don't need a border window
74 if (!nStyle)
75 {
76 mpWindowImpl->mbOverlapWin = true;
77 nStyle |= WB_DIALOGCONTROL;
78 ImplInit(pParent, nStyle, nullptr);
79 }
80 else
81 {
82 if (!(nStyle & WB_NODIALOGCONTROL))
83 nStyle |= WB_DIALOGCONTROL;
84
85 if (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
86 && !(nStyle & WB_OWNERDRAWDECORATION))
87 {
88 WinBits nFloatWinStyle = nStyle;
89 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
90 // nFloatWinStyle |= WB_CLOSEABLE;
91 mpWindowImpl->mbFrame = true;
92 mpWindowImpl->mbOverlapWin = true;
93 ImplInit(pParent, nFloatWinStyle & ~WB_BORDER, nullptr);
94 }
95 else
96 {
97 VclPtr<ImplBorderWindow> pBorderWin;
98 BorderWindowStyle nBorderStyle = BorderWindowStyle::Float;
99
100 if (nStyle & WB_OWNERDRAWDECORATION)
101 nBorderStyle |= BorderWindowStyle::Frame;
102 else
103 nBorderStyle |= BorderWindowStyle::Overlap;
104
105 if ((nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)))
106 {
107 nBorderStyle |= BorderWindowStyle::Frame;
108 nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
109 }
110 pBorderWin = VclPtr<ImplBorderWindow>::Create(pParent, nStyle, nBorderStyle);
111 ImplInit(pBorderWin, nStyle & ~WB_BORDER, nullptr);
112 pBorderWin->mpWindowImpl->mpClientWindow = this;
113 pBorderWin->GetBorder(mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder,
114 mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder);
115 pBorderWin->SetDisplayActive(true);
116 mpWindowImpl->mpBorderWindow = pBorderWin;
117 mpWindowImpl->mpRealParent = pParent;
118 }
119 }
120 SetActivateMode( ActivateModeFlags::NONE );
121
122 mpNextFloat = nullptr;
123 mpFirstPopupModeWin = nullptr;
124 mnPostId = nullptr;
125 mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FloatWinTitleType::Normal : FloatWinTitleType::NONE;
126 mnOldTitle = mnTitle;
127 mnPopupModeFlags = FloatWinPopupFlags::NONE;
128 mbInPopupMode = false;
129 mbPopupMode = false;
130 mbPopupModeCanceled = false;
131 mbPopupModeTearOff = false;
132 mbMouseDown = false;
133
134 ImplInitSettings();
135}
136
137void FloatingWindow::ImplInitSettings()
138{
139 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
140
141 Color aColor;
142 if (IsControlBackground())
143 aColor = GetControlBackground();
144 else if (Window::GetStyle() & WB_3DLOOK)
145 aColor = rStyleSettings.GetFaceColor();
146 else
147 aColor = rStyleSettings.GetWindowColor();
148 SetBackground(aColor);
149}
150
151FloatingWindow::FloatingWindow(vcl::Window* pParent, WinBits nStyle) :
152 SystemWindow(WindowType::FLOATINGWINDOW)
153{
154 ImplInitFloating(pParent, nStyle);
155}
156
157FloatingWindow::FloatingWindow(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame)
158 : SystemWindow(WindowType::FLOATINGWINDOW)
159 , mpNextFloat(nullptr)
160 , mpFirstPopupModeWin(nullptr)
161 , mnPostId(nullptr)
162 , mnPopupModeFlags(FloatWinPopupFlags::NONE)
163 , mnTitle(FloatWinTitleType::Unknown)
164 , mnOldTitle(FloatWinTitleType::Unknown)
165 , mbInPopupMode(false)
166 , mbPopupMode(false)
167 , mbPopupModeCanceled(false)
168 , mbPopupModeTearOff(false)
169 , mbMouseDown(false)
170 , mbGrabFocus(false)
171 , mbInCleanUp(false)
172{
173 loadUI(pParent, rID, rUIXMLDescription, rFrame);
174}
175
176//Find the real parent stashed in mpDialogParent.
177void FloatingWindow::doDeferredInit(WinBits nBits)
178{
179 vcl::Window *pParent = mpDialogParent;
180 mpDialogParent = nullptr;
181 ImplInitFloating(pParent, nBits);
182 mbIsDeferredInit = false;
183}
184
185void FloatingWindow::ApplySettings(vcl::RenderContext& rRenderContext)
186{
187 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
188
189 Color aColor;
190 if (Window::GetStyle() & WB_3DLOOK)
191 aColor = rStyleSettings.GetFaceColor();
192 else
193 aColor = rStyleSettings.GetWindowColor();
194
195 ApplyControlBackground(rRenderContext, aColor);
196}
197
198FloatingWindow::~FloatingWindow()
199{
200 disposeOnce();
201 assert (!mnPostId)(static_cast <bool> (!mnPostId) ? void (0) : __assert_fail
("!mnPostId", "/home/maarten/src/libreoffice/core/vcl/source/window/floatwin.cxx"
, 201, __extension__ __PRETTY_FUNCTION__))
;
202}
203
204void FloatingWindow::dispose()
205{
206 ReleaseLOKNotifier();
207
208 if (mpImplData)
1
Taking true branch
209 {
210 if( mbPopupModeCanceled )
2
Assuming field 'mbPopupModeCanceled' is false
3
Taking false branch
211 // indicates that ESC key was pressed
212 // will be handled in Window::ImplGrabFocus()
213 SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel );
214
215 if ( IsInPopupMode() )
4
Assuming the condition is true
5
Taking true branch
216 EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll | FloatWinPopupEndFlags::DontCallHdl );
6
Calling 'FloatingWindow::EndPopupMode'
217
218 if ( mnPostId )
219 Application::RemoveUserEvent( mnPostId );
220 mnPostId = nullptr;
221 }
222
223 mpImplData.reset();
224
225 mpNextFloat.clear();
226 mpFirstPopupModeWin.clear();
227 mxPrevFocusWin.clear();
228 SystemWindow::dispose();
229}
230
231Point FloatingWindow::CalcFloatingPosition( vcl::Window* pWindow, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags, sal_uInt16& rArrangeIndex )
232{
233 return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
234}
235
236Point FloatingWindow::ImplCalcPos(vcl::Window* pWindow,
237 const tools::Rectangle& rRect, FloatWinPopupFlags nFlags,
238 sal_uInt16& rArrangeIndex, Point* pLOKTwipsPos)
239{
240 // get window position
241 Point aPos;
242 Size aSize = ::isLayoutEnabled(pWindow) ? pWindow->get_preferred_size() : pWindow->GetSizePixel();
243 tools::Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
244 FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
245
246 // convert...
247 vcl::Window* pW = pWindow;
248 if ( pW->mpWindowImpl->mpRealParent )
249 pW = pW->mpWindowImpl->mpRealParent;
250
251 tools::Rectangle normRect( rRect ); // rRect is already relative to top-level window
252 normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
253
254 bool bRTL = AllSettings::GetLayoutRTL();
255
256 tools::Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
257 pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
258
259 tools::Rectangle devRectRTL( devRect );
260 if( bRTL )
261 // create a rect that can be compared to desktop coordinates
262 devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
263 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
264 aScreenRect = Application::GetScreenPosSizePixel(
265 Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
266
267 FloatWinPopupFlags nArrangeAry[5];
268 sal_uInt16 nArrangeAttempts = 5;
269 Point e1,e2; // the common edge between the item rect and the floating window
270
271 if ( nFlags & FloatWinPopupFlags::Left )
272 {
273 nArrangeAry[0] = FloatWinPopupFlags::Left;
274 nArrangeAry[1] = FloatWinPopupFlags::Right;
275 nArrangeAry[2] = FloatWinPopupFlags::Up;
276 nArrangeAry[3] = FloatWinPopupFlags::Down;
277 nArrangeAry[4] = FloatWinPopupFlags::Left;
278 }
279 else if ( nFlags & FloatWinPopupFlags::Right )
280 {
281 nArrangeAry[0] = FloatWinPopupFlags::Right;
282 nArrangeAry[1] = FloatWinPopupFlags::Left;
283 nArrangeAry[2] = FloatWinPopupFlags::Up;
284 nArrangeAry[3] = FloatWinPopupFlags::Down;
285 nArrangeAry[4] = FloatWinPopupFlags::Right;
286 }
287 else if ( nFlags & FloatWinPopupFlags::Up )
288 {
289 nArrangeAry[0] = FloatWinPopupFlags::Up;
290 nArrangeAry[1] = FloatWinPopupFlags::Down;
291 if (nFlags & FloatWinPopupFlags::NoHorzPlacement)
292 {
293 nArrangeAry[2] = FloatWinPopupFlags::Up;
294 nArrangeAttempts = 3;
295 }
296 else
297 {
298 nArrangeAry[2] = FloatWinPopupFlags::Right;
299 nArrangeAry[3] = FloatWinPopupFlags::Left;
300 nArrangeAry[4] = FloatWinPopupFlags::Up;
301 }
302 }
303 else
304 {
305 nArrangeAry[0] = FloatWinPopupFlags::Down;
306 nArrangeAry[1] = FloatWinPopupFlags::Up;
307 if (nFlags & FloatWinPopupFlags::NoHorzPlacement)
308 {
309 nArrangeAry[2] = FloatWinPopupFlags::Down;
310 nArrangeAttempts = 3;
311 }
312 else
313 {
314 nArrangeAry[2] = FloatWinPopupFlags::Right;
315 nArrangeAry[3] = FloatWinPopupFlags::Left;
316 nArrangeAry[4] = FloatWinPopupFlags::Down;
317 }
318 }
319
320 sal_uInt16 nArrangeIndex = 0;
321 const bool bLOKActive = comphelper::LibreOfficeKit::isActive();
322
323 for ( ; nArrangeIndex < nArrangeAttempts; nArrangeIndex++ )
324 {
325 bool bBreak = true;
326 switch ( nArrangeAry[nArrangeIndex] )
327 {
328
329 case FloatWinPopupFlags::Left:
330 aPos.setX( devRect.Left()-aSize.Width()+1 );
331 aPos.setY( devRect.Top() );
332 aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
333 if( bRTL )
334 {
335 if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
336 bBreak = false;
337 }
338 else
339 {
340 if ( aPos.X() < aScreenRect.Left() )
341 bBreak = false;
342 }
343 if (bBreak || bLOKActive)
344 {
345 e1 = devRect.TopLeft();
346 e2 = devRect.BottomLeft();
347 // set non-zero width
348 e2.AdjustX( 1 );
349 // don't clip corners
350 e1.AdjustY( 1 );
351 e2.AdjustY( -1 );
352 }
353 break;
354 case FloatWinPopupFlags::Right:
355 aPos = devRect.TopRight();
356 aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
357 if( bRTL )
358 {
359 if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
360 bBreak = false;
361 }
362 else
363 {
364 if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
365 bBreak = false;
366 }
367 if (bBreak || bLOKActive)
368 {
369 e1 = devRect.TopRight();
370 e2 = devRect.BottomRight();
371 // set non-zero width
372 e2.AdjustX( 1 );
373 // don't clip corners
374 e1.AdjustY( 1 );
375 e2.AdjustY( -1 );
376 }
377 break;
378 case FloatWinPopupFlags::Up:
379 aPos.setX( devRect.Left() );
380 aPos.setY( devRect.Top()-aSize.Height()+1 );
381 if ( aPos.Y() < aScreenRect.Top() )
382 bBreak = false;
383 if (bBreak || bLOKActive)
384 {
385 e1 = devRect.TopLeft();
386 e2 = devRect.TopRight();
387 // set non-zero height
388 e2.AdjustY( 1 );
389 // don't clip corners
390 e1.AdjustX( 1 );
391 e2.AdjustX( -1 );
392 }
393 break;
394 case FloatWinPopupFlags::Down:
395 aPos = devRect.BottomLeft();
396 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
397 bBreak = false;
398 if (bBreak || bLOKActive)
399 {
400 e1 = devRect.BottomLeft();
401 e2 = devRect.BottomRight();
402 // set non-zero height
403 e2.AdjustY( 1 );
404 // don't clip corners
405 e1.AdjustX( 1 );
406 e2.AdjustX( -1 );
407 }
408 break;
409 default: break;
410 }
411
412 // no further adjustment for LibreOfficeKit
413 if (bLOKActive)
414 break;
415
416 // adjust if necessary
417 if (bBreak)
418 {
419 if ( (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Left) ||
420 (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Right) )
421 {
422 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
423 {
424 aPos.setY( devRect.Bottom()-aSize.Height()+1 );
425 if ( aPos.Y() < aScreenRect.Top() )
426 aPos.setY( aScreenRect.Top() );
427 }
428 }
429 else
430 {
431 if( bRTL )
432 {
433 if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
434 aPos.AdjustX( -(aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1) );
435 }
436 else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
437 {
438 aPos.setX( devRect.Right()-aSize.Width()+1 );
439 if ( aPos.X() < aScreenRect.Left() )
440 aPos.setX( aScreenRect.Left() );
441 }
442 }
443 }
444
445 if ( bBreak )
446 break;
447 }
448 if (nArrangeIndex >= nArrangeAttempts)
449 nArrangeIndex = nArrangeAttempts - 1;
450
451 rArrangeIndex = nArrangeIndex;
452
453 aPos = pW->AbsoluteScreenToOutputPixel( aPos );
454
455 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
456 if( pFloatingWindow && pFloatingWindow->mpImplData->mpBox )
457 {
458 pFloatingWindow->mpImplData->maItemEdgeClipRect =
459 tools::Rectangle( e1, e2 );
460 }
461
462 if (bLOKActive && pLOKTwipsPos)
463 {
464 if (pW->IsMapModeEnabled() || pW->GetMapMode().GetMapUnit() == MapUnit::MapPixel)
465 {
466 // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)),
467 // for pixel conversions when map mode is not enabled, we get
468 // a 20 twips per pixel conversion since LogicToLogic uses
469 // a fixed 72 dpi value, instead of a correctly computed output
470 // device dpi or at least the most commonly used 96 dpi value;
471 // and anyway the following is what we already do in
472 // ScGridWindow::LogicInvalidate when map mode is not enabled.
473
474 *pLOKTwipsPos = pW->PixelToLogic(aPos, MapMode(MapUnit::MapTwip));
475 }
476 else
477 {
478 *pLOKTwipsPos = OutputDevice::LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip));
479 }
480 }
481
482 // caller expects coordinates relative to top-level win
483 return pW->OutputToScreenPixel( aPos );
484}
485
486Point FloatingWindow::ImplConvertToAbsPos(vcl::Window* pReference, const Point& rPos)
487{
488 Point aAbsolute( rPos );
489
490 const OutputDevice *pWindowOutDev = pReference->GetOutDev();
491
492 // compare coordinates in absolute screen coordinates
493 if( pReference->HasMirroredGraphics() )
494 {
495 if(!pReference->IsRTLEnabled() )
496 pWindowOutDev->ReMirror( aAbsolute );
497
498 tools::Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
499 aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
500 aAbsolute = aRect.TopLeft();
501 }
502 else
503 aAbsolute = pReference->OutputToAbsoluteScreenPixel(
504 pReference->ScreenToOutputPixel(rPos) );
505
506 return aAbsolute;
507}
508
509tools::Rectangle FloatingWindow::ImplConvertToAbsPos(vcl::Window* pReference, const tools::Rectangle& rRect)
510{
511 tools::Rectangle aFloatRect = rRect;
512
513 const OutputDevice *pParentWinOutDev = pReference->GetOutDev();
514
515 // compare coordinates in absolute screen coordinates
516 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
517 if( pReference->HasMirroredGraphics() )
518 {
519 if(!pReference->IsRTLEnabled() )
520 pParentWinOutDev->ReMirror(aFloatRect);
521
522 aFloatRect.SetPos(pReference->ScreenToOutputPixel(aFloatRect.TopLeft()));
523 aFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect);
524 }
525 else
526 aFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
527 return aFloatRect;
528}
529
530FloatingWindow* FloatingWindow::ImplFloatHitTest( vcl::Window* pReference, const Point& rPos, bool& rbHitTestInsideRect )
531{
532 FloatingWindow* pWin = this;
533 rbHitTestInsideRect = false;
534
535 Point aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference, rPos));
536
537 do
538 {
539 // compute the floating window's size in absolute screen coordinates
540
541 // use the border window to have the exact position
542 vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border );
543 if (!pBorderWin)
544 break;
545
546 // the top-left corner in output coordinates ie (0,0)
547 tools::Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( tools::Rectangle( Point(), pBorderWin->GetSizePixel()) ) ) ;
548 if ( devRect.IsInside( aAbsolute ) )
549 {
550 // inside the window
551 return pWin;
552 }
553
554 // test, if mouse is in rectangle, (this is typically the rect of the active
555 // toolbox item or similar)
556 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
557 // is already in absolute device coordinates
558 if ( pWin->maFloatRect.IsInside( aAbsolute ) )
559 {
560 rbHitTestInsideRect = true;
561 return pWin;
562 }
563
564 pWin = pWin->mpNextFloat;
565 }
566 while ( pWin );
567
568 return nullptr;
569}
570
571FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
572{
573 FloatingWindow* pWin = this;
574 FloatingWindow* pLastFoundWin = pWin;
575
576 do
577 {
578 if ( pWin->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel )
579 pLastFoundWin = pWin;
580
581 pWin = pWin->mpNextFloat;
582 }
583 while ( pWin );
584
585 return pLastFoundWin;
586}
587
588bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window* pWindow )
589{
590 FloatingWindow* pWin = this;
591
592 do
593 {
594 if ( pWin->mpFirstPopupModeWin == pWindow )
595 return true;
596
597 pWin = pWin->mpNextFloat;
598 }
599 while ( pWin );
600
601 return false;
602}
603
604IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void*, void)void FloatingWindow::LinkStubImplEndPopupModeHdl(void * instance
, void* data) { return static_cast<FloatingWindow *>(instance
)->ImplEndPopupModeHdl(data); } void FloatingWindow::ImplEndPopupModeHdl
(__attribute__ ((unused)) void*)
605{
606 VclPtr<FloatingWindow> pThis(this);
607 mnPostId = nullptr;
608 mnPopupModeFlags = FloatWinPopupFlags::NONE;
609 mbPopupMode = false;
610 PopupModeEnd();
611}
612
613bool FloatingWindow::EventNotify( NotifyEvent& rNEvt )
614{
615 // call Base Class first for tab control
616 bool bRet = SystemWindow::EventNotify( rNEvt );
617 if ( !bRet )
618 {
619 if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
620 {
621 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
622 vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
623 sal_uInt16 nKeyCode = aKeyCode.GetCode();
624
625 if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
626 {
627 Close();
628 return true;
629 }
630 }
631 }
632
633 return bRet;
634}
635
636void FloatingWindow::PixelInvalidate(const tools::Rectangle* /*pRectangle*/)
637{
638 if (VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier())
639 {
640 std::vector<vcl::LOKPayloadItem> aPayload;
641 const tools::Rectangle aRect(Point(0,0), Size(GetSizePixel().Width()+1, GetSizePixel().Height()+1));
642 aPayload.push_back(std::make_pair(OString("rectangle"), aRect.toString()));
643 const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier();
644 pNotifier->notifyWindow(GetLOKWindowId(), "invalidate", aPayload);
645 }
646}
647
648void FloatingWindow::StateChanged( StateChangedType nType )
649{
650 if (nType == StateChangedType::InitShow)
651 {
652 DoInitialLayout();
653 }
654
655 SystemWindow::StateChanged( nType );
656
657 VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier();
658 if (pParent)
659 {
660 if (nType == StateChangedType::InitShow)
661 {
662 std::vector<vcl::LOKPayloadItem> aItems;
663 if (pParent == this)
664 {
665 // we are a toplevel window, let's so far pretend to be a
666 // dialog - but maybe we'll need a separate type for this
667 // later
668 aItems.emplace_back("type", "dialog");
669 aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips
670 }
671 else
672 {
673 SetLOKNotifier(pParent->GetLOKNotifier());
674 if (dynamic_cast<HelpTextWindow*>(this))
675 aItems.emplace_back("type", "tooltip");
676 else
677 aItems.emplace_back("type", "child");
678
679 aItems.emplace_back("parentId", OString::number(pParent->GetLOKWindowId()));
680 if (mbInPopupMode)
681 aItems.emplace_back("position", mpImplData->maPos.toString()); // pixels
682 else // mpImplData->maPos is not set
683 aItems.emplace_back("position", GetPosPixel().toString());
684
685 }
686 aItems.emplace_back("size", GetSizePixel().toString());
687 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems);
688 }
689 else if (!IsVisible() && nType == StateChangedType::Visible)
690 {
691 if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
692 {
693 pNotifier->notifyWindow(GetLOKWindowId(), "close");
694 ReleaseLOKNotifier();
695 }
696 }
697 }
698
699 if ( nType == StateChangedType::ControlBackground )
700 {
701 ImplInitSettings();
702 Invalidate();
703 }
704}
705
706void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
707{
708 SystemWindow::DataChanged( rDCEvt );
709
710 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
711 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
712 {
713 ImplInitSettings();
714 Invalidate();
715 }
716}
717
718void FloatingWindow::ImplCallPopupModeEnd()
719{
720 // PopupMode is finished
721 mbInPopupMode = false;
722
723 // call Handler asynchronously.
724 if ( mpImplData && !mnPostId )
725 mnPostId = Application::PostUserEvent(LINK(this, FloatingWindow, ImplEndPopupModeHdl)::tools::detail::makeLink( ::tools::detail::castTo<FloatingWindow
*>(this), &FloatingWindow::LinkStubImplEndPopupModeHdl
)
);
726}
727
728void FloatingWindow::PopupModeEnd()
729{
730 maPopupModeEndHdl.Call( this );
731}
732
733void FloatingWindow::SetTitleType( FloatWinTitleType nTitle )
734{
735 if ( (mnTitle == nTitle) || !mpWindowImpl->mpBorderWindow )
736 return;
737
738 mnTitle = nTitle;
739 Size aOutSize = GetOutputSizePixel();
740 BorderWindowTitleType nTitleStyle;
741 if ( nTitle == FloatWinTitleType::Normal )
742 nTitleStyle = BorderWindowTitleType::Small;
743 else if ( nTitle == FloatWinTitleType::TearOff )
744 nTitleStyle = BorderWindowTitleType::Tearoff;
745 else if ( nTitle == FloatWinTitleType::Popup )
746 nTitleStyle = BorderWindowTitleType::Popup;
747 else // nTitle == FloatWinTitleType::NONE
748 nTitleStyle = BorderWindowTitleType::NONE;
749 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetTitleType( nTitleStyle, aOutSize );
750 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
751}
752
753void FloatingWindow::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopupFlags nFlags )
754{
755 if ( IsRollUp() )
756 RollDown();
757
758 // remove title
759 mnOldTitle = mnTitle;
760 if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() )
761 SetTitleType( FloatWinTitleType::Popup );
762 else if ( nFlags & FloatWinPopupFlags::AllowTearOff )
763 SetTitleType( FloatWinTitleType::TearOff );
764 else
765 SetTitleType( FloatWinTitleType::NONE );
766
767 // avoid close on focus change for decorated floating windows only
768 if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
769 nFlags |= FloatWinPopupFlags::NoAppFocusClose;
770
771 // compute window position according to flags and arrangement
772 sal_uInt16 nArrangeIndex;
773 DoInitialLayout();
774 mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos);
775 SetPosPixel( mpImplData->maPos );
776 ImplGetFrame()->PositionByToolkit(rRect, nFlags);
777
778 // set data and display window
779 // convert maFloatRect to absolute device coordinates
780 // so they can be compared across different frames
781 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
782 maFloatRect = FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect);
783
784 maFloatRect.AdjustLeft( -2 );
785 maFloatRect.AdjustTop( -2 );
786 maFloatRect.AdjustRight(2 );
787 maFloatRect.AdjustBottom(2 );
788 mnPopupModeFlags = nFlags;
789 mbInPopupMode = true;
790 mbPopupMode = true;
791 mbPopupModeCanceled = false;
792 mbPopupModeTearOff = false;
793 mbMouseDown = false;
794
795 // add FloatingWindow to list of windows that are in popup mode
796 ImplSVData* pSVData = ImplGetSVData();
797 mpNextFloat = pSVData->mpWinData->mpFirstFloat;
798 pSVData->mpWinData->mpFirstFloat = this;
799 if (nFlags & FloatWinPopupFlags::GrabFocus)
800 {
801 // force key input even without focus (useful for menus)
802 mbGrabFocus = true;
803 mxPrevFocusWin = Window::SaveFocus();
804 mpWindowImpl->mpFrameData->mbHasFocus = true;
805 GrabFocus();
806 }
807 Show( true, ShowFlags::NoActivate );
808}
809
810void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags )
811{
812 mpImplData->mpBox = pBox;
813
814 // get selected button
815 sal_uInt16 nItemId = pBox->GetDownItemId();
816
817 if ( nItemId )
818 pBox->ImplFloatControl( true, this );
819
820 // retrieve some data from the ToolBox
821 tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect();
822
823 // convert to parent's screen coordinates
824 mpImplData->maPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
825 aRect.SetPos( mpImplData->maPos );
826
827 nFlags |=
828 FloatWinPopupFlags::AllMouseButtonClose |
829 FloatWinPopupFlags::NoMouseUpClose;
830
831 // set Flags for positioning
832 if ( !(nFlags & (FloatWinPopupFlags::Down | FloatWinPopupFlags::Up |
833 FloatWinPopupFlags::Left | FloatWinPopupFlags::Right)) )
834 {
835 if ( pBox->IsHorizontal() )
836 nFlags |= FloatWinPopupFlags::Down;
837 else
838 nFlags |= FloatWinPopupFlags::Right;
839 }
840
841 // start FloatingMode
842 StartPopupMode( aRect, nFlags );
843}
844
845void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags, const VclPtr<vcl::Window>& xFocusId )
846{
847 if ( !mbInPopupMode )
8
Assuming field 'mbInPopupMode' is true
9
Taking false branch
848 return;
849
850 ImplSVData* pSVData = ImplGetSVData();
851
852 mbInCleanUp = true; // prevent killing this window due to focus change while working with it
853
854 if (!(nFlags & FloatWinPopupEndFlags::NoCloseChildren))
10
Taking true branch
855 {
856 // stop the PopupMode also for all PopupMode windows created after us
857 std::vector<VclPtr<FloatingWindow>> aCancelFloats;
858 // stop the PopupMode also for all following PopupMode windows
859 for (auto pFloat = pSVData->mpWinData->mpFirstFloat;
860 pFloat != nullptr && pFloat != this;
861 pFloat = pFloat->mpNextFloat)
862 aCancelFloats.push_back(pFloat);
863 for (auto & it : aCancelFloats)
864 it->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::NoCloseChildren);
865 }
866
867 // delete window from the list
868 pSVData->mpWinData->mpFirstFloat = mpNextFloat;
11
Calling implicit copy assignment operator for 'VclPtr<FloatingWindow>'
12
Calling copy assignment operator for 'Reference<FloatingWindow>'
18
Returning from copy assignment operator for 'Reference<FloatingWindow>'
19
Returning from copy assignment operator for 'VclPtr<FloatingWindow>'
869 mpNextFloat = nullptr;
20
Calling 'VclPtr::operator='
30
Returning; memory was released
870
871 FloatWinPopupFlags nPopupModeFlags = mnPopupModeFlags;
872 mbPopupModeTearOff = nFlags & FloatWinPopupEndFlags::TearOff &&
873 nPopupModeFlags & FloatWinPopupFlags::AllowTearOff;
874
875 // hide window again if it was not deleted
876 if (!mbPopupModeTearOff
30.1
Field 'mbPopupModeTearOff' is false
30.1
Field 'mbPopupModeTearOff' is false
30.1
Field 'mbPopupModeTearOff' is false
30.1
Field 'mbPopupModeTearOff' is false
)
31
Taking true branch
877 Show( false, ShowFlags::NoFocusChange );
878
879 if (HasChildPathFocus() && xFocusId != nullptr)
32
Assuming the condition is false
880 {
881 // restore focus to previous focus window if we still have the focus
882 Window::EndSaveFocus(xFocusId);
883 }
884 else if ( pSVData->mpWinData->mpFocusWin && pSVData->mpWinData->mpFirstFloat &&
33
Calling 'VclPtr::operator bool'
885 ImplIsWindowOrChild( pSVData->mpWinData->mpFocusWin ) )
886 {
887 // maybe pass focus on to a suitable FloatingWindow
888 pSVData->mpWinData->mpFirstFloat->GrabFocus();
889 }
890
891 mbPopupModeCanceled = bool(nFlags & FloatWinPopupEndFlags::Cancel);
892
893 // redo title
894 SetTitleType( mnOldTitle );
895
896 // set ToolBox again to normal
897 if (mpImplData && mpImplData->mpBox)
898 {
899 mpImplData->mpBox->ImplFloatControl( false, this );
900 // if the parent ToolBox is in popup mode, it should be closed too.
901 if ( GetDockingManager()->IsInPopupMode( mpImplData->mpBox ) )
902 nFlags |= FloatWinPopupEndFlags::CloseAll;
903
904 mpImplData->mpBox = nullptr;
905 }
906
907 // call PopupModeEnd-Handler depending on parameter
908 if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) )
909 ImplCallPopupModeEnd();
910
911 // close all other windows depending on parameter
912 if ( nFlags & FloatWinPopupEndFlags::CloseAll )
913 {
914 if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) )
915 {
916 if (pSVData->mpWinData->mpFirstFloat)
917 {
918 FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
919 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
920 }
921 }
922 }
923
924 mbInCleanUp = false;
925}
926
927void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags )
928{
929 ImplEndPopupMode(nFlags, mxPrevFocusWin);
7
Calling 'FloatingWindow::ImplEndPopupMode'
930}
931
932void FloatingWindow::AddPopupModeWindow(vcl::Window* pWindow)
933{
934 // !!! up-to-now only 1 window and not yet a list
935 mpFirstPopupModeWin = pWindow;
936}
937bool FloatingWindow::UpdatePositionData()
938{
939 auto pWin = ImplGetParent();
940 if (pWin)
941 {
942 // Simulate Move, so the relative position of the floating window will be recalculated
943 pWin->ImplCallMove();
944 return true;
945 }
946
947 return false;
948}
949
950/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody
21.1
'pBody' is null
21.1
'pBody' is null
21.1
'pBody' is null
21.1
'pBody' is null
)
14
Assuming 'pBody' is non-null
15
Taking true branch
22
Taking false branch
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld
15.1
'pOld' is null
22.1
'pOld' is non-null
15.1
'pOld' is null
22.1
'pOld' is non-null
15.1
'pOld' is null
22.1
'pOld' is non-null
15.1
'pOld' is null
22.1
'pOld' is non-null
)
16
Taking false branch
23
Taking true branch
127 pOld->release();
24
Calling 'VclReferenceBase::release'
28
Returning; memory was released
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
13
Calling 'Reference::set'
17
Returning from 'Reference::set'
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
35
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
21
Calling 'Reference::set'
29
Returning; memory was released
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
34
Calling 'Reference::get'
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
25
Assuming the condition is true
26
Taking true branch
40 delete this;
27
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif