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/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 #define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE | WB_ROLLABLE )
40 class ImplDockFloatWin2
: public FloatingWindow
43 ImplDockingWindowWrapper
* mpDockWin
;
44 sal_uInt64 mnLastTicks
;
46 Timer m_aEndDockTimer
;
48 tools::Rectangle maDockRect
;
50 ImplSVEvent
* mnLastUserEvent
;
52 DECL_LINK(DockingHdl
, void *, void);
53 DECL_LINK(DockTimerHdl
, Timer
*, void);
54 DECL_LINK(EndDockTimerHdl
, Timer
*, void);
56 ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
57 ImplDockingWindowWrapper
* pDockingWin
);
58 virtual ~ImplDockFloatWin2() override
;
59 virtual void dispose() override
;
61 virtual void Move() override
;
62 virtual void Resize() override
;
63 virtual void TitleButtonClick( TitleButton nButton
) override
;
64 virtual void Resizing( Size
& rSize
) override
;
65 virtual bool Close() override
;
70 ImplDockFloatWin2::ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
71 ImplDockingWindowWrapper
* pDockingWin
) :
72 FloatingWindow( pParent
, nWinBits
),
73 mpDockWin( pDockingWin
),
74 mnLastTicks( tools::Time::GetSystemTicks() ),
76 mnLastUserEvent( nullptr )
78 // copy state of DockingWindow
81 SetSettings( pDockingWin
->GetWindow()->GetSettings() );
82 Enable( pDockingWin
->GetWindow()->IsEnabled(), false );
83 EnableInput( pDockingWin
->GetWindow()->IsInputEnabled(), false );
84 AlwaysEnableInput( pDockingWin
->GetWindow()->IsAlwaysEnableInput(), false );
85 EnableAlwaysOnTop( pDockingWin
->GetWindow()->IsAlwaysOnTopEnabled() );
86 SetActivateMode( pDockingWin
->GetWindow()->GetActivateMode() );
89 SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );
91 m_aDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, DockTimerHdl
) );
92 m_aDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
93 m_aDockTimer
.SetTimeout( 50 );
94 m_aDockTimer
.SetDebugName( "vcl::ImplDockFloatWin2 m_aDockTimer" );
96 m_aEndDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, EndDockTimerHdl
) );
97 m_aEndDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
98 m_aEndDockTimer
.SetTimeout( 50 );
99 m_aEndDockTimer
.SetDebugName( "vcl::ImplDockFloatWin2 m_aEndDockTimer" );
102 ImplDockFloatWin2::~ImplDockFloatWin2()
107 void ImplDockFloatWin2::dispose()
109 if( mnLastUserEvent
)
110 Application::RemoveUserEvent( mnLastUserEvent
);
111 FloatingWindow::dispose();
114 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockTimerHdl
, Timer
*, void)
116 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "docktimer called but not floating" );
118 PointerState aState
= GetPointerState();
120 if( aState
.mnState
& KEY_MOD1
)
122 // i43499 CTRL disables docking now
123 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
124 if( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) )
125 m_aDockTimer
.Start();
127 else if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
129 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
130 mpDockWin
->EndDocking( maDockRect
, false );
134 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
135 m_aDockTimer
.Start();
139 IMPL_LINK_NOARG(ImplDockFloatWin2
, EndDockTimerHdl
, Timer
*, void)
141 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "enddocktimer called but not floating" );
143 PointerState aState
= GetPointerState();
144 if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
146 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
147 mpDockWin
->EndDocking( maDockRect
, true );
150 m_aEndDockTimer
.Start();
153 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockingHdl
, void*, void)
155 // called during move of a floating window
156 mnLastUserEvent
= nullptr;
158 vcl::Window
*pDockingArea
= mpDockWin
->GetWindow()->GetParent();
159 PointerState aState
= pDockingArea
->GetPointerState();
161 bool bRealMove
= true;
162 if( GetStyle() & WB_OWNERDRAWDECORATION
)
164 // for windows with ownerdraw decoration
165 // we allow docking only when the window was moved
166 // by dragging its caption
167 // and ignore move request due to resizing
168 vcl::Window
*pBorder
= GetWindow( GetWindowType::Border
);
169 if( pBorder
!= this )
171 tools::Rectangle
aBorderRect( Point(), pBorder
->GetSizePixel() );
172 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
173 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
174 // limit borderrect to the caption part only and without the resizing borders
175 aBorderRect
.SetBottom( aBorderRect
.Top() + nTop
);
176 aBorderRect
.AdjustLeft(nLeft
);
177 aBorderRect
.AdjustRight( -nRight
);
179 PointerState aBorderState
= pBorder
->GetPointerState();
180 bRealMove
= aBorderRect
.IsInside( aBorderState
.maPos
);
184 if( mpDockWin
->GetWindow()->IsVisible() &&
185 (tools::Time::GetSystemTicks() - mnLastTicks
> 500) &&
186 ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) &&
187 !(aState
.mnState
& KEY_MOD1
) && // i43499 CTRL disables docking now
190 maDockPos
= pDockingArea
->OutputToScreenPixel( pDockingArea
->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) );
191 maDockRect
= tools::Rectangle( maDockPos
, mpDockWin
->GetSizePixel() );
193 // mouse pos in screen pixels
194 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
196 if( ! mpDockWin
->IsDocking() )
197 mpDockWin
->StartDocking( aMousePos
, maDockRect
);
199 bool bFloatMode
= mpDockWin
->Docking( aMousePos
, maDockRect
);
203 // indicates that the window could be docked at maDockRect
204 maDockRect
.SetPos( mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ScreenToOutputPixel(
205 maDockRect
.TopLeft() ) );
206 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
207 m_aEndDockTimer
.Stop();
208 m_aDockTimer
.Invoke();
212 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
214 m_aEndDockTimer
.Invoke();
220 void ImplDockFloatWin2::Move()
226 FloatingWindow::Move();
227 mpDockWin
->GetWindow()->Move();
230 * note: the window should only dock if KEY_MOD1 is pressed
231 * and the user releases all mouse buttons. The real problem here
232 * is that we don't get mouse events (at least not on X)
233 * if the mouse is on the decoration. So we have to start an
234 * awkward timer based process that polls the modifier/buttons
235 * to see whether they are in the right condition shortly after the
238 if( ! mnLastUserEvent
)
239 mnLastUserEvent
= Application::PostUserEvent( LINK( this, ImplDockFloatWin2
, DockingHdl
), nullptr, true );
242 void ImplDockFloatWin2::Resize()
244 // forwarding of resize only required if we have no borderwindow ( GetWindow() then returns 'this' )
245 if( GetWindow( GetWindowType::Border
) == this )
247 FloatingWindow::Resize();
248 Size
aSize( GetSizePixel() );
249 mpDockWin
->GetWindow()->ImplPosSizeWindow( 0, 0, aSize
.Width(), aSize
.Height(), PosSizeFlags::PosSize
); // TODO: is this needed ???
253 void ImplDockFloatWin2::TitleButtonClick( TitleButton nButton
)
255 FloatingWindow::TitleButtonClick( nButton
);
256 mpDockWin
->TitleButtonClick( nButton
);
259 void ImplDockFloatWin2::Resizing( Size
& rSize
)
261 FloatingWindow::Resizing( rSize
);
262 mpDockWin
->Resizing( rSize
);
265 bool ImplDockFloatWin2::Close()
270 DockingManager::DockingManager()
274 DockingManager::~DockingManager()
278 ImplDockingWindowWrapper
* DockingManager::GetDockingWindowWrapper( const vcl::Window
*pWindow
)
280 for( const auto& xWrapper
: mvDockingWindows
)
282 if (xWrapper
&& xWrapper
->mpDockingWindow
== pWindow
)
283 return xWrapper
.get();
288 bool DockingManager::IsDockable( const vcl::Window
*pWindow
)
290 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
293 if( pWindow->HasDockingHandler() )
296 return (pWrapper
!= nullptr);
299 bool DockingManager::IsFloating( const vcl::Window
*pWindow
)
301 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
303 return pWrapper
->IsFloatingMode();
308 bool DockingManager::IsLocked( const vcl::Window
*pWindow
)
310 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
311 return pWrapper
&& pWrapper
->IsLocked();
314 void DockingManager::Lock( const vcl::Window
*pWindow
)
316 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
321 void DockingManager::Unlock( const vcl::Window
*pWindow
)
323 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
328 void DockingManager::SetFloatingMode( const vcl::Window
*pWindow
, bool bFloating
)
330 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
332 pWrapper
->SetFloatingMode( bFloating
);
335 void DockingManager::StartPopupMode( const vcl::Window
*pWindow
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
337 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
339 pWrapper
->StartPopupMode( rRect
, nFlags
);
342 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
, FloatWinPopupFlags nFlags
)
344 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
346 pWrapper
->StartPopupMode( pParentToolBox
, nFlags
);
349 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
)
351 StartPopupMode( pParentToolBox
, pWindow
, FloatWinPopupFlags::AllowTearOff
|
352 FloatWinPopupFlags::AllMouseButtonClose
|
353 FloatWinPopupFlags::NoMouseUpClose
);
356 bool DockingManager::IsInPopupMode( const vcl::Window
*pWindow
)
358 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
359 return pWrapper
&& pWrapper
->IsInPopupMode();
362 void DockingManager::EndPopupMode( const vcl::Window
*pWin
)
364 ImplDockingWindowWrapper
*pWrapper
= GetDockingWindowWrapper( pWin
);
365 if( pWrapper
&& pWrapper
->GetFloatingWindow() && pWrapper
->GetFloatingWindow()->IsInPopupMode() )
366 pWrapper
->GetFloatingWindow()->EndPopupMode();
369 void DockingManager::SetPopupModeEndHdl( const vcl::Window
*pWindow
, const Link
<FloatingWindow
*,void>& rLink
)
371 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
373 pWrapper
->SetPopupModeEndHdl(rLink
);
376 void DockingManager::AddWindow( const vcl::Window
*pWindow
)
378 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
381 mvDockingWindows
.emplace_back( new ImplDockingWindowWrapper( pWindow
) );
384 void DockingManager::RemoveWindow( const vcl::Window
*pWindow
)
386 for( auto it
= mvDockingWindows
.begin(); it
!= mvDockingWindows
.end(); ++it
)
388 const auto& xWrapper
= *it
;
389 if (xWrapper
&& xWrapper
->mpDockingWindow
== pWindow
)
391 mvDockingWindows
.erase( it
);
397 void DockingManager::SetPosSizePixel( vcl::Window
const *pWindow
, tools::Long nX
, tools::Long nY
,
398 tools::Long nWidth
, tools::Long nHeight
,
399 PosSizeFlags nFlags
)
401 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
403 pWrapper
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
406 tools::Rectangle
DockingManager::GetPosSizePixel( const vcl::Window
*pWindow
)
408 tools::Rectangle aRect
;
409 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
411 aRect
= tools::Rectangle( pWrapper
->GetPosPixel(), pWrapper
->GetSizePixel() );
416 class ImplPopupFloatWin
: public FloatingWindow
422 ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
);
423 virtual ~ImplPopupFloatWin() override
;
424 virtual css::uno::Reference
< css::accessibility::XAccessible
> CreateAccessible() override
;
427 ImplPopupFloatWin::ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
) :
428 FloatingWindow( pParent
, bToolBox
? WB_BORDER
| WB_POPUP
| WB_SYSTEMWINDOW
| WB_NOSHADOW
: WB_STDPOPUP
),
429 mbToolBox( bToolBox
)
433 // indicate window type, required for accessibility
434 // which should not see this window as a toplevel window
435 mpWindowImpl
->mbToolbarFloatingWindow
= true;
439 ImplPopupFloatWin::~ImplPopupFloatWin()
444 css::uno::Reference
< css::accessibility::XAccessible
> ImplPopupFloatWin::CreateAccessible()
447 return FloatingWindow::CreateAccessible();
449 // switch off direct accessibility support for this window
451 // this is to avoid appearance of this window as standalone window in the accessibility hierarchy
452 // as this window is only used as a helper for subtoolbars that are not teared-off, the parent toolbar
453 // has to provide accessibility support (as implemented in the toolkit)
454 // so the contained toolbar should appear as child of the corresponding toolbar item of the parent toolbar
455 return css::uno::Reference
< css::accessibility::XAccessible
>();
458 ImplDockingWindowWrapper::ImplDockingWindowWrapper( const vcl::Window
*pWindow
)
459 : mpDockingWindow(const_cast<vcl::Window
*>(pWindow
))
460 , mpFloatWin(nullptr)
461 , mpOldBorderWin(nullptr)
462 , mpParent(pWindow
->GetParent())
463 , maMaxOutSize( SHRT_MAX
, SHRT_MAX
)
472 , mnFloatBits(WB_BORDER
| WB_CLOSEABLE
| WB_SIZEABLE
| (pWindow
->GetStyle() & DOCKWIN_FLOATSTYLES
))
473 , mbDockCanceled(false)
475 , mbLastFloatMode(false)
479 // must be enabled in Window::Notify to prevent permanent docking during mouse move
480 , mbStartDockingEnabled(false)
483 assert(mpDockingWindow
);
484 DockingWindow
*pDockWin
= dynamic_cast< DockingWindow
* > ( mpDockingWindow
.get() );
486 mnFloatBits
= pDockWin
->GetFloatStyle();
489 ImplDockingWindowWrapper::~ImplDockingWindowWrapper()
491 if ( IsFloatingMode() )
493 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
494 SetFloatingMode(false);
498 void ImplDockingWindowWrapper::ImplStartDocking( const Point
& rPos
)
500 if( !mbStartDockingEnabled
)
505 mbLastFloatMode
= IsFloatingMode();
507 // calculate FloatingBorder
508 VclPtr
<FloatingWindow
> pWin
;
512 pWin
= VclPtr
<ImplDockFloatWin2
>::Create( mpParent
, mnFloatBits
, nullptr );
513 pWin
->GetBorder( mnDockLeft
, mnDockTop
, mnDockRight
, mnDockBottom
);
515 pWin
.disposeAndClear();
517 Point aPos
= GetWindow()->ImplOutputToFrame( Point() );
518 Size aSize
= GetWindow()->GetOutputSizePixel();
521 mnTrackWidth
= aSize
.Width();
522 mnTrackHeight
= aSize
.Height();
524 if ( mbLastFloatMode
)
526 maMouseOff
.AdjustX(mnDockLeft
);
527 maMouseOff
.AdjustY(mnDockTop
);
528 mnTrackX
-= mnDockLeft
;
529 mnTrackY
-= mnDockTop
;
530 mnTrackWidth
+= mnDockLeft
+mnDockRight
;
531 mnTrackHeight
+= mnDockTop
+mnDockBottom
;
534 vcl::Window
*pDockingArea
= GetWindow()->GetParent();
535 vcl::Window::PointerState aState
= pDockingArea
->GetPointerState();
537 // mouse pos in screen pixels
538 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
539 Point aDockPos
= pDockingArea
->AbsoluteScreenToOutputPixel( GetWindow()->OutputToAbsoluteScreenPixel( GetWindow()->GetPosPixel() ) );
540 tools::Rectangle
aDockRect( aDockPos
, GetWindow()->GetSizePixel() );
541 StartDocking( aMousePos
, aDockRect
);
543 GetWindow()->ImplUpdateAll();
544 GetWindow()->ImplGetFrameWindow()->ImplUpdateAll();
546 GetWindow()->StartTracking( StartTrackingFlags::KeyMod
);
549 void ImplDockingWindowWrapper::Tracking( const TrackingEvent
& rTEvt
)
551 // used during docking of a currently docked window
555 if ( rTEvt
.IsTrackingEnded() )
558 GetWindow()->HideTracking();
559 if ( rTEvt
.IsTrackingCanceled() )
561 mbDockCanceled
= true;
562 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
563 mbDockCanceled
= false;
566 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
568 // Docking only upon non-synthetic MouseEvents
569 else if ( !rTEvt
.GetMouseEvent().IsSynthetic() || rTEvt
.GetMouseEvent().IsModifierChanged() )
571 Point aMousePos
= rTEvt
.GetMouseEvent().GetPosPixel();
572 Point aFrameMousePos
= GetWindow()->ImplOutputToFrame( aMousePos
);
573 Size aFrameSize
= GetWindow()->ImplGetFrameWindow()->GetOutputSizePixel();
574 if ( aFrameMousePos
.X() < 0 )
575 aFrameMousePos
.setX( 0 );
576 if ( aFrameMousePos
.Y() < 0 )
577 aFrameMousePos
.setY( 0 );
578 if ( aFrameMousePos
.X() > aFrameSize
.Width()-1 )
579 aFrameMousePos
.setX( aFrameSize
.Width()-1 );
580 if ( aFrameMousePos
.Y() > aFrameSize
.Height()-1 )
581 aFrameMousePos
.setY( aFrameSize
.Height()-1 );
582 aMousePos
= GetWindow()->ImplFrameToOutput( aFrameMousePos
);
583 aMousePos
.AdjustX( -(maMouseOff
.X()) );
584 aMousePos
.AdjustY( -(maMouseOff
.Y()) );
585 Point aPos
= GetWindow()->ImplOutputToFrame( aMousePos
);
586 tools::Rectangle
aTrackRect( aPos
, Size( mnTrackWidth
, mnTrackHeight
) );
587 tools::Rectangle aCompRect
= aTrackRect
;
588 aPos
.AdjustX(maMouseOff
.X() );
589 aPos
.AdjustY(maMouseOff
.Y() );
591 bool bFloatMode
= Docking( aPos
, aTrackRect
);
593 if ( mbLastFloatMode
!= bFloatMode
)
597 aTrackRect
.AdjustLeft( -mnDockLeft
);
598 aTrackRect
.AdjustTop( -mnDockTop
);
599 aTrackRect
.AdjustRight(mnDockRight
);
600 aTrackRect
.AdjustBottom(mnDockBottom
);
604 if ( aCompRect
== aTrackRect
)
606 aTrackRect
.AdjustLeft(mnDockLeft
);
607 aTrackRect
.AdjustTop(mnDockTop
);
608 aTrackRect
.AdjustRight( -mnDockRight
);
609 aTrackRect
.AdjustBottom( -mnDockBottom
);
612 mbLastFloatMode
= bFloatMode
;
615 ShowTrackFlags nTrackStyle
;
617 nTrackStyle
= ShowTrackFlags::Object
;
619 nTrackStyle
= ShowTrackFlags::Big
;
620 tools::Rectangle aShowTrackRect
= aTrackRect
;
621 aShowTrackRect
.SetPos( GetWindow()->ImplFrameToOutput( aShowTrackRect
.TopLeft() ) );
623 GetWindow()->ShowTracking( aShowTrackRect
, nTrackStyle
);
625 // calculate mouse offset again, as the rectangle was changed
626 maMouseOff
.setX( aPos
.X() - aTrackRect
.Left() );
627 maMouseOff
.setY( aPos
.Y() - aTrackRect
.Top() );
629 mnTrackX
= aTrackRect
.Left();
630 mnTrackY
= aTrackRect
.Top();
631 mnTrackWidth
= aTrackRect
.GetWidth();
632 mnTrackHeight
= aTrackRect
.GetHeight();
636 void ImplDockingWindowWrapper::StartDocking( const Point
& rPoint
, tools::Rectangle
const & rRect
)
638 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
640 GetWindow()->CallEventListeners( VclEventId::WindowStartDocking
, &data
);
644 bool ImplDockingWindowWrapper::Docking( const Point
& rPoint
, tools::Rectangle
& rRect
)
646 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
648 GetWindow()->CallEventListeners( VclEventId::WindowDocking
, &data
);
649 rRect
= data
.maTrackRect
;
650 return data
.mbFloating
;
653 void ImplDockingWindowWrapper::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
655 tools::Rectangle
aRect( rRect
);
657 bool bOrigDockCanceled
= mbDockCanceled
;
658 if (bFloatMode
&& !StyleSettings::GetDockingFloatsSupported())
659 mbDockCanceled
= true;
661 if ( !IsDockingCanceled() )
664 if ( bFloatMode
!= IsFloatingMode() )
666 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
667 SetFloatingMode( bFloatMode
);
671 // #i44800# always use outputsize - as in all other places
672 mpFloatWin
->SetOutputSizePixel( aRect
.GetSize() );
673 mpFloatWin
->SetPosPixel( aRect
.TopLeft() );
678 Point aPos
= aRect
.TopLeft();
679 aPos
= GetWindow()->GetParent()->ScreenToOutputPixel( aPos
);
680 GetWindow()->SetPosSizePixel( aPos
, aRect
.GetSize() );
684 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
687 EndDockingData
data( aRect
, IsFloatingMode(), IsDockingCanceled() );
688 GetWindow()->CallEventListeners( VclEventId::WindowEndDocking
, &data
);
692 // must be enabled in Window::Notify to prevent permanent docking during mouse move
693 mbStartDockingEnabled
= false;
695 mbDockCanceled
= bOrigDockCanceled
;
698 bool ImplDockingWindowWrapper::PrepareToggleFloatingMode()
700 bool bFloating
= true;
701 GetWindow()->CallEventListeners( VclEventId::WindowPrepareToggleFloating
, &bFloating
);
705 void ImplDockingWindowWrapper::ToggleFloatingMode()
707 // notify dockingwindow/toolbox
708 // note: this must be done *before* notifying the
709 // listeners to have the toolbox in the proper state
710 if( GetWindow()->IsDockingWindow() )
711 static_cast<DockingWindow
*>(GetWindow())->ToggleFloatingMode();
713 // now notify listeners
714 GetWindow()->CallEventListeners( VclEventId::WindowToggleFloating
);
716 // must be enabled in Window::Notify to prevent permanent docking during mouse move
717 mbStartDockingEnabled
= false;
720 void ImplDockingWindowWrapper::TitleButtonClick( TitleButton nType
)
722 if( nType
== TitleButton::Menu
)
724 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
727 pToolBox
->ExecuteCustomMenu();
730 if( nType
== TitleButton::Docking
)
732 SetFloatingMode( !IsFloatingMode() );
736 void ImplDockingWindowWrapper::Resizing( Size
& rSize
)
738 // TODO: add virtual Resizing() to class Window, so we can get rid of class DockingWindow
739 DockingWindow
*pDockingWindow
= dynamic_cast< DockingWindow
* >( GetWindow() );
741 pDockingWindow
->Resizing( rSize
);
744 void ImplDockingWindowWrapper::ShowTitleButton( TitleButton nButton
, bool bVisible
)
747 mpFloatWin
->ShowTitleButton( nButton
, bVisible
);
750 if ( nButton
== TitleButton::Docking
)
751 mbDockBtn
= bVisible
;
752 else // if ( nButton == TitleButton::Hide )
753 mbHideBtn
= bVisible
;
757 void ImplDockingWindowWrapper::ImplPreparePopupMode()
759 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
761 // prepare reparenting
762 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
763 mpOldBorderWin
= GetWindow()->GetWindow( GetWindowType::Border
);
764 if( mpOldBorderWin
.get() == GetWindow() )
765 mpOldBorderWin
= nullptr; // no border window found
767 // the new parent for popup mode
768 VclPtrInstance
<ImplPopupFloatWin
> pWin( mpParent
, GetWindow()->GetType() == WindowType::TOOLBOX
);
769 pWin
->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper
, PopupModeEnd
) );
771 // At least for DockingWindow, GetText() has a side effect of setting deferred
772 // properties. This must be done before setting the border window (see below),
773 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
774 // the border window (See DockingWindow::setPosSizeOnContainee() and
775 // DockingWindow::GetOptimalSize()).
776 pWin
->SetText( GetWindow()->GetText() );
777 pWin
->SetOutputSizePixel( GetWindow()->GetSizePixel() );
779 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
780 GetWindow()->mpWindowImpl
->mnLeftBorder
= 0;
781 GetWindow()->mpWindowImpl
->mnTopBorder
= 0;
782 GetWindow()->mpWindowImpl
->mnRightBorder
= 0;
783 GetWindow()->mpWindowImpl
->mnBottomBorder
= 0;
785 // reparent borderwindow and window
786 if ( mpOldBorderWin
)
787 mpOldBorderWin
->SetParent( pWin
);
788 GetWindow()->SetParent( pWin
);
790 // correct border window pointers
791 GetWindow()->mpWindowImpl
->mpBorderWindow
= pWin
;
792 pWin
->mpWindowImpl
->mpClientWindow
= GetWindow();
793 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
795 // set mpFloatWin not until all window positioning is done !!!
796 // (SetPosPixel etc. check for valid mpFloatWin pointer)
800 void ImplDockingWindowWrapper::StartPopupMode( ToolBox
*pParentToolBox
, FloatWinPopupFlags nFlags
)
802 // do nothing if window is floating
803 if( IsFloatingMode() )
806 ImplPreparePopupMode();
808 // don't allow tearoff, if globally disabled
809 if( !StyleSettings::GetDockingFloatsSupported() ||
810 ( GetWindow()->GetType() == WindowType::TOOLBOX
&& ToolBox::AlwaysLocked() ) )
811 nFlags
&= ~FloatWinPopupFlags::AllowTearOff
;
813 // if the subtoolbar was opened via keyboard make sure that key events
814 // will go into subtoolbar
815 if( pParentToolBox
->IsKeyEvent() )
816 nFlags
|= FloatWinPopupFlags::GrabFocus
;
818 mpFloatWin
->StartPopupMode( pParentToolBox
, nFlags
);
821 if( pParentToolBox
->IsKeyEvent() )
823 // send HOME key to subtoolbar in order to select first item
824 KeyEvent
aEvent( 0, vcl::KeyCode( KEY_HOME
) );
825 GetWindow()->KeyInput(aEvent
);
829 void ImplDockingWindowWrapper::StartPopupMode( const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
831 // do nothing if window is floating
832 if( IsFloatingMode() )
835 ImplPreparePopupMode();
836 mpFloatWin
->StartPopupMode( rRect
, nFlags
);
840 IMPL_LINK_NOARG(ImplDockingWindowWrapper
, PopupModeEnd
, FloatingWindow
*, void)
842 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
844 // set parameter for handler before destroying floating window
845 EndPopupModeData
aData( mpFloatWin
->GetWindow( GetWindowType::Border
)->GetPosPixel(), mpFloatWin
->IsPopupModeTearOff() );
847 // before deleting change parent back, so we can delete the floating window alone
848 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
849 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
850 if ( mpOldBorderWin
)
852 GetWindow()->SetParent( mpOldBorderWin
);
853 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
854 GetWindow()->mpWindowImpl
->mnLeftBorder
, GetWindow()->mpWindowImpl
->mnTopBorder
,
855 GetWindow()->mpWindowImpl
->mnRightBorder
, GetWindow()->mpWindowImpl
->mnBottomBorder
);
856 mpOldBorderWin
->Resize();
858 GetWindow()->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
859 GetWindow()->SetParent( pRealParent
);
860 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
862 maPopupModeEndHdl
.Call(mpFloatWin
);
863 mpFloatWin
.disposeAndClear();
865 // call handler - which will destroy the window and thus the wrapper as well !
866 GetWindow()->CallEventListeners( VclEventId::WindowEndPopupMode
, &aData
);
869 bool ImplDockingWindowWrapper::IsInPopupMode() const
871 if( GetFloatingWindow() )
872 return GetFloatingWindow()->IsInPopupMode();
877 void ImplDockingWindowWrapper::SetFloatingMode( bool bFloatMode
)
879 // do nothing if window is docked and locked
880 if( !IsFloatingMode() && IsLocked() )
883 if ( IsFloatingMode() == bFloatMode
)
886 if ( !PrepareToggleFloatingMode() )
889 bool bVisible
= GetWindow()->IsVisible();
893 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
895 maDockPos
= GetWindow()->GetPosPixel();
897 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
898 mpOldBorderWin
= GetWindow()->GetWindow( GetWindowType::Border
);
899 if( mpOldBorderWin
== mpDockingWindow
)
900 mpOldBorderWin
= nullptr; // no border window found
902 VclPtrInstance
<ImplDockFloatWin2
> pWin(
904 mnFloatBits
& ( WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
) ?
905 mnFloatBits
| WB_SYSTEMWINDOW
906 | WB_OWNERDRAWDECORATION
910 // At least for DockingWindow, GetText() has a side effect of setting deferred
911 // properties. This must be done before setting the border window (see below),
912 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
913 // the border window (See DockingWindow::setPosSizeOnContainee() and
914 // DockingWindow::GetOptimalSize()).
915 pWin
->SetText( GetWindow()->GetText() );
917 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
918 GetWindow()->mpWindowImpl
->mnLeftBorder
= 0;
919 GetWindow()->mpWindowImpl
->mnTopBorder
= 0;
920 GetWindow()->mpWindowImpl
->mnRightBorder
= 0;
921 GetWindow()->mpWindowImpl
->mnBottomBorder
= 0;
923 // if the parent gets destroyed, we also have to reset the parent of the BorderWindow
924 if ( mpOldBorderWin
)
925 mpOldBorderWin
->SetParent( pWin
);
926 GetWindow()->SetParent( pWin
);
927 pWin
->SetPosPixel( Point() );
929 GetWindow()->mpWindowImpl
->mpBorderWindow
= pWin
;
930 pWin
->mpWindowImpl
->mpClientWindow
= mpDockingWindow
;
931 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
933 pWin
->SetOutputSizePixel( GetWindow()->GetSizePixel() );
934 pWin
->SetPosPixel( maFloatPos
);
935 // pass on DockingData to FloatingWindow
936 pWin
->ShowTitleButton( TitleButton::Docking
, mbDockBtn
);
937 pWin
->ShowTitleButton( TitleButton::Hide
, mbHideBtn
);
942 pWin
->SetRollUpOutputSizePixel( maRollUpOutSize
);
943 pWin
->SetMinOutputSizePixel( maMinOutSize
);
944 pWin
->SetMaxOutputSizePixel( maMaxOutSize
);
949 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
951 ToggleFloatingMode();
955 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
957 // store FloatingData in FloatingWindow
958 maFloatPos
= mpFloatWin
->GetPosPixel();
959 mbDockBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Docking
);
960 mbHideBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Hide
);
961 mbRollUp
= mpFloatWin
->IsRollUp();
962 maRollUpOutSize
= mpFloatWin
->GetRollUpOutputSizePixel();
963 maMinOutSize
= mpFloatWin
->GetMinOutputSizePixel();
964 maMaxOutSize
= mpFloatWin
->GetMaxOutputSizePixel();
966 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
); //mpWindowImpl->mpRealParent;
967 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
968 if ( mpOldBorderWin
)
970 GetWindow()->SetParent( mpOldBorderWin
);
971 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
972 GetWindow()->mpWindowImpl
->mnLeftBorder
, GetWindow()->mpWindowImpl
->mnTopBorder
,
973 GetWindow()->mpWindowImpl
->mnRightBorder
, GetWindow()->mpWindowImpl
->mnBottomBorder
);
974 mpOldBorderWin
->Resize();
976 GetWindow()->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
977 GetWindow()->SetParent( pRealParent
);
978 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
980 mpFloatWin
.disposeAndClear();
981 GetWindow()->SetPosPixel( maDockPos
);
986 ToggleFloatingMode();
991 void ImplDockingWindowWrapper::SetFloatStyle( WinBits nStyle
)
993 mnFloatBits
= nStyle
;
997 void ImplDockingWindowWrapper::setPosSizePixel( tools::Long nX
, tools::Long nY
,
998 tools::Long nWidth
, tools::Long nHeight
,
999 PosSizeFlags nFlags
)
1002 mpFloatWin
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
1004 GetWindow()->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
1007 Point
ImplDockingWindowWrapper::GetPosPixel() const
1010 return mpFloatWin
->GetPosPixel();
1012 return mpDockingWindow
->GetPosPixel();
1015 Size
ImplDockingWindowWrapper::GetSizePixel() const
1018 return mpFloatWin
->GetSizePixel();
1020 return mpDockingWindow
->GetSizePixel();
1023 // old inlines from DockingWindow
1025 void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size
& rSize
)
1028 mpFloatWin
->SetMinOutputSizePixel( rSize
);
1029 maMinOutSize
= rSize
;
1032 void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size
& rSize
)
1035 mpFloatWin
->SetMaxOutputSizePixel( rSize
);
1036 maMaxOutSize
= rSize
;
1039 bool ImplDockingWindowWrapper::IsFloatingMode() const
1041 return (mpFloatWin
!= nullptr);
1044 void ImplDockingWindowWrapper::SetDragArea( const tools::Rectangle
& rRect
)
1050 void ImplDockingWindowWrapper::Lock()
1053 // only toolbars support locking
1054 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1056 pToolBox
->Lock( mbLocked
);
1059 void ImplDockingWindowWrapper::Unlock()
1062 // only toolbars support locking
1063 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1065 pToolBox
->Lock( mbLocked
);
1069 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */