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 )
38 class ImplDockFloatWin2
: public FloatingWindow
41 ImplDockingWindowWrapper
* mpDockWin
;
42 sal_uInt64
const mnLastTicks
;
44 Timer m_aEndDockTimer
;
46 tools::Rectangle maDockRect
;
48 ImplSVEvent
* mnLastUserEvent
;
50 DECL_LINK(DockingHdl
, void *, void);
51 DECL_LINK(DockTimerHdl
, Timer
*, void);
52 DECL_LINK(EndDockTimerHdl
, Timer
*, void);
54 ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
55 ImplDockingWindowWrapper
* pDockingWin
);
56 virtual ~ImplDockFloatWin2() override
;
57 virtual void dispose() override
;
59 virtual void Move() override
;
60 virtual void Resize() override
;
61 virtual void TitleButtonClick( TitleButton nButton
) override
;
62 virtual void Resizing( Size
& rSize
) override
;
63 virtual bool Close() override
;
66 ImplDockFloatWin2::ImplDockFloatWin2( vcl::Window
* pParent
, WinBits nWinBits
,
67 ImplDockingWindowWrapper
* pDockingWin
) :
68 FloatingWindow( pParent
, nWinBits
),
69 mpDockWin( pDockingWin
),
70 mnLastTicks( tools::Time::GetSystemTicks() ),
72 mnLastUserEvent( nullptr )
74 // copy state of DockingWindow
77 SetSettings( pDockingWin
->GetWindow()->GetSettings() );
78 Enable( pDockingWin
->GetWindow()->IsEnabled(), false );
79 EnableInput( pDockingWin
->GetWindow()->IsInputEnabled(), false );
80 AlwaysEnableInput( pDockingWin
->GetWindow()->IsAlwaysEnableInput(), false );
81 EnableAlwaysOnTop( pDockingWin
->GetWindow()->IsAlwaysOnTopEnabled() );
82 SetActivateMode( pDockingWin
->GetWindow()->GetActivateMode() );
85 SetBackground( GetSettings().GetStyleSettings().GetFaceColor() );
87 m_aDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, DockTimerHdl
) );
88 m_aDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
89 m_aDockTimer
.SetTimeout( 50 );
90 m_aDockTimer
.SetDebugName( "vcl::ImplDockFloatWin2 m_aDockTimer" );
92 m_aEndDockTimer
.SetInvokeHandler( LINK( this, ImplDockFloatWin2
, EndDockTimerHdl
) );
93 m_aEndDockTimer
.SetPriority( TaskPriority::HIGH_IDLE
);
94 m_aEndDockTimer
.SetTimeout( 50 );
95 m_aEndDockTimer
.SetDebugName( "vcl::ImplDockFloatWin2 m_aEndDockTimer" );
98 ImplDockFloatWin2::~ImplDockFloatWin2()
103 void ImplDockFloatWin2::dispose()
105 if( mnLastUserEvent
)
106 Application::RemoveUserEvent( mnLastUserEvent
);
107 FloatingWindow::dispose();
110 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockTimerHdl
, Timer
*, void)
112 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "docktimer called but not floating" );
114 PointerState aState
= GetPointerState();
116 if( aState
.mnState
& KEY_MOD1
)
118 // i43499 CTRL disables docking now
119 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
120 if( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) )
121 m_aDockTimer
.Start();
123 else if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
125 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
126 mpDockWin
->EndDocking( maDockRect
, false );
130 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
131 m_aDockTimer
.Start();
135 IMPL_LINK_NOARG(ImplDockFloatWin2
, EndDockTimerHdl
, Timer
*, void)
137 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "enddocktimer called but not floating" );
139 PointerState aState
= GetPointerState();
140 if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
142 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
143 mpDockWin
->EndDocking( maDockRect
, true );
146 m_aEndDockTimer
.Start();
149 IMPL_LINK_NOARG(ImplDockFloatWin2
, DockingHdl
, void*, void)
151 // called during move of a floating window
152 mnLastUserEvent
= nullptr;
154 vcl::Window
*pDockingArea
= mpDockWin
->GetWindow()->GetParent();
155 PointerState aState
= pDockingArea
->GetPointerState();
157 bool bRealMove
= true;
158 if( GetStyle() & WB_OWNERDRAWDECORATION
)
160 // for windows with ownerdraw decoration
161 // we allow docking only when the window was moved
162 // by dragging its caption
163 // and ignore move request due to resizing
164 vcl::Window
*pBorder
= GetWindow( GetWindowType::Border
);
165 if( pBorder
!= this )
167 tools::Rectangle
aBorderRect( Point(), pBorder
->GetSizePixel() );
168 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
169 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
170 // limit borderrect to the caption part only and without the resizing borders
171 aBorderRect
.SetBottom( aBorderRect
.Top() + nTop
);
172 aBorderRect
.AdjustLeft(nLeft
);
173 aBorderRect
.AdjustRight( -nRight
);
175 PointerState aBorderState
= pBorder
->GetPointerState();
176 bRealMove
= aBorderRect
.IsInside( aBorderState
.maPos
);
180 if( mpDockWin
->GetWindow()->IsVisible() &&
181 (tools::Time::GetSystemTicks() - mnLastTicks
> 500) &&
182 ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) &&
183 !(aState
.mnState
& KEY_MOD1
) && // i43499 CTRL disables docking now
186 maDockPos
= pDockingArea
->OutputToScreenPixel( pDockingArea
->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) ) );
187 maDockRect
= tools::Rectangle( maDockPos
, mpDockWin
->GetSizePixel() );
189 // mouse pos in screen pixels
190 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
192 if( ! mpDockWin
->IsDocking() )
193 mpDockWin
->StartDocking( aMousePos
, maDockRect
);
195 bool bFloatMode
= mpDockWin
->Docking( aMousePos
, maDockRect
);
199 // indicates that the window could be docked at maDockRect
200 maDockRect
.SetPos( mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ScreenToOutputPixel(
201 maDockRect
.TopLeft() ) );
202 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
203 m_aEndDockTimer
.Stop();
204 m_aDockTimer
.Invoke();
208 mpDockWin
->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
210 m_aEndDockTimer
.Invoke();
216 void ImplDockFloatWin2::Move()
222 FloatingWindow::Move();
223 mpDockWin
->GetWindow()->Move();
226 * note: the window should only dock if KEY_MOD1 is pressed
227 * and the user releases all mouse buttons. The real problem here
228 * is that we don't get mouse events (at least not on X)
229 * if the mouse is on the decoration. So we have to start an
230 * awkward timer based process that polls the modifier/buttons
231 * to see whether they are in the right condition shortly after the
234 if( ! mnLastUserEvent
)
235 mnLastUserEvent
= Application::PostUserEvent( LINK( this, ImplDockFloatWin2
, DockingHdl
), nullptr, true );
238 void ImplDockFloatWin2::Resize()
240 // forwarding of resize only required if we have no borderwindow ( GetWindow() then returns 'this' )
241 if( GetWindow( GetWindowType::Border
) == this )
243 FloatingWindow::Resize();
244 Size
aSize( GetSizePixel() );
245 mpDockWin
->GetWindow()->ImplPosSizeWindow( 0, 0, aSize
.Width(), aSize
.Height(), PosSizeFlags::PosSize
); // TODO: is this needed ???
249 void ImplDockFloatWin2::TitleButtonClick( TitleButton nButton
)
251 FloatingWindow::TitleButtonClick( nButton
);
252 mpDockWin
->TitleButtonClick( nButton
);
255 void ImplDockFloatWin2::Resizing( Size
& rSize
)
257 FloatingWindow::Resizing( rSize
);
258 mpDockWin
->Resizing( rSize
);
261 bool ImplDockFloatWin2::Close()
266 DockingManager::DockingManager()
270 DockingManager::~DockingManager()
274 ImplDockingWindowWrapper
* DockingManager::GetDockingWindowWrapper( const vcl::Window
*pWindow
)
276 for( const auto& xWrapper
: mvDockingWindows
)
278 if( xWrapper
->mpDockingWindow
== pWindow
)
279 return xWrapper
.get();
284 bool DockingManager::IsDockable( const vcl::Window
*pWindow
)
286 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
289 if( pWindow->HasDockingHandler() )
292 return (pWrapper
!= nullptr);
295 bool DockingManager::IsFloating( const vcl::Window
*pWindow
)
297 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
299 return pWrapper
->IsFloatingMode();
304 bool DockingManager::IsLocked( const vcl::Window
*pWindow
)
306 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
307 return pWrapper
&& pWrapper
->IsLocked();
310 void DockingManager::Lock( const vcl::Window
*pWindow
)
312 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
317 void DockingManager::Unlock( const vcl::Window
*pWindow
)
319 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
324 void DockingManager::SetFloatingMode( const vcl::Window
*pWindow
, bool bFloating
)
326 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
328 pWrapper
->SetFloatingMode( bFloating
);
331 void DockingManager::StartPopupMode( const vcl::Window
*pWindow
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
333 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
335 pWrapper
->StartPopupMode( rRect
, nFlags
);
338 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
, FloatWinPopupFlags nFlags
)
340 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
342 pWrapper
->StartPopupMode( pParentToolBox
, nFlags
);
345 void DockingManager::StartPopupMode( ToolBox
*pParentToolBox
, const vcl::Window
*pWindow
)
347 StartPopupMode( pParentToolBox
, pWindow
, FloatWinPopupFlags::AllowTearOff
|
348 FloatWinPopupFlags::AllMouseButtonClose
|
349 FloatWinPopupFlags::NoMouseUpClose
);
352 bool DockingManager::IsInPopupMode( const vcl::Window
*pWindow
)
354 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
355 return pWrapper
&& pWrapper
->IsInPopupMode();
358 void DockingManager::EndPopupMode( const vcl::Window
*pWin
)
360 ImplDockingWindowWrapper
*pWrapper
= GetDockingWindowWrapper( pWin
);
361 if( pWrapper
&& pWrapper
->GetFloatingWindow() && pWrapper
->GetFloatingWindow()->IsInPopupMode() )
362 pWrapper
->GetFloatingWindow()->EndPopupMode();
365 void DockingManager::AddWindow( const vcl::Window
*pWindow
)
367 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
370 mvDockingWindows
.emplace_back( new ImplDockingWindowWrapper( pWindow
) );
373 void DockingManager::RemoveWindow( const vcl::Window
*pWindow
)
375 for( auto it
= mvDockingWindows
.begin(); it
!= mvDockingWindows
.end(); ++it
)
377 if( (*it
)->mpDockingWindow
== pWindow
)
379 mvDockingWindows
.erase( it
);
385 void DockingManager::SetPosSizePixel( vcl::Window
const *pWindow
, long nX
, long nY
,
386 long nWidth
, long nHeight
,
387 PosSizeFlags nFlags
)
389 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
391 pWrapper
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
394 tools::Rectangle
DockingManager::GetPosSizePixel( const vcl::Window
*pWindow
)
396 tools::Rectangle aRect
;
397 ImplDockingWindowWrapper
* pWrapper
= GetDockingWindowWrapper( pWindow
);
399 aRect
= tools::Rectangle( pWrapper
->GetPosPixel(), pWrapper
->GetSizePixel() );
404 class ImplPopupFloatWin
: public FloatingWindow
407 bool const mbToolBox
;
410 ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
);
411 virtual ~ImplPopupFloatWin() override
;
412 virtual css::uno::Reference
< css::accessibility::XAccessible
> CreateAccessible() override
;
415 ImplPopupFloatWin::ImplPopupFloatWin( vcl::Window
* pParent
, bool bToolBox
) :
416 FloatingWindow( pParent
, bToolBox
? WB_BORDER
| WB_POPUP
| WB_SYSTEMWINDOW
| WB_NOSHADOW
: WB_STDPOPUP
),
417 mbToolBox( bToolBox
)
421 // indicate window type, required for accessibility
422 // which should not see this window as a toplevel window
423 mpWindowImpl
->mbToolbarFloatingWindow
= true;
427 ImplPopupFloatWin::~ImplPopupFloatWin()
432 css::uno::Reference
< css::accessibility::XAccessible
> ImplPopupFloatWin::CreateAccessible()
435 return FloatingWindow::CreateAccessible();
437 // switch off direct accessibility support for this window
439 // this is to avoid appearance of this window as standalone window in the accessibility hierarchy
440 // as this window is only used as a helper for subtoolbars that are not teared-off, the parent toolbar
441 // has to provide accessibility support (as implemented in the toolkit)
442 // so the contained toolbar should appear as child of the corresponding toolbar item of the parent toolbar
443 return css::uno::Reference
< css::accessibility::XAccessible
>();
446 ImplDockingWindowWrapper::ImplDockingWindowWrapper( const vcl::Window
*pWindow
)
447 : mpDockingWindow(const_cast<vcl::Window
*>(pWindow
))
448 , mpFloatWin(nullptr)
449 , mpOldBorderWin(nullptr)
450 , mpParent(pWindow
->GetParent())
451 , maMaxOutSize( SHRT_MAX
, SHRT_MAX
)
460 , mnFloatBits(WB_BORDER
| WB_CLOSEABLE
| WB_SIZEABLE
| (pWindow
->GetStyle() & DOCKWIN_FLOATSTYLES
))
461 , mbDockCanceled(false)
463 , mbLastFloatMode(false)
467 // must be enabled in Window::Notify to prevent permanent docking during mouse move
468 , mbStartDockingEnabled(false)
471 DockingWindow
*pDockWin
= dynamic_cast< DockingWindow
* > ( mpDockingWindow
.get() );
473 mnFloatBits
= pDockWin
->GetFloatStyle();
476 ImplDockingWindowWrapper::~ImplDockingWindowWrapper()
478 if ( IsFloatingMode() )
480 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
481 SetFloatingMode(false);
485 void ImplDockingWindowWrapper::ImplStartDocking( const Point
& rPos
)
487 if( !mbStartDockingEnabled
)
492 mbLastFloatMode
= IsFloatingMode();
494 // calculate FloatingBorder
495 VclPtr
<FloatingWindow
> pWin
;
499 pWin
= VclPtr
<ImplDockFloatWin2
>::Create( mpParent
, mnFloatBits
, nullptr );
500 pWin
->GetBorder( mnDockLeft
, mnDockTop
, mnDockRight
, mnDockBottom
);
502 pWin
.disposeAndClear();
504 Point aPos
= GetWindow()->ImplOutputToFrame( Point() );
505 Size aSize
= GetWindow()->GetOutputSizePixel();
508 mnTrackWidth
= aSize
.Width();
509 mnTrackHeight
= aSize
.Height();
511 if ( mbLastFloatMode
)
513 maMouseOff
.AdjustX(mnDockLeft
);
514 maMouseOff
.AdjustY(mnDockTop
);
515 mnTrackX
-= mnDockLeft
;
516 mnTrackY
-= mnDockTop
;
517 mnTrackWidth
+= mnDockLeft
+mnDockRight
;
518 mnTrackHeight
+= mnDockTop
+mnDockBottom
;
521 vcl::Window
*pDockingArea
= GetWindow()->GetParent();
522 vcl::Window::PointerState aState
= pDockingArea
->GetPointerState();
524 // mouse pos in screen pixels
525 Point aMousePos
= pDockingArea
->OutputToScreenPixel( aState
.maPos
);
526 Point aDockPos
= pDockingArea
->AbsoluteScreenToOutputPixel( GetWindow()->OutputToAbsoluteScreenPixel( GetWindow()->GetPosPixel() ) );
527 tools::Rectangle
aDockRect( aDockPos
, GetWindow()->GetSizePixel() );
528 StartDocking( aMousePos
, aDockRect
);
530 GetWindow()->ImplUpdateAll();
531 GetWindow()->ImplGetFrameWindow()->ImplUpdateAll();
533 GetWindow()->StartTracking( StartTrackingFlags::KeyMod
);
536 void ImplDockingWindowWrapper::Tracking( const TrackingEvent
& rTEvt
)
538 // used during docking of a currently docked window
541 if ( rTEvt
.IsTrackingEnded() )
544 GetWindow()->HideTracking();
545 if ( rTEvt
.IsTrackingCanceled() )
547 mbDockCanceled
= true;
548 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
549 mbDockCanceled
= false;
552 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
554 // Docking only upon non-synthetic MouseEvents
555 else if ( !rTEvt
.GetMouseEvent().IsSynthetic() || rTEvt
.GetMouseEvent().IsModifierChanged() )
557 Point aMousePos
= rTEvt
.GetMouseEvent().GetPosPixel();
558 Point aFrameMousePos
= GetWindow()->ImplOutputToFrame( aMousePos
);
559 Size aFrameSize
= GetWindow()->ImplGetFrameWindow()->GetOutputSizePixel();
560 if ( aFrameMousePos
.X() < 0 )
561 aFrameMousePos
.setX( 0 );
562 if ( aFrameMousePos
.Y() < 0 )
563 aFrameMousePos
.setY( 0 );
564 if ( aFrameMousePos
.X() > aFrameSize
.Width()-1 )
565 aFrameMousePos
.setX( aFrameSize
.Width()-1 );
566 if ( aFrameMousePos
.Y() > aFrameSize
.Height()-1 )
567 aFrameMousePos
.setY( aFrameSize
.Height()-1 );
568 aMousePos
= GetWindow()->ImplFrameToOutput( aFrameMousePos
);
569 aMousePos
.AdjustX( -(maMouseOff
.X()) );
570 aMousePos
.AdjustY( -(maMouseOff
.Y()) );
571 Point aPos
= GetWindow()->ImplOutputToFrame( aMousePos
);
572 tools::Rectangle
aTrackRect( aPos
, Size( mnTrackWidth
, mnTrackHeight
) );
573 tools::Rectangle aCompRect
= aTrackRect
;
574 aPos
.AdjustX(maMouseOff
.X() );
575 aPos
.AdjustY(maMouseOff
.Y() );
577 bool bFloatMode
= Docking( aPos
, aTrackRect
);
579 if ( mbLastFloatMode
!= bFloatMode
)
583 aTrackRect
.AdjustLeft( -mnDockLeft
);
584 aTrackRect
.AdjustTop( -mnDockTop
);
585 aTrackRect
.AdjustRight(mnDockRight
);
586 aTrackRect
.AdjustBottom(mnDockBottom
);
590 if ( aCompRect
== aTrackRect
)
592 aTrackRect
.AdjustLeft(mnDockLeft
);
593 aTrackRect
.AdjustTop(mnDockTop
);
594 aTrackRect
.AdjustRight( -mnDockRight
);
595 aTrackRect
.AdjustBottom( -mnDockBottom
);
598 mbLastFloatMode
= bFloatMode
;
601 ShowTrackFlags nTrackStyle
;
603 nTrackStyle
= ShowTrackFlags::Object
;
605 nTrackStyle
= ShowTrackFlags::Big
;
606 tools::Rectangle aShowTrackRect
= aTrackRect
;
607 aShowTrackRect
.SetPos( GetWindow()->ImplFrameToOutput( aShowTrackRect
.TopLeft() ) );
609 GetWindow()->ShowTracking( aShowTrackRect
, nTrackStyle
);
611 // calculate mouse offset again, as the rectangle was changed
612 maMouseOff
.setX( aPos
.X() - aTrackRect
.Left() );
613 maMouseOff
.setY( aPos
.Y() - aTrackRect
.Top() );
615 mnTrackX
= aTrackRect
.Left();
616 mnTrackY
= aTrackRect
.Top();
617 mnTrackWidth
= aTrackRect
.GetWidth();
618 mnTrackHeight
= aTrackRect
.GetHeight();
623 void ImplDockingWindowWrapper::StartDocking( const Point
& rPoint
, tools::Rectangle
const & rRect
)
625 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
627 GetWindow()->CallEventListeners( VclEventId::WindowStartDocking
, &data
);
631 bool ImplDockingWindowWrapper::Docking( const Point
& rPoint
, tools::Rectangle
& rRect
)
633 DockingData
data( rPoint
, rRect
, IsFloatingMode() );
635 GetWindow()->CallEventListeners( VclEventId::WindowDocking
, &data
);
636 rRect
= data
.maTrackRect
;
637 return data
.mbFloating
;
640 void ImplDockingWindowWrapper::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
642 tools::Rectangle
aRect( rRect
);
644 bool bOrigDockCanceled
= mbDockCanceled
;
645 if (bFloatMode
&& !StyleSettings::GetDockingFloatsSupported())
646 mbDockCanceled
= true;
648 if ( !IsDockingCanceled() )
651 if ( bFloatMode
!= IsFloatingMode() )
653 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
654 SetFloatingMode( bFloatMode
);
658 // #i44800# always use outputsize - as in all other places
659 mpFloatWin
->SetOutputSizePixel( aRect
.GetSize() );
660 mpFloatWin
->SetPosPixel( aRect
.TopLeft() );
665 Point aPos
= aRect
.TopLeft();
666 aPos
= GetWindow()->GetParent()->ScreenToOutputPixel( aPos
);
667 GetWindow()->SetPosSizePixel( aPos
, aRect
.GetSize() );
671 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
674 EndDockingData
data( aRect
, IsFloatingMode(), IsDockingCanceled() );
675 GetWindow()->CallEventListeners( VclEventId::WindowEndDocking
, &data
);
679 // must be enabled in Window::Notify to prevent permanent docking during mouse move
680 mbStartDockingEnabled
= false;
682 mbDockCanceled
= bOrigDockCanceled
;
685 bool ImplDockingWindowWrapper::PrepareToggleFloatingMode()
687 bool bFloating
= true;
688 GetWindow()->CallEventListeners( VclEventId::WindowPrepareToggleFloating
, &bFloating
);
692 void ImplDockingWindowWrapper::ToggleFloatingMode()
694 // notify dockingwindow/toolbox
695 // note: this must be done *before* notifying the
696 // listeners to have the toolbox in the proper state
697 if( GetWindow()->IsDockingWindow() )
698 static_cast<DockingWindow
*>(GetWindow())->ToggleFloatingMode();
700 // now notify listeners
701 GetWindow()->CallEventListeners( VclEventId::WindowToggleFloating
);
703 // must be enabled in Window::Notify to prevent permanent docking during mouse move
704 mbStartDockingEnabled
= false;
707 void ImplDockingWindowWrapper::TitleButtonClick( TitleButton nType
)
709 if( nType
== TitleButton::Menu
)
711 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
714 pToolBox
->ExecuteCustomMenu();
717 if( nType
== TitleButton::Docking
)
719 SetFloatingMode( !IsFloatingMode() );
723 void ImplDockingWindowWrapper::Resizing( Size
& rSize
)
725 // TODO: add virtual Resizing() to class Window, so we can get rid of class DockingWindow
726 DockingWindow
*pDockingWindow
= dynamic_cast< DockingWindow
* >( GetWindow() );
728 pDockingWindow
->Resizing( rSize
);
731 void ImplDockingWindowWrapper::ShowTitleButton( TitleButton nButton
, bool bVisible
)
734 mpFloatWin
->ShowTitleButton( nButton
, bVisible
);
737 if ( nButton
== TitleButton::Docking
)
738 mbDockBtn
= bVisible
;
739 else // if ( nButton == TitleButton::Hide )
740 mbHideBtn
= bVisible
;
744 void ImplDockingWindowWrapper::ImplPreparePopupMode()
746 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
748 // prepare reparenting
749 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
750 mpOldBorderWin
= GetWindow()->GetWindow( GetWindowType::Border
);
751 if( mpOldBorderWin
.get() == GetWindow() )
752 mpOldBorderWin
= nullptr; // no border window found
754 // the new parent for popup mode
755 VclPtrInstance
<ImplPopupFloatWin
> pWin( mpParent
, GetWindow()->GetType() == WindowType::TOOLBOX
);
756 pWin
->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper
, PopupModeEnd
) );
758 // At least for DockingWindow, GetText() has a side effect of setting deferred
759 // properties. This must be done before setting the border window (see below),
760 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
761 // the border window (See DockingWindow::setPosSizeOnContainee() and
762 // DockingWindow::GetOptimalSize()).
763 pWin
->SetText( GetWindow()->GetText() );
764 pWin
->SetOutputSizePixel( GetWindow()->GetSizePixel() );
766 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
767 GetWindow()->mpWindowImpl
->mnLeftBorder
= 0;
768 GetWindow()->mpWindowImpl
->mnTopBorder
= 0;
769 GetWindow()->mpWindowImpl
->mnRightBorder
= 0;
770 GetWindow()->mpWindowImpl
->mnBottomBorder
= 0;
772 // reparent borderwindow and window
773 if ( mpOldBorderWin
)
774 mpOldBorderWin
->SetParent( pWin
);
775 GetWindow()->SetParent( pWin
);
777 // correct border window pointers
778 GetWindow()->mpWindowImpl
->mpBorderWindow
= pWin
;
779 pWin
->mpWindowImpl
->mpClientWindow
= GetWindow();
780 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
782 // set mpFloatWin not until all window positioning is done !!!
783 // (SetPosPixel etc. check for valid mpFloatWin pointer)
787 void ImplDockingWindowWrapper::StartPopupMode( ToolBox
*pParentToolBox
, FloatWinPopupFlags nFlags
)
789 // do nothing if window is floating
790 if( IsFloatingMode() )
793 ImplPreparePopupMode();
795 // don't allow tearoff, if globally disabled
796 if( !StyleSettings::GetDockingFloatsSupported() ||
797 ( GetWindow()->GetType() == WindowType::TOOLBOX
&& ToolBox::AlwaysLocked() ) )
798 nFlags
&= ~FloatWinPopupFlags::AllowTearOff
;
800 // if the subtoolbar was opened via keyboard make sure that key events
801 // will go into subtoolbar
802 if( pParentToolBox
->IsKeyEvent() )
803 nFlags
|= FloatWinPopupFlags::GrabFocus
;
805 mpFloatWin
->StartPopupMode( pParentToolBox
, nFlags
);
808 if( pParentToolBox
->IsKeyEvent() )
810 // send HOME key to subtoolbar in order to select first item
811 KeyEvent
aEvent( 0, vcl::KeyCode( KEY_HOME
) );
812 GetWindow()->KeyInput(aEvent
);
816 void ImplDockingWindowWrapper::StartPopupMode( const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
818 // do nothing if window is floating
819 if( IsFloatingMode() )
822 ImplPreparePopupMode();
823 mpFloatWin
->StartPopupMode( rRect
, nFlags
);
827 IMPL_LINK_NOARG(ImplDockingWindowWrapper
, PopupModeEnd
, FloatingWindow
*, void)
829 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
831 // set parameter for handler before destroying floating window
832 EndPopupModeData
aData( mpFloatWin
->GetWindow( GetWindowType::Border
)->GetPosPixel(), mpFloatWin
->IsPopupModeTearOff() );
834 // before deleting change parent back, so we can delete the floating window alone
835 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
836 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
837 if ( mpOldBorderWin
)
839 GetWindow()->SetParent( mpOldBorderWin
);
840 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
841 GetWindow()->mpWindowImpl
->mnLeftBorder
, GetWindow()->mpWindowImpl
->mnTopBorder
,
842 GetWindow()->mpWindowImpl
->mnRightBorder
, GetWindow()->mpWindowImpl
->mnBottomBorder
);
843 mpOldBorderWin
->Resize();
845 GetWindow()->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
846 GetWindow()->SetParent( pRealParent
);
847 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
849 mpFloatWin
.disposeAndClear();
851 // call handler - which will destroy the window and thus the wrapper as well !
852 GetWindow()->CallEventListeners( VclEventId::WindowEndPopupMode
, &aData
);
855 bool ImplDockingWindowWrapper::IsInPopupMode() const
857 if( GetFloatingWindow() )
858 return GetFloatingWindow()->IsInPopupMode();
863 void ImplDockingWindowWrapper::SetFloatingMode( bool bFloatMode
)
865 // do nothing if window is docked and locked
866 if( !IsFloatingMode() && IsLocked() )
869 if ( IsFloatingMode() != bFloatMode
)
871 if ( PrepareToggleFloatingMode() )
873 bool bVisible
= GetWindow()->IsVisible();
877 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
879 maDockPos
= GetWindow()->GetPosPixel();
881 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
);
882 mpOldBorderWin
= GetWindow()->GetWindow( GetWindowType::Border
);
883 if( mpOldBorderWin
== mpDockingWindow
)
884 mpOldBorderWin
= nullptr; // no border window found
886 VclPtrInstance
<ImplDockFloatWin2
> pWin(
888 mnFloatBits
& ( WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
) ?
889 mnFloatBits
| WB_SYSTEMWINDOW
890 | WB_OWNERDRAWDECORATION
894 // At least for DockingWindow, GetText() has a side effect of setting deferred
895 // properties. This must be done before setting the border window (see below),
896 // so that the border width will end up in mpWindowImpl->mnBorderWidth, not in
897 // the border window (See DockingWindow::setPosSizeOnContainee() and
898 // DockingWindow::GetOptimalSize()).
899 pWin
->SetText( GetWindow()->GetText() );
901 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
902 GetWindow()->mpWindowImpl
->mnLeftBorder
= 0;
903 GetWindow()->mpWindowImpl
->mnTopBorder
= 0;
904 GetWindow()->mpWindowImpl
->mnRightBorder
= 0;
905 GetWindow()->mpWindowImpl
->mnBottomBorder
= 0;
907 // if the parent gets destroyed, we also have to reset the parent of the BorderWindow
908 if ( mpOldBorderWin
)
909 mpOldBorderWin
->SetParent( pWin
);
910 GetWindow()->SetParent( pWin
);
911 pWin
->SetPosPixel( Point() );
913 GetWindow()->mpWindowImpl
->mpBorderWindow
= pWin
;
914 pWin
->mpWindowImpl
->mpClientWindow
= mpDockingWindow
;
915 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
917 pWin
->SetOutputSizePixel( GetWindow()->GetSizePixel() );
918 pWin
->SetPosPixel( maFloatPos
);
919 // pass on DockingData to FloatingWindow
920 pWin
->ShowTitleButton( TitleButton::Docking
, mbDockBtn
);
921 pWin
->ShowTitleButton( TitleButton::Hide
, mbHideBtn
);
926 pWin
->SetRollUpOutputSizePixel( maRollUpOutSize
);
927 pWin
->SetMinOutputSizePixel( maMinOutSize
);
928 pWin
->SetMaxOutputSizePixel( maMaxOutSize
);
933 GetWindow()->Show( true, ShowFlags::NoFocusChange
| ShowFlags::NoActivate
);
935 ToggleFloatingMode();
939 GetWindow()->Show( false, ShowFlags::NoFocusChange
);
941 // store FloatingData in FloatingWindow
942 maFloatPos
= mpFloatWin
->GetPosPixel();
943 mbDockBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Docking
);
944 mbHideBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Hide
);
945 mbRollUp
= mpFloatWin
->IsRollUp();
946 maRollUpOutSize
= mpFloatWin
->GetRollUpOutputSizePixel();
947 maMinOutSize
= mpFloatWin
->GetMinOutputSizePixel();
948 maMaxOutSize
= mpFloatWin
->GetMaxOutputSizePixel();
950 vcl::Window
* pRealParent
= GetWindow()->GetWindow( GetWindowType::Parent
); //mpWindowImpl->mpRealParent;
951 GetWindow()->mpWindowImpl
->mpBorderWindow
= nullptr;
952 if ( mpOldBorderWin
)
954 GetWindow()->SetParent( mpOldBorderWin
);
955 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder(
956 GetWindow()->mpWindowImpl
->mnLeftBorder
, GetWindow()->mpWindowImpl
->mnTopBorder
,
957 GetWindow()->mpWindowImpl
->mnRightBorder
, GetWindow()->mpWindowImpl
->mnBottomBorder
);
958 mpOldBorderWin
->Resize();
960 GetWindow()->mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
961 GetWindow()->SetParent( pRealParent
);
962 GetWindow()->mpWindowImpl
->mpRealParent
= pRealParent
;
964 mpFloatWin
.disposeAndClear();
965 GetWindow()->SetPosPixel( maDockPos
);
970 ToggleFloatingMode();
977 void ImplDockingWindowWrapper::SetFloatStyle( WinBits nStyle
)
979 mnFloatBits
= nStyle
;
983 void ImplDockingWindowWrapper::setPosSizePixel( long nX
, long nY
,
984 long nWidth
, long nHeight
,
985 PosSizeFlags nFlags
)
988 mpFloatWin
->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
990 GetWindow()->setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
993 Point
ImplDockingWindowWrapper::GetPosPixel() const
996 return mpFloatWin
->GetPosPixel();
998 return mpDockingWindow
->GetPosPixel();
1001 Size
ImplDockingWindowWrapper::GetSizePixel() const
1004 return mpFloatWin
->GetSizePixel();
1006 return mpDockingWindow
->GetSizePixel();
1009 // old inlines from DockingWindow
1011 void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size
& rSize
)
1014 mpFloatWin
->SetMinOutputSizePixel( rSize
);
1015 maMinOutSize
= rSize
;
1018 void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size
& rSize
)
1021 mpFloatWin
->SetMaxOutputSizePixel( rSize
);
1022 maMaxOutSize
= rSize
;
1025 bool ImplDockingWindowWrapper::IsFloatingMode() const
1027 return (mpFloatWin
!= nullptr);
1030 void ImplDockingWindowWrapper::SetDragArea( const tools::Rectangle
& rRect
)
1036 void ImplDockingWindowWrapper::Lock()
1039 // only toolbars support locking
1040 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1042 pToolBox
->Lock( mbLocked
);
1045 void ImplDockingWindowWrapper::Unlock()
1048 // only toolbars support locking
1049 ToolBox
*pToolBox
= dynamic_cast< ToolBox
* >( GetWindow() );
1051 pToolBox
->Lock( mbLocked
);
1055 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */