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 <vcl/event.hxx>
23 #include <vcl/toolkit/floatwin.hxx>
24 #include <vcl/layout.hxx>
25 #include <vcl/dockwin.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/timer.hxx>
28 #include <vcl/idle.hxx>
29 #include <vcl/settings.hxx>
30 #include <comphelper/lok.hxx>
37 #include "impldockingwrapper.hxx"
39 #define DOCKWIN_FLOATSTYLES (WB_SIZEABLE | WB_MOVEABLE | WB_CLOSEABLE | WB_STANDALONE)
41 class DockingWindow::ImplData
46 VclPtr
<vcl::Window
> mpParent
;
50 DockingWindow::ImplData::ImplData()
53 maMaxOutSize
= Size( SHRT_MAX
, SHRT_MAX
);
58 class ImplDockFloatWin
: public FloatingWindow
61 VclPtr
<DockingWindow
> mpDockWin
;
62 sal_uInt64 mnLastTicks
;
65 tools::Rectangle maDockRect
;
67 ImplSVEvent
* mnLastUserEvent
;
69 DECL_LINK(DockingHdl
, void *, void);
70 DECL_LINK(DockTimerHdl
, Timer
*, void);
72 ImplDockFloatWin( vcl::Window
* pParent
, WinBits nWinBits
,
73 DockingWindow
* pDockingWin
);
74 virtual ~ImplDockFloatWin() override
;
75 virtual void dispose() override
;
77 virtual void Move() override
;
78 virtual void Resize() override
;
79 virtual void Resizing( Size
& rSize
) override
;
80 virtual bool Close() override
;
85 ImplDockFloatWin::ImplDockFloatWin( vcl::Window
* pParent
, WinBits nWinBits
,
86 DockingWindow
* pDockingWin
) :
87 FloatingWindow( pParent
, nWinBits
),
88 mpDockWin( pDockingWin
),
89 mnLastTicks( tools::Time::GetSystemTicks() ),
90 maDockIdle( "vcl::ImplDockFloatWin maDockIdle" ),
92 mnLastUserEvent( nullptr )
94 // copy settings of DockingWindow
97 GetOutDev()->SetSettings( pDockingWin
->GetSettings() );
98 Enable( pDockingWin
->IsEnabled(), false );
99 EnableInput( pDockingWin
->IsInputEnabled(), false );
100 AlwaysEnableInput( pDockingWin
->IsAlwaysEnableInput(), false );
101 EnableAlwaysOnTop( pDockingWin
->IsAlwaysOnTopEnabled() );
102 SetActivateMode( pDockingWin
->GetActivateMode() );
107 maDockIdle
.SetInvokeHandler( LINK( this, ImplDockFloatWin
, DockTimerHdl
) );
108 maDockIdle
.SetPriority( TaskPriority::HIGH_IDLE
);
111 ImplDockFloatWin::~ImplDockFloatWin()
116 void ImplDockFloatWin::dispose()
118 if( mnLastUserEvent
)
119 Application::RemoveUserEvent( mnLastUserEvent
);
124 FloatingWindow::dispose();
127 IMPL_LINK_NOARG(ImplDockFloatWin
, DockTimerHdl
, Timer
*, void)
129 SAL_WARN_IF( !mpDockWin
->IsFloatingMode(), "vcl", "docktimer called but not floating" );
132 PointerState aState
= GetPointerState();
134 if( aState
.mnState
& KEY_MOD1
)
136 // i43499 CTRL disables docking now
137 mpDockWin
->GetParent()->ImplGetFrameWindow()->HideTracking();
138 mpDockWin
->EndDocking( maDockRect
, true );
139 if( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) )
142 else if( ! ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) )
144 mpDockWin
->GetParent()->ImplGetFrameWindow()->HideTracking();
145 mpDockWin
->EndDocking( maDockRect
, false );
149 mpDockWin
->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Big
| ShowTrackFlags::TrackWindow
);
154 IMPL_LINK_NOARG(ImplDockFloatWin
, DockingHdl
, void*, void)
156 PointerState aState
= mpDockWin
->GetParent()->GetPointerState();
158 mnLastUserEvent
= nullptr;
159 if( mpDockWin
->IsDockable() &&
160 (tools::Time::GetSystemTicks() - mnLastTicks
> 500) &&
161 ( aState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) ) &&
162 !(aState
.mnState
& KEY_MOD1
) ) // i43499 CTRL disables docking now
164 maDockPos
= mpDockWin
->GetParent()->AbsoluteScreenToOutputPixel( OutputToAbsoluteScreenPixel( Point() ) );
165 maDockPos
= mpDockWin
->GetParent()->OutputToScreenPixel( maDockPos
); // sfx expects screen coordinates
167 if( ! mpDockWin
->IsDocking() )
168 mpDockWin
->StartDocking();
169 maDockRect
= tools::Rectangle( maDockPos
, mpDockWin
->GetSizePixel() );
171 // mouse pos also in screen pixels
172 Point aMousePos
= mpDockWin
->GetParent()->OutputToScreenPixel( aState
.maPos
);
174 bool bFloatMode
= mpDockWin
->Docking( aMousePos
, maDockRect
);
177 mpDockWin
->GetParent()->ImplGetFrameWindow()->ShowTracking( maDockRect
, ShowTrackFlags::Object
| ShowTrackFlags::TrackWindow
);
178 DockTimerHdl( nullptr );
182 mpDockWin
->GetParent()->ImplGetFrameWindow()->HideTracking();
184 mpDockWin
->EndDocking( maDockRect
, true );
190 void ImplDockFloatWin::Move()
196 FloatingWindow::Move();
200 * note: the window should only dock if
201 * the user releases all mouse buttons. The real problem here
202 * is that we don't get mouse events (at least not on X)
203 * if the mouse is on the decoration. So we have to start an
204 * awkward timer based process that polls the modifier/buttons
205 * to see whether they are in the right condition shortly after the
208 if( ! mnLastUserEvent
)
209 mnLastUserEvent
= Application::PostUserEvent( LINK( this, ImplDockFloatWin
, DockingHdl
), nullptr, true );
212 void ImplDockFloatWin::Resize()
214 FloatingWindow::Resize();
215 Size
aSize( GetSizePixel() );
216 mpDockWin
->ImplPosSizeWindow( 0, 0, aSize
.Width(), aSize
.Height(), PosSizeFlags::PosSize
);
219 void ImplDockFloatWin::Resizing( Size
& rSize
)
221 FloatingWindow::Resizing( rSize
);
222 mpDockWin
->Resizing( rSize
);
225 bool ImplDockFloatWin::Close()
227 return mpDockWin
->Close();
230 void DockingWindow::ImplStartDocking( const Point
& rPos
)
237 mbLastFloatMode
= IsFloatingMode();
238 mbStartFloat
= mbLastFloatMode
;
240 // calculate FloatingBorder
241 VclPtr
<FloatingWindow
> pWin
;
245 pWin
= VclPtr
<ImplDockFloatWin
>::Create( mpImplData
->mpParent
, mnFloatBits
, nullptr );
246 pWin
->GetBorder( mnDockLeft
, mnDockTop
, mnDockRight
, mnDockBottom
);
248 pWin
.disposeAndClear();
250 Point aPos
= ImplOutputToFrame( Point() );
251 Size aSize
= Window::GetOutputSizePixel();
254 mnTrackWidth
= aSize
.Width();
255 mnTrackHeight
= aSize
.Height();
257 if ( mbLastFloatMode
)
259 maMouseOff
.AdjustX(mnDockLeft
);
260 maMouseOff
.AdjustY(mnDockTop
);
261 mnTrackX
-= mnDockLeft
;
262 mnTrackY
-= mnDockTop
;
263 mnTrackWidth
+= mnDockLeft
+mnDockRight
;
264 mnTrackHeight
+= mnDockTop
+mnDockBottom
;
267 if ( GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Docking
&&
268 !( mnFloatBits
& ( WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
) ) ) // no full drag when migrating to system window
275 ImplGetFrameWindow()->ImplUpdateAll();
278 StartTracking( StartTrackingFlags::KeyMod
);
281 void DockingWindow::ImplInitDockingWindowData()
283 mpWindowImpl
->mbDockWin
= true;
284 mpFloatWin
= nullptr;
285 mpOldBorderWin
= nullptr;
286 mpImplData
.reset(new ImplData
);
296 mbDockCanceled
= false;
300 mbLastFloatMode
= false;
301 mbStartFloat
= false;
304 mbIsDeferredInit
= false;
305 mbIsCalculatingInitialLayoutSize
= false;
306 mpDialogParent
= nullptr;
308 //To-Do, reuse maResizeTimer
309 maLayoutIdle
.SetPriority(TaskPriority::RESIZE
);
310 maLayoutIdle
.SetInvokeHandler( LINK( this, DockingWindow
, ImplHandleLayoutTimerHdl
) );
313 void DockingWindow::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
315 if ( !(nStyle
& WB_NODIALOGCONTROL
) )
316 nStyle
|= WB_DIALOGCONTROL
;
318 mpImplData
->mpParent
= pParent
;
319 mbDockable
= (nStyle
& WB_DOCKABLE
) != 0;
320 mnFloatBits
= WB_BORDER
| (nStyle
& DOCKWIN_FLOATSTYLES
);
321 nStyle
&= ~(DOCKWIN_FLOATSTYLES
| WB_BORDER
);
323 Window::ImplInit( pParent
, nStyle
, nullptr );
328 void DockingWindow::ImplInitSettings()
330 // Hack: to be able to build DockingWindows w/o background before switching
332 if ( !IsBackground() )
335 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
338 if ( IsControlBackground() )
339 aColor
= GetControlBackground();
340 else if ( Window::GetStyle() & WB_3DLOOK
)
341 aColor
= rStyleSettings
.GetFaceColor();
343 aColor
= rStyleSettings
.GetWindowColor();
344 SetBackground( aColor
);
347 DockingWindow::DockingWindow( WindowType nType
, const char* pIdleDebugName
) :
349 maLayoutIdle( pIdleDebugName
)
351 ImplInitDockingWindowData();
354 DockingWindow::DockingWindow( vcl::Window
* pParent
, WinBits nStyle
, const char* pIdleDebugName
) :
355 Window( WindowType::DOCKINGWINDOW
),
356 maLayoutIdle( pIdleDebugName
)
358 ImplInitDockingWindowData();
359 ImplInit( pParent
, nStyle
);
362 //Find the real parent stashed in mpDialogParent.
363 void DockingWindow::doDeferredInit(WinBits nBits
)
365 vcl::Window
*pParent
= mpDialogParent
;
366 mpDialogParent
= nullptr;
367 ImplInit(pParent
, nBits
);
368 mbIsDeferredInit
= false;
371 void DockingWindow::loadUI(vcl::Window
* pParent
, const OUString
& rID
, const OUString
& rUIXMLDescription
,
372 const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
374 mbIsDeferredInit
= true;
375 mpDialogParent
= pParent
; //should be unset in doDeferredInit
376 m_pUIBuilder
.reset( new VclBuilder(this, AllSettings::GetUIRootDir(), rUIXMLDescription
, rID
, rFrame
) );
379 DockingWindow::DockingWindow(vcl::Window
* pParent
, const OUString
& rID
,
380 const OUString
& rUIXMLDescription
, const char* pIdleDebugName
,
381 const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
382 : Window(WindowType::DOCKINGWINDOW
),
383 maLayoutIdle( pIdleDebugName
)
385 ImplInitDockingWindowData();
387 loadUI(pParent
, rID
, rUIXMLDescription
, rFrame
);
390 DockingWindow::~DockingWindow()
395 void DockingWindow::dispose()
397 if ( IsFloatingMode() )
399 Show( false, ShowFlags::NoFocusChange
);
400 SetFloatingMode(false);
404 mpOldBorderWin
.clear();
405 mpDialogParent
.clear();
410 void DockingWindow::Tracking( const TrackingEvent
& rTEvt
)
412 if( GetDockingManager()->IsDockable( this ) ) // new docking interface
413 return Window::Tracking( rTEvt
);
418 if ( rTEvt
.IsTrackingEnded() )
423 // reset old state on Cancel
424 if ( rTEvt
.IsTrackingCanceled() )
427 tools::Rectangle
aRect( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) );
428 EndDocking( aRect
, mbStartFloat
);
434 if ( rTEvt
.IsTrackingCanceled() )
436 mbDockCanceled
= true;
437 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
438 mbDockCanceled
= false;
441 EndDocking( tools::Rectangle( Point( mnTrackX
, mnTrackY
), Size( mnTrackWidth
, mnTrackHeight
) ), mbLastFloatMode
);
444 // dock only for non-synthetic MouseEvents
445 else if ( !rTEvt
.GetMouseEvent().IsSynthetic() || rTEvt
.GetMouseEvent().IsModifierChanged() )
447 Point aMousePos
= rTEvt
.GetMouseEvent().GetPosPixel();
448 Point aFrameMousePos
= ImplOutputToFrame( aMousePos
);
449 Size aFrameSize
= mpWindowImpl
->mpFrameWindow
->GetOutputSizePixel();
450 if ( aFrameMousePos
.X() < 0 )
451 aFrameMousePos
.setX( 0 );
452 if ( aFrameMousePos
.Y() < 0 )
453 aFrameMousePos
.setY( 0 );
454 if ( aFrameMousePos
.X() > aFrameSize
.Width()-1 )
455 aFrameMousePos
.setX( aFrameSize
.Width()-1 );
456 if ( aFrameMousePos
.Y() > aFrameSize
.Height()-1 )
457 aFrameMousePos
.setY( aFrameSize
.Height()-1 );
458 aMousePos
= ImplFrameToOutput( aFrameMousePos
);
459 aMousePos
.AdjustX( -(maMouseOff
.X()) );
460 aMousePos
.AdjustY( -(maMouseOff
.Y()) );
461 Point aFramePos
= ImplOutputToFrame( aMousePos
);
462 tools::Rectangle
aTrackRect( aFramePos
, Size( mnTrackWidth
, mnTrackHeight
) );
463 tools::Rectangle aCompRect
= aTrackRect
;
464 aFramePos
.AdjustX(maMouseOff
.X() );
465 aFramePos
.AdjustY(maMouseOff
.Y() );
468 bool bFloatMode
= Docking( aFramePos
, aTrackRect
);
469 if ( mbLastFloatMode
!= bFloatMode
)
473 aTrackRect
.AdjustLeft( -mnDockLeft
);
474 aTrackRect
.AdjustTop( -mnDockTop
);
475 aTrackRect
.AdjustRight(mnDockRight
);
476 aTrackRect
.AdjustBottom(mnDockBottom
);
480 if ( aCompRect
== aTrackRect
)
482 aTrackRect
.AdjustLeft(mnDockLeft
);
483 aTrackRect
.AdjustTop(mnDockTop
);
484 aTrackRect
.AdjustRight( -mnDockRight
);
485 aTrackRect
.AdjustBottom( -mnDockBottom
);
488 mbLastFloatMode
= bFloatMode
;
492 Point aOldPos
= OutputToScreenPixel( Point() );
493 EndDocking( aTrackRect
, mbLastFloatMode
);
494 // repaint if state or position has changed
495 if ( aOldPos
!= OutputToScreenPixel( Point() ) )
498 ImplGetFrameWindow()->ImplUpdateAll();
500 // EndDocking( aTrackRect, mbLastFloatMode );
504 ShowTrackFlags nTrackStyle
;
506 nTrackStyle
= ShowTrackFlags::Big
;
508 nTrackStyle
= ShowTrackFlags::Object
;
509 tools::Rectangle aShowTrackRect
= aTrackRect
;
510 aShowTrackRect
.SetPos( ImplFrameToOutput( aShowTrackRect
.TopLeft() ) );
511 ShowTracking( aShowTrackRect
, nTrackStyle
);
513 // recalculate mouse offset, as the rectangle was changed
514 maMouseOff
.setX( aFramePos
.X() - aTrackRect
.Left() );
515 maMouseOff
.setY( aFramePos
.Y() - aTrackRect
.Top() );
518 mnTrackX
= aTrackRect
.Left();
519 mnTrackY
= aTrackRect
.Top();
520 mnTrackWidth
= aTrackRect
.GetWidth();
521 mnTrackHeight
= aTrackRect
.GetHeight();
525 bool DockingWindow::EventNotify( NotifyEvent
& rNEvt
)
527 if( GetDockingManager()->IsDockable( this ) ) // new docking interface
528 return Window::EventNotify( rNEvt
);
532 const bool bDockingSupportCrippled
= !StyleSettings::GetDockingFloatsSupported();
534 if ( rNEvt
.GetType() == NotifyEventType::MOUSEBUTTONDOWN
)
536 const MouseEvent
* pMEvt
= rNEvt
.GetMouseEvent();
537 if ( pMEvt
->IsLeft() )
539 if (!bDockingSupportCrippled
&& pMEvt
->IsMod1() && (pMEvt
->GetClicks() == 2) )
541 SetFloatingMode( !IsFloatingMode() );
542 if ( IsFloatingMode() )
543 ToTop( ToTopFlags::GrabFocusOnly
);
546 else if ( pMEvt
->GetClicks() == 1 )
548 // check if window is floating standalone (IsFloating())
549 // or only partially floating and still docked with one border
550 // ( !mpWindowImpl->mbFrame)
551 if( ! IsFloatingMode() || ! mpFloatWin
->mpWindowImpl
->mbFrame
)
553 Point aPos
= pMEvt
->GetPosPixel();
554 vcl::Window
* pWindow
= rNEvt
.GetWindow();
555 if ( pWindow
!= this )
557 aPos
= pWindow
->OutputToScreenPixel( aPos
);
558 aPos
= ScreenToOutputPixel( aPos
);
560 ImplStartDocking( aPos
);
566 else if( rNEvt
.GetType() == NotifyEventType::KEYINPUT
)
568 const vcl::KeyCode
& rKey
= rNEvt
.GetKeyEvent()->GetKeyCode();
569 if( rKey
.GetCode() == KEY_F10
&& rKey
.GetModifier() &&
570 rKey
.IsShift() && rKey
.IsMod1() && !bDockingSupportCrippled
)
572 SetFloatingMode( !IsFloatingMode() );
573 if ( IsFloatingMode() )
574 ToTop( ToTopFlags::GrabFocusOnly
);
580 return Window::EventNotify( rNEvt
);
583 void DockingWindow::StartDocking()
588 bool DockingWindow::Docking( const Point
&, tools::Rectangle
& )
590 return IsFloatingMode();
593 void DockingWindow::EndDocking( const tools::Rectangle
& rRect
, bool bFloatMode
)
595 bool bOrigDockCanceled
= mbDockCanceled
;
596 if (bFloatMode
&& !StyleSettings::GetDockingFloatsSupported())
597 mbDockCanceled
= true;
599 if ( !IsDockingCanceled() )
601 if ( bFloatMode
!= IsFloatingMode() )
603 SetFloatingMode( bFloatMode
);
604 if ( IsFloatingMode() )
605 ToTop( ToTopFlags::GrabFocusOnly
);
606 if ( bFloatMode
&& mpFloatWin
)
607 mpFloatWin
->SetPosSizePixel( rRect
.TopLeft(), rRect
.GetSize() );
611 Point aPos
= rRect
.TopLeft();
612 aPos
= GetParent()->ScreenToOutputPixel( aPos
);
613 Window::SetPosSizePixel( aPos
, rRect
.GetSize() );
617 mbDockCanceled
= bOrigDockCanceled
;
620 bool DockingWindow::PrepareToggleFloatingMode()
625 bool DockingWindow::Close()
627 VclPtr
<vcl::Window
> xWindow
= this;
628 CallEventListeners( VclEventId::WindowClose
);
629 if ( xWindow
->isDisposed() )
632 if ( mpWindowImpl
->mxWindowPeer
.is() && IsCreatedWithToolkit() )
635 Show( false, ShowFlags::NoFocusChange
);
639 void DockingWindow::ToggleFloatingMode()
643 void DockingWindow::Resizing( Size
& )
647 void DockingWindow::DoInitialLayout()
649 if (GetSettings().GetStyleSettings().GetAutoMnemonic())
650 GenerateAutoMnemonicsOnHierarchy(this);
652 if (isLayoutEnabled())
654 mbIsCalculatingInitialLayoutSize
= true;
655 setDeferredProperties();
656 if (IsFloatingMode())
657 setOptimalLayoutSize();
658 mbIsCalculatingInitialLayoutSize
= false;
662 void DockingWindow::StateChanged( StateChangedType nType
)
666 case StateChangedType::InitShow
:
670 case StateChangedType::ControlBackground
:
675 case StateChangedType::Style
:
676 mbDockable
= (GetStyle() & WB_DOCKABLE
) != 0;
683 Window::StateChanged( nType
);
686 void DockingWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
688 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
689 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
695 Window::DataChanged( rDCEvt
);
698 void DockingWindow::SetFloatingMode( bool bFloatMode
)
700 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
703 pWrapper
->SetFloatingMode( bFloatMode
);
706 if ( IsFloatingMode() == bFloatMode
)
709 if ( !PrepareToggleFloatingMode() ) // changes to floating mode can be vetoed
712 bool bVisible
= IsVisible();
716 // set deferred properties early, so border width will end up
717 // in our mpWindowImpl->mnBorderWidth, not in mpBorderWindow.
718 // (see its usage in setPosSizeOnContainee and GetOptimalSize.)
719 setDeferredProperties();
721 Show( false, ShowFlags::NoFocusChange
);
723 maDockPos
= Window::GetPosPixel();
725 vcl::Window
* pRealParent
= mpWindowImpl
->mpRealParent
;
726 mpOldBorderWin
= mpWindowImpl
->mpBorderWindow
;
728 VclPtrInstance
<ImplDockFloatWin
> pWin(
729 mpImplData
->mpParent
,
730 mnFloatBits
& ( WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
) ? mnFloatBits
| WB_SYSTEMWINDOW
: mnFloatBits
,
733 mpWindowImpl
->mpBorderWindow
= nullptr;
734 mpWindowImpl
->mnLeftBorder
= 0;
735 mpWindowImpl
->mnTopBorder
= 0;
736 mpWindowImpl
->mnRightBorder
= 0;
737 mpWindowImpl
->mnBottomBorder
= 0;
738 // if the parent gets destroyed, we also have to reset the parent of the BorderWindow
739 if ( mpOldBorderWin
)
740 mpOldBorderWin
->SetParent( pWin
);
742 // #i123765# reset the buffered DropTargets when undocking, else it may not
743 // be correctly initialized
744 mpWindowImpl
->mxDNDListenerContainer
.clear();
747 SetPosPixel( Point() );
748 mpWindowImpl
->mpBorderWindow
= pWin
;
749 pWin
->mpWindowImpl
->mpClientWindow
= this;
750 mpWindowImpl
->mpRealParent
= pRealParent
;
751 pWin
->SetText( Window::GetText() );
752 Size
aSize(Window::GetSizePixel());
753 pWin
->SetOutputSizePixel(aSize
);
754 pWin
->SetPosPixel( maFloatPos
);
755 // pass on DockingData to FloatingWindow
756 pWin
->ShowTitleButton( TitleButton::Docking
, mbDockBtn
);
757 pWin
->ShowTitleButton( TitleButton::Hide
, mbHideBtn
);
758 pWin
->SetMinOutputSizePixel( maMinOutSize
);
760 pWin
->SetMaxOutputSizePixel( mpImplData
->maMaxOutSize
);
762 ToggleFloatingMode();
769 Show( false, ShowFlags::NoFocusChange
);
771 // store FloatingData in FloatingWindow
772 maFloatPos
= mpFloatWin
->GetPosPixel();
773 mbDockBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Docking
);
774 mbHideBtn
= mpFloatWin
->IsTitleButtonVisible( TitleButton::Hide
);
775 maMinOutSize
= mpFloatWin
->GetMinOutputSizePixel();
776 mpImplData
->maMaxOutSize
= mpFloatWin
->GetMaxOutputSizePixel();
778 vcl::Window
* pRealParent
= mpWindowImpl
->mpRealParent
;
779 mpWindowImpl
->mpBorderWindow
= nullptr;
780 if ( mpOldBorderWin
)
782 SetParent( mpOldBorderWin
);
783 static_cast<ImplBorderWindow
*>(mpOldBorderWin
.get())->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
784 mpOldBorderWin
->Resize();
786 mpWindowImpl
->mpBorderWindow
= mpOldBorderWin
;
787 SetParent( pRealParent
);
788 mpWindowImpl
->mpRealParent
= pRealParent
;
789 mpFloatWin
.disposeAndClear();
790 SetPosPixel( maDockPos
);
792 ToggleFloatingMode();
799 void DockingWindow::SetFloatStyle( WinBits nStyle
)
801 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
804 pWrapper
->SetFloatStyle( nStyle
);
808 mnFloatBits
= nStyle
;
811 WinBits
DockingWindow::GetFloatStyle() const
813 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
816 return pWrapper
->GetFloatStyle();
822 void DockingWindow::setPosSizePixel( tools::Long nX
, tools::Long nY
,
823 tools::Long nWidth
, tools::Long nHeight
,
824 PosSizeFlags nFlags
)
826 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
829 if (!pWrapper
->mpFloatWin
)
830 Window::setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
835 Window::setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
836 else if (comphelper::LibreOfficeKit::isActive())
838 if ((nFlags
& PosSizeFlags::Size
) == PosSizeFlags::Size
)
839 mpFloatWin
->SetOutputSizePixel({ nWidth
, nHeight
});
840 if ((nFlags
& PosSizeFlags::Pos
) == PosSizeFlags::Pos
)
841 mpFloatWin
->SetPosPixel({ nX
, nY
});
845 if (::isLayoutEnabled(this))
846 setPosSizeOnContainee();
849 Point
DockingWindow::GetPosPixel() const
851 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
854 if ( pWrapper
->mpFloatWin
)
855 return pWrapper
->mpFloatWin
->GetPosPixel();
857 return Window::GetPosPixel();
861 return mpFloatWin
->GetPosPixel();
863 return Window::GetPosPixel();
866 Size
DockingWindow::GetSizePixel() const
868 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
871 if ( pWrapper
->mpFloatWin
)
872 return pWrapper
->mpFloatWin
->GetSizePixel();
874 return Window::GetSizePixel();
878 return mpFloatWin
->GetSizePixel();
880 return Window::GetSizePixel();
883 void DockingWindow::SetOutputSizePixel( const Size
& rNewSize
)
885 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
888 if ( pWrapper
->mpFloatWin
)
889 pWrapper
->mpFloatWin
->SetOutputSizePixel( rNewSize
);
891 Window::SetOutputSizePixel( rNewSize
);
896 mpFloatWin
->SetOutputSizePixel( rNewSize
);
898 Window::SetOutputSizePixel( rNewSize
);
901 Size
DockingWindow::GetOutputSizePixel() const
903 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
906 if ( pWrapper
->mpFloatWin
)
907 return pWrapper
->mpFloatWin
->GetOutputSizePixel();
909 return Window::GetOutputSizePixel();
913 return mpFloatWin
->GetOutputSizePixel();
915 return Window::GetOutputSizePixel();
918 Point
DockingWindow::GetFloatingPos() const
920 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
923 if ( pWrapper
->mpFloatWin
)
925 vcl::WindowData aData
;
926 aData
.setMask(vcl::WindowDataMask::Pos
);
927 pWrapper
->mpFloatWin
->GetWindowState( aData
);
928 Point
aPos(aData
.x(), aData
.y());
929 // LOK needs logic coordinates not absolute screen position for autofilter menu
930 if (!comphelper::LibreOfficeKit::isActive() || get_id() != "check_list_menu")
931 aPos
= pWrapper
->mpFloatWin
->GetParent()->ImplGetFrameWindow()->AbsoluteScreenToOutputPixel( aPos
);
940 vcl::WindowData aData
;
941 aData
.setMask(vcl::WindowDataMask::Pos
);
942 mpFloatWin
->GetWindowState( aData
);
943 Point
aPos(aData
.x(), aData
.y());
944 aPos
= mpFloatWin
->GetParent()->ImplGetFrameWindow()->AbsoluteScreenToOutputPixel( aPos
);
951 bool DockingWindow::IsFloatingMode() const
953 ImplDockingWindowWrapper
*pWrapper
= ImplGetDockingManager()->GetDockingWindowWrapper( this );
955 return pWrapper
->IsFloatingMode();
957 return (mpFloatWin
!= nullptr);
960 void DockingWindow::SetMaxOutputSizePixel( const Size
& rSize
)
963 mpFloatWin
->SetMaxOutputSizePixel( rSize
);
964 mpImplData
->maMaxOutSize
= rSize
;
967 void DockingWindow::SetText(const OUString
& rStr
)
969 setDeferredProperties();
970 Window::SetText(rStr
);
973 OUString
DockingWindow::GetText() const
975 const_cast<DockingWindow
*>(this)->setDeferredProperties();
976 return Window::GetText();
979 bool DockingWindow::isLayoutEnabled() const
981 //pre dtor called, and single child is a container => we're layout enabled
982 return mpImplData
&& ::isLayoutEnabled(this);
985 void DockingWindow::setOptimalLayoutSize()
989 //resize DockingWindow to fit requisition on initial show
990 Size aSize
= get_preferred_size();
992 Size
aMax(bestmaxFrameSizeForScreenSize(GetDesktopRectPixel().GetSize()));
994 aSize
.setWidth( std::min(aMax
.Width(), aSize
.Width()) );
995 aSize
.setHeight( std::min(aMax
.Height(), aSize
.Height()) );
997 SetMinOutputSizePixel(aSize
);
998 setPosSizeOnContainee();
1001 void DockingWindow::setPosSizeOnContainee()
1003 Size aSize
= GetOutputSizePixel();
1005 // Don't make the border width accessible via get_border_width(),
1006 // otherwise the floating window will handle the border as well.
1007 sal_Int32 nBorderWidth
= mpWindowImpl
->mnBorderWidth
;
1009 aSize
.AdjustWidth( -(2 * nBorderWidth
) );
1010 aSize
.AdjustHeight( -(2 * nBorderWidth
) );
1012 Window
* pBox
= GetWindow(GetWindowType::FirstChild
);
1014 VclContainer::setLayoutAllocation(*pBox
, Point(nBorderWidth
, nBorderWidth
), aSize
);
1017 Size
DockingWindow::GetOptimalSize() const
1019 if (!isLayoutEnabled())
1020 return Window::GetOptimalSize();
1022 Size aSize
= VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild
));
1024 // Don't make the border width accessible via get_border_width(),
1025 // otherwise the floating window will handle the border as well.
1026 sal_Int32 nBorderWidth
= mpWindowImpl
->mnBorderWidth
;
1028 aSize
.AdjustHeight(2 * nBorderWidth
);
1029 aSize
.AdjustWidth(2 * nBorderWidth
);
1034 void DockingWindow::queue_resize(StateChangedType eReason
)
1036 bool bTriggerLayout
= true;
1037 if (maLayoutIdle
.IsActive() || mbIsCalculatingInitialLayoutSize
)
1039 bTriggerLayout
= false;
1041 if (!isLayoutEnabled())
1043 bTriggerLayout
= false;
1047 InvalidateSizeCache();
1048 maLayoutIdle
.Start();
1050 vcl::Window::queue_resize(eReason
);
1053 IMPL_LINK_NOARG(DockingWindow
, ImplHandleLayoutTimerHdl
, Timer
*, void)
1055 if (!isLayoutEnabled())
1057 SAL_WARN_IF(GetWindow(GetWindowType::FirstChild
), "vcl.layout", "DockingWindow has become non-layout because extra children have been added directly to it.");
1060 setPosSizeOnContainee();
1063 void DockingWindow::SetMinOutputSizePixel( const Size
& rSize
)
1066 mpFloatWin
->SetMinOutputSizePixel( rSize
);
1067 maMinOutSize
= rSize
;
1070 const Size
& DockingWindow::GetMinOutputSizePixel() const
1073 return mpFloatWin
->GetMinOutputSizePixel();
1074 return maMinOutSize
;
1077 void DockingWindow::SetFloatingPos( const Point
& rNewPos
)
1080 mpFloatWin
->SetPosPixel( rNewPos
);
1082 maFloatPos
= rNewPos
;
1085 SystemWindow
* DockingWindow::GetFloatingWindow() const
1090 DropdownDockingWindow::DropdownDockingWindow(vcl::Window
* pParent
, const css::uno::Reference
<css::frame::XFrame
>& rFrame
, bool bTearable
)
1091 : DockingWindow(pParent
,
1092 !bTearable
? OUString("InterimDockParent") : OUString("InterimTearableParent"),
1093 !bTearable
? OUString("vcl/ui/interimdockparent.ui") : OUString("vcl/ui/interimtearableparent.ui"),
1094 "vcl::DropdownDockingWindow maLayoutIdle",
1096 , m_xBox(m_pUIBuilder
->get("box"))
1100 DropdownDockingWindow::~DropdownDockingWindow()
1105 void DropdownDockingWindow::dispose()
1108 DockingWindow::dispose();
1111 ResizableDockingWindow::ResizableDockingWindow(vcl::Window
* pParent
, const css::uno::Reference
<css::frame::XFrame
>& rFrame
)
1112 : DockingWindow(pParent
, "DockingWindow", "vcl/ui/dockingwindow.ui", "vcl::ResizableDockingWindow maLayoutIdle", rFrame
)
1113 , m_xBox(m_pUIBuilder
->get("box"))
1117 ResizableDockingWindow::ResizableDockingWindow(vcl::Window
* pParent
, WinBits nStyle
)
1118 : DockingWindow(pParent
, nStyle
, "vcl::ResizableDockingWindow maLayoutIdle")
1122 // needed to blow away the cached size of the boundary between vcl and hosted child widget
1123 void ResizableDockingWindow::InvalidateChildSizeCache()
1125 // find the bottom vcl::Window of the hierarchy and queue_resize on that
1126 // one will invalidate all the size caches upwards
1127 vcl::Window
* pChild
= GetWindow(GetWindowType::FirstChild
);
1130 vcl::Window
* pSubChild
= pChild
->GetWindow(GetWindowType::FirstChild
);
1135 pChild
->queue_resize();
1138 ResizableDockingWindow::~ResizableDockingWindow()
1143 void ResizableDockingWindow::dispose()
1146 DockingWindow::dispose();
1149 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */