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 brdwin.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/brdwin.cxx

/home/maarten/src/libreoffice/core/vcl/source/window/brdwin.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 <strings.hrc>
21#include <svdata.hxx>
22#include <brdwin.hxx>
23#include <window.h>
24
25#include <vcl/textrectinfo.hxx>
26#include <vcl/event.hxx>
27#include <vcl/decoview.hxx>
28#include <vcl/syswin.hxx>
29#include <vcl/dockwin.hxx>
30#include <vcl/floatwin.hxx>
31#include <vcl/help.hxx>
32#include <vcl/toolkit/edit.hxx>
33#include <vcl/settings.hxx>
34#include <vcl/toolbox.hxx>
35#include <vcl/ptrstyle.hxx>
36
37using namespace ::com::sun::star::uno;
38
39// useful caption height for title bar buttons
40#define MIN_CAPTION_HEIGHT18 18
41
42namespace vcl {
43
44void Window::ImplCalcSymbolRect( tools::Rectangle& rRect )
45{
46 // Add border, not shown in the non-default representation,
47 // as we want to use it for small buttons
48 rRect.AdjustLeft( -1 );
49 rRect.AdjustTop( -1 );
50 rRect.AdjustRight( 1 );
51 rRect.AdjustBottom( 1 );
52
53 // we leave 5% room between the symbol and the button border
54 long nExtraWidth = ((rRect.GetWidth()*50)+500)/1000;
55 long nExtraHeight = ((rRect.GetHeight()*50)+500)/1000;
56 rRect.AdjustLeft(nExtraWidth );
57 rRect.AdjustRight( -nExtraWidth );
58 rRect.AdjustTop(nExtraHeight );
59 rRect.AdjustBottom( -nExtraHeight );
60}
61
62} /* namespace vcl */
63
64static void ImplDrawBrdWinSymbol( vcl::RenderContext* pDev,
65 const tools::Rectangle& rRect, SymbolType eSymbol )
66{
67 // we leave 5% room between the symbol and the button border
68 DecorationView aDecoView( pDev );
69 tools::Rectangle aTempRect = rRect;
70 vcl::Window::ImplCalcSymbolRect( aTempRect );
71 aDecoView.DrawSymbol( aTempRect, eSymbol,
72 pDev->GetSettings().GetStyleSettings().GetButtonTextColor() );
73}
74
75static void ImplDrawBrdWinSymbolButton( vcl::RenderContext* pDev,
76 const tools::Rectangle& rRect,
77 SymbolType eSymbol, DrawButtonFlags nState )
78{
79 bool bMouseOver(nState & DrawButtonFlags::Highlight);
80 nState &= ~DrawButtonFlags::Highlight;
81
82 tools::Rectangle aTempRect;
83 vcl::Window *pWin = dynamic_cast< vcl::Window* >(pDev);
84 if( pWin )
85 {
86 if( bMouseOver )
87 {
88 // provide a bright background for selection effect
89 pDev->SetFillColor( pDev->GetSettings().GetStyleSettings().GetWindowColor() );
90 pDev->SetLineColor();
91 pDev->DrawRect( rRect );
92 pWin->DrawSelectionBackground( rRect, 2, bool(nState & DrawButtonFlags::Pressed),
93 true );
94 }
95 aTempRect = rRect;
96 aTempRect.AdjustLeft(3 );
97 aTempRect.AdjustRight( -4 );
98 aTempRect.AdjustTop(3 );
99 aTempRect.AdjustBottom( -4 );
100 }
101 else
102 {
103 DecorationView aDecoView( pDev );
104 aTempRect = aDecoView.DrawButton( rRect, nState|DrawButtonFlags::Flat );
105 }
106 ImplDrawBrdWinSymbol( pDev, aTempRect, eSymbol );
107}
108
109
110ImplBorderWindowView::~ImplBorderWindowView()
111{
112}
113
114bool ImplBorderWindowView::MouseMove( const MouseEvent& )
115{
116 return false;
117}
118
119bool ImplBorderWindowView::MouseButtonDown( const MouseEvent& )
120{
121 return false;
122}
123
124bool ImplBorderWindowView::Tracking( const TrackingEvent& )
125{
126 return false;
127}
128
129OUString ImplBorderWindowView::RequestHelp( const Point&, tools::Rectangle& )
130{
131 return OUString();
132}
133
134tools::Rectangle ImplBorderWindowView::GetMenuRect() const
135{
136 return tools::Rectangle();
137}
138
139void ImplBorderWindowView::ImplInitTitle(ImplBorderFrameData* pData)
140{
141 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
142
143 if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) ||
144 (pData->mnTitleType == BorderWindowTitleType::NONE) )
145 {
146 pData->mnTitleType = BorderWindowTitleType::NONE;
147 pData->mnTitleHeight = 0;
148 }
149 else
150 {
151 const StyleSettings& rStyleSettings = pData->mpOutDev->GetSettings().GetStyleSettings();
152 if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
153 pData->mnTitleHeight = ToolBox::ImplGetDragWidth(*pData->mpBorderWindow, false) + 2;
154 else
155 {
156 if (pData->mnTitleType == BorderWindowTitleType::Small)
157 {
158 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetFloatTitleFont() );
159 pData->mnTitleHeight = rStyleSettings.GetFloatTitleHeight();
160 }
161 else // pData->mnTitleType == BorderWindowTitleType::Normal
162 {
163 // FIXME RenderContext
164 pBorderWindow->SetPointFont(*pBorderWindow, rStyleSettings.GetTitleFont());
165 pData->mnTitleHeight = rStyleSettings.GetTitleHeight();
166 }
167 long nTextHeight = pBorderWindow->GetTextHeight();
168 if (nTextHeight > pData->mnTitleHeight)
169 pData->mnTitleHeight = nTextHeight;
170 }
171 }
172}
173
174BorderWindowHitTest ImplBorderWindowView::ImplHitTest( ImplBorderFrameData const * pData, const Point& rPos )
175{
176 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
177
178 if ( pData->maTitleRect.IsInside( rPos ) )
179 {
180 if ( pData->maCloseRect.IsInside( rPos ) )
181 return BorderWindowHitTest::Close;
182 else if ( pData->maRollRect.IsInside( rPos ) )
183 return BorderWindowHitTest::Roll;
184 else if ( pData->maMenuRect.IsInside( rPos ) )
185 return BorderWindowHitTest::Menu;
186 else if ( pData->maDockRect.IsInside( rPos ) )
187 return BorderWindowHitTest::Dock;
188 else if ( pData->maHideRect.IsInside( rPos ) )
189 return BorderWindowHitTest::Hide;
190 else if ( pData->maHelpRect.IsInside( rPos ) )
191 return BorderWindowHitTest::Help;
192 else
193 return BorderWindowHitTest::Title;
194 }
195
196 if ( (pBorderWindow->GetStyle() & WB_SIZEABLE) &&
197 !pBorderWindow->mbRollUp )
198 {
199 long nSizeWidth = pData->mnNoTitleTop+pData->mnTitleHeight;
200 if ( nSizeWidth < 16 )
201 nSizeWidth = 16;
202
203 // no corner resize for floating toolbars, which would lead to jumps while formatting
204 // setting nSizeWidth = 0 will only return pure left,top,right,bottom
205 if( pBorderWindow->GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP) )
206 nSizeWidth = 0;
207
208 if ( rPos.X() < pData->mnLeftBorder )
209 {
210 if ( rPos.Y() < nSizeWidth )
211 return BorderWindowHitTest::TopLeft;
212 else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
213 return BorderWindowHitTest::BottomLeft;
214 else
215 return BorderWindowHitTest::Left;
216 }
217 else if ( rPos.X() >= pData->mnWidth-pData->mnRightBorder )
218 {
219 if ( rPos.Y() < nSizeWidth )
220 return BorderWindowHitTest::TopRight;
221 else if ( rPos.Y() >= pData->mnHeight-nSizeWidth )
222 return BorderWindowHitTest::BottomRight;
223 else
224 return BorderWindowHitTest::Right;
225 }
226 else if ( rPos.Y() < pData->mnNoTitleTop )
227 {
228 if ( rPos.X() < nSizeWidth )
229 return BorderWindowHitTest::TopLeft;
230 else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
231 return BorderWindowHitTest::TopRight;
232 else
233 return BorderWindowHitTest::Top;
234 }
235 else if ( rPos.Y() >= pData->mnHeight-pData->mnBottomBorder )
236 {
237 if ( rPos.X() < nSizeWidth )
238 return BorderWindowHitTest::BottomLeft;
239 else if ( rPos.X() >= pData->mnWidth-nSizeWidth )
240 return BorderWindowHitTest::BottomRight;
241 else
242 return BorderWindowHitTest::Bottom;
243 }
244 }
245
246 return BorderWindowHitTest::NONE;
247}
248
249void ImplBorderWindowView::ImplMouseMove( ImplBorderFrameData* pData, const MouseEvent& rMEvt )
250{
251 DrawButtonFlags oldCloseState = pData->mnCloseState;
252 DrawButtonFlags oldMenuState = pData->mnMenuState;
253 pData->mnCloseState &= ~DrawButtonFlags::Highlight;
254 pData->mnMenuState &= ~DrawButtonFlags::Highlight;
255
256 Point aMousePos = rMEvt.GetPosPixel();
257 BorderWindowHitTest nHitTest = ImplHitTest( pData, aMousePos );
258 PointerStyle ePtrStyle = PointerStyle::Arrow;
259 if ( nHitTest & BorderWindowHitTest::Left )
260 ePtrStyle = PointerStyle::WindowWSize;
261 else if ( nHitTest & BorderWindowHitTest::Right )
262 ePtrStyle = PointerStyle::WindowESize;
263 else if ( nHitTest & BorderWindowHitTest::Top )
264 ePtrStyle = PointerStyle::WindowNSize;
265 else if ( nHitTest & BorderWindowHitTest::Bottom )
266 ePtrStyle = PointerStyle::WindowSSize;
267 else if ( nHitTest & BorderWindowHitTest::TopLeft )
268 ePtrStyle = PointerStyle::WindowNWSize;
269 else if ( nHitTest & BorderWindowHitTest::BottomRight )
270 ePtrStyle = PointerStyle::WindowSESize;
271 else if ( nHitTest & BorderWindowHitTest::TopRight )
272 ePtrStyle = PointerStyle::WindowNESize;
273 else if ( nHitTest & BorderWindowHitTest::BottomLeft )
274 ePtrStyle = PointerStyle::WindowSWSize;
275 else if ( nHitTest & BorderWindowHitTest::Close )
276 pData->mnCloseState |= DrawButtonFlags::Highlight;
277 else if ( nHitTest & BorderWindowHitTest::Menu )
278 pData->mnMenuState |= DrawButtonFlags::Highlight;
279 else if ( nHitTest & BorderWindowHitTest::Title &&
280 pData->mnTitleType == BorderWindowTitleType::Tearoff && !rMEvt.IsLeaveWindow() )
281 ePtrStyle = PointerStyle::Move;
282 pData->mpBorderWindow->SetPointer( ePtrStyle );
283
284 if( pData->mnCloseState != oldCloseState )
285 pData->mpBorderWindow->Invalidate( pData->maCloseRect );
286 if( pData->mnMenuState != oldMenuState )
287 pData->mpBorderWindow->Invalidate( pData->maMenuRect );
288}
289
290OUString ImplBorderWindowView::ImplRequestHelp( ImplBorderFrameData const * pData,
291 const Point& rPos,
292 tools::Rectangle& rHelpRect )
293{
294 const char* pHelpId = nullptr;
295 OUString aHelpStr;
296 BorderWindowHitTest nHitTest = ImplHitTest( pData, rPos );
297 if ( nHitTest != BorderWindowHitTest::NONE )
298 {
299 if ( nHitTest & BorderWindowHitTest::Close )
300 {
301 pHelpId = SV_HELPTEXT_CLOSEreinterpret_cast<char const *>("SV_HELPTEXT_CLOSE" "\004"
u8"Close")
;
302 rHelpRect = pData->maCloseRect;
303 }
304 else if ( nHitTest & BorderWindowHitTest::Roll )
305 {
306 if ( pData->mpBorderWindow->mbRollUp )
307 pHelpId = SV_HELPTEXT_ROLLDOWNreinterpret_cast<char const *>("SV_HELPTEXT_ROLLDOWN" "\004"
u8"Drop down")
;
308 else
309 pHelpId = SV_HELPTEXT_ROLLUPreinterpret_cast<char const *>("SV_HELPTEXT_ROLLUP" "\004"
u8"Roll up")
;
310 rHelpRect = pData->maRollRect;
311 }
312 else if ( nHitTest & BorderWindowHitTest::Dock )
313 {
314 pHelpId = SV_HELPTEXT_MAXIMIZEreinterpret_cast<char const *>("SV_HELPTEXT_MAXIMIZE" "\004"
u8"Maximize")
;
315 rHelpRect = pData->maDockRect;
316 }
317 else if ( nHitTest & BorderWindowHitTest::Hide )
318 {
319 pHelpId = SV_HELPTEXT_MINIMIZEreinterpret_cast<char const *>("SV_HELPTEXT_MINIMIZE" "\004"
u8"Minimize")
;
320 rHelpRect = pData->maHideRect;
321 }
322 else if ( nHitTest & BorderWindowHitTest::Help )
323 {
324 pHelpId = SV_HELPTEXT_HELPreinterpret_cast<char const *>("SV_HELPTEXT_HELP" "\004"
u8"Help")
;
325 rHelpRect = pData->maHelpRect;
326 }
327 else if ( nHitTest & BorderWindowHitTest::Title )
328 {
329 if( !pData->maTitleRect.IsEmpty() )
330 {
331 // tooltip only if title truncated
332 if( pData->mbTitleClipped )
333 {
334 rHelpRect = pData->maTitleRect;
335 // no help id, use window title as help string
336 aHelpStr = pData->mpBorderWindow->GetText();
337 }
338 }
339 }
340 }
341
342 if (pHelpId)
343 aHelpStr = VclResId(pHelpId);
344
345 return aHelpStr;
346}
347
348long ImplBorderWindowView::ImplCalcTitleWidth( const ImplBorderFrameData* pData )
349{
350 // title is not visible therefore no width
351 if ( !pData->mnTitleHeight )
352 return 0;
353
354 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
355 long nTitleWidth = pBorderWindow->GetTextWidth( pBorderWindow->GetText() )+6;
356 nTitleWidth += pData->maCloseRect.GetWidth();
357 nTitleWidth += pData->maRollRect.GetWidth();
358 nTitleWidth += pData->maDockRect.GetWidth();
359 nTitleWidth += pData->maMenuRect.GetWidth();
360 nTitleWidth += pData->maHideRect.GetWidth();
361 nTitleWidth += pData->maHelpRect.GetWidth();
362 nTitleWidth += pData->mnLeftBorder+pData->mnRightBorder;
363 return nTitleWidth;
364}
365
366
367ImplNoBorderWindowView::ImplNoBorderWindowView()
368{
369}
370
371void ImplNoBorderWindowView::Init( OutputDevice*, long, long )
372{
373}
374
375void ImplNoBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
376 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
377{
378 rLeftBorder = 0;
379 rTopBorder = 0;
380 rRightBorder = 0;
381 rBottomBorder = 0;
382}
383
384long ImplNoBorderWindowView::CalcTitleWidth() const
385{
386 return 0;
387}
388
389void ImplNoBorderWindowView::DrawWindow(vcl::RenderContext&, const Point*)
390{
391}
392
393ImplSmallBorderWindowView::ImplSmallBorderWindowView( ImplBorderWindow* pBorderWindow )
394 : mpBorderWindow(pBorderWindow)
395 , mpOutDev(nullptr)
396 , mnWidth(0)
397 , mnHeight(0)
398 , mnLeftBorder(0)
399 , mnTopBorder(0)
400 , mnRightBorder(0)
401 , mnBottomBorder(0)
402 , mbNWFBorder(false)
403{
404}
405
406void ImplSmallBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
407{
408 mpOutDev = pDev;
409 mnWidth = nWidth;
410 mnHeight = nHeight;
411 mbNWFBorder = false;
412
413 vcl::Window *pWin = nullptr, *pCtrl = nullptr;
414 if (mpOutDev->GetOutDevType() == OUTDEV_WINDOW)
415 pWin = static_cast<vcl::Window*>(mpOutDev.get());
416
417 if (pWin)
418 pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
419
420 long nOrigLeftBorder = mnLeftBorder;
421 long nOrigTopBorder = mnTopBorder;
422 long nOrigRightBorder = mnRightBorder;
423 long nOrigBottomBorder = mnBottomBorder;
424
425 WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
426 if ( nBorderStyle & WindowBorderStyle::NOBORDER )
427 {
428 mnLeftBorder = 0;
429 mnTopBorder = 0;
430 mnRightBorder = 0;
431 mnBottomBorder = 0;
432 }
433 else
434 {
435 // FIXME: this is currently only on macOS, check with other
436 // platforms
437 if( ImplGetSVData()->maNWFData.mbNoFocusRects && !( nBorderStyle & WindowBorderStyle::NWF ) )
438 {
439 // for native widget drawing we must find out what
440 // control this border belongs to
441 ControlType aCtrlType = ControlType::Generic;
442 if (pCtrl)
443 {
444 switch( pCtrl->GetType() )
445 {
446 case WindowType::LISTBOX:
447 if( pCtrl->GetStyle() & WB_DROPDOWN )
448 {
449 aCtrlType = ControlType::Listbox;
450 mbNWFBorder = true;
451 }
452 break;
453 case WindowType::COMBOBOX:
454 if( pCtrl->GetStyle() & WB_DROPDOWN )
455 {
456 aCtrlType = ControlType::Combobox;
457 mbNWFBorder = true;
458 }
459 break;
460 case WindowType::MULTILINEEDIT:
461 aCtrlType = ControlType::MultilineEditbox;
462 mbNWFBorder = true;
463 break;
464 case WindowType::EDIT:
465 case WindowType::PATTERNFIELD:
466 case WindowType::METRICFIELD:
467 case WindowType::CURRENCYFIELD:
468 case WindowType::DATEFIELD:
469 case WindowType::TIMEFIELD:
470 case WindowType::SPINFIELD:
471 case WindowType::FORMATTEDFIELD:
472 case WindowType::CALCINPUTLINE:
473 mbNWFBorder = true;
474 if (pCtrl->GetStyle() & WB_SPIN)
475 aCtrlType = ControlType::Spinbox;
476 else
477 aCtrlType = ControlType::Editbox;
478 break;
479 default:
480 break;
481 }
482 }
483 if( mbNWFBorder )
484 {
485 ImplControlValue aControlValue;
486 Size aMinSize( mnWidth - mnLeftBorder - mnRightBorder, mnHeight - mnTopBorder - mnBottomBorder );
487 if( aMinSize.Width() < 10 ) aMinSize.setWidth( 10 );
488 if( aMinSize.Height() < 10 ) aMinSize.setHeight( 10 );
489 tools::Rectangle aCtrlRegion( Point(mnLeftBorder, mnTopBorder), aMinSize );
490 tools::Rectangle aBounds, aContent;
491 if( pWin->GetNativeControlRegion( aCtrlType, ControlPart::Entire, aCtrlRegion,
492 ControlState::ENABLED, aControlValue,
493 aBounds, aContent ) )
494 {
495 mnLeftBorder = aContent.Left() - aBounds.Left();
496 mnRightBorder = aBounds.Right() - aContent.Right();
497 mnTopBorder = aContent.Top() - aBounds.Top();
498 mnBottomBorder = aBounds.Bottom() - aContent.Bottom();
499 if( mnWidth && mnHeight )
500 {
501
502 mpBorderWindow->SetPaintTransparent( true );
503 mpBorderWindow->SetBackground();
504 pCtrl->SetPaintTransparent( true );
505
506 vcl::Window* pCompoundParent = nullptr;
507 if( pWin->GetParent() && pWin->GetParent()->IsCompoundControl() )
508 pCompoundParent = pWin->GetParent();
509
510 if( pCompoundParent )
511 pCompoundParent->SetPaintTransparent( true );
512
513 if( mnWidth < aBounds.GetWidth() || mnHeight < aBounds.GetHeight() )
514 {
515 if( ! pCompoundParent ) // compound controls have to fix themselves
516 {
517 Point aPos( mpBorderWindow->GetPosPixel() );
518 if( mnWidth < aBounds.GetWidth() )
519 aPos.AdjustX( -((aBounds.GetWidth() - mnWidth) / 2) );
520 if( mnHeight < aBounds.GetHeight() )
521 aPos.AdjustY( -((aBounds.GetHeight() - mnHeight) / 2) );
522 mpBorderWindow->SetPosSizePixel( aPos, aBounds.GetSize() );
523 }
524 }
525 }
526 }
527 else
528 mbNWFBorder = false;
529 }
530 }
531
532 if( ! mbNWFBorder )
533 {
534 DrawFrameStyle nStyle = DrawFrameStyle::NONE;
535 DrawFrameFlags nFlags = DrawFrameFlags::NoDraw;
536 // move border outside if border was converted or if the BorderWindow is a frame window,
537 if ( mpBorderWindow->mbSmallOutBorder )
538 nStyle = DrawFrameStyle::DoubleOut;
539 else if ( nBorderStyle & WindowBorderStyle::NWF )
540 nStyle = DrawFrameStyle::NWF;
541 else
542 nStyle = DrawFrameStyle::DoubleIn;
543 if ( nBorderStyle & WindowBorderStyle::MONO )
544 nFlags |= DrawFrameFlags::Mono;
545
546 DecorationView aDecoView( mpOutDev );
547 tools::Rectangle aRect( 0, 0, 10, 10 );
548 tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, nStyle, nFlags );
549 mnLeftBorder = aCalcRect.Left();
550 mnTopBorder = aCalcRect.Top();
551 mnRightBorder = aRect.Right()-aCalcRect.Right();
552 mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
553 }
554 }
555
556 if (pCtrl)
557 {
558 //fdo#57090 If the borders have changed, then trigger a queue_resize on
559 //the bordered window, which will resync its borders at that point
560 if (nOrigLeftBorder != mnLeftBorder ||
561 nOrigTopBorder != mnTopBorder ||
562 nOrigRightBorder != mnRightBorder ||
563 nOrigBottomBorder != mnBottomBorder)
564 {
565 pCtrl->queue_resize();
566 }
567 }
568}
569
570void ImplSmallBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
571 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
572{
573 rLeftBorder = mnLeftBorder;
574 rTopBorder = mnTopBorder;
575 rRightBorder = mnRightBorder;
576 rBottomBorder = mnBottomBorder;
577}
578
579long ImplSmallBorderWindowView::CalcTitleWidth() const
580{
581 return 0;
582}
583
584void ImplSmallBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point*)
585{
586 WindowBorderStyle nBorderStyle = mpBorderWindow->GetBorderStyle();
587 if (nBorderStyle & WindowBorderStyle::NOBORDER)
588 return;
589
590 bool bNativeOK = false;
591 // for native widget drawing we must find out what
592 // control this border belongs to
593 vcl::Window* pCtrl = mpBorderWindow->GetWindow(GetWindowType::Client);
594
595 ControlType aCtrlType = ControlType::Generic;
596 ControlPart aCtrlPart = ControlPart::Entire;
597 if (pCtrl)
598 {
599 switch (pCtrl->GetType())
600 {
601 case WindowType::MULTILINEEDIT:
602 aCtrlType = ControlType::MultilineEditbox;
603 break;
604 case WindowType::EDIT:
605 case WindowType::PATTERNFIELD:
606 case WindowType::METRICFIELD:
607 case WindowType::CURRENCYFIELD:
608 case WindowType::DATEFIELD:
609 case WindowType::TIMEFIELD:
610 case WindowType::SPINFIELD:
611 case WindowType::FORMATTEDFIELD:
612 case WindowType::CALCINPUTLINE:
613 if (pCtrl->GetStyle() & WB_SPIN)
614 aCtrlType = ControlType::Spinbox;
615 else
616 aCtrlType = ControlType::Editbox;
617 break;
618
619 case WindowType::LISTBOX:
620 case WindowType::MULTILISTBOX:
621 case WindowType::TREELISTBOX:
622 aCtrlType = ControlType::Listbox;
623 if (pCtrl->GetStyle() & WB_DROPDOWN)
624 aCtrlPart = ControlPart::Entire;
625 else
626 aCtrlPart = ControlPart::ListboxWindow;
627 break;
628
629 case WindowType::LISTBOXWINDOW:
630 aCtrlType = ControlType::Listbox;
631 aCtrlPart = ControlPart::ListboxWindow;
632 break;
633
634 case WindowType::COMBOBOX:
635 case WindowType::PATTERNBOX:
636 case WindowType::NUMERICBOX:
637 case WindowType::METRICBOX:
638 case WindowType::CURRENCYBOX:
639 case WindowType::DATEBOX:
640 case WindowType::TIMEBOX:
641 case WindowType::LONGCURRENCYBOX:
642 if (pCtrl->GetStyle() & WB_DROPDOWN)
643 {
644 aCtrlType = ControlType::Combobox;
645 aCtrlPart = ControlPart::Entire;
646 }
647 else
648 {
649 aCtrlType = ControlType::Listbox;
650 aCtrlPart = ControlPart::ListboxWindow;
651 }
652 break;
653
654 default:
655 break;
656 }
657 }
658
659 if (aCtrlType != ControlType::Generic && pCtrl->IsNativeControlSupported(aCtrlType, aCtrlPart))
660 {
661 ImplControlValue aControlValue;
662 ControlState nState = ControlState::ENABLED;
663
664 if (!mpBorderWindow->IsEnabled())
665 nState &= ~ControlState::ENABLED;
666 if (mpBorderWindow->HasFocus())
667 nState |= ControlState::FOCUSED;
668 else if(mbNWFBorder)
669 {
670 // FIXME: this is currently only on macOS, see if other platforms can profit
671
672 // FIXME: for macOS focus rings all controls need to support GetNativeControlRegion
673 // for the dropdown style
674 if (pCtrl->HasFocus() || pCtrl->HasChildPathFocus())
675 nState |= ControlState::FOCUSED;
676 }
677
678 bool bMouseOver = false;
679 vcl::Window *pCtrlChild = pCtrl->GetWindow(GetWindowType::FirstChild);
680 while(pCtrlChild)
681 {
682 bMouseOver = pCtrlChild->IsMouseOver();
683 if (bMouseOver)
684 break;
685 pCtrlChild = pCtrlChild->GetWindow(GetWindowType::Next);
686 }
687
688 if (bMouseOver)
689 nState |= ControlState::ROLLOVER;
690
691 Point aPoint;
692 tools::Rectangle aCtrlRegion(aPoint, Size(mnWidth, mnHeight));
693
694 tools::Rectangle aBoundingRgn(aPoint, Size(mnWidth, mnHeight));
695 tools::Rectangle aContentRgn(aCtrlRegion);
696 if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize &&
697 rRenderContext.GetNativeControlRegion(aCtrlType, aCtrlPart, aCtrlRegion,
698 nState, aControlValue,
699 aBoundingRgn, aContentRgn))
700 {
701 aCtrlRegion=aContentRgn;
702 }
703
704 Color aBackgroundColor = COL_AUTO;
705 if (pCtrl->IsControlBackground())
706 aBackgroundColor = pCtrl->GetBackgroundColor();
707 bNativeOK = rRenderContext.DrawNativeControl(aCtrlType, aCtrlPart, aCtrlRegion, nState, aControlValue, OUString(), aBackgroundColor);
708
709 // if the native theme draws the spinbuttons in one call, make sure the proper settings
710 // are passed, this might force a redraw though... (TODO: improve)
711 if ((aCtrlType == ControlType::Spinbox) && !pCtrl->IsNativeControlSupported(ControlType::Spinbox, ControlPart::ButtonUp))
712 {
713 Edit* pEdit = static_cast<Edit*>(pCtrl)->GetSubEdit();
714 if (pEdit && !pEdit->SupportsDoubleBuffering())
715 pCtrl->Paint(*pCtrl, tools::Rectangle()); // make sure the buttons are also drawn as they might overwrite the border
716 }
717 }
718
719 if (bNativeOK)
720 return;
721
722 DrawFrameStyle nStyle = DrawFrameStyle::NONE;
723 DrawFrameFlags nFlags = DrawFrameFlags::NONE;
724 // move border outside if border was converted or if the border window is a frame window,
725 if (mpBorderWindow->mbSmallOutBorder)
726 nStyle = DrawFrameStyle::DoubleOut;
727 else if (nBorderStyle & WindowBorderStyle::NWF)
728 nStyle = DrawFrameStyle::NWF;
729 else
730 nStyle = DrawFrameStyle::DoubleIn;
731 if (nBorderStyle & WindowBorderStyle::MONO)
732 nFlags |= DrawFrameFlags::Mono;
733 if (nBorderStyle & WindowBorderStyle::MENU)
734 nFlags |= DrawFrameFlags::Menu;
735 // tell DrawFrame that we're drawing a window border of a frame window to avoid round corners
736 if (mpBorderWindow == mpBorderWindow->ImplGetFrameWindow())
737 nFlags |= DrawFrameFlags::WindowBorder;
738
739 DecorationView aDecoView(&rRenderContext);
740 tools::Rectangle aInRect(Point(), Size(mnWidth, mnHeight));
741 aDecoView.DrawFrame(aInRect, nStyle, nFlags);
742}
743
744
745ImplStdBorderWindowView::ImplStdBorderWindowView( ImplBorderWindow* pBorderWindow )
746{
747 maFrameData.mpBorderWindow = pBorderWindow;
748 maFrameData.mbDragFull = false;
749 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
750 maFrameData.mnCloseState = DrawButtonFlags::NONE;
751 maFrameData.mnRollState = DrawButtonFlags::NONE;
752 maFrameData.mnDockState = DrawButtonFlags::NONE;
753 maFrameData.mnMenuState = DrawButtonFlags::NONE;
754 maFrameData.mnHideState = DrawButtonFlags::NONE;
755 maFrameData.mnHelpState = DrawButtonFlags::NONE;
756 maFrameData.mbTitleClipped = false;
757}
758
759ImplStdBorderWindowView::~ImplStdBorderWindowView()
760{
761}
762
763bool ImplStdBorderWindowView::MouseMove( const MouseEvent& rMEvt )
764{
765 ImplMouseMove( &maFrameData, rMEvt );
766 return true;
767}
768
769bool ImplStdBorderWindowView::MouseButtonDown( const MouseEvent& rMEvt )
770{
771 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
772
773 if ( rMEvt.IsLeft() || rMEvt.IsRight() )
774 {
775 maFrameData.maMouseOff = rMEvt.GetPosPixel();
776 maFrameData.mnHitTest = ImplHitTest( &maFrameData, maFrameData.maMouseOff );
777 if ( maFrameData.mnHitTest != BorderWindowHitTest::NONE )
778 {
779 DragFullOptions nDragFullTest = DragFullOptions::NONE;
780 bool bTracking = true;
781 bool bHitTest = true;
782
783 if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
784 {
785 maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
786 pBorderWindow->InvalidateBorder();
787 }
788 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
789 {
790 maFrameData.mnRollState |= DrawButtonFlags::Pressed;
791 pBorderWindow->InvalidateBorder();
792 }
793 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
794 {
795 maFrameData.mnDockState |= DrawButtonFlags::Pressed;
796 pBorderWindow->InvalidateBorder();
797 }
798 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
799 {
800 maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
801 pBorderWindow->InvalidateBorder();
802
803 // call handler already on mouse down
804 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
805 {
806 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
807 pClientWindow->TitleButtonClick( TitleButton::Menu );
808 }
809 }
810 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
811 {
812 maFrameData.mnHideState |= DrawButtonFlags::Pressed;
813 pBorderWindow->InvalidateBorder();
814 }
815 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
816 {
817 maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
818 pBorderWindow->InvalidateBorder();
819 }
820 else
821 {
822 if ( rMEvt.GetClicks() == 1 )
823 {
824 Point aPos = pBorderWindow->GetPosPixel();
825 Size aSize = pBorderWindow->GetOutputSizePixel();
826 maFrameData.mnTrackX = aPos.X();
827 maFrameData.mnTrackY = aPos.Y();
828 maFrameData.mnTrackWidth = aSize.Width();
829 maFrameData.mnTrackHeight = aSize.Height();
830
831 if (maFrameData.mnHitTest & BorderWindowHitTest::Title)
832 nDragFullTest = DragFullOptions::WindowMove;
833 else
834 nDragFullTest = DragFullOptions::WindowSize;
835 }
836 else
837 {
838 bTracking = false;
839
840 if ( (maFrameData.mnHitTest & BorderWindowHitTest::Title) &&
841 ((rMEvt.GetClicks() % 2) == 0) )
842 {
843 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
844 bHitTest = false;
845
846 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
847 {
848 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
849 // always perform docking on double click, no button required
850 pClientWindow->TitleButtonClick( TitleButton::Docking );
851 }
852 }
853 }
854 }
855
856 if ( bTracking )
857 {
858 maFrameData.mbDragFull = false;
859 if ( nDragFullTest != DragFullOptions::NONE )
860 maFrameData.mbDragFull = true; // always fulldrag for proper docking, ignore system settings
861 pBorderWindow->StartTracking();
862 }
863 else if ( bHitTest )
864 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
865 }
866 }
867
868 return true;
869}
870
871bool ImplStdBorderWindowView::Tracking( const TrackingEvent& rTEvt )
872{
873 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
874
875 if ( rTEvt.IsTrackingEnded() )
876 {
877 BorderWindowHitTest nHitTest = maFrameData.mnHitTest;
878 maFrameData.mnHitTest = BorderWindowHitTest::NONE;
879
880 if ( nHitTest & BorderWindowHitTest::Close )
881 {
882 if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
883 {
884 maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
885 pBorderWindow->InvalidateBorder();
886
887 // do not call a Click-Handler when aborting
888 if ( !rTEvt.IsTrackingCanceled() )
889 {
890 // dispatch to correct window type (why is Close() not virtual ??? )
891 // TODO: make Close() virtual
892 VclPtr<vcl::Window> pWin = pBorderWindow->ImplGetClientWindow()->ImplGetWindow();
893 SystemWindow *pSysWin = dynamic_cast<SystemWindow* >(pWin.get());
894 DockingWindow *pDockWin = dynamic_cast<DockingWindow*>(pWin.get());
895 if ( pSysWin )
896 pSysWin->Close();
897 else if ( pDockWin )
898 pDockWin->Close();
899 }
900 }
901 }
902 else if ( nHitTest & BorderWindowHitTest::Roll )
903 {
904 if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
905 {
906 maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
907 pBorderWindow->InvalidateBorder();
908
909 // do not call a Click-Handler when aborting
910 if ( !rTEvt.IsTrackingCanceled() )
911 {
912 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
913 {
914 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
915 if ( pClientWindow->IsRollUp() )
916 pClientWindow->RollDown();
917 else
918 pClientWindow->RollUp();
919 }
920 }
921 }
922 }
923 else if ( nHitTest & BorderWindowHitTest::Dock )
924 {
925 if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
926 {
927 maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
928 pBorderWindow->InvalidateBorder();
929
930 // do not call a Click-Handler when aborting
931 if ( !rTEvt.IsTrackingCanceled() )
932 {
933 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
934 {
935 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
936 pClientWindow->TitleButtonClick( TitleButton::Docking );
937 }
938 }
939 }
940 }
941 else if ( nHitTest & BorderWindowHitTest::Menu )
942 {
943 if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
944 {
945 maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
946 pBorderWindow->InvalidateBorder();
947
948 // handler already called on mouse down
949 }
950 }
951 else if ( nHitTest & BorderWindowHitTest::Hide )
952 {
953 if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
954 {
955 maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
956 pBorderWindow->InvalidateBorder();
957
958 // do not call a Click-Handler when aborting
959 if ( !rTEvt.IsTrackingCanceled() )
960 {
961 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
962 {
963 SystemWindow* pClientWindow = static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow());
964 pClientWindow->TitleButtonClick( TitleButton::Hide );
965 }
966 }
967 }
968 }
969 else if ( nHitTest & BorderWindowHitTest::Help )
970 {
971 if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
972 {
973 maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
974 pBorderWindow->InvalidateBorder();
975 }
976 }
977 else
978 {
979 if ( maFrameData.mbDragFull )
980 {
981 // restore old state when aborting
982 if ( rTEvt.IsTrackingCanceled() )
983 pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
984 }
985 else
986 {
987 pBorderWindow->HideTracking();
988 if ( !rTEvt.IsTrackingCanceled() )
989 pBorderWindow->SetPosSizePixel( Point( maFrameData.mnTrackX, maFrameData.mnTrackY ), Size( maFrameData.mnTrackWidth, maFrameData.mnTrackHeight ) );
990 }
991
992 if ( !rTEvt.IsTrackingCanceled() )
993 {
994 if ( pBorderWindow->ImplGetClientWindow()->ImplIsFloatingWindow() )
995 {
996 if ( static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->IsInPopupMode() )
997 static_cast<FloatingWindow*>(pBorderWindow->ImplGetClientWindow())->EndPopupMode( FloatWinPopupEndFlags::TearOff );
998 }
999 }
1000 }
1001 }
1002 else if ( !rTEvt.GetMouseEvent().IsSynthetic() )
1003 {
1004 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1005
1006 if ( maFrameData.mnHitTest & BorderWindowHitTest::Close )
1007 {
1008 if ( maFrameData.maCloseRect.IsInside( aMousePos ) )
1009 {
1010 if ( !(maFrameData.mnCloseState & DrawButtonFlags::Pressed) )
1011 {
1012 maFrameData.mnCloseState |= DrawButtonFlags::Pressed;
1013 pBorderWindow->InvalidateBorder();
1014 }
1015 }
1016 else
1017 {
1018 if ( maFrameData.mnCloseState & DrawButtonFlags::Pressed )
1019 {
1020 maFrameData.mnCloseState &= ~DrawButtonFlags::Pressed;
1021 pBorderWindow->InvalidateBorder();
1022 }
1023 }
1024 }
1025 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Roll )
1026 {
1027 if ( maFrameData.maRollRect.IsInside( aMousePos ) )
1028 {
1029 if ( !(maFrameData.mnRollState & DrawButtonFlags::Pressed) )
1030 {
1031 maFrameData.mnRollState |= DrawButtonFlags::Pressed;
1032 pBorderWindow->InvalidateBorder();
1033 }
1034 }
1035 else
1036 {
1037 if ( maFrameData.mnRollState & DrawButtonFlags::Pressed )
1038 {
1039 maFrameData.mnRollState &= ~DrawButtonFlags::Pressed;
1040 pBorderWindow->InvalidateBorder();
1041 }
1042 }
1043 }
1044 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Dock )
1045 {
1046 if ( maFrameData.maDockRect.IsInside( aMousePos ) )
1047 {
1048 if ( !(maFrameData.mnDockState & DrawButtonFlags::Pressed) )
1049 {
1050 maFrameData.mnDockState |= DrawButtonFlags::Pressed;
1051 pBorderWindow->InvalidateBorder();
1052 }
1053 }
1054 else
1055 {
1056 if ( maFrameData.mnDockState & DrawButtonFlags::Pressed )
1057 {
1058 maFrameData.mnDockState &= ~DrawButtonFlags::Pressed;
1059 pBorderWindow->InvalidateBorder();
1060 }
1061 }
1062 }
1063 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Menu )
1064 {
1065 if ( maFrameData.maMenuRect.IsInside( aMousePos ) )
1066 {
1067 if ( !(maFrameData.mnMenuState & DrawButtonFlags::Pressed) )
1068 {
1069 maFrameData.mnMenuState |= DrawButtonFlags::Pressed;
1070 pBorderWindow->InvalidateBorder();
1071 }
1072 }
1073 else
1074 {
1075 if ( maFrameData.mnMenuState & DrawButtonFlags::Pressed )
1076 {
1077 maFrameData.mnMenuState &= ~DrawButtonFlags::Pressed;
1078 pBorderWindow->InvalidateBorder();
1079 }
1080 }
1081 }
1082 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Hide )
1083 {
1084 if ( maFrameData.maHideRect.IsInside( aMousePos ) )
1085 {
1086 if ( !(maFrameData.mnHideState & DrawButtonFlags::Pressed) )
1087 {
1088 maFrameData.mnHideState |= DrawButtonFlags::Pressed;
1089 pBorderWindow->InvalidateBorder();
1090 }
1091 }
1092 else
1093 {
1094 if ( maFrameData.mnHideState & DrawButtonFlags::Pressed )
1095 {
1096 maFrameData.mnHideState &= ~DrawButtonFlags::Pressed;
1097 pBorderWindow->InvalidateBorder();
1098 }
1099 }
1100 }
1101 else if ( maFrameData.mnHitTest & BorderWindowHitTest::Help )
1102 {
1103 if ( maFrameData.maHelpRect.IsInside( aMousePos ) )
1104 {
1105 if ( !(maFrameData.mnHelpState & DrawButtonFlags::Pressed) )
1106 {
1107 maFrameData.mnHelpState |= DrawButtonFlags::Pressed;
1108 pBorderWindow->InvalidateBorder();
1109 }
1110 }
1111 else
1112 {
1113 if ( maFrameData.mnHelpState & DrawButtonFlags::Pressed )
1114 {
1115 maFrameData.mnHelpState &= ~DrawButtonFlags::Pressed;
1116 pBorderWindow->InvalidateBorder();
1117 }
1118 }
1119 }
1120 else
1121 {
1122 aMousePos.AdjustX( -(maFrameData.maMouseOff.X()) );
1123 aMousePos.AdjustY( -(maFrameData.maMouseOff.Y()) );
1124
1125 if ( maFrameData.mnHitTest & BorderWindowHitTest::Title )
1126 {
1127 maFrameData.mpBorderWindow->SetPointer( PointerStyle::Move );
1128
1129 Point aPos = pBorderWindow->GetPosPixel();
1130 aPos.AdjustX(aMousePos.X() );
1131 aPos.AdjustY(aMousePos.Y() );
1132 if ( maFrameData.mbDragFull )
1133 {
1134 pBorderWindow->SetPosPixel( aPos );
1135 pBorderWindow->ImplUpdateAll();
1136 pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1137 }
1138 else
1139 {
1140 maFrameData.mnTrackX = aPos.X();
1141 maFrameData.mnTrackY = aPos.Y();
1142 pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aPos ), pBorderWindow->GetOutputSizePixel() ), ShowTrackFlags::Big );
1143 }
1144 }
1145 else
1146 {
1147 Point aOldPos = pBorderWindow->GetPosPixel();
1148 Size aSize = pBorderWindow->GetSizePixel();
1149 tools::Rectangle aNewRect( aOldPos, aSize );
1150 long nOldWidth = aSize.Width();
1151 long nOldHeight = aSize.Height();
1152 long nBorderWidth = maFrameData.mnLeftBorder+maFrameData.mnRightBorder;
1153 long nBorderHeight = maFrameData.mnTopBorder+maFrameData.mnBottomBorder;
1154 long nMinWidth = pBorderWindow->mnMinWidth+nBorderWidth;
1155 long nMinHeight = pBorderWindow->mnMinHeight+nBorderHeight;
1156 long nMinWidth2 = nBorderWidth;
1157 long nMaxWidth = pBorderWindow->mnMaxWidth+nBorderWidth;
1158 long nMaxHeight = pBorderWindow->mnMaxHeight+nBorderHeight;
1159
1160 if ( maFrameData.mnTitleHeight )
1161 {
1162 nMinWidth2 += 4;
1163
1164 if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1165 nMinWidth2 += maFrameData.maCloseRect.GetWidth();
1166 }
1167 if ( nMinWidth2 > nMinWidth )
1168 nMinWidth = nMinWidth2;
1169 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1170 {
1171 aNewRect.AdjustLeft(aMousePos.X() );
1172 if ( aNewRect.GetWidth() < nMinWidth )
1173 aNewRect.SetLeft( aNewRect.Right()-nMinWidth+1 );
1174 else if ( aNewRect.GetWidth() > nMaxWidth )
1175 aNewRect.SetLeft( aNewRect.Right()-nMaxWidth+1 );
1176 }
1177 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1178 {
1179 aNewRect.AdjustRight(aMousePos.X() );
1180 if ( aNewRect.GetWidth() < nMinWidth )
1181 aNewRect.SetRight( aNewRect.Left()+nMinWidth+1 );
1182 else if ( aNewRect.GetWidth() > nMaxWidth )
1183 aNewRect.SetRight( aNewRect.Left()+nMaxWidth+1 );
1184 }
1185 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1186 {
1187 aNewRect.AdjustTop(aMousePos.Y() );
1188 if ( aNewRect.GetHeight() < nMinHeight )
1189 aNewRect.SetTop( aNewRect.Bottom()-nMinHeight+1 );
1190 else if ( aNewRect.GetHeight() > nMaxHeight )
1191 aNewRect.SetTop( aNewRect.Bottom()-nMaxHeight+1 );
1192 }
1193 else if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1194 {
1195 aNewRect.AdjustBottom(aMousePos.Y() );
1196 if ( aNewRect.GetHeight() < nMinHeight )
1197 aNewRect.SetBottom( aNewRect.Top()+nMinHeight+1 );
1198 else if ( aNewRect.GetHeight() > nMaxHeight )
1199 aNewRect.SetBottom( aNewRect.Top()+nMaxHeight+1 );
1200 }
1201
1202 // call Resizing-Handler for SystemWindows
1203 if ( pBorderWindow->ImplGetClientWindow()->IsSystemWindow() )
1204 {
1205 // adjust size for Resizing-call
1206 aSize = aNewRect.GetSize();
1207 aSize.AdjustWidth( -nBorderWidth );
1208 aSize.AdjustHeight( -nBorderHeight );
1209 static_cast<SystemWindow*>(pBorderWindow->ImplGetClientWindow())->Resizing( aSize );
1210 aSize.AdjustWidth(nBorderWidth );
1211 aSize.AdjustHeight(nBorderHeight );
1212 if ( aSize.Width() < nMinWidth )
1213 aSize.setWidth( nMinWidth );
1214 if ( aSize.Height() < nMinHeight )
1215 aSize.setHeight( nMinHeight );
1216 if ( aSize.Width() > nMaxWidth )
1217 aSize.setWidth( nMaxWidth );
1218 if ( aSize.Height() > nMaxHeight )
1219 aSize.setHeight( nMaxHeight );
1220 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Left | BorderWindowHitTest::TopLeft | BorderWindowHitTest::BottomLeft) )
1221 aNewRect.SetLeft( aNewRect.Right()-aSize.Width()+1 );
1222 else
1223 aNewRect.SetRight( aNewRect.Left()+aSize.Width()-1 );
1224 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Top | BorderWindowHitTest::TopLeft | BorderWindowHitTest::TopRight) )
1225 aNewRect.SetTop( aNewRect.Bottom()-aSize.Height()+1 );
1226 else
1227 aNewRect.SetBottom( aNewRect.Top()+aSize.Height()-1 );
1228 }
1229
1230 if ( maFrameData.mbDragFull )
1231 {
1232 // no move (only resize) if position did not change
1233 if( aOldPos != aNewRect.TopLeft() )
1234 pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1235 aNewRect.GetWidth(), aNewRect.GetHeight() );
1236 else
1237 pBorderWindow->setPosSizePixel( aNewRect.Left(), aNewRect.Top(),
1238 aNewRect.GetWidth(), aNewRect.GetHeight(), PosSizeFlags::Size );
1239
1240 pBorderWindow->ImplUpdateAll();
1241 pBorderWindow->ImplGetFrameWindow()->ImplUpdateAll();
1242 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Right | BorderWindowHitTest::TopRight | BorderWindowHitTest::BottomRight) )
1243 maFrameData.maMouseOff.AdjustX(aNewRect.GetWidth()-nOldWidth );
1244 if ( maFrameData.mnHitTest & (BorderWindowHitTest::Bottom | BorderWindowHitTest::BottomLeft | BorderWindowHitTest::BottomRight) )
1245 maFrameData.maMouseOff.AdjustY(aNewRect.GetHeight()-nOldHeight );
1246 }
1247 else
1248 {
1249 maFrameData.mnTrackX = aNewRect.Left();
1250 maFrameData.mnTrackY = aNewRect.Top();
1251 maFrameData.mnTrackWidth = aNewRect.GetWidth();
1252 maFrameData.mnTrackHeight = aNewRect.GetHeight();
1253 pBorderWindow->ShowTracking( tools::Rectangle( pBorderWindow->ScreenToOutputPixel( aNewRect.TopLeft() ), aNewRect.GetSize() ), ShowTrackFlags::Big );
1254 }
1255 }
1256 }
1257 }
1258
1259 return true;
1260}
1261
1262OUString ImplStdBorderWindowView::RequestHelp( const Point& rPos, tools::Rectangle& rHelpRect )
1263{
1264 return ImplRequestHelp( &maFrameData, rPos, rHelpRect );
1265}
1266
1267tools::Rectangle ImplStdBorderWindowView::GetMenuRect() const
1268{
1269 return maFrameData.maMenuRect;
1270}
1271
1272void ImplStdBorderWindowView::Init( OutputDevice* pDev, long nWidth, long nHeight )
1273{
1274 ImplBorderFrameData* pData = &maFrameData;
1275 ImplBorderWindow* pBorderWindow = maFrameData.mpBorderWindow;
1276 const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
1277 DecorationView aDecoView( pDev );
1278 tools::Rectangle aRect( 0, 0, 10, 10 );
1279 tools::Rectangle aCalcRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleOut, DrawFrameFlags::NoDraw );
1280
1281 pData->mpOutDev = pDev;
1282 pData->mnWidth = nWidth;
1283 pData->mnHeight = nHeight;
1284
1285 pData->mnTitleType = pBorderWindow->mnTitleType;
1286
1287 if ( !(pBorderWindow->GetStyle() & (WB_MOVEABLE | WB_POPUP)) || (pData->mnTitleType == BorderWindowTitleType::NONE) )
1288 pData->mnBorderSize = 0;
1289 else if ( pData->mnTitleType == BorderWindowTitleType::Tearoff )
1290 pData->mnBorderSize = 0;
1291 else
1292 pData->mnBorderSize = StyleSettings::GetBorderSize();
1293 pData->mnLeftBorder = aCalcRect.Left();
1294 pData->mnTopBorder = aCalcRect.Top();
1295 pData->mnRightBorder = aRect.Right()-aCalcRect.Right();
1296 pData->mnBottomBorder = aRect.Bottom()-aCalcRect.Bottom();
1297 pData->mnLeftBorder += pData->mnBorderSize;
1298 pData->mnTopBorder += pData->mnBorderSize;
1299 pData->mnRightBorder += pData->mnBorderSize;
1300 pData->mnBottomBorder += pData->mnBorderSize;
1301 pData->mnNoTitleTop = pData->mnTopBorder;
1302
1303 ImplInitTitle(&maFrameData);
1304 if (pData->mnTitleHeight)
1305 {
1306 // to improve symbol display force a minimum title height
1307 if (pData->mnTitleType != BorderWindowTitleType::Tearoff &&
1308 pData->mnTitleHeight < MIN_CAPTION_HEIGHT18)
1309 pData->mnTitleHeight = MIN_CAPTION_HEIGHT18;
1310
1311 // set a proper background for drawing
1312 // highlighted buttons in the title
1313 pBorderWindow->SetBackground( rStyleSettings.GetFaceColor() );
1314
1315 pData->maTitleRect.SetLeft( pData->mnLeftBorder );
1316 pData->maTitleRect.SetRight( nWidth-pData->mnRightBorder-1 );
1317 pData->maTitleRect.SetTop( pData->mnTopBorder );
1318 pData->maTitleRect.SetBottom( pData->maTitleRect.Top()+pData->mnTitleHeight-1 );
1319
1320 if ( pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small) )
1321 {
1322 long nRight = pData->maTitleRect.Right() - 3;
1323 long const nItemTop = pData->maTitleRect.Top() + 2;
1324 long const nItemBottom = pData->maTitleRect.Bottom() - 2;
1325
1326 auto addSquareOnRight = [&nRight, nItemTop, nItemBottom](
1327 tools::Rectangle & rect, long gap)
1328 {
1329 rect.SetTop( nItemTop );
1330 rect.SetBottom( nItemBottom );
1331 rect.SetRight( nRight );
1332 rect.SetLeft( rect.Right() - rect.GetHeight() + 1 );
1333 nRight -= rect.GetWidth() + gap;
1334 };
1335
1336 if ( pBorderWindow->GetStyle() & WB_CLOSEABLE )
1337 {
1338 addSquareOnRight(pData->maCloseRect, 3);
1339 }
1340
1341 if ( pBorderWindow->mbMenuBtn )
1342 {
1343 addSquareOnRight(pData->maMenuRect, 0);
1344 }
1345
1346 if ( pBorderWindow->mbDockBtn )
1347 {
1348 addSquareOnRight(pData->maDockRect, 0);
1349 }
1350
1351 if ( pBorderWindow->mbHideBtn )
1352 {
1353 addSquareOnRight(pData->maHideRect, 0);
1354 }
1355
1356 if ( pBorderWindow->GetStyle() & WB_ROLLABLE )
1357 {
1358 addSquareOnRight(pData->maRollRect, 0);
1359 }
1360 }
1361 else
1362 {
1363 pData->maCloseRect.SetEmpty();
1364 pData->maDockRect.SetEmpty();
1365 pData->maMenuRect.SetEmpty();
1366 pData->maHideRect.SetEmpty();
1367 pData->maRollRect.SetEmpty();
1368 pData->maHelpRect.SetEmpty();
1369 }
1370
1371 pData->mnTopBorder += pData->mnTitleHeight;
1372 }
1373 else
1374 {
1375 pData->maTitleRect.SetEmpty();
1376 pData->maCloseRect.SetEmpty();
1377 pData->maDockRect.SetEmpty();
1378 pData->maMenuRect.SetEmpty();
1379 pData->maHideRect.SetEmpty();
1380 pData->maRollRect.SetEmpty();
1381 pData->maHelpRect.SetEmpty();
1382 }
1383}
1384
1385void ImplStdBorderWindowView::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
1386 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
1387{
1388 rLeftBorder = maFrameData.mnLeftBorder;
1389 rTopBorder = maFrameData.mnTopBorder;
1390 rRightBorder = maFrameData.mnRightBorder;
1391 rBottomBorder = maFrameData.mnBottomBorder;
1392}
1393
1394long ImplStdBorderWindowView::CalcTitleWidth() const
1395{
1396 return ImplCalcTitleWidth( &maFrameData );
1397}
1398
1399void ImplStdBorderWindowView::DrawWindow(vcl::RenderContext& rRenderContext, const Point* pOffset)
1400{
1401 ImplBorderFrameData* pData = &maFrameData;
1402 ImplBorderWindow* pBorderWindow = pData->mpBorderWindow;
1403 Point aTmpPoint = pOffset ? *pOffset : Point();
1404 tools::Rectangle aInRect( aTmpPoint, Size( pData->mnWidth, pData->mnHeight ) );
1405 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1406 Color aFaceColor(rStyleSettings.GetFaceColor());
1407 Color aFrameColor(aFaceColor);
1408
1409 aFrameColor.DecreaseContrast(sal_uInt8(0.5 * 255));
1410
1411 // Draw Frame
1412 vcl::Region oldClipRgn(rRenderContext.GetClipRegion());
1413
1414 // for popups, don't draw part of the frame
1415 if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1416 {
1417 FloatingWindow* pWin = dynamic_cast<FloatingWindow*>(pData->mpBorderWindow->GetWindow(GetWindowType::Client));
1418 if (pWin)
1419 {
1420 vcl::Region aClipRgn(aInRect);
1421 tools::Rectangle aItemClipRect(pWin->ImplGetItemEdgeClipRect());
1422 if (!aItemClipRect.IsEmpty())
1423 {
1424 aItemClipRect.SetPos(pData->mpBorderWindow->AbsoluteScreenToOutputPixel(aItemClipRect.TopLeft()));
1425 aClipRgn.Exclude(aItemClipRect);
1426 rRenderContext.SetClipRegion(aClipRgn);
1427 }
1428 }
1429 }
1430
1431 // single line frame
1432 rRenderContext.SetLineColor(aFrameColor);
1433 rRenderContext.SetFillColor();
1434 rRenderContext.DrawRect(aInRect);
1435 aInRect.AdjustLeft( 1 );
1436 aInRect.AdjustRight( -1 );
1437 aInRect.AdjustTop( 1 );
1438 aInRect.AdjustBottom( -1 );
1439
1440 // restore
1441 if (!(pData->mnTitleType & (BorderWindowTitleType::Normal | BorderWindowTitleType::Small)))
1442 rRenderContext.SetClipRegion(oldClipRgn);
1443
1444 // Draw Border
1445 rRenderContext.SetLineColor();
1446 long nBorderSize = pData->mnBorderSize;
1447 if (nBorderSize)
1448 {
1449 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
1450 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top()),
1451 Size(aInRect.GetWidth(), nBorderSize)));
1452 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Top() + nBorderSize),
1453 Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1454 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Left(), aInRect.Bottom() - nBorderSize + 1),
1455 Size(aInRect.GetWidth(), nBorderSize)));
1456 rRenderContext.DrawRect(tools::Rectangle(Point(aInRect.Right()-nBorderSize + 1, aInRect.Top() + nBorderSize),
1457 Size(nBorderSize, aInRect.GetHeight() - nBorderSize)));
1458 }
1459
1460 // Draw Title
1461 if (!pData->maTitleRect.IsEmpty())
1462 {
1463 aInRect = pData->maTitleRect;
1464
1465 // use no gradient anymore, just a static titlecolor
1466 if (pData->mnTitleType == BorderWindowTitleType::Tearoff)
1467 rRenderContext.SetFillColor(rStyleSettings.GetFaceGradientColor());
1468 else if (pData->mnTitleType == BorderWindowTitleType::Popup)
1469 rRenderContext.SetFillColor(aFaceColor);
1470 else
1471 rRenderContext.SetFillColor(aFrameColor);
1472
1473 rRenderContext.SetTextColor(rStyleSettings.GetButtonTextColor());
1474 tools::Rectangle aTitleRect(pData->maTitleRect);
1475 if(pOffset)
1476 aTitleRect.Move(pOffset->X(), pOffset->Y());
1477 rRenderContext.DrawRect(aTitleRect);
1478
1479 if (pData->mnTitleType != BorderWindowTitleType::Tearoff)
1480 {
1481 aInRect.AdjustLeft(2 );
1482 aInRect.AdjustRight( -2 );
1483
1484 if (!pData->maHelpRect.IsEmpty())
1485 aInRect.SetRight( pData->maHelpRect.Left() - 2 );
1486 else if (!pData->maRollRect.IsEmpty())
1487 aInRect.SetRight( pData->maRollRect.Left() - 2 );
1488 else if (!pData->maHideRect.IsEmpty())
1489 aInRect.SetRight( pData->maHideRect.Left() - 2 );
1490 else if (!pData->maDockRect.IsEmpty())
1491 aInRect.SetRight( pData->maDockRect.Left() - 2 );
1492 else if (!pData->maMenuRect.IsEmpty())
1493 aInRect.SetRight( pData->maMenuRect.Left() - 2 );
1494 else if (!pData->maCloseRect.IsEmpty())
1495 aInRect.SetRight( pData->maCloseRect.Left() - 2 );
1496
1497 if (pOffset)
1498 aInRect.Move(pOffset->X(), pOffset->Y());
1499
1500 DrawTextFlags nTextStyle = DrawTextFlags::Left | DrawTextFlags::VCenter | DrawTextFlags::EndEllipsis | DrawTextFlags::Clip;
1501
1502 // must show tooltip ?
1503 TextRectInfo aInfo;
1504 rRenderContext.GetTextRect(aInRect, pBorderWindow->GetText(), nTextStyle, &aInfo);
1505 pData->mbTitleClipped = aInfo.IsEllipses();
1506
1507 rRenderContext.DrawText(aInRect, pBorderWindow->GetText(), nTextStyle);
1508 }
1509 else
1510 {
1511 ToolBox::ImplDrawGrip(rRenderContext, aTitleRect, ToolBox::ImplGetDragWidth(rRenderContext, false),
1512 WindowAlign::Left, false);
1513 }
1514 }
1515
1516 if (!pData->maCloseRect.IsEmpty())
1517 {
1518 tools::Rectangle aSymbolRect(pData->maCloseRect);
1519 if (pOffset)
1520 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1521 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::CLOSE, pData->mnCloseState);
1522 }
1523 if (!pData->maDockRect.IsEmpty())
1524 {
1525 tools::Rectangle aSymbolRect(pData->maDockRect);
1526 if (pOffset)
1527 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1528 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::DOCK, pData->mnDockState);
1529 }
1530 if (!pData->maMenuRect.IsEmpty())
1531 {
1532 tools::Rectangle aSymbolRect(pData->maMenuRect);
1533 if (pOffset)
1534 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1535 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::MENU, pData->mnMenuState);
1536 }
1537 if (!pData->maHideRect.IsEmpty())
1538 {
1539 tools::Rectangle aSymbolRect(pData->maHideRect);
1540 if (pOffset)
1541 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1542 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HIDE, pData->mnHideState);
1543 }
1544 if (!pData->maRollRect.IsEmpty())
1545 {
1546 SymbolType eType;
1547 if (pBorderWindow->mbRollUp)
1548 eType = SymbolType::ROLLDOWN;
1549 else
1550 eType = SymbolType::ROLLUP;
1551 tools::Rectangle aSymbolRect(pData->maRollRect);
1552 if (pOffset)
1553 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1554 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, eType, pData->mnRollState);
1555 }
1556
1557 if (!pData->maHelpRect.IsEmpty())
1558 {
1559 tools::Rectangle aSymbolRect(pData->maHelpRect);
1560 if (pOffset)
1561 aSymbolRect.Move(pOffset->X(), pOffset->Y());
1562 ImplDrawBrdWinSymbolButton(&rRenderContext, aSymbolRect, SymbolType::HELP, pData->mnHelpState);
1563 }
1564}
1565
1566void ImplBorderWindow::ImplInit( vcl::Window* pParent,
1567 WinBits nStyle, BorderWindowStyle nTypeStyle,
1568 SystemParentData* pSystemParentData
1569 )
1570{
1571 // remove all unwanted WindowBits
1572 WinBits nOrgStyle = nStyle;
1573 WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW | WB_POPUP);
1574 if ( nTypeStyle & BorderWindowStyle::App )
1575 nTestStyle |= WB_APP;
1576 nStyle &= nTestStyle;
1577
1578 mpWindowImpl->mbBorderWin = true;
1579 mbSmallOutBorder = false;
1580 if ( nTypeStyle & BorderWindowStyle::Frame )
1581 {
1582 if( nStyle & WB_SYSTEMCHILDWINDOW )
1583 {
1584 mpWindowImpl->mbOverlapWin = true;
1585 mpWindowImpl->mbFrame = true;
1586 mbFrameBorder = false;
1587 }
1588 else if( nStyle & (WB_OWNERDRAWDECORATION | WB_POPUP) )
1589 {
1590 mpWindowImpl->mbOverlapWin = true;
1591 mpWindowImpl->mbFrame = true;
1592 mbFrameBorder = (nOrgStyle & WB_NOBORDER) == 0;
1593 }
1594 else
1595 {
1596 mpWindowImpl->mbOverlapWin = true;
1597 mpWindowImpl->mbFrame = true;
1598 mbFrameBorder = false;
1599 // closeable windows may have a border as well, eg. system floating windows without caption
1600 if ( (nOrgStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE/* | WB_CLOSEABLE*/)) == WB_BORDER )
1601 mbSmallOutBorder = true;
1602 }
1603 }
1604 else if ( nTypeStyle & BorderWindowStyle::Overlap )
1605 {
1606 mpWindowImpl->mbOverlapWin = true;
1607 mbFrameBorder = true;
1608 }
1609 else
1610 mbFrameBorder = false;
1611
1612 if ( nTypeStyle & BorderWindowStyle::Float )
1613 mbFloatWindow = true;
1614 else
1615 mbFloatWindow = false;
1616
1617 Window::ImplInit( pParent, nStyle, pSystemParentData );
1618 SetBackground();
1619 SetTextFillColor();
1620
1621 mpMenuBarWindow = nullptr;
1622 mnMinWidth = 0;
1623 mnMinHeight = 0;
1624 mnMaxWidth = SHRT_MAX32767;
1625 mnMaxHeight = SHRT_MAX32767;
1626 mnOrgMenuHeight = 0;
1627 mbRollUp = false;
1628 mbMenuHide = false;
1629 mbDockBtn = false;
1630 mbMenuBtn = false;
1631 mbHideBtn = false;
1632 mbDisplayActive = IsActive();
1633
1634 if ( nTypeStyle & BorderWindowStyle::Float )
1635 mnTitleType = BorderWindowTitleType::Small;
1636 else
1637 mnTitleType = BorderWindowTitleType::Normal;
1638 mnBorderStyle = WindowBorderStyle::NORMAL;
1639 InitView();
1640}
1641
1642ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent,
1643 SystemParentData* pSystemParentData,
1644 WinBits nStyle, BorderWindowStyle nTypeStyle
1645 ) : Window( WindowType::BORDERWINDOW )
1646{
1647 ImplInit( pParent, nStyle, nTypeStyle, pSystemParentData );
1648}
1649
1650ImplBorderWindow::ImplBorderWindow( vcl::Window* pParent, WinBits nStyle ,
1651 BorderWindowStyle nTypeStyle ) :
1652 Window( WindowType::BORDERWINDOW )
1653{
1654 ImplInit( pParent, nStyle, nTypeStyle, nullptr );
1655}
1656
1657ImplBorderWindow::~ImplBorderWindow()
1658{
1659 disposeOnce();
1660}
1661
1662void ImplBorderWindow::dispose()
1663{
1664 mpBorderView.reset();
1665 mpMenuBarWindow.clear();
1666 mpNotebookBar.disposeAndClear();
1667 vcl::Window::dispose();
1668}
1669
1670void ImplBorderWindow::MouseMove( const MouseEvent& rMEvt )
1671{
1672 if (mpBorderView)
1673 mpBorderView->MouseMove( rMEvt );
1674}
1675
1676void ImplBorderWindow::MouseButtonDown( const MouseEvent& rMEvt )
1677{
1678 if (mpBorderView)
1679 mpBorderView->MouseButtonDown( rMEvt );
1680}
1681
1682void ImplBorderWindow::Tracking( const TrackingEvent& rTEvt )
1683{
1684 if (mpBorderView)
1685 mpBorderView->Tracking( rTEvt );
1686}
1687
1688void ImplBorderWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
1689{
1690 if (mpBorderView)
1691 mpBorderView->DrawWindow(rRenderContext);
1692}
1693
1694void ImplBorderWindow::Draw( OutputDevice* pOutDev, const Point& rPos )
1695{
1696 if (mpBorderView)
1697 mpBorderView->DrawWindow(*pOutDev, &rPos);
1698}
1699
1700void ImplBorderWindow::Activate()
1701{
1702 SetDisplayActive( true );
1703 Window::Activate();
1704}
1705
1706void ImplBorderWindow::Deactivate()
1707{
1708 // remove active windows from the ruler, also ignore the Deactivate
1709 // if a menu becomes active
1710 if (GetActivateMode() != ActivateModeFlags::NONE && !ImplGetSVData()->mpWinData->mbNoDeactivate)
1711 SetDisplayActive( false );
1712 Window::Deactivate();
1713}
1714
1715void ImplBorderWindow::RequestHelp( const HelpEvent& rHEvt )
1716{
1717 // no keyboard help for border window
1718 if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
1719 {
1720 Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
1721 tools::Rectangle aHelpRect;
1722 OUString aHelpStr( mpBorderView->RequestHelp( aMousePosPixel, aHelpRect ) );
1723
1724 // retrieve rectangle
1725 if ( !aHelpStr.isEmpty() )
1726 {
1727 aHelpRect.SetPos( OutputToScreenPixel( aHelpRect.TopLeft() ) );
1728 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1729 Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aHelpStr );
1730 else
1731 Help::ShowQuickHelp( this, aHelpRect, aHelpStr );
1732 return;
1733 }
1734 }
1735
1736 Window::RequestHelp( rHEvt );
1737}
1738
1739void ImplBorderWindow::Resize()
1740{
1741 Size aSize = GetOutputSizePixel();
1742
1743 if ( !mbRollUp )
1744 {
1745 vcl::Window* pClientWindow = ImplGetClientWindow();
1746
1747 sal_Int32 nLeftBorder;
1748 sal_Int32 nTopBorder;
1749 sal_Int32 nRightBorder;
1750 sal_Int32 nBottomBorder;
1751 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1752
1753 if (mpMenuBarWindow)
1754 {
1755 long nMenuHeight = mpMenuBarWindow->GetSizePixel().Height();
1756 if ( mbMenuHide )
1757 {
1758 if ( nMenuHeight )
1759 mnOrgMenuHeight = nMenuHeight;
1760 nMenuHeight = 0;
1761 }
1762 else
1763 {
1764 if ( !nMenuHeight )
1765 nMenuHeight = mnOrgMenuHeight;
1766 }
1767 mpMenuBarWindow->setPosSizePixel(
1768 nLeftBorder, nTopBorder,
1769 aSize.Width()-nLeftBorder-nRightBorder,
1770 nMenuHeight);
1771
1772 // shift the notebookbar down accordingly
1773 nTopBorder += nMenuHeight;
1774 }
1775
1776 if (mpNotebookBar)
1777 {
1778 long nNotebookBarHeight = mpNotebookBar->GetSizePixel().Height();
1779
1780 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1781 const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader();
1782 // since size of notebookbar changes, to make common persona for menubar
1783 // and notebookbar persona should be set again with changed coordinates
1784 if (!aPersona.IsEmpty())
1785 {
1786 Wallpaper aWallpaper(aPersona);
1787 aWallpaper.SetStyle(WallpaperStyle::TopRight);
1788 aWallpaper.SetRect(tools::Rectangle(Point(0, -nTopBorder),
1789 Size(aSize.Width() - nLeftBorder - nRightBorder,
1790 nNotebookBarHeight + nTopBorder)));
1791 mpNotebookBar->SetBackground(aWallpaper);
1792 }
1793
1794 mpNotebookBar->setPosSizePixel(
1795 nLeftBorder, nTopBorder,
1796 aSize.Width() - nLeftBorder - nRightBorder,
1797 nNotebookBarHeight);
1798 }
1799
1800 GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1801 pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1802 pClientWindow->ImplPosSizeWindow( pClientWindow->mpWindowImpl->mnLeftBorder,
1803 pClientWindow->mpWindowImpl->mnTopBorder,
1804 aSize.Width()-pClientWindow->mpWindowImpl->mnLeftBorder-pClientWindow->mpWindowImpl->mnRightBorder,
1805 aSize.Height()-pClientWindow->mpWindowImpl->mnTopBorder-pClientWindow->mpWindowImpl->mnBottomBorder,
1806 PosSizeFlags::X | PosSizeFlags::Y |
1807 PosSizeFlags::Width | PosSizeFlags::Height );
1808 }
1809
1810 // UpdateView
1811 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1812 InvalidateBorder();
1813
1814 Window::Resize();
1815}
1816
1817void ImplBorderWindow::StateChanged( StateChangedType nType )
1818{
1819 if ( (nType == StateChangedType::Text) ||
1820 (nType == StateChangedType::Data) )
1821 {
1822 if (IsReallyVisible() && mbFrameBorder)
1823 InvalidateBorder();
1824 }
1825
1826 Window::StateChanged( nType );
1827}
1828
1829void ImplBorderWindow::DataChanged( const DataChangedEvent& rDCEvt )
1830{
1831 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1832 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1833 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1834 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1835 {
1836 if ( !mpWindowImpl->mbFrame || (GetStyle() & (WB_OWNERDRAWDECORATION | WB_POPUP)) )
1837 UpdateView( true, ImplGetWindow()->GetOutputSizePixel() );
1838 }
1839
1840 Window::DataChanged( rDCEvt );
1841}
1842
1843void ImplBorderWindow::InitView()
1844{
1845 if ( mbSmallOutBorder )
1846 mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1847 else if ( mpWindowImpl->mbFrame )
1848 {
1849 if( mbFrameBorder )
1850 mpBorderView.reset(new ImplStdBorderWindowView( this ));
1851 else
1852 mpBorderView.reset(new ImplNoBorderWindowView);
1853 }
1854 else if ( !mbFrameBorder )
1855 mpBorderView.reset(new ImplSmallBorderWindowView( this ));
1856 else
1857 mpBorderView.reset(new ImplStdBorderWindowView( this ));
1858 Size aSize = GetOutputSizePixel();
1859 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1860}
1861
1862void ImplBorderWindow::UpdateView( bool bNewView, const Size& rNewOutSize )
1863{
1864 sal_Int32 nLeftBorder;
1865 sal_Int32 nTopBorder;
1866 sal_Int32 nRightBorder;
1867 sal_Int32 nBottomBorder;
1868 Size aOldSize = GetSizePixel();
1869 Size aOutputSize = rNewOutSize;
1870
1871 if ( bNewView )
1872 {
1873 mpBorderView.reset();
1874 InitView();
1875 }
1876 else
1877 {
1878 Size aSize = aOutputSize;
1879 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1880 aSize.AdjustWidth(nLeftBorder+nRightBorder );
1881 aSize.AdjustHeight(nTopBorder+nBottomBorder );
1882 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1883 }
1884
1885 vcl::Window* pClientWindow = ImplGetClientWindow();
1886 if ( pClientWindow )
1887 {
1888 GetBorder( pClientWindow->mpWindowImpl->mnLeftBorder, pClientWindow->mpWindowImpl->mnTopBorder,
1889 pClientWindow->mpWindowImpl->mnRightBorder, pClientWindow->mpWindowImpl->mnBottomBorder );
1890 }
1891 GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1892 if ( aOldSize.Width() || aOldSize.Height() )
1893 {
1894 aOutputSize.AdjustWidth(nLeftBorder+nRightBorder );
1895 aOutputSize.AdjustHeight(nTopBorder+nBottomBorder );
1896 if ( aOutputSize == GetSizePixel() )
1897 InvalidateBorder();
1898 else
1899 SetSizePixel( aOutputSize );
1900 }
1901}
1902
1903void ImplBorderWindow::InvalidateBorder()
1904{
1905 if ( !IsReallyVisible() )
1906 return;
1907
1908 // invalidate only if we have a border
1909 sal_Int32 nLeftBorder;
1910 sal_Int32 nTopBorder;
1911 sal_Int32 nRightBorder;
1912 sal_Int32 nBottomBorder;
1913 mpBorderView->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
1914 if ( !(nLeftBorder || nTopBorder || nRightBorder || nBottomBorder) )
1915 return;
1916
1917 tools::Rectangle aWinRect( Point( 0, 0 ), GetOutputSizePixel() );
1918 vcl::Region aRegion( aWinRect );
1919 aWinRect.AdjustLeft(nLeftBorder );
1920 aWinRect.AdjustTop(nTopBorder );
1921 aWinRect.AdjustRight( -nRightBorder );
1922 aWinRect.AdjustBottom( -nBottomBorder );
1923 // no output area anymore, now invalidate all
1924 if ( (aWinRect.Right() < aWinRect.Left()) ||
1925 (aWinRect.Bottom() < aWinRect.Top()) )
1926 Invalidate( InvalidateFlags::NoChildren );
1927 else
1928 {
1929 aRegion.Exclude( aWinRect );
1930 Invalidate( aRegion, InvalidateFlags::NoChildren );
1931 }
1932}
1933
1934void ImplBorderWindow::SetDisplayActive( bool bActive )
1935{
1936 if ( mbDisplayActive != bActive )
1937 {
1938 mbDisplayActive = bActive;
1939 if ( mbFrameBorder )
1940 InvalidateBorder();
1941 }
1942}
1943
1944void ImplBorderWindow::SetTitleType( BorderWindowTitleType nTitleType, const Size& rSize )
1945{
1946 mnTitleType = nTitleType;
1947 UpdateView( false, rSize );
1948}
1949
1950void ImplBorderWindow::SetBorderStyle( WindowBorderStyle nStyle )
1951{
1952 if ( !mbFrameBorder && (mnBorderStyle != nStyle) )
1953 {
1954 mnBorderStyle = nStyle;
1955 UpdateView( false, ImplGetWindow()->GetOutputSizePixel() );
1956 }
1957}
1958
1959void ImplBorderWindow::SetRollUp( bool bRollUp, const Size& rSize )
1960{
1961 mbRollUp = bRollUp;
1962 UpdateView( false, rSize );
1963}
1964
1965void ImplBorderWindow::SetCloseButton()
1966{
1967 SetStyle( GetStyle() | WB_CLOSEABLE );
1968 Size aSize = GetOutputSizePixel();
1969 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1970 InvalidateBorder();
1971}
1972
1973void ImplBorderWindow::SetDockButton( bool bDockButton )
1974{
1975 mbDockBtn = bDockButton;
1976 Size aSize = GetOutputSizePixel();
1977 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1978 InvalidateBorder();
1979}
1980
1981void ImplBorderWindow::SetHideButton( bool bHideButton )
1982{
1983 mbHideBtn = bHideButton;
1984 Size aSize = GetOutputSizePixel();
1985 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1986 InvalidateBorder();
1987}
1988
1989void ImplBorderWindow::SetMenuButton( bool bMenuButton )
1990{
1991 mbMenuBtn = bMenuButton;
1992 Size aSize = GetOutputSizePixel();
1993 mpBorderView->Init( this, aSize.Width(), aSize.Height() );
1994 InvalidateBorder();
1995}
1996
1997void ImplBorderWindow::UpdateMenuHeight()
1998{
1999 Resize();
2000}
2001
2002void ImplBorderWindow::SetMenuBarWindow( vcl::Window* pWindow )
2003{
2004 mpMenuBarWindow = pWindow;
2005 UpdateMenuHeight();
2006 if ( pWindow )
2007 pWindow->Show();
2008}
2009
2010void ImplBorderWindow::SetMenuBarMode( bool bHide )
2011{
2012 mbMenuHide = bHide;
2013 UpdateMenuHeight();
2014}
2015
2016void ImplBorderWindow::SetNotebookBar(const OUString& rUIXMLDescription,
2017 const css::uno::Reference<css::frame::XFrame>& rFrame,
2018 const NotebookBarAddonsItem& aNotebookBarAddonsItem)
2019{
2020 if (mpNotebookBar)
2021 mpNotebookBar.disposeAndClear();
2022 mpNotebookBar = VclPtr<NotebookBar>::Create(this, "NotebookBar", rUIXMLDescription, rFrame,
2023 aNotebookBarAddonsItem);
2024 Resize();
2025}
2026
2027void ImplBorderWindow::CloseNotebookBar()
2028{
2029 if (mpNotebookBar)
1
Taking true branch
2030 mpNotebookBar.disposeAndClear();
2
Calling 'VclPtr::disposeAndClear'
2031 mpNotebookBar = nullptr;
2032 Resize();
2033}
2034
2035void ImplBorderWindow::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2036 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2037{
2038 mpBorderView->GetBorder(rLeftBorder, rTopBorder, rRightBorder, rBottomBorder);
2039
2040 if (mpMenuBarWindow && !mbMenuHide)
2041 rTopBorder += mpMenuBarWindow->GetSizePixel().Height();
2042
2043 if (mpNotebookBar && mpNotebookBar->IsVisible())
2044 rTopBorder += mpNotebookBar->GetSizePixel().Height();
2045}
2046
2047long ImplBorderWindow::CalcTitleWidth() const
2048{
2049 return mpBorderView->CalcTitleWidth();
2050}
2051
2052tools::Rectangle ImplBorderWindow::GetMenuRect() const
2053{
2054 return mpBorderView->GetMenuRect();
2055}
2056
2057Size ImplBorderWindow::GetOptimalSize() const
2058{
2059 const vcl::Window* pClientWindow = ImplGetClientWindow();
2060 if (pClientWindow)
2061 return pClientWindow->GetOptimalSize();
2062 return Size(mnMinWidth, mnMinHeight);
2063}
2064
2065void ImplBorderWindow::queue_resize(StateChangedType eReason)
2066{
2067 //if we are floating, then we don't want to inform our parent that it needs
2068 //to calculate a new layout allocation. Because while we are a child
2069 //of our parent we are not embedded into the parent so it doesn't care
2070 //about us.
2071 if (mbFloatWindow)
2072 return;
2073 vcl::Window::queue_resize(eReason);
2074}
2075
2076/* 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);
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;
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 ;-)
3
Calling 'Reference::clear'
10
Returning; memory was released
205 if (aTmp.get()) {
11
Calling 'Reference::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/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)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
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 );
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
3.1
Field 'm_pBody' is non-null
3.1
Field 'm_pBody' is non-null
3.1
Field 'm_pBody' is non-null
3.1
Field 'm_pBody' is non-null
)
4
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
5
Calling 'VclReferenceBase::release'
9
Returning; memory was released
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;
12
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/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)
6
Assuming the condition is true
7
Taking true branch
40 delete this;
8
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