1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/time.hxx>
21 #include <sal/log.hxx>
22 #include <o3tl/deleter.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/toolkit/floatwin.hxx>
30 #include <vcl/dockwin.hxx>
31 #include <vcl/toolbox.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/timer.hxx>
34 #include <vcl/settings.hxx>
36 #include "impldockingwrapper.hxx"
38 #define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE)
42 class ImplDockFloatWin2
: public FloatingWindow
45 ImplDockingWindowWrapper
* mpDockWin
;
46 sal_uInt64 mnLastTicks
;
48 Timer m_aEndDockTimer
;
50 tools::Rectangle maDockRect
;
52 ImplSVEvent
* mnLastUserEvent
;
54 DECL_LINK(DockingHdl
, void *, void);
55 DECL_LINK(DockTimerHdl
, Timer
*, void);
56 DECL_LINK(EndDockTimerHdl
, Timer
*, void);
58 ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
59 ImplDockingWindowWrapper
* pDockingWin
);
60 virtual ~ImplDockFloatWin2() override
;
61 virtual void dispose() override
;
63 virtual void Move() override
;
64 virtual void Resize() override
;
65 virtual void TitleButtonClick( TitleButton nButton
) override
;
66 virtual void Resizing( Size
& rSize
) override
;
67 virtual bool Close() override
;
72 ImplDockFloatWin2::ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
73 ImplDockingWindowWrapper
* pDockingWin
) :
74 FloatingWindow( pParent
, nWinBits
),
75 mpDockWin( pDockingWin
),
76 mnLastTicks( tools::Time::GetSystemTicks() ),
77 m_aDockTimer("vcl::ImplDockFloatWin2 m_aDockTimer"),
78 m_aEndDockTimer( "vcl::ImplDockFloatWin2 m_aEndDockTimer" ),
80 mnLastUserEvent( nullptr )
82 // copy state of DockingWindow
85 GetOutDev()->SetSettings( pDockingWin
->GetWindow()->GetSettings() );
86 Enable( pDockingWin
->GetWindow()->IsEnabled(), false );
87 EnableInput( pDockingWin
->GetWindow()->IsInputEnabled(), false );
88 AlwaysEnableInput( pDockingWin
->GetWindow()->IsAlwaysEnableInput(), false );
89 EnableAlwaysOnTop( pDockingWin
->GetWindow()->IsAlwaysOnTopEnabled() );
90 SetActivateMode( pDockingWin
->GetWindow()->GetActivateMode() );
93 SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );
95 m_aDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, DockTimerHdl
) );
96 m_aDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
97 m_aDockTimer
.SetTimeout( 50 );
99 m_aEndDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, EndDockTimerHdl
) );
100 m_aEndDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
101 m_aEndDockTimer
.SetTimeout( 50 );
104 ImplDockFloatWin2::~ImplDockFloatWin2()
109 void ImplDockFloatWin2::dispose()
111 if( mnLastUserEvent
)
112 Application::RemoveUserEvent( mnLastUserEvent
);
113 FloatingWindow::dispose();
116 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockTimerHdl
, Timer
*, void)
118 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "docktimer called but not floating" );
120 PointerState aState
= GetPointerState();
122 if( aState
.mnState
& KEY_MOD1
)
124 // i43499 CTRL disables docking now
125 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
126 if( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) )
127 m_aDockTimer
.Start();
129 else if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
131 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
132 mpDockWin
->EndDocking( maDockRect
, false );
136 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
137 m_aDockTimer
.Start();
141 IMPL_LINK_NOARG(ImplDockFloatWin2
, EndDockTimerHdl
, Timer
*, void)
143 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "enddocktimer called but not floating" );
145 PointerState aState
= GetPointerState();
146 if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
148 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
149 mpDockWin
->EndDocking( maDockRect
, true );
152 m_aEndDockTimer
.Start();
155 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockingHdl
, void*, void)
157 // called during move of a floating window
158 mnLastUserEvent
= nullptr;
160 vcl::Window
*pDockingArea
= mpDockWin
->GetWindow()->GetParent();
161 PointerState aState
= pDockingArea
->GetPointerState();
163 bool bRealMove
= true;
164 if( GetStyle() & WB_OWNERDRAWDECORATION
)
166 // for windows with ownerdraw decoration
167 // we allow docking only when the window was moved
168 // by dragging its caption
169 // and ignore move request due to resizing
170 vcl::Window
*pBorder
= GetWindow( GetWindowType::Border
);
171 if( pBorder
!= this )
173 tools::Rectangle
aBorderRect( Point(), pBorder
->GetSizePixel() );
174 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
175 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
176 // limit borderrect to the caption part only and without the resizing borders
177 aBorderRect
.SetBottom( aBorderRect
.Top() + nTop
);
178 aBorderRect
.AdjustLeft(nLeft
);
179 aBorderRect
.AdjustRight( -nRight
);
181 PointerState aBorderState
= pBorder
->GetPointerState();
182 bRealMove
= aBorderRect
.Contains( aBorderState
.maPos
);
186 if( mpDockWin
->GetWindow()->IsVisible() &&
187 (tools::Time::GetSystemTicks() - mnLastTicks
> 500) &&
188 ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) &&
189 !(aState
.mnState
& KEY_MOD1
) && // i43499 CTRL disables docking now
192 maDockPos
= pDockingArea
->OutputToScreenPixel( pDockingArea
->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) );
193 maDockRect
= tools::Rectangle( maDockPos
, mpDockWin
->GetSizePixel() );
195 // mouse pos in screen pixels
196 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
198 if( ! mpDockWin
->IsDocking() )
199 mpDockWin
->StartDocking( aMousePos
, maDockRect
);
201 bool bFloatMode
= mpDockWin
->Docking( aMousePos
, maDockRect
);
205 // indicates that the window could be docked at maDockRect
206 maDockRect
.SetPos( mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ScreenToOutputPixel(
207 maDockRect
.TopLeft() ) );
208 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
209 m_aEndDockTimer
.Stop();
210 m_aDockTimer
.Invoke();
214 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
216 m_aEndDockTimer
.Invoke();
222 void ImplDockFloatWin2::Move()
228 FloatingWindow::Move();
229 mpDockWin
->GetWindow()->Move();
232 * note: the window should only dock if KEY_MOD1 is pressed
233 * and the user releases all mouse buttons. The real problem here
234 * is that we don't get mouse events (at least not on X)
235 * if the mouse is on the decoration. So we have to start an
236 * awkward timer based process that polls the modifier/buttons
237 * to see whether they are in the right condition shortly after the
240 if( ! mnLastUserEvent
)
241 mnLastUserEvent
= Application::PostUserEvent( LINK( this, ImplDockFloatWin2
, DockingHdl
), nullptr, true );
244 void ImplDockFloatWin2::Resize()
246 // forwarding of resize only required if we have no borderwindow ( GetWindow() then returns 'this' )
247 if( GetWindow( GetWindowType::Border
) == this )
249 FloatingWindow::Resize();
250 Size
aSize( GetSizePixel() );
251 mpDockWin
->GetWindow()->ImplPosSizeWindow( 0, 0, aSize
.Width(), aSize
.Height(), PosSizeFlags::PosSize
); // TODO: is this needed ???
255 void ImplDockFloatWin2::TitleButtonClick( TitleButton nButton
)
257 FloatingWindow::TitleButtonClick( nButton
);
258 mpDockWin
->TitleButtonClick( nButton
);
261 void ImplDockFloatWin2::Resizing( Size
& rSize
)
263 FloatingWindow::Resizing( rSize
);
264 mpDockWin
->Resizing( rSize
);
267 bool ImplDockFloatWin2::Close()
272 DockingManager::DockingManager()
276 DockingManager::~DockingManager()
280 ImplDockingWindowWrapper
* DockingManager::GetDockingWindowWrapper( const vcl::Window
*pWindow
)
282 for( const auto& xWrapper
: mvDockingWindows
)
284 if (xWrapper
&& xWrapper
->mpDockingWindow
== pWindow
)
285 return xWrapper
.get();
290 bool DockingManager::IsDockable( const vcl::Window
*pWindow
)
292 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
295 if( pWindow->HasDockingHandler() )
298 return (pWrapper
!= nullptr);
301 bool DockingManager::IsFloating( const vcl::Window
*pWindow
)
303 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
305 return pWrapper
->IsFloatingMode();
310 bool DockingManager::IsLocked( const vcl::Window
*pWindow
)
312 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
313 return pWrapper
&& pWrapper
->IsLocked();
316 void DockingManager::Lock( const vcl::Window
*pWindow
)
318 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
323 void DockingManager::Unlock( const vcl::Window
*pWindow
)
325 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
330 void DockingManager::SetFloatingMode( const vcl::Window
*pWindow
, bool bFloating
)
332 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
334 pWrapper
->SetFloatingMode( bFloating
);
337 void DockingManager::StartPopupMode( const vcl::Window
*pWindow
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
339 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
341 pWrapper
->StartPopupMode( rRect
, nFlags
);
344 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
, FloatWinPopupFlags nFlags
)
346 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
348 pWrapper
->StartPopupMode( pParentToolBox
, nFlags
);
351 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
)
353 StartPopupMode( pParentToolBox
, pWindow
, FloatWinPopupFlags::AllowTearOff
|
354 FloatWinPopupFlags::AllMouseButtonClose
|
355 FloatWinPopupFlags::NoMouseUpClose
);
358 bool DockingManager::IsInPopupMode( const vcl::Window
*pWindow
)
360 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
361 return pWrapper
&& pWrapper
->IsInPopupMode();
364 void DockingManager::EndPopupMode( const vcl::Window
*pWin
)
366 ImplDockingWindowWrapper
*pWrapper
= GetDockingWindowWrapper( pWin
);
367 if( pWrapper
&& pWrapper
->GetFloatingWindow() && static_cast<FloatingWindow
*>(pWrapper
->GetFloatingWindow())->IsInPopupMode() )
368 static_cast<FloatingWindow
*>(pWrapper
->GetFloatingWindow())->EndPopupMode();
371 SystemWindow
* DockingManager::GetFloatingWindow(const vcl::Window
*pWin
)
373 ImplDockingWindowWrapper
*pWrapper
= GetDockingWindowWrapper( pWin
);
375 return pWrapper
->GetFloatingWindow();
379 void DockingManager::SetPopupModeEndHdl( const vcl::Window
*pWindow
, const Link
<FloatingWindow
*,void>& rLink
)
381 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
383 pWrapper
->SetPopupModeEndHdl(rLink
);
386 void DockingManager::AddWindow( const vcl::Window
*pWindow
)
388 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
391 mvDockingWindows
.emplace_back( new ImplDockingWindowWrapper( pWindow
) );
394 void DockingManager::RemoveWindow( const vcl::Window
*pWindow
)
396 for( auto it
= mvDockingWindows
.begin(); it
!= mvDockingWindows
.end(); ++it
)
398 const auto& xWrapper
= *it
;
399 if (xWrapper
&& xWrapper
->mpDockingWindow
== pWindow
)
401 // deleting wrappers calls set of actions which may want to use
402 // wrapper we want to delete - avoid crash using temporary owner
404 auto pTemporaryOwner
= std::move(*it
);
405 mvDockingWindows
.erase( it
);
411 void DockingManager::SetPosSizePixel( vcl::Window
const *pWindow
, tools::Long nX
, tools::Long nY
,
412 tools::Long nWidth
, tools::Long nHeight
,
413 PosSizeFlags nFlags
)
415 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
417 pWrapper
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
420 tools::Rectangle
DockingManager::GetPosSizePixel( const vcl::Window
*pWindow
)
422 tools::Rectangle aRect
;
423 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
425 aRect
= tools::Rectangle( pWrapper
->GetPosPixel(), pWrapper
->GetSizePixel() );
430 class ImplPopupFloatWin
: public FloatingWindow
436 ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
);
437 virtual ~ImplPopupFloatWin() override
;
438 virtual css::uno::Reference
< css::accessibility::XAccessible
> CreateAccessible() override
;
441 ImplPopupFloatWin::ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
) :
442 FloatingWindow( pParent
, bToolBox
? WB_BORDER
| WB_POPUP
| WB_SYSTEMWINDOW
| WB_NOSHADOW
: WB_STDPOPUP
),
443 mbToolBox( bToolBox
)
447 // indicate window type, required for accessibility
448 // which should not see this window as a toplevel window
449 mpWindowImpl
->mbToolbarFloatingWindow
= true;
453 ImplPopupFloatWin::~ImplPopupFloatWin()
458 css::uno::Reference
< css::accessibility::XAccessible
> ImplPopupFloatWin::CreateAccessible()
461 return FloatingWindow::CreateAccessible();
463 // switch off direct accessibility support for this window
465 // this is to avoid appearance of this window as standalone window in the accessibility hierarchy
466 // as this window is only used as a helper for subtoolbars that are not teared-off, the parent toolbar
467 // has to provide accessibility support (as implemented in the toolkit)
468 // so the contained toolbar should appear as child of the corresponding toolbar item of the parent toolbar
469 return css::uno::Reference
< css::accessibility::XAccessible
>();
472 ImplDockingWindowWrapper::ImplDockingWindowWrapper( const vcl::Window
*pWindow
)
473 : mpDockingWindow(const_cast<vcl::Window
*>(pWindow
))
474 , mpFloatWin(nullptr)
475 , mpOldBorderWin(nullptr)
476 , mpParent(pWindow
->GetParent())
477 , maMaxOutSize( SHRT_MAX
, SHRT_MAX
)
486 , mnFloatBits(WB_BORDER
| WB_CLOSEABLE
| WB_SIZEABLE
| (pWindow
->GetStyle() & DOCKWIN_FLOATSTYLES
))
487 , mbDockCanceled(false)
489 , mbLastFloatMode(false)
492 // must be enabled in Window::Notify to prevent permanent docking during mouse move
493 , mbStartDockingEnabled(false)
496 assert(mpDockingWindow
);
497 DockingWindow
*pDockWin
= dynamic_cast< DockingWindow
* > ( mpDockingWindow
.get() );
499 mnFloatBits
= pDockWin
->GetFloatStyle();
502 ImplDockingWindowWrapper::~ImplDockingWindowWrapper()
504 if ( IsFloatingMode() )
506 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
507 SetFloatingMode(false);
511 void ImplDockingWindowWrapper::ImplStartDocking( const Point
& rPos
)
513 if( !mbStartDockingEnabled
)
518 mbLastFloatMode
= IsFloatingMode();
520 // calculate FloatingBorder
521 VclPtr
<FloatingWindow
> pWin
;
525 pWin
= VclPtr
<ImplDockFloatWin2
>::Create( mpParent
, mnFloatBits
, nullptr );
526 pWin
->GetBorder( mnDockLeft
, mnDockTop
, mnDockRight
, mnDockBottom
);
528 pWin
.disposeAndClear();
530 Point aPos
= GetWindow()->OutputToScreenPixel( Point() );
531 Size aSize
= GetWindow()->GetOutputSizePixel();
534 mnTrackWidth
= aSize
.Width();
535 mnTrackHeight
= aSize
.Height();
537 if ( mbLastFloatMode
)
539 maMouseOff
.AdjustX(mnDockLeft
);
540 maMouseOff
.AdjustY(mnDockTop
);
541 mnTrackX
-= mnDockLeft
;
542 mnTrackY
-= mnDockTop
;
543 mnTrackWidth
+= mnDockLeft
+mnDockRight
;
544 mnTrackHeight
+= mnDockTop
+mnDockBottom
;
547 vcl::Window
*pDockingArea
= GetWindow()->GetParent();
548 vcl::Window::PointerState aState
= pDockingArea
->GetPointerState();
550 // mouse pos in screen pixels
551 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
552 Point aDockPos
= pDockingArea
->AbsoluteScreenToOutputPixel( GetWindow()->OutputToAbsoluteScreenPixel( GetWindow()->GetPosPixel() ) );
553 tools::Rectangle
aDockRect( aDockPos
, GetWindow()->GetSizePixel() );
554 StartDocking( aMousePos
, aDockRect
);
556 GetWindow()->ImplUpdateAll();
557 GetWindow()->ImplGetFrameWindow()->ImplUpdateAll();
559 GetWindow()->StartTracking( StartTrackingFlags::KeyMod
);
562 void ImplDockingWindowWrapper::Tracking( const TrackingEvent
& rTEvt
)
564 // used during docking of a currently docked window
568 if ( rTEvt
.IsTrackingEnded() )
571 GetWindow()->HideTracking();
572 if ( rTEvt
.IsTrackingCanceled() )
574 mbDockCanceled
= true;
575 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
576 mbDockCanceled
= false;
579 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
581 // Docking only upon non-synthetic MouseEvents
582 else if ( !rTEvt
.GetMouseEvent().IsSynthetic() || rTEvt
.GetMouseEvent().IsModifierChanged() )
584 Point aMousePos
= rTEvt
.GetMouseEvent().GetPosPixel();
585 Point aFrameMousePos
= GetWindow()->OutputToScreenPixel( aMousePos
);
586 Size aFrameSize
= GetWindow()->ImplGetFrameWindow()->GetOutputSizePixel();
587 if ( aFrameMousePos
.X() < 0 )
588 aFrameMousePos
.setX( 0 );
589 if ( aFrameMousePos
.Y() < 0 )
590 aFrameMousePos
.setY( 0 );
591 if ( aFrameMousePos
.X() > aFrameSize
.Width()-1 )
592 aFrameMousePos
.setX( aFrameSize
.Width()-1 );
593 if ( aFrameMousePos
.Y() > aFrameSize
.Height()-1 )
594 aFrameMousePos
.setY( aFrameSize
.Height()-1 );
595 aMousePos
= GetWindow()->ScreenToOutputPixel( aFrameMousePos
);
596 aMousePos
.AdjustX( -(maMouseOff
.X()) );
597 aMousePos
.AdjustY( -(maMouseOff
.Y()) );
598 Point aPos
= GetWindow()->OutputToScreenPixel( aMousePos
);
599 tools::Rectangle
aTrackRect( aPos
, Size( mnTrackWidth
, mnTrackHeight
) );
600 tools::Rectangle aCompRect
= aTrackRect
;
601 aPos
.AdjustX(maMouseOff
.X() );
602 aPos
.AdjustY(maMouseOff
.Y() );
604 bool bFloatMode
= Docking( aPos
, aTrackRect
);
606 if ( mbLastFloatMode
!= bFloatMode
)
610 aTrackRect
.AdjustLeft( -mnDockLeft
);
611 aTrackRect
.AdjustTop( -mnDockTop
);
612 aTrackRect
.AdjustRight(mnDockRight
);
613 aTrackRect
.AdjustBottom(mnDockBottom
);
617 if ( aCompRect
== aTrackRect
)
619 aTrackRect
.AdjustLeft(mnDockLeft
);
620 aTrackRect
.AdjustTop(mnDockTop
);
621 aTrackRect
.AdjustRight( -mnDockRight
);
622 aTrackRect
.AdjustBottom( -mnDockBottom
);
625 mbLastFloatMode
= bFloatMode
;
628 ShowTrackFlags nTrackStyle
;
630 nTrackStyle
= ShowTrackFlags::Object
;
632 nTrackStyle
= ShowTrackFlags::Big
;
633 tools::Rectangle aShowTrackRect
= aTrackRect
;
634 aShowTrackRect
.SetPos( GetWindow()->ScreenToOutputPixel( aShowTrackRect
.TopLeft() ) );
636 GetWindow()->ShowTracking( aShowTrackRect
, nTrackStyle
);
638 // calculate mouse offset again, as the rectangle was changed
639 maMouseOff
.setX( aPos
.X() - aTrackRect
.Left() );
640 maMouseOff
.setY( aPos
.Y() - aTrackRect
.Top() );
642 mnTrackX
= aTrackRect
.Left();
643 mnTrackY
= aTrackRect
.Top();
644 mnTrackWidth
= aTrackRect
.GetWidth();
645 mnTrackHeight
= aTrackRect
.GetHeight();
649 void ImplDockingWindowWrapper::StartDocking( const Point
& rPoint
, tools::Rectangle
const & rRect
)
651 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
653 GetWindow()->CallEventListeners( VclEventId::WindowStartDocking
, &data
);
657 bool ImplDockingWindowWrapper::Docking( const Point
& rPoint
, tools::Rectangle
& rRect
)
659 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
661 GetWindow()->CallEventListeners( VclEventId::WindowDocking
, &data
);
662 rRect
= data
.maTrackRect
;
663 return data
.mbFloating
;
666 void ImplDockingWindowWrapper::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
668 tools::Rectangle
aRect( rRect
);
670 bool bOrigDockCanceled
= mbDockCanceled
;
671 if (bFloatMode
&& !StyleSettings::GetDockingFloatsSupported())
672 mbDockCanceled
= true;
674 if ( !IsDockingCanceled() )
677 if ( bFloatMode
!= IsFloatingMode() )
679 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
680 SetFloatingMode( bFloatMode
);
684 // #i44800# always use outputsize - as in all other places
685 mpFloatWin
->SetOutputSizePixel( aRect
.GetSize() );
686 mpFloatWin
->SetPosPixel( aRect
.TopLeft() );
691 Point aPos
= aRect
.TopLeft();
692 aPos
= GetWindow()->GetParent()->ScreenToOutputPixel( aPos
);
693 GetWindow()->SetPosSizePixel( aPos
, aRect
.GetSize() );
697 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
700 EndDockingData
data( aRect
, IsFloatingMode(), IsDockingCanceled() );
701 GetWindow()->CallEventListeners( VclEventId::WindowEndDocking
, &data
);
705 // must be enabled in Window::Notify to prevent permanent docking during mouse move
706 mbStartDockingEnabled
= false;
708 mbDockCanceled
= bOrigDockCanceled
;
711 bool ImplDockingWindowWrapper::PrepareToggleFloatingMode()
713 bool bFloating
= true;
714 GetWindow()->CallEventListeners( VclEventId::WindowPrepareToggleFloating
, &bFloating
);
718 void ImplDockingWindowWrapper::ToggleFloatingMode()
720 // notify dockingwindow/toolbox
721 // note: this must be done *before* notifying the
722 // listeners to have the toolbox in the proper state
723 if( GetWindow()->IsDockingWindow() )
724 static_cast<DockingWindow
*>(GetWindow())->ToggleFloatingMode();
726 // now notify listeners
727 GetWindow()->CallEventListeners( VclEventId::WindowToggleFloating
);
729 // must be enabled in Window::Notify to prevent permanent docking during mouse move
730 mbStartDockingEnabled
= false;
733 void ImplDockingWindowWrapper::TitleButtonClick( TitleButton nType
)
735 if( nType
== TitleButton::Menu
)
737 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
740 pToolBox
->ExecuteCustomMenu();
743 if( nType
== TitleButton::Docking
)
745 SetFloatingMode( !IsFloatingMode() );
749 void ImplDockingWindowWrapper::Resizing( Size
& rSize
)
751 // TODO: add virtual Resizing() to class Window, so we can get rid of class DockingWindow
752 DockingWindow
*pDockingWindow
= dynamic_cast< DockingWindow
* >( GetWindow() );
754 pDockingWindow
->Resizing( rSize
);
757 void ImplDockingWindowWrapper::ShowMenuTitleButton( bool bVisible
)
760 mpFloatWin
->ShowTitleButton( TitleButton::Menu
, bVisible
);
763 void ImplDockingWindowWrapper::ImplPreparePopupMode()
765 VclPtr
<vcl::Window
> xWindow
= GetWindow();
766 xWindow
->Show( false, ShowFlags::NoFocusChange
);
768 // prepare reparenting
769 vcl::Window
* pRealParent
= xWindow
->GetWindow( GetWindowType::Parent
);
770 mpOldBorderWin
= xWindow
->GetWindow( GetWindowType::Border
);
771 if( mpOldBorderWin
.get() == xWindow
)
772 mpOldBorderWin
= nullptr; // no border window found
774 // the new parent for popup mode
775 VclPtrInstance
<ImplPopupFloatWin
> pWin( mpParent
, xWindow
->GetType() == WindowType::TOOLBOX
);
776 pWin
->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper
, PopupModeEnd
) );
778 // At least for DockingWindow, GetText() has a side effect of setting deferred
779 // properties. This must be done before setting the border window (see below),
780 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
781 // the border window (See DockingWindow::setPosSizeOnContainee() and
782 // DockingWindow::GetOptimalSize()).
783 pWin
->SetText( xWindow
->GetText() );
784 pWin
->SetOutputSizePixel( xWindow
->GetSizePixel() );
786 xWindow
->mpWindowImpl
->mpBorderWindow
= nullptr;
787 xWindow
->mpWindowImpl
->mnLeftBorder
= 0;
788 xWindow
->mpWindowImpl
->mnTopBorder
= 0;
789 xWindow
->mpWindowImpl
->mnRightBorder
= 0;
790 xWindow
->mpWindowImpl
->mnBottomBorder
= 0;
792 // reparent borderwindow and window
793 if ( mpOldBorderWin
)
794 mpOldBorderWin
->SetParent( pWin
);
795 xWindow
->SetParent( pWin
);
797 // correct border window pointers
798 xWindow
->mpWindowImpl
->mpBorderWindow
= pWin
;
799 pWin
->mpWindowImpl
->mpClientWindow
= xWindow
;
800 xWindow
->mpWindowImpl
->mpRealParent
= pRealParent
;
802 // set mpFloatWin not until all window positioning is done !!!
803 // (SetPosPixel etc. check for valid mpFloatWin pointer)
807 void ImplDockingWindowWrapper::StartPopupMode( ToolBox
*pParentToolBox
, FloatWinPopupFlags nFlags
)
809 // do nothing if window is floating
810 if( IsFloatingMode() )
813 ImplPreparePopupMode();
815 // don't allow tearoff, if globally disabled
816 if( !StyleSettings::GetDockingFloatsSupported() )
817 nFlags
&= ~FloatWinPopupFlags::AllowTearOff
;
819 // if the subtoolbar was opened via keyboard make sure that key events
820 // will go into subtoolbar
821 if( pParentToolBox
->IsKeyEvent() )
822 nFlags
|= FloatWinPopupFlags::GrabFocus
;
824 mpFloatWin
->StartPopupMode( pParentToolBox
, nFlags
);
826 // grab focus (again) after showing docking window, as e.g. a11y focus
827 // events require window to be visible first
828 if (nFlags
& FloatWinPopupFlags::GrabFocus
)
829 mpFloatWin
->GrabFocus();
831 if( pParentToolBox
->IsKeyEvent() )
833 // send HOME key to subtoolbar in order to select first item
834 KeyEvent
aEvent( 0, vcl::KeyCode( KEY_HOME
) );
835 GetWindow()->KeyInput(aEvent
);
839 void ImplDockingWindowWrapper::StartPopupMode( const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
841 // do nothing if window is floating
842 if( IsFloatingMode() )
845 ImplPreparePopupMode();
846 mpFloatWin
->StartPopupMode( rRect
, nFlags
);
848 // grab focus (again) after showing docking window, as e.g. a11y focus
849 // events require window to be visible first
850 if (nFlags
& FloatWinPopupFlags::GrabFocus
)
851 mpFloatWin
->GrabFocus();
854 IMPL_LINK_NOARG(ImplDockingWindowWrapper
, PopupModeEnd
, FloatingWindow
*, void)
856 VclPtr
<vcl::Window
> xWindow
= GetWindow();
857 xWindow
->Show( false, ShowFlags::NoFocusChange
);
859 // set parameter for handler before destroying floating window
860 EndPopupModeData
aData( mpFloatWin
->GetWindow( GetWindowType::Border
)->GetPosPixel(), mpFloatWin
->IsPopupModeTearOff() );
862 // before deleting change parent back, so we can delete the floating window alone
863 vcl::Window
* pRealParent
= xWindow
->GetWindow( GetWindowType::Parent
);
864 xWindow
->mpWindowImpl
->mpBorderWindow
= nullptr;
865 if ( mpOldBorderWin
)
867 xWindow
->SetParent( mpOldBorderWin
);
868 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
869 xWindow
->mpWindowImpl
->mnLeftBorder
, xWindow
->mpWindowImpl
->mnTopBorder
,
870 xWindow
->mpWindowImpl
->mnRightBorder
, xWindow
->mpWindowImpl
->mnBottomBorder
);
871 mpOldBorderWin
->Resize();
873 xWindow
->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
874 xWindow
->SetParent( pRealParent
);
875 xWindow
->mpWindowImpl
->mpRealParent
= pRealParent
;
877 // take ownership to local variable to protect against maPopupModeEndHdl destroying this object
878 auto xFloatWin
= std::move(mpFloatWin
);
879 maPopupModeEndHdl
.Call(xFloatWin
);
880 xFloatWin
.disposeAndClear();
882 // call handler - which will destroy the window and thus the wrapper as well !
883 xWindow
->CallEventListeners( VclEventId::WindowEndPopupMode
, &aData
);
886 bool ImplDockingWindowWrapper::IsInPopupMode() const
888 if( GetFloatingWindow() )
889 return static_cast<FloatingWindow
*>(GetFloatingWindow())->IsInPopupMode();
894 void ImplDockingWindowWrapper::SetFloatingMode( bool bFloatMode
)
896 // do nothing if window is docked and locked
897 if( !IsFloatingMode() && IsLocked() )
900 if ( IsFloatingMode() == bFloatMode
)
903 if ( !PrepareToggleFloatingMode() )
906 bool bVisible
= GetWindow()->IsVisible();
910 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
912 maDockPos
= GetWindow()->GetPosPixel();
914 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
915 mpOldBorderWin
= GetWindow()->GetWindow( GetWindowType::Border
);
916 if( mpOldBorderWin
== mpDockingWindow
)
917 mpOldBorderWin
= nullptr; // no border window found
919 VclPtrInstance
<ImplDockFloatWin2
> pWin(
921 mnFloatBits
& ( WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
) ?
922 mnFloatBits
| WB_SYSTEMWINDOW
923 | WB_OWNERDRAWDECORATION
927 // At least for DockingWindow, GetText() has a side effect of setting deferred
928 // properties. This must be done before setting the border window (see below),
929 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
930 // the border window (See DockingWindow::setPosSizeOnContainee() and
931 // DockingWindow::GetOptimalSize()).
932 pWin
->SetText( GetWindow()->GetText() );
934 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
935 GetWindow()->mpWindowImpl
->mnLeftBorder
= 0;
936 GetWindow()->mpWindowImpl
->mnTopBorder
= 0;
937 GetWindow()->mpWindowImpl
->mnRightBorder
= 0;
938 GetWindow()->mpWindowImpl
->mnBottomBorder
= 0;
940 // if the parent gets destroyed, we also have to reset the parent of the BorderWindow
941 if ( mpOldBorderWin
)
942 mpOldBorderWin
->SetParent( pWin
);
943 GetWindow()->SetParent( pWin
);
944 pWin
->SetPosPixel( Point() );
946 GetWindow()->mpWindowImpl
->mpBorderWindow
= pWin
;
947 pWin
->mpWindowImpl
->mpClientWindow
= mpDockingWindow
;
948 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
950 pWin
->SetOutputSizePixel( GetWindow()->GetSizePixel() );
951 pWin
->SetPosPixel( maFloatPos
);
952 // pass on DockingData to FloatingWindow
953 pWin
->ShowTitleButton( TitleButton::Docking
, mbDockBtn
);
954 pWin
->ShowTitleButton( TitleButton::Hide
, mbHideBtn
);
955 pWin
->SetMinOutputSizePixel( maMinOutSize
);
956 pWin
->SetMaxOutputSizePixel( maMaxOutSize
);
961 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
963 ToggleFloatingMode();
967 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
969 // store FloatingData in FloatingWindow
970 maFloatPos
= mpFloatWin
->GetPosPixel();
971 mbDockBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Docking
);
972 mbHideBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Hide
);
973 maMinOutSize
= mpFloatWin
->GetMinOutputSizePixel();
974 maMaxOutSize
= mpFloatWin
->GetMaxOutputSizePixel();
976 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
); //mpWindowImpl->mpRealParent;
977 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
978 if ( mpOldBorderWin
)
980 GetWindow()->SetParent( mpOldBorderWin
);
981 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
982 GetWindow()->mpWindowImpl
->mnLeftBorder
, GetWindow()->mpWindowImpl
->mnTopBorder
,
983 GetWindow()->mpWindowImpl
->mnRightBorder
, GetWindow()->mpWindowImpl
->mnBottomBorder
);
984 mpOldBorderWin
->Resize();
986 GetWindow()->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
987 GetWindow()->SetParent( pRealParent
);
988 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
990 mpFloatWin
.disposeAndClear();
991 GetWindow()->SetPosPixel( maDockPos
);
996 ToggleFloatingMode();
1001 void ImplDockingWindowWrapper::SetFloatStyle( WinBits nStyle
)
1003 mnFloatBits
= nStyle
;
1007 void ImplDockingWindowWrapper::setPosSizePixel( tools::Long nX
, tools::Long nY
,
1008 tools::Long nWidth
, tools::Long nHeight
,
1009 PosSizeFlags nFlags
)
1012 mpFloatWin
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
1014 GetWindow()->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
1017 Point
ImplDockingWindowWrapper::GetPosPixel() const
1020 return mpFloatWin
->GetPosPixel();
1022 return mpDockingWindow
->GetPosPixel();
1025 Size
ImplDockingWindowWrapper::GetSizePixel() const
1028 return mpFloatWin
->GetSizePixel();
1030 return mpDockingWindow
->GetSizePixel();
1033 // old inlines from DockingWindow
1035 void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size
& rSize
)
1038 mpFloatWin
->SetMinOutputSizePixel( rSize
);
1039 maMinOutSize
= rSize
;
1042 void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size
& rSize
)
1045 mpFloatWin
->SetMaxOutputSizePixel( rSize
);
1046 maMaxOutSize
= rSize
;
1049 bool ImplDockingWindowWrapper::IsFloatingMode() const
1051 return (mpFloatWin
!= nullptr);
1054 void ImplDockingWindowWrapper::SetDragArea( const tools::Rectangle
& rRect
)
1060 void ImplDockingWindowWrapper::Lock()
1063 // only toolbars support locking
1064 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1066 pToolBox
->Lock( mbLocked
);
1069 void ImplDockingWindowWrapper::Unlock()
1072 // only toolbars support locking
1073 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1075 pToolBox
->Lock( mbLocked
);
1078 SystemWindow
* ImplDockingWindowWrapper::GetFloatingWindow() const
1083 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */