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 dockwin.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 /usr/include/libxml2 -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 SFX2_DLLIMPLEMENTATION -D ENABLE_CUPS -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/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/sfx2/inc -I /home/maarten/src/libreoffice/core/sfx2/source/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sfx2/sdi -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/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -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/sfx2/source/dialog/dockwin.cxx

/home/maarten/src/libreoffice/core/sfx2/source/dialog/dockwin.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 <svl/eitem.hxx>
21#include <svl/solar.hrc>
22#include <vcl/event.hxx>
23#include <vcl/layout.hxx>
24#include <vcl/settings.hxx>
25
26#include <vcl/svapp.hxx>
27#include <vcl/timer.hxx>
28#include <vcl/idle.hxx>
29#include <o3tl/safeint.hxx>
30#include <osl/diagnose.h>
31#include <rtl/instance.hxx>
32#include <toolkit/helper/vclunohelper.hxx>
33#include <tools/debug.hxx>
34#include <comphelper/processfactory.hxx>
35#include <comphelper/propertysequence.hxx>
36
37#include <sfx2/dockwin.hxx>
38#include <sfx2/bindings.hxx>
39#include <sfx2/viewfrm.hxx>
40#include <sfx2/dispatch.hxx>
41#include <workwin.hxx>
42#include <splitwin.hxx>
43#include <sfx2/viewsh.hxx>
44
45#include <com/sun/star/beans/UnknownPropertyException.hpp>
46#include <com/sun/star/lang/XSingleComponentFactory.hpp>
47#include <com/sun/star/awt/XWindow.hpp>
48#include <com/sun/star/uno/XComponentContext.hpp>
49#include <com/sun/star/frame/ModuleManager.hpp>
50#include <com/sun/star/container/XNameAccess.hpp>
51#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
52#include <com/sun/star/ui/theWindowContentFactoryManager.hpp>
53
54#define MAX_TOGGLEAREA_WIDTH20 20
55#define MAX_TOGGLEAREA_HEIGHT20 20
56
57using namespace ::com::sun::star;
58
59// If you want to change the number you also have to:
60// - Add new slot ids to sfxsids.hrc
61// - Add new slots to frmslots.sdi
62// - Add new slot definitions to sfx.sdi
63const int NUM_OF_DOCKINGWINDOWS = 10;
64
65namespace {
66
67class SfxTitleDockingWindow : public SfxDockingWindow
68{
69 VclPtr<vcl::Window> m_pWrappedWindow;
70
71public:
72 SfxTitleDockingWindow(
73 SfxBindings* pBindings ,
74 SfxChildWindow* pChildWin ,
75 vcl::Window* pParent ,
76 WinBits nBits);
77 virtual ~SfxTitleDockingWindow() override;
78 virtual void dispose() override;
79
80 vcl::Window* GetWrappedWindow() const { return m_pWrappedWindow; }
81 void SetWrappedWindow(vcl::Window* const pWindow);
82
83 virtual void StateChanged( StateChangedType nType ) override;
84 virtual void Resize() override;
85 virtual void Resizing( Size& rSize ) override;
86};
87
88 struct WindowState
89 {
90 OUString sTitle;
91 };
92}
93
94static bool lcl_getWindowState( const uno::Reference< container::XNameAccess >& xWindowStateMgr, const OUString& rResourceURL, WindowState& rWindowState )
95{
96 bool bResult = false;
97
98 try
99 {
100 uno::Any a;
101 uno::Sequence< beans::PropertyValue > aWindowState;
102 a = xWindowStateMgr->getByName( rResourceURL );
103 if ( a >>= aWindowState )
104 {
105 for ( const auto& rProp : std::as_const(aWindowState) )
106 {
107 if ( rProp.Name == "UIName" )
108 {
109 rProp.Value >>= rWindowState.sTitle;
110 }
111 }
112 }
113
114 bResult = true;
115 }
116 catch ( container::NoSuchElementException& )
117 {
118 bResult = false;
119 }
120
121 return bResult;
122}
123
124SfxDockingWrapper::SfxDockingWrapper( vcl::Window* pParentWnd ,
125 sal_uInt16 nId ,
126 SfxBindings* pBindings ,
127 SfxChildWinInfo* pInfo )
128 : SfxChildWindow( pParentWnd , nId )
129{
130 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
131
132 VclPtr<SfxTitleDockingWindow> pTitleDockWindow = VclPtr<SfxTitleDockingWindow>::Create( pBindings, this, pParentWnd,
133 WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE);
134 SetWindow( pTitleDockWindow );
135
136 // Use factory manager to retrieve XWindow factory. That can be used to instantiate
137 // the real window factory.
138 uno::Reference< lang::XSingleComponentFactory > xFactoryMgr = ui::theWindowContentFactoryManager::get(xContext);
139
140 SfxDispatcher* pDispatcher = pBindings->GetDispatcher();
141 uno::Reference< frame::XFrame > xFrame = pDispatcher->GetFrame()->GetFrame().GetFrameInterface();
142 // create a resource URL from the nId provided by the sfx2
143 OUString aResourceURL = "private:resource/dockingwindow/" + OUString::number(nId);
144 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
145 {
146 {"Frame", uno::Any(xFrame)},
147 {"ResourceURL", uno::Any(aResourceURL)},
148 }));
149
150 uno::Reference< awt::XWindow > xWindow;
151 try
152 {
153 xWindow.set(
154 xFactoryMgr->createInstanceWithArgumentsAndContext( aArgs, xContext ),
155 uno::UNO_QUERY );
156
157 static uno::WeakReference< frame::XModuleManager2 > s_xModuleManager;
158
159 uno::Reference< frame::XModuleManager2 > xModuleManager( s_xModuleManager );
160 if ( !xModuleManager.is() )
161 {
162 xModuleManager = frame::ModuleManager::create(xContext);
163 s_xModuleManager = xModuleManager;
164 }
165
166 static uno::WeakReference< container::XNameAccess > s_xWindowStateConfiguration;
167
168 uno::Reference< container::XNameAccess > xWindowStateConfiguration( s_xWindowStateConfiguration );
169 if ( !xWindowStateConfiguration.is() )
170 {
171 xWindowStateConfiguration = ui::theWindowStateConfiguration::get( xContext );
172 s_xWindowStateConfiguration = xWindowStateConfiguration;
173 }
174
175 OUString sModuleIdentifier = xModuleManager->identify( xFrame );
176
177 uno::Reference< container::XNameAccess > xModuleWindowState(
178 xWindowStateConfiguration->getByName( sModuleIdentifier ),
179 uno::UNO_QUERY );
180 if ( xModuleWindowState.is() )
181 {
182 WindowState aDockWinState;
183 if ( lcl_getWindowState( xModuleWindowState, aResourceURL, aDockWinState ))
184 pTitleDockWindow->SetText( aDockWinState.sTitle );
185 }
186 }
187 catch ( beans::UnknownPropertyException& )
188 {
189 }
190 catch ( uno::RuntimeException& )
191 {
192 }
193 catch ( uno::Exception& )
194 {
195 }
196
197 VclPtr<vcl::Window> pContentWindow = VCLUnoHelper::GetWindow(xWindow);
198 if ( pContentWindow )
199 pContentWindow->SetStyle( pContentWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL );
200 pTitleDockWindow->SetWrappedWindow(pContentWindow);
201
202 GetWindow()->SetOutputSizePixel( Size( 270, 240 ) );
203
204 static_cast<SfxDockingWindow*>( GetWindow() )->Initialize( pInfo );
205 SetHideNotDelete( true );
206}
207
208std::unique_ptr<SfxChildWindow> SfxDockingWrapper::CreateImpl(vcl::Window *pParent, sal_uInt16 nId,
209 SfxBindings *pBindings, SfxChildWinInfo* pInfo)
210{
211 return std::make_unique<SfxDockingWrapper>(pParent, nId, pBindings, pInfo);
212}
213
214void SfxDockingWrapper::RegisterChildWindow (bool bVis, SfxModule *pMod, SfxChildWindowFlags nFlags)
215{
216 // pre-register a couple of docking windows
217 for (int i=0; i < NUM_OF_DOCKINGWINDOWS; i++ )
218 {
219 sal_uInt16 nID = sal_uInt16(SID_DOCKWIN_START9800+i);
220 auto pFact = std::make_unique<SfxChildWinFactory>( SfxDockingWrapper::CreateImpl, nID, 0xffff );
221 pFact->aInfo.nFlags |= nFlags;
222 pFact->aInfo.bVisible = bVis;
223 SfxChildWindow::RegisterChildWindow(pMod, std::move(pFact));
224 }
225}
226
227SfxChildWinInfo SfxDockingWrapper::GetInfo() const
228{
229 SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
230 static_cast<SfxDockingWindow*>(GetWindow())->FillInfo( aInfo );
231 return aInfo;
232};
233
234SfxTitleDockingWindow::SfxTitleDockingWindow(SfxBindings* pBind, SfxChildWindow* pChildWin,
235 vcl::Window* pParent, WinBits nBits)
236 : SfxDockingWindow(pBind, pChildWin, pParent, nBits)
237 , m_pWrappedWindow(nullptr)
238{
239}
240
241SfxTitleDockingWindow::~SfxTitleDockingWindow()
242{
243 disposeOnce();
244}
245
246void SfxTitleDockingWindow::dispose()
247{
248 m_pWrappedWindow.disposeAndClear();
249 SfxDockingWindow::dispose();
250}
251
252void SfxTitleDockingWindow::SetWrappedWindow( vcl::Window* const pWindow )
253{
254 m_pWrappedWindow = pWindow;
255 if (m_pWrappedWindow)
256 {
257 m_pWrappedWindow->SetParent(this);
258 m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
259 m_pWrappedWindow->Show();
260 }
261}
262
263void SfxTitleDockingWindow::StateChanged( StateChangedType nType )
264{
265 if ( nType == StateChangedType::InitShow )
266 {
267 vcl::Window* pWindow = GetWrappedWindow();
268 if ( pWindow )
269 {
270 pWindow->SetSizePixel( GetOutputSizePixel() );
271 pWindow->Show();
272 }
273 }
274
275 SfxDockingWindow::StateChanged(nType);
276}
277
278void SfxTitleDockingWindow::Resize()
279{
280 SfxDockingWindow::Resize();
281 if (m_pWrappedWindow)
282 m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
283}
284
285void SfxTitleDockingWindow::Resizing( Size &rSize )
286{
287 SfxDockingWindow::Resizing( rSize );
288 if (m_pWrappedWindow)
289 m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() );
290}
291
292namespace
293{
294 struct ChildrenRegisteredMap : public rtl::Static< bool, ChildrenRegisteredMap > {};
295}
296
297static bool lcl_checkDockingWindowID( sal_uInt16 nID )
298{
299 return nID >= SID_DOCKWIN_START9800 && nID < o3tl::make_unsigned(SID_DOCKWIN_START9800+NUM_OF_DOCKINGWINDOWS);
300}
301
302static SfxWorkWindow* lcl_getWorkWindowFromXFrame( const uno::Reference< frame::XFrame >& rFrame )
303{
304 // We need to find the corresponding SfxFrame of our XFrame
305 SfxFrame* pFrame = SfxFrame::GetFirst();
306 SfxFrame* pXFrame = nullptr;
307 while ( pFrame )
308 {
309 uno::Reference< frame::XFrame > xViewShellFrame( pFrame->GetFrameInterface() );
310 if ( xViewShellFrame == rFrame )
311 {
312 pXFrame = pFrame;
313 break;
314 }
315 else
316 pFrame = SfxFrame::GetNext( *pFrame );
317 }
318
319 // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows)
320 if ( pXFrame )
321 return pXFrame->GetWorkWindow_Impl();
322 else
323 return nullptr;
324}
325
326/** Factory function used by the framework layout manager to "create" a docking window with a special name.
327 The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located
328 in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
329*/
330void SfxDockingWindowFactory( const uno::Reference< frame::XFrame >& rFrame, const OUString& rDockingWindowName )
331{
332 SolarMutexGuard aGuard;
333 sal_uInt16 nID = sal_uInt16(rDockingWindowName.toInt32());
334
335 // Check the range of the provided ID otherwise nothing will happen
336 if ( !lcl_checkDockingWindowID( nID ))
337 return;
338
339 SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame );
340 if ( pWorkWindow )
341 {
342 SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
343 if ( !pChildWindow )
344 {
345 // Register window at the workwindow child window list
346 pWorkWindow->SetChildWindow_Impl( nID, true, false );
347 }
348 }
349}
350
351/** Function used by the framework layout manager to determine the visibility state of a docking window with
352 a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot
353 range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800).
354*/
355bool IsDockingWindowVisible( const uno::Reference< frame::XFrame >& rFrame, const OUString& rDockingWindowName )
356{
357 SolarMutexGuard aGuard;
358
359 sal_uInt16 nID = sal_uInt16(rDockingWindowName.toInt32());
360
361 // Check the range of the provided ID otherwise nothing will happen
362 if ( lcl_checkDockingWindowID( nID ))
363 {
364 SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame );
365 if ( pWorkWindow )
366 {
367 SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID);
368 if ( pChildWindow )
369 return true;
370 }
371 }
372
373 return false;
374}
375
376class SfxDockingWindow_Impl
377{
378friend class SfxDockingWindow;
379
380 SfxChildAlignment eLastAlignment;
381 SfxChildAlignment eDockAlignment;
382 bool bConstructed;
383 Size aMinSize;
384 VclPtr<SfxSplitWindow> pSplitWin;
385 Idle aMoveIdle;
386
387 // The following members are only valid in the time from startDocking to
388 // EndDocking:
389 Size aSplitSize;
390 long nHorizontalSize;
391 long nVerticalSize;
392 sal_uInt16 nLine;
393 sal_uInt16 nPos;
394 sal_uInt16 nDockLine;
395 sal_uInt16 nDockPos;
396 bool bNewLine;
397 bool bDockingPrevented;
398 OString aWinState;
399
400 explicit SfxDockingWindow_Impl(SfxDockingWindow *pBase);
401 SfxChildAlignment GetLastAlignment() const
402 { return eLastAlignment; }
403 void SetLastAlignment(SfxChildAlignment eAlign)
404 { eLastAlignment = eAlign; }
405 SfxChildAlignment GetDockAlignment() const
406 { return eDockAlignment; }
407 void SetDockAlignment(SfxChildAlignment eAlign)
408 { eDockAlignment = eAlign; }
409};
410
411SfxDockingWindow_Impl::SfxDockingWindow_Impl(SfxDockingWindow* pBase)
412 :eLastAlignment(SfxChildAlignment::NOALIGNMENT)
413 ,eDockAlignment(SfxChildAlignment::NOALIGNMENT)
414 ,bConstructed(false)
415 ,pSplitWin(nullptr)
416 ,nHorizontalSize(0)
417 ,nVerticalSize(0)
418 ,nLine(0)
419 ,nPos(0)
420 ,nDockLine(0)
421 ,nDockPos(0)
422 ,bNewLine(false)
423 ,bDockingPrevented(false)
424{
425 aMoveIdle.SetPriority(TaskPriority::RESIZE);
426 aMoveIdle.SetInvokeHandler(LINK(pBase,SfxDockingWindow,TimerHdl)::tools::detail::makeLink( ::tools::detail::castTo<SfxDockingWindow
*>(pBase), &SfxDockingWindow::LinkStubTimerHdl)
);
427 aMoveIdle.SetDebugName( "sfx::SfxDockingWindow_Impl aMoveIdle" );
428}
429
430/* [Description]
431
432 This virtual method of the class FloatingWindow keeps track of changes in
433 FloatingSize. If this method is overridden by a derived class,
434 then the FloatingWindow: Resize() must also be called.
435*/
436void SfxDockingWindow::Resize()
437{
438 DockingWindow::Resize();
439 Invalidate();
440 if ( !pImpl || !pImpl->bConstructed || !pMgr )
441 return;
442
443 if ( IsFloatingMode() )
444 {
445 // start timer for saving window status information
446 pImpl->aMoveIdle.Start();
447 }
448 else
449 {
450 Size aSize( GetSizePixel() );
451 switch ( pImpl->GetDockAlignment() )
452 {
453 case SfxChildAlignment::LEFT:
454 case SfxChildAlignment::FIRSTLEFT:
455 case SfxChildAlignment::LASTLEFT:
456 case SfxChildAlignment::RIGHT:
457 case SfxChildAlignment::FIRSTRIGHT:
458 case SfxChildAlignment::LASTRIGHT:
459 pImpl->nHorizontalSize = aSize.Width();
460 pImpl->aSplitSize = aSize;
461 break;
462 case SfxChildAlignment::TOP:
463 case SfxChildAlignment::LOWESTTOP:
464 case SfxChildAlignment::HIGHESTTOP:
465 case SfxChildAlignment::BOTTOM:
466 case SfxChildAlignment::HIGHESTBOTTOM:
467 case SfxChildAlignment::LOWESTBOTTOM:
468 pImpl->nVerticalSize = aSize.Height();
469 pImpl->aSplitSize = aSize;
470 break;
471 default:
472 break;
473 }
474 }
475}
476
477/* [Description]
478
479 This virtual method of the class DockingWindow makes it possible to
480 intervene in the switching of the floating mode.
481 If this method is overridden by a derived class,
482 then the SfxDockingWindow::PrepareToggleFloatingMode() must be called
483 afterwards, if not FALSE is returned.
484*/
485bool SfxDockingWindow::PrepareToggleFloatingMode()
486{
487 if (!pImpl || !pImpl->bConstructed)
488 return true;
489
490 if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr )
491 return false;
492
493 if ( pImpl->bDockingPrevented )
494 return false;
495
496 if (!IsFloatingMode())
497 {
498 // Test, if FloatingMode is permitted.
499 if ( CheckAlignment(GetAlignment(),SfxChildAlignment::NOALIGNMENT) != SfxChildAlignment::NOALIGNMENT )
500 return false;
501
502 if ( pImpl->pSplitWin )
503 {
504 // The DockingWindow is inside a SplitWindow and will be teared of.
505 pImpl->pSplitWin->RemoveWindow(this/*, sal_False*/);
506 pImpl->pSplitWin = nullptr;
507 }
508 }
509 else if ( pMgr )
510 {
511 pImpl->aWinState = GetFloatingWindow()->GetWindowState();
512
513 // Test if it is allowed to dock,
514 if (CheckAlignment(GetAlignment(),pImpl->GetLastAlignment()) == SfxChildAlignment::NOALIGNMENT)
515 return false;
516
517 // Test, if the Workwindow allows for docking at the moment.
518 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
519 if ( !pWorkWin->IsDockingAllowed() || !pWorkWin->IsInternalDockingAllowed() )
520 return false;
521 }
522
523 return true;
524}
525
526/* [Description]
527
528 This virtual method of the DockingWindow class sets the internal data of
529 the SfxDockingWindow and ensures the correct alignment on the parent window.
530 Through PrepareToggleFloatMode and Initialize it is ensured that
531 pImpl-> GetLastAlignment() always delivers an allowed alignment. If this
532 method is overridden by a derived class, then first the
533 SfxDockingWindow::ToggleFloatingMode() must be called.
534*/
535void SfxDockingWindow::ToggleFloatingMode()
536{
537 if ( !pImpl || !pImpl->bConstructed || !pMgr )
538 return; // No Handler call
539
540 // Remember old alignment and then switch.
541 // SV has already switched, but the alignment SfxDockingWindow is still
542 // the old one. What I was before?
543 SfxChildAlignment eLastAlign = GetAlignment();
544
545 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
546
547 if (IsFloatingMode())
548 {
549 SetAlignment(SfxChildAlignment::NOALIGNMENT);
550 if ( !pImpl->aWinState.isEmpty() )
551 GetFloatingWindow()->SetWindowState( pImpl->aWinState );
552 else
553 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
554 }
555 else
556 {
557 if (pImpl->GetDockAlignment() == eLastAlign)
558 {
559 // If ToggleFloatingMode was called, but the DockAlignment still
560 // is unchanged, then this means that it must have been a toggling
561 // through DClick, so use last alignment
562 SetAlignment (pImpl->GetLastAlignment());
563 }
564 else
565 {
566
567 // Toggling was triggered by dragging
568 pImpl->nLine = pImpl->nDockLine;
569 pImpl->nPos = pImpl->nDockPos;
570 SetAlignment (pImpl->GetDockAlignment());
571 }
572
573 // The DockingWindow is now in a SplitWindow
574 pImpl->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
575
576 // The LastAlignment is still the last docked
577 SfxSplitWindow *pSplit = pWorkWin->GetSplitWindow_Impl(pImpl->GetLastAlignment());
578
579 DBG_ASSERT( pSplit, "LastAlignment is not correct!" )do { if (true && (!(pSplit))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/dialog/dockwin.cxx"
":" "579" ": "), "%s", "LastAlignment is not correct!"); } }
while (false)
;
580 if ( pSplit && pSplit != pImpl->pSplitWin )
581 pSplit->ReleaseWindow_Impl(this);
582 if ( pImpl->GetDockAlignment() == eLastAlign )
583 pImpl->pSplitWin->InsertWindow( this, pImpl->aSplitSize );
584 else
585 pImpl->pSplitWin->InsertWindow( this, pImpl->aSplitSize, pImpl->nLine, pImpl->nPos, pImpl->bNewLine );
586 if ( !pImpl->pSplitWin->IsFadeIn() )
587 pImpl->pSplitWin->FadeIn();
588 }
589
590 // Keep the old alignment for the next toggle; set it only now due to the
591 // unregister SplitWindow!
592 pImpl->SetLastAlignment(eLastAlign);
593
594 // Reset DockAlignment, if EndDocking is still called
595 pImpl->SetDockAlignment(GetAlignment());
596
597 // Dock or undock SfxChildWindow correctly.
598 pWorkWin->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW, SfxDockingConfig::TOGGLEFLOATMODE, pMgr->GetType() );
599}
600
601/* [Description]
602
603 This virtual method of the DockingWindow class takes the inner and outer
604 docking rectangle from the parent window. If this method is overridden by
605 a derived class, then SfxDockingWindow:StartDocking() has to be called at
606 the end.
607*/
608void SfxDockingWindow::StartDocking()
609{
610 if ( !pImpl || !pImpl->bConstructed || !pMgr )
611 return;
612 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
613 pWorkWin->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW, SfxDockingConfig::SETDOCKINGRECTS, pMgr->GetType() );
614 pImpl->SetDockAlignment(GetAlignment());
615
616 if ( pImpl->pSplitWin )
617 {
618 // Get the current docking data
619 pImpl->pSplitWin->GetWindowPos(this, pImpl->nLine, pImpl->nPos);
620 pImpl->nDockLine = pImpl->nLine;
621 pImpl->nDockPos = pImpl->nPos;
622 pImpl->bNewLine = false;
623 }
624}
625
626/* [Description]
627
628 This virtual method of the DockingWindow class calculates the current
629 tracking rectangle. For this purpose the method CalcAlignment(RPOs, rRect)
630 is used, the behavior can be influenced by the derived classes (see below).
631 This method should if possible not be overwritten.
632*/
633bool SfxDockingWindow::Docking( const Point& rPos, tools::Rectangle& rRect )
634{
635 if ( Application::IsInModalMode() )
636 return true;
637
638 if ( !pImpl || !pImpl->bConstructed || !pMgr )
639 {
640 rRect.SetSize( Size() );
641 return IsFloatingMode();
642 }
643
644 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
645 if ( pImpl->bDockingPrevented || !pWorkWin->IsInternalDockingAllowed() )
646 return false;
647
648 bool bFloatMode = false;
649
650 if ( GetOuterRect().IsInside( rPos ) )
651 {
652 // Mouse within OuterRect: calculate Alignment and Rectangle
653 SfxChildAlignment eAlign = CalcAlignment(rPos, rRect);
654 if (eAlign == SfxChildAlignment::NOALIGNMENT)
655 bFloatMode = true;
656 pImpl->SetDockAlignment(eAlign);
657 }
658 else
659 {
660 // Mouse is not within OuterRect: must be FloatingWindow
661 // Is this allowed?
662 if (CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT) != SfxChildAlignment::NOALIGNMENT)
663 return false;
664 bFloatMode = true;
665 if ( SfxChildAlignment::NOALIGNMENT != pImpl->GetDockAlignment() )
666 {
667 // Due to a bug the rRect may only be changed when the
668 // alignment is changed!
669 pImpl->SetDockAlignment(SfxChildAlignment::NOALIGNMENT);
670 rRect.SetSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT));
671 }
672 }
673
674 return bFloatMode;
675}
676
677/** Virtual method of the DockingWindow class ensures the correct alignment on
678 the parent window. If this method is overridden by a derived class, then
679 SfxDockingWindow::EndDocking() must be called first.
680*/
681void SfxDockingWindow::EndDocking( const tools::Rectangle& rRect, bool bFloatMode )
682{
683 if ( !pImpl || !pImpl->bConstructed || IsDockingCanceled() || !pMgr )
684 return;
685
686 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
687
688 // If the alignment changes and the window is in a docked state in a
689 // SplitWindow, then it must be re-registered. If it is docked again,
690 // PrepareToggleFloatingMode() and ToggleFloatingMode() perform the
691 // re-registered
692 bool bReArrange = !bFloatMode;
693
694 if ( bReArrange )
695 {
696 if ( GetAlignment() != pImpl->GetDockAlignment() )
697 {
698 // before Show() is called must the reassignment have been made,
699 // therefore the base class can not be called
700 if ( IsFloatingMode() )
701 Show( false, ShowFlags::NoFocusChange );
702
703 // Set the size for toggling.
704 pImpl->aSplitSize = rRect.GetSize();
705 if ( IsFloatingMode() )
706 {
707 SetFloatingMode( bFloatMode );
708 if ( IsFloatingMode() )
709 Show( true, ShowFlags::NoFocusChange );
710 }
711 else
712 {
713 pImpl->pSplitWin->RemoveWindow(this,false);
714 pImpl->nLine = pImpl->nDockLine;
715 pImpl->nPos = pImpl->nDockPos;
716 pImpl->pSplitWin->ReleaseWindow_Impl(this);
717 pImpl->pSplitWin = pWorkWin->GetSplitWindow_Impl(pImpl->GetDockAlignment());
718 pImpl->pSplitWin->InsertWindow( this, pImpl->aSplitSize, pImpl->nDockLine, pImpl->nDockPos, pImpl->bNewLine );
719 if ( !pImpl->pSplitWin->IsFadeIn() )
720 pImpl->pSplitWin->FadeIn();
721 }
722 }
723 else if ( pImpl->nLine != pImpl->nDockLine || pImpl->nPos != pImpl->nDockPos || pImpl->bNewLine )
724 {
725 // Moved within Splitwindows
726 if ( pImpl->nLine != pImpl->nDockLine )
727 pImpl->aSplitSize = rRect.GetSize();
728 pImpl->pSplitWin->MoveWindow( this, pImpl->aSplitSize, pImpl->nDockLine, pImpl->nDockPos, pImpl->bNewLine );
729 }
730 }
731 else
732 {
733 DockingWindow::EndDocking(rRect, bFloatMode);
734 }
735
736 SetAlignment( IsFloatingMode() ? SfxChildAlignment::NOALIGNMENT : pImpl->GetDockAlignment() );
737}
738
739/* [Description]
740
741 Virtual method of the DockingWindow class. Here, the interactive resize in
742 FloatingMode can be influenced, for example by only allowing for discrete
743 values for width and / or height. The base implementation prevents that the
744 output size is smaller than one set with SetMinOutputSizePixel().
745*/
746void SfxDockingWindow::Resizing( Size& /*rSize*/ )
747{
748
749}
750
751/* [Description]
752
753 Constructor for the SfxDockingWindow class. A SfxChildWindow will be
754 required because the docking is implemented in Sfx through SfxChildWindows.
755*/
756SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
757 vcl::Window* pParent, WinBits nWinBits) :
758 DockingWindow (pParent, nWinBits),
759 pBindings(pBindinx),
760 pMgr(pCW)
761{
762 pImpl.reset(new SfxDockingWindow_Impl(this));
763}
764
765/** Constructor for the SfxDockingWindow class. A SfxChildWindow will be
766 required because the docking is implemented in Sfx through SfxChildWindows.
767*/
768SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW,
769 vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
770 : DockingWindow(pParent, "DockingWindow", "sfx/ui/dockingwindow.ui")
771 , pBindings(pBindinx)
772 , pMgr(pCW)
773{
774 m_xVclContentArea = VclPtr<VclVBox>::Create(this);
1
Calling 'VclPtr::Create'
3
Returned allocated memory
4
Calling implicit destructor for 'VclPtr<VclVBox>'
5
Calling '~Reference'
12
Returning from '~Reference'
13
Returning from destructor for 'VclPtr<VclVBox>'
775 m_xVclContentArea->Show();
14
Calling 'VclPtr::operator->'
776 m_xBuilder.reset(Application::CreateInterimBuilder(m_xVclContentArea, rUIXMLDescription, true));
777 m_xContainer = m_xBuilder->weld_container(rID);
778
779 pImpl.reset(new SfxDockingWindow_Impl(this));
780}
781
782/** Initialization of the SfxDockingDialog class via a SfxChildWinInfo.
783 The initialization is done only in a 2nd step after the constructor, this
784 constructor should be called from the derived class or from the
785 SfxChildWindows.
786*/
787void SfxDockingWindow::Initialize(SfxChildWinInfo *pInfo)
788{
789 if ( !pMgr )
790 {
791 pImpl->SetDockAlignment( SfxChildAlignment::NOALIGNMENT );
792 pImpl->bConstructed = true;
793 return;
794 }
795
796 if (pInfo && (pInfo->nFlags & SfxChildWindowFlags::FORCEDOCK))
797 pImpl->bDockingPrevented = true;
798
799 pImpl->aSplitSize = GetOutputSizePixel();
800 if ( !GetFloatingSize().Width() )
801 {
802 Size aMinSize( GetMinOutputSizePixel() );
803 SetFloatingSize( pImpl->aSplitSize );
804 if ( pImpl->aSplitSize.Width() < aMinSize.Width() )
805 pImpl->aSplitSize.setWidth( aMinSize.Width() );
806 if ( pImpl->aSplitSize.Height() < aMinSize.Height() )
807 pImpl->aSplitSize.setHeight( aMinSize.Height() );
808 }
809
810 bool bVertHorzRead( false );
811 if (pInfo && !pInfo->aExtraString.isEmpty())
812 {
813 // get information about alignment, split size and position in SplitWindow
814 OUString aStr;
815 sal_Int32 nPos = pInfo->aExtraString.indexOf("AL:");
816 if ( nPos != -1 )
817 {
818 // alignment information
819 sal_Int32 n1 = pInfo->aExtraString.indexOf('(', nPos);
820 if ( n1 != -1 )
821 {
822 sal_Int32 n2 = pInfo->aExtraString.indexOf(')', n1);
823 if ( n2 != -1 )
824 {
825 // extract alignment information from extrastring
826 aStr = pInfo->aExtraString.copy(nPos, n2 - nPos + 1);
827 pInfo->aExtraString = pInfo->aExtraString.replaceAt(nPos, n2 - nPos + 1, "");
828 aStr = aStr.replaceAt(nPos, n1-nPos+1, "");
829 }
830 }
831 }
832
833 if ( !aStr.isEmpty() )
834 {
835 // accept window state only if alignment is also set
836 pImpl->aWinState = pInfo->aWinState;
837
838 // check for valid alignment
839 SfxChildAlignment eLocalAlignment = static_cast<SfxChildAlignment>(static_cast<sal_uInt16>(aStr.toInt32()));
840 bool bIgnoreFloatConfig = (eLocalAlignment == SfxChildAlignment::NOALIGNMENT &&
841 !StyleSettings::GetDockingFloatsSupported());
842 if (pImpl->bDockingPrevented || bIgnoreFloatConfig)
843 // docking prevented, ignore old configuration and take alignment from default
844 aStr.clear();
845 else
846 SetAlignment( eLocalAlignment );
847
848 SfxChildAlignment eAlign = CheckAlignment(GetAlignment(),GetAlignment());
849 if ( eAlign != GetAlignment() )
850 {
851 OSL_FAIL("Invalid Alignment!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/dialog/dockwin.cxx"
":" "851" ": "), "%s", "Invalid Alignment!"); } } while (false
)
;
852 SetAlignment( eAlign );
853 aStr.clear();
854 }
855
856 // get last alignment (for toggling)
857 nPos = aStr.indexOf(',');
858 if ( nPos != -1 )
859 {
860 aStr = aStr.copy(nPos+1);
861 pImpl->SetLastAlignment( static_cast<SfxChildAlignment>(static_cast<sal_uInt16>(aStr.toInt32())) );
862 }
863
864 nPos = aStr.indexOf(',');
865 if ( nPos != -1 )
866 {
867 // get split size and position in SplitWindow
868 Point aPos;
869 aStr = aStr.copy(nPos+1);
870 if ( GetPosSizeFromString( aStr, aPos, pImpl->aSplitSize ) )
871 {
872 pImpl->nLine = pImpl->nDockLine = static_cast<sal_uInt16>(aPos.X());
873 pImpl->nPos = pImpl->nDockPos = static_cast<sal_uInt16>(aPos.Y());
874 pImpl->nVerticalSize = pImpl->aSplitSize.Height();
875 pImpl->nHorizontalSize = pImpl->aSplitSize.Width();
876 if ( GetSplitSizeFromString( aStr, pImpl->aSplitSize ))
877 bVertHorzRead = true;
878 }
879 }
880 }
881 else {
882 OSL_FAIL( "Information is missing!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/dialog/dockwin.cxx"
":" "882" ": "), "%s", "Information is missing!"); } } while
(false)
;
883 }
884 }
885
886 if ( !bVertHorzRead )
887 {
888 pImpl->nVerticalSize = pImpl->aSplitSize.Height();
889 pImpl->nHorizontalSize = pImpl->aSplitSize.Width();
890 }
891
892 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
893 if ( GetAlignment() != SfxChildAlignment::NOALIGNMENT )
894 {
895 // check if SfxWorkWindow is able to allow docking at its border
896 if (
897 !pWorkWin->IsDockingAllowed() ||
898 !pWorkWin->IsInternalDockingAllowed() ||
899 ( (GetFloatStyle() & WB_STANDALONE) && Application::IsInModalMode()) )
900 {
901 SetAlignment( SfxChildAlignment::NOALIGNMENT );
902 }
903 }
904
905 // detect floating mode
906 // toggling mode will not execute code in handlers, because pImpl->bConstructed is not set yet
907 bool bFloatMode = IsFloatingMode();
908 if ( bFloatMode != (GetAlignment() == SfxChildAlignment::NOALIGNMENT) )
909 {
910 bFloatMode = !bFloatMode;
911 SetFloatingMode( bFloatMode );
912 if ( bFloatMode )
913 {
914 if ( !pImpl->aWinState.isEmpty() )
915 GetFloatingWindow()->SetWindowState( pImpl->aWinState );
916 else
917 GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() );
918 }
919 }
920
921 if ( IsFloatingMode() )
922 {
923 // validate last alignment
924 SfxChildAlignment eLastAlign = pImpl->GetLastAlignment();
925 if ( eLastAlign == SfxChildAlignment::NOALIGNMENT)
926 eLastAlign = CheckAlignment(eLastAlign, SfxChildAlignment::LEFT);
927 if ( eLastAlign == SfxChildAlignment::NOALIGNMENT)
928 eLastAlign = CheckAlignment(eLastAlign, SfxChildAlignment::RIGHT);
929 if ( eLastAlign == SfxChildAlignment::NOALIGNMENT)
930 eLastAlign = CheckAlignment(eLastAlign, SfxChildAlignment::TOP);
931 if ( eLastAlign == SfxChildAlignment::NOALIGNMENT)
932 eLastAlign = CheckAlignment(eLastAlign, SfxChildAlignment::BOTTOM);
933 pImpl->SetLastAlignment(eLastAlign);
934 }
935 else
936 {
937 // docked window must have NOALIGNMENT as last alignment
938 pImpl->SetLastAlignment(SfxChildAlignment::NOALIGNMENT);
939
940 pImpl->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment());
941 pImpl->pSplitWin->InsertWindow(this, pImpl->aSplitSize);
942 }
943
944 // save alignment
945 pImpl->SetDockAlignment( GetAlignment() );
946}
947
948void SfxDockingWindow::Initialize_Impl()
949{
950 if ( !pMgr )
951 {
952 pImpl->bConstructed = true;
953 return;
954 }
955
956 FloatingWindow* pFloatWin = GetFloatingWindow();
957 bool bSet = false;
958 if ( pFloatWin )
959 {
960 bSet = !pFloatWin->IsDefaultPos();
961 }
962 else
963 {
964 Point aPos = GetFloatingPos();
965 if ( aPos != Point() )
966 bSet = true;
967 }
968
969 if ( !bSet)
970 {
971 SfxViewFrame *pFrame = pBindings->GetDispatcher_Impl()->GetFrame();
972 vcl::Window* pEditWin = pFrame->GetViewShell()->GetWindow();
973 Point aPos = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
974 aPos = GetParent()->ScreenToOutputPixel( aPos );
975 SetFloatingPos( aPos );
976 }
977
978 if ( pFloatWin )
979 {
980 // initialize floating window
981 if ( pImpl->aWinState.isEmpty() )
982 // window state never set before, get if from defaults
983 pImpl->aWinState = pFloatWin->GetWindowState();
984
985 // trick: use VCL method SetWindowState to adjust position and size
986 pFloatWin->SetWindowState( pImpl->aWinState );
987 Size aSize(pFloatWin->GetSizePixel());
988
989 // remember floating size for calculating alignment and tracking rectangle
990 SetFloatingSize(aSize);
991
992 }
993
994 // allow calling of docking handlers
995 pImpl->bConstructed = true;
996}
997
998/** Fills a SfxChildWinInfo with specific data from SfxDockingWindow,
999 so that it can be written in the INI file. It is assumed that rinfo
1000 receives all other possible relevant data in the ChildWindow class.
1001 Insertions are marked with size and the ZoomIn flag.
1002 If this method is overridden, the base implementation must be called first.
1003*/
1004void SfxDockingWindow::FillInfo(SfxChildWinInfo& rInfo) const
1005{
1006 if (!pMgr || !pImpl)
1007 return;
1008
1009 if (GetFloatingWindow() && pImpl->bConstructed)
1010 pImpl->aWinState = GetFloatingWindow()->GetWindowState();
1011
1012 rInfo.aWinState = pImpl->aWinState;
1013 rInfo.aExtraString = "AL:(";
1014 rInfo.aExtraString += OUString::number(static_cast<sal_uInt16>(GetAlignment()));
1015 rInfo.aExtraString += ",";
1016 rInfo.aExtraString += OUString::number (static_cast<sal_uInt16>(pImpl->GetLastAlignment()));
1017
1018 Point aPos(pImpl->nLine, pImpl->nPos);
1019 rInfo.aExtraString += ",";
1020 rInfo.aExtraString += OUString::number( aPos.X() );
1021 rInfo.aExtraString += "/";
1022 rInfo.aExtraString += OUString::number( aPos.Y() );
1023 rInfo.aExtraString += "/";
1024 rInfo.aExtraString += OUString::number( pImpl->nHorizontalSize );
1025 rInfo.aExtraString += "/";
1026 rInfo.aExtraString += OUString::number( pImpl->nVerticalSize );
1027 rInfo.aExtraString += ",";
1028 rInfo.aExtraString += OUString::number( pImpl->aSplitSize.Width() );
1029 rInfo.aExtraString += ";";
1030 rInfo.aExtraString += OUString::number( pImpl->aSplitSize.Height() );
1031
1032 rInfo.aExtraString += ")";
1033}
1034
1035SfxDockingWindow::~SfxDockingWindow()
1036{
1037 disposeOnce();
1038}
1039
1040void SfxDockingWindow::dispose()
1041{
1042 ReleaseChildWindow_Impl();
1043 pImpl.reset();
1044 m_xContainer.reset();
1045 m_xBuilder.reset();
1046 m_xVclContentArea.disposeAndClear();
1047 DockingWindow::dispose();
1048}
1049
1050void SfxDockingWindow::ReleaseChildWindow_Impl()
1051{
1052 if ( pMgr && pMgr->GetFrame() == pBindings->GetActiveFrame() )
1053 pBindings->SetActiveFrame( nullptr );
1054
1055 if ( pMgr && pImpl->pSplitWin && pImpl->pSplitWin->IsItemValid( GetType() ) )
1056 pImpl->pSplitWin->RemoveWindow(this);
1057
1058 pMgr=nullptr;
1059}
1060
1061/** This method calculates a resulting alignment for the given mouse position
1062 and tracking rectangle. When changing the alignment it can also be that
1063 the tracking rectangle is changed, so that an altered rectangle is
1064 returned. The user of this class can influence behaviour of this method,
1065 and thus the behavior of his DockinWindow class when docking where the
1066 called virtual method:
1067
1068 SfxDockingWindow::CalcDockingSize (SfxChildAlignment eAlign)
1069
1070 is overridden (see below).
1071*/
1072SfxChildAlignment SfxDockingWindow::CalcAlignment(const Point& rPos, tools::Rectangle& rRect)
1073{
1074 // calculate hypothetical sizes for different modes
1075 Size aFloatingSize(CalcDockingSize(SfxChildAlignment::NOALIGNMENT));
1076
1077 // check if docking is permitted
1078 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1079 if ( !pWorkWin->IsDockingAllowed() )
1080 {
1081 rRect.SetSize( aFloatingSize );
1082 return pImpl->GetDockAlignment();
1083 }
1084
1085 // calculate borders to shrink inner area before checking for intersection with tracking rectangle
1086 long nLRBorder, nTBBorder;
1087
1088 // take the smaller size of docked and floating mode
1089 Size aBorderTmp = pImpl->aSplitSize;
1090 if ( GetFloatingSize().Height() < aBorderTmp.Height() )
1091 aBorderTmp.setHeight( GetFloatingSize().Height() );
1092 if ( GetFloatingSize().Width() < aBorderTmp.Width() )
1093 aBorderTmp.setWidth( GetFloatingSize().Width() );
1094
1095 nLRBorder = aBorderTmp.Width();
1096 nTBBorder = aBorderTmp.Height();
1097
1098 // limit border to predefined constant values
1099 if ( nLRBorder > MAX_TOGGLEAREA_WIDTH20 )
1100 nLRBorder = MAX_TOGGLEAREA_WIDTH20;
1101 if ( nTBBorder > MAX_TOGGLEAREA_WIDTH20 )
1102 nTBBorder = MAX_TOGGLEAREA_WIDTH20;
1103
1104 // shrink area for floating mode if possible
1105 tools::Rectangle aInRect = GetInnerRect();
1106 if ( aInRect.GetWidth() > nLRBorder )
1107 aInRect.AdjustLeft(nLRBorder/2 );
1108 if ( aInRect.GetWidth() > nLRBorder )
1109 aInRect.AdjustRight( -(nLRBorder/2) );
1110 if ( aInRect.GetHeight() > nTBBorder )
1111 aInRect.AdjustTop(nTBBorder/2 );
1112 if ( aInRect.GetHeight() > nTBBorder )
1113 aInRect.AdjustBottom( -(nTBBorder/2) );
1114
1115 // calculate alignment resulting from docking rectangle
1116 bool bBecomesFloating = false;
1117 SfxChildAlignment eDockAlign = pImpl->GetDockAlignment();
1118 tools::Rectangle aDockingRect( rRect );
1119 if ( !IsFloatingMode() )
1120 {
1121 // don't use tracking rectangle for alignment check, because it will be too large
1122 // to get a floating mode as result - switch to floating size
1123 // so the calculation only depends on the position of the rectangle, not the current
1124 // docking state of the window
1125 aDockingRect.SetSize( GetFloatingSize() );
1126
1127 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
1128 aDockingRect.SetPos( pWorkWin->GetWindow()->OutputToScreenPixel( pWorkWin->GetWindow()->GetPointerPosPixel() ) );
1129 }
1130
1131 Point aPos = aDockingRect.TopLeft();
1132 tools::Rectangle aIntersect = GetOuterRect().GetIntersection( aDockingRect );
1133 if ( aIntersect.IsEmpty() )
1134 // docking rectangle completely outside docking area -> floating mode
1135 bBecomesFloating = true;
1136 else
1137 {
1138 // create a small test rect around the mouse position and use this one
1139 // instead of the passed rRect to not dock too easily or by accident
1140 tools::Rectangle aSmallDockingRect;
1141 aSmallDockingRect.SetSize( Size( MAX_TOGGLEAREA_WIDTH20, MAX_TOGGLEAREA_HEIGHT20 ) );
1142 Point aNewPos(rPos);
1143 aNewPos.AdjustX( -(aSmallDockingRect.GetWidth()/2) );
1144 aNewPos.AdjustY( -(aSmallDockingRect.GetHeight()/2) );
1145 aSmallDockingRect.SetPos(aNewPos);
1146 tools::Rectangle aIntersectRect = aInRect.GetIntersection( aSmallDockingRect );
1147 if ( aIntersectRect == aSmallDockingRect )
1148 // docking rectangle completely inside (shrunk) inner area -> floating mode
1149 bBecomesFloating = true;
1150 }
1151
1152 if ( bBecomesFloating )
1153 {
1154 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT);
1155 }
1156 else
1157 {
1158 // docking rectangle is in the "sensible area"
1159 Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
1160 Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
1161 Size aInSize = aInRect.GetSize();
1162 bool bNoChange = false;
1163
1164 // check if alignment is still unchanged
1165 switch ( GetAlignment() )
1166 {
1167 case SfxChildAlignment::LEFT:
1168 case SfxChildAlignment::FIRSTLEFT:
1169 case SfxChildAlignment::LASTLEFT:
1170 if (aInPosTL.X() <= 0)
1171 {
1172 eDockAlign = GetAlignment();
1173 bNoChange = true;
1174 }
1175 break;
1176 case SfxChildAlignment::TOP:
1177 case SfxChildAlignment::LOWESTTOP:
1178 case SfxChildAlignment::HIGHESTTOP:
1179 if ( aInPosTL.Y() <= 0)
1180 {
1181 eDockAlign = GetAlignment();
1182 bNoChange = true;
1183 }
1184 break;
1185 case SfxChildAlignment::RIGHT:
1186 case SfxChildAlignment::FIRSTRIGHT:
1187 case SfxChildAlignment::LASTRIGHT:
1188 if ( aInPosBR.X() >= aInSize.Width())
1189 {
1190 eDockAlign = GetAlignment();
1191 bNoChange = true;
1192 }
1193 break;
1194 case SfxChildAlignment::BOTTOM:
1195 case SfxChildAlignment::LOWESTBOTTOM:
1196 case SfxChildAlignment::HIGHESTBOTTOM:
1197 if ( aInPosBR.Y() >= aInSize.Height())
1198 {
1199 eDockAlign = GetAlignment();
1200 bNoChange = true;
1201 }
1202 break;
1203 default:
1204 break;
1205 }
1206
1207 if ( !bNoChange )
1208 {
1209 // alignment will change, test alignment according to distance of the docking rectangles edges
1210 bool bForbidden = true;
1211 if ( aInPosTL.X() <= 0)
1212 {
1213 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::LEFT);
1214 bForbidden = ( eDockAlign != SfxChildAlignment::LEFT &&
1215 eDockAlign != SfxChildAlignment::FIRSTLEFT &&
1216 eDockAlign != SfxChildAlignment::LASTLEFT );
1217 }
1218
1219 if ( bForbidden && aInPosTL.Y() <= 0)
1220 {
1221 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::TOP);
1222 bForbidden = ( eDockAlign != SfxChildAlignment::TOP &&
1223 eDockAlign != SfxChildAlignment::HIGHESTTOP &&
1224 eDockAlign != SfxChildAlignment::LOWESTTOP );
1225 }
1226
1227 if ( bForbidden && aInPosBR.X() >= aInSize.Width())
1228 {
1229 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::RIGHT);
1230 bForbidden = ( eDockAlign != SfxChildAlignment::RIGHT &&
1231 eDockAlign != SfxChildAlignment::FIRSTRIGHT &&
1232 eDockAlign != SfxChildAlignment::LASTRIGHT );
1233 }
1234
1235 if ( bForbidden && aInPosBR.Y() >= aInSize.Height())
1236 {
1237 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::BOTTOM);
1238 bForbidden = ( eDockAlign != SfxChildAlignment::BOTTOM &&
1239 eDockAlign != SfxChildAlignment::HIGHESTBOTTOM &&
1240 eDockAlign != SfxChildAlignment::LOWESTBOTTOM );
1241 }
1242
1243 // the calculated alignment was rejected by the window -> take floating mode
1244 if ( bForbidden )
1245 eDockAlign = CheckAlignment(pImpl->GetDockAlignment(),SfxChildAlignment::NOALIGNMENT);
1246 }
1247 }
1248
1249 if ( eDockAlign == SfxChildAlignment::NOALIGNMENT )
1250 {
1251 // In the FloatingMode the tracking rectangle will get the floating
1252 // size. Due to a bug the rRect may only be changed when the
1253 // alignment is changed!
1254 if ( eDockAlign != pImpl->GetDockAlignment() )
1255 aDockingRect.SetSize( aFloatingSize );
1256 }
1257 else
1258 {
1259 sal_uInt16 nLine, nPos;
1260 SfxSplitWindow *pSplitWin = pWorkWin->GetSplitWindow_Impl(eDockAlign);
1261 aPos = pSplitWin->ScreenToOutputPixel( aPos );
1262 if ( pSplitWin->GetWindowPos( aPos, nLine, nPos ) )
1263 {
1264 // mouse over splitwindow, get line and position
1265 pImpl->nDockLine = nLine;
1266 pImpl->nDockPos = nPos;
1267 pImpl->bNewLine = false;
1268 }
1269 else
1270 {
1271 // mouse touches inner border -> create new line
1272 if ( eDockAlign == GetAlignment() && pImpl->pSplitWin &&
1273 pImpl->nLine == pImpl->pSplitWin->GetLineCount()-1 && pImpl->pSplitWin->GetWindowCount(pImpl->nLine) == 1 )
1274 {
1275 // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow
1276 pImpl->nDockLine = pImpl->nLine;
1277 pImpl->nDockPos = pImpl->nPos;
1278 pImpl->bNewLine = false;
1279 }
1280 else
1281 {
1282 // create new line
1283 pImpl->nDockLine = pSplitWin->GetLineCount();
1284 pImpl->nDockPos = 0;
1285 pImpl->bNewLine = true;
1286 }
1287 }
1288
1289 bool bChanged = pImpl->nLine != pImpl->nDockLine || pImpl->nPos != pImpl->nDockPos || eDockAlign != GetAlignment();
1290 if ( !bChanged && !IsFloatingMode() )
1291 {
1292 // window only slightly moved, no change of any property
1293 rRect.SetSize( pImpl->aSplitSize );
1294 rRect.SetPos( aDockingRect.TopLeft() );
1295 return eDockAlign;
1296 }
1297
1298 // calculate new size and position
1299 Size aSize;
1300 Point aPoint = aDockingRect.TopLeft();
1301 Size aInnerSize = GetInnerRect().GetSize();
1302 if ( eDockAlign == SfxChildAlignment::LEFT || eDockAlign == SfxChildAlignment::RIGHT )
1303 {
1304 if ( pImpl->bNewLine )
1305 {
1306 // set height to height of free area
1307 aSize.setHeight( aInnerSize.Height() );
1308 aSize.setWidth( pImpl->nHorizontalSize );
1309 if ( eDockAlign == SfxChildAlignment::LEFT )
1310 {
1311 aPoint = aInnerRect.TopLeft();
1312 }
1313 else
1314 {
1315 aPoint = aInnerRect.TopRight();
1316 aPoint.AdjustX( -(aSize.Width()) );
1317 }
1318 }
1319 else
1320 {
1321 // get width from splitwindow
1322 aSize.setWidth( pSplitWin->GetLineSize(nLine) );
1323 aSize.setHeight( pImpl->aSplitSize.Height() );
1324 }
1325 }
1326 else
1327 {
1328 if ( pImpl->bNewLine )
1329 {
1330 // set width to width of free area
1331 aSize.setWidth( aInnerSize.Width() );
1332 aSize.setHeight( pImpl->nVerticalSize );
1333 if ( eDockAlign == SfxChildAlignment::TOP )
1334 {
1335 aPoint = aInnerRect.TopLeft();
1336 }
1337 else
1338 {
1339 aPoint = aInnerRect.BottomLeft();
1340 aPoint.AdjustY( -(aSize.Height()) );
1341 }
1342 }
1343 else
1344 {
1345 // get height from splitwindow
1346 aSize.setHeight( pSplitWin->GetLineSize(nLine) );
1347 aSize.setWidth( pImpl->aSplitSize.Width() );
1348 }
1349 }
1350
1351 aDockingRect.SetSize( aSize );
1352 aDockingRect.SetPos( aPoint );
1353 }
1354
1355 rRect = aDockingRect;
1356 return eDockAlign;
1357}
1358
1359/** Virtual method of the SfxDockingWindow class. This method determines how
1360 the size of the DockingWindows changes depending on the alignment. The base
1361 implementation uses the floating mode, the size of the marked Floating
1362 Size. For horizontal alignment, the width will be the width of the outer
1363 DockingRectangle, with vertical alignment the height will be the height of
1364 the inner DockingRectangle (resulting from the order in which the SFX child
1365 windows are displayed). The other size is set to the current floating-size,
1366 this could changed by a to intervening derived class. The docking size must
1367 be the same for Left/Right and Top/Bottom.
1368*/
1369Size SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign)
1370{
1371 // Note: if the resizing is also possible in the docked state, then the
1372 // Floating-size does also have to be adjusted?
1373
1374 Size aSize = GetFloatingSize();
1375 switch (eAlign)
1376 {
1377 case SfxChildAlignment::TOP:
1378 case SfxChildAlignment::BOTTOM:
1379 case SfxChildAlignment::LOWESTTOP:
1380 case SfxChildAlignment::HIGHESTTOP:
1381 case SfxChildAlignment::LOWESTBOTTOM:
1382 case SfxChildAlignment::HIGHESTBOTTOM:
1383 aSize.setWidth( aOuterRect.Right() - aOuterRect.Left() );
1384 break;
1385 case SfxChildAlignment::LEFT:
1386 case SfxChildAlignment::RIGHT:
1387 case SfxChildAlignment::FIRSTLEFT:
1388 case SfxChildAlignment::LASTLEFT:
1389 case SfxChildAlignment::FIRSTRIGHT:
1390 case SfxChildAlignment::LASTRIGHT:
1391 aSize.setHeight( aInnerRect.Bottom() - aInnerRect.Top() );
1392 break;
1393 case SfxChildAlignment::NOALIGNMENT:
1394 break;
1395 default:
1396 break;
1397 }
1398
1399 return aSize;
1400}
1401
1402/** Virtual method of the SfxDockingWindow class. Here a derived class can
1403 disallow certain alignments. The base implementation does not
1404 prohibit alignment.
1405*/
1406SfxChildAlignment SfxDockingWindow::CheckAlignment(SfxChildAlignment,
1407 SfxChildAlignment eAlign)
1408{
1409 return eAlign;
1410}
1411
1412/** The window is closed when the ChildWindow is destroyed by running the
1413 ChildWindow-slots. If this is method is overridden by a derived class
1414 method, then the SfxDockingDialogWindow: Close() must be called afterwards
1415 if the Close() was not cancelled with "return sal_False".
1416*/
1417bool SfxDockingWindow::Close()
1418{
1419 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
1420 if ( !pMgr )
1421 return true;
1422
1423 SfxBoolItem aValue( pMgr->GetType(), false);
1424 pBindings->GetDispatcher_Impl()->ExecuteList(
1425 pMgr->GetType(), SfxCallMode::RECORD | SfxCallMode::ASYNCHRON,
1426 { &aValue });
1427 return true;
1428}
1429
1430void SfxDockingWindow::Paint(vcl::RenderContext&, const tools::Rectangle& /*rRect*/)
1431{
1432}
1433
1434/** With this method, a minimal OutputSize be can set, that is queried in
1435 the Resizing()-Handler.
1436*/
1437void SfxDockingWindow::SetMinOutputSizePixel( const Size& rSize )
1438{
1439 pImpl->aMinSize = rSize;
1440 DockingWindow::SetMinOutputSizePixel( rSize );
1441}
1442
1443/** Set the minimum size which is returned.*/
1444const Size& SfxDockingWindow::GetMinOutputSizePixel() const
1445{
1446 return pImpl->aMinSize;
1447}
1448
1449bool SfxDockingWindow::EventNotify( NotifyEvent& rEvt )
1450{
1451 if ( !pImpl )
1452 return DockingWindow::EventNotify( rEvt );
1453
1454 if ( rEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1455 {
1456 if (pMgr != nullptr)
1457 pBindings->SetActiveFrame( pMgr->GetFrame() );
1458
1459 if ( pImpl->pSplitWin )
1460 pImpl->pSplitWin->SetActiveWindow_Impl( this );
1461 else if (pMgr != nullptr)
1462 pMgr->Activate_Impl();
1463
1464 // In VCL EventNotify goes first to the window itself, also call the
1465 // base class, otherwise the parent learns nothing
1466 // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer
1467 DockingWindow::EventNotify( rEvt );
1468 return true;
1469 }
1470 else if( rEvt.GetType() == MouseNotifyEvent::KEYINPUT )
1471 {
1472 // First, allow KeyInput for Dialog functions
1473 if (!DockingWindow::EventNotify(rEvt) && SfxViewShell::Current())
1474 {
1475 // then also for valid global accelerators.
1476 return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() );
1477 }
1478 return true;
1479 }
1480 else if ( rEvt.GetType() == MouseNotifyEvent::LOSEFOCUS && !HasChildPathFocus() )
1481 {
1482 pBindings->SetActiveFrame( nullptr );
1483 }
1484
1485 return DockingWindow::EventNotify( rEvt );
1486}
1487
1488
1489void SfxDockingWindow::SetItemSize_Impl( const Size& rSize )
1490{
1491 pImpl->aSplitSize = rSize;
1492
1493 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1494 pWorkWin->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW, SfxDockingConfig::ALIGNDOCKINGWINDOW, pMgr->GetType() );
1495}
1496
1497void SfxDockingWindow::Disappear_Impl()
1498{
1499 if ( pImpl->pSplitWin && pImpl->pSplitWin->IsItemValid( GetType() ) )
1500 pImpl->pSplitWin->RemoveWindow(this);
1501}
1502
1503void SfxDockingWindow::Reappear_Impl()
1504{
1505 if ( pImpl->pSplitWin && !pImpl->pSplitWin->IsItemValid( GetType() ) )
1506 {
1507 pImpl->pSplitWin->InsertWindow( this, pImpl->aSplitSize );
1508 }
1509}
1510
1511bool SfxDockingWindow::IsAutoHide_Impl() const
1512{
1513 if ( pImpl->pSplitWin )
1514 return !pImpl->pSplitWin->IsFadeIn();
1515 else
1516 return false;
1517}
1518
1519void SfxDockingWindow::AutoShow_Impl()
1520{
1521 if ( pImpl->pSplitWin )
1522 {
1523 pImpl->pSplitWin->FadeIn();
1524 }
1525}
1526
1527void SfxDockingWindow::StateChanged( StateChangedType nStateChange )
1528{
1529 if ( nStateChange == StateChangedType::InitShow )
1530 Initialize_Impl();
1531
1532 DockingWindow::StateChanged( nStateChange );
1533}
1534
1535void SfxDockingWindow::Move()
1536{
1537 if ( pImpl )
1538 pImpl->aMoveIdle.Start();
1539}
1540
1541IMPL_LINK_NOARG(SfxDockingWindow, TimerHdl, Timer *, void)void SfxDockingWindow::LinkStubTimerHdl(void * instance, Timer
* data) { return static_cast<SfxDockingWindow *>(instance
)->TimerHdl(data); } void SfxDockingWindow::TimerHdl(__attribute__
((unused)) Timer *)
1542{
1543 pImpl->aMoveIdle.Stop();
1544 if ( IsReallyVisible() && IsFloatingMode() )
1545 {
1546 if( !GetFloatingWindow()->IsRollUp() )
1547 SetFloatingSize( GetOutputSizePixel() );
1548 pImpl->aWinState = GetFloatingWindow()->GetWindowState();
1549 SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl();
1550 pWorkWin->ConfigChild_Impl( SfxChildIdentifier::SPLITWINDOW, SfxDockingConfig::ALIGNDOCKINGWINDOW, pMgr->GetType() );
1551 }
1552}
1553
1554/* 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 );
2
Memory is allocated
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
15
Calling 'Reference::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 ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/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
5.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
)
6
Taking true branch
113 m_pBody->release();
7
Calling 'VclReferenceBase::release'
11
Returning; memory was released
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)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
16
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)
8
Assuming the condition is true
9
Taking true branch
40 delete this;
10
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