Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / source / window / dockmgr.cxx
blob45708e8d709f23b7740b6f6d720bbd1ec56039c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
24 #include <brdwin.hxx>
25 #include <svdata.hxx>
26 #include <window.h>
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
40 private:
41 ImplDockingWindowWrapper* mpDockWin;
42 sal_uInt64 const mnLastTicks;
43 Timer m_aDockTimer;
44 Timer m_aEndDockTimer;
45 Point maDockPos;
46 tools::Rectangle maDockRect;
47 bool mbInMove;
48 ImplSVEvent * mnLastUserEvent;
50 DECL_LINK(DockingHdl, void *, void);
51 DECL_LINK(DockTimerHdl, Timer *, void);
52 DECL_LINK(EndDockTimerHdl, Timer *, void);
53 public:
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() ),
71 mbInMove( false ),
72 mnLastUserEvent( nullptr )
74 // copy state of DockingWindow
75 if ( pDockingWin )
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()
100 disposeOnce();
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 );
128 else
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 );
145 else
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
184 bRealMove )
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 );
197 if( ! bFloatMode )
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();
206 else
208 mpDockWin->GetWindow()->GetParent()->ImplGetFrameWindow()->HideTracking();
209 m_aDockTimer.Stop();
210 m_aEndDockTimer.Invoke();
213 mbInMove = false;
216 void ImplDockFloatWin2::Move()
218 if( mbInMove )
219 return;
221 mbInMove = true;
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
232 * last Move message.
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()
263 return true;
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();
281 return nullptr;
284 bool DockingManager::IsDockable( const vcl::Window *pWindow )
286 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
289 if( pWindow->HasDockingHandler() )
290 return true;
292 return (pWrapper != nullptr);
295 bool DockingManager::IsFloating( const vcl::Window *pWindow )
297 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
298 if( pWrapper )
299 return pWrapper->IsFloatingMode();
300 else
301 return false;
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 );
313 if( pWrapper )
314 pWrapper->Lock();
317 void DockingManager::Unlock( const vcl::Window *pWindow )
319 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
320 if( pWrapper )
321 pWrapper->Unlock();
324 void DockingManager::SetFloatingMode( const vcl::Window *pWindow, bool bFloating )
326 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
327 if( pWrapper )
328 pWrapper->SetFloatingMode( bFloating );
331 void DockingManager::StartPopupMode( const vcl::Window *pWindow, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags )
333 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
334 if( pWrapper )
335 pWrapper->StartPopupMode( rRect, nFlags );
338 void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const vcl::Window *pWindow, FloatWinPopupFlags nFlags )
340 ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow );
341 if( pWrapper )
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 );
368 if( pWrapper )
369 return;
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 );
380 break;
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 );
390 if( pWrapper )
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 );
398 if( pWrapper )
399 aRect = tools::Rectangle( pWrapper->GetPosPixel(), pWrapper->GetSizePixel() );
401 return aRect;
404 class ImplPopupFloatWin : public FloatingWindow
406 private:
407 bool const mbToolBox;
409 public:
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 )
419 if ( 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()
429 disposeOnce();
432 css::uno::Reference< css::accessibility::XAccessible > ImplPopupFloatWin::CreateAccessible()
434 if ( !mbToolBox )
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 )
452 , mnTrackX(0)
453 , mnTrackY(0)
454 , mnTrackWidth(0)
455 , mnTrackHeight(0)
456 , mnDockLeft(0)
457 , mnDockTop(0)
458 , mnDockRight(0)
459 , mnDockBottom(0)
460 , mnFloatBits(WB_BORDER | WB_CLOSEABLE | WB_SIZEABLE | (pWindow->GetStyle() & DOCKWIN_FLOATSTYLES))
461 , mbDockCanceled(false)
462 , mbDocking(false)
463 , mbLastFloatMode(false)
464 , mbRollUp(false)
465 , mbDockBtn(false)
466 , mbHideBtn(false)
467 // must be enabled in Window::Notify to prevent permanent docking during mouse move
468 , mbStartDockingEnabled(false)
469 , mbLocked(false)
471 DockingWindow *pDockWin = dynamic_cast< DockingWindow* > ( mpDockingWindow.get() );
472 if( pDockWin )
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 )
488 return;
490 maMouseOff = rPos;
491 mbDocking = true;
492 mbLastFloatMode = IsFloatingMode();
494 // calculate FloatingBorder
495 VclPtr<FloatingWindow> pWin;
496 if ( mpFloatWin )
497 pWin = mpFloatWin;
498 else
499 pWin = VclPtr<ImplDockFloatWin2>::Create( mpParent, mnFloatBits, nullptr );
500 pWin->GetBorder( mnDockLeft, mnDockTop, mnDockRight, mnDockBottom );
501 if ( !mpFloatWin )
502 pWin.disposeAndClear();
504 Point aPos = GetWindow()->ImplOutputToFrame( Point() );
505 Size aSize = GetWindow()->GetOutputSizePixel();
506 mnTrackX = aPos.X();
507 mnTrackY = aPos.Y();
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
539 if ( mbDocking )
541 if ( rTEvt.IsTrackingEnded() )
543 mbDocking = false;
544 GetWindow()->HideTracking();
545 if ( rTEvt.IsTrackingCanceled() )
547 mbDockCanceled = true;
548 EndDocking( tools::Rectangle( Point( mnTrackX, mnTrackY ), Size( mnTrackWidth, mnTrackHeight ) ), mbLastFloatMode );
549 mbDockCanceled = false;
551 else
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 )
581 if ( bFloatMode )
583 aTrackRect.AdjustLeft( -mnDockLeft );
584 aTrackRect.AdjustTop( -mnDockTop );
585 aTrackRect.AdjustRight(mnDockRight );
586 aTrackRect.AdjustBottom(mnDockBottom );
588 else
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;
602 if ( bFloatMode )
603 nTrackStyle = ShowTrackFlags::Object;
604 else
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 );
628 mbDocking = true;
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() )
650 bool bShow = false;
651 if ( bFloatMode != IsFloatingMode() )
653 GetWindow()->Show( false, ShowFlags::NoFocusChange );
654 SetFloatingMode( bFloatMode );
655 bShow = true;
656 if ( bFloatMode )
658 // #i44800# always use outputsize - as in all other places
659 mpFloatWin->SetOutputSizePixel( aRect.GetSize() );
660 mpFloatWin->SetPosPixel( aRect.TopLeft() );
663 if ( !bFloatMode )
665 Point aPos = aRect.TopLeft();
666 aPos = GetWindow()->GetParent()->ScreenToOutputPixel( aPos );
667 GetWindow()->SetPosSizePixel( aPos, aRect.GetSize() );
670 if ( bShow )
671 GetWindow()->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
674 EndDockingData data( aRect, IsFloatingMode(), IsDockingCanceled() );
675 GetWindow()->CallEventListeners( VclEventId::WindowEndDocking, &data );
677 mbDocking = false;
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 );
689 return 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() );
712 if( pToolBox )
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() );
727 if( pDockingWindow )
728 pDockingWindow->Resizing( rSize );
731 void ImplDockingWindowWrapper::ShowTitleButton( TitleButton nButton, bool bVisible )
733 if ( mpFloatWin )
734 mpFloatWin->ShowTitleButton( nButton, bVisible );
735 else
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)
784 mpFloatWin = pWin;
787 void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox, FloatWinPopupFlags nFlags )
789 // do nothing if window is floating
790 if( IsFloatingMode() )
791 return;
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 );
806 GetWindow()->Show();
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() )
820 return;
822 ImplPreparePopupMode();
823 mpFloatWin->StartPopupMode( rRect, nFlags );
824 GetWindow()->Show();
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();
859 else
860 return false;
863 void ImplDockingWindowWrapper::SetFloatingMode( bool bFloatMode )
865 // do nothing if window is docked and locked
866 if( !IsFloatingMode() && IsLocked() )
867 return;
869 if ( IsFloatingMode() != bFloatMode )
871 if ( PrepareToggleFloatingMode() )
873 bool bVisible = GetWindow()->IsVisible();
875 if ( bFloatMode )
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(
887 mpParent,
888 mnFloatBits & ( WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE ) ?
889 mnFloatBits | WB_SYSTEMWINDOW
890 | WB_OWNERDRAWDECORATION
891 : mnFloatBits,
892 this );
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 );
922 if ( mbRollUp )
923 pWin->RollUp();
924 else
925 pWin->RollDown();
926 pWin->SetRollUpOutputSizePixel( maRollUpOutSize );
927 pWin->SetMinOutputSizePixel( maMinOutSize );
928 pWin->SetMaxOutputSizePixel( maMaxOutSize );
930 mpFloatWin = pWin;
932 if ( bVisible )
933 GetWindow()->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
935 ToggleFloatingMode();
937 else
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 );
967 if ( bVisible )
968 GetWindow()->Show();
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 )
987 if ( mpFloatWin )
988 mpFloatWin->setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
989 else
990 GetWindow()->setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
993 Point ImplDockingWindowWrapper::GetPosPixel() const
995 if ( mpFloatWin )
996 return mpFloatWin->GetPosPixel();
997 else
998 return mpDockingWindow->GetPosPixel();
1001 Size ImplDockingWindowWrapper::GetSizePixel() const
1003 if ( mpFloatWin )
1004 return mpFloatWin->GetSizePixel();
1005 else
1006 return mpDockingWindow->GetSizePixel();
1009 // old inlines from DockingWindow
1011 void ImplDockingWindowWrapper::SetMinOutputSizePixel( const Size& rSize )
1013 if ( mpFloatWin )
1014 mpFloatWin->SetMinOutputSizePixel( rSize );
1015 maMinOutSize = rSize;
1018 void ImplDockingWindowWrapper::SetMaxOutputSizePixel( const Size& rSize )
1020 if ( mpFloatWin )
1021 mpFloatWin->SetMaxOutputSizePixel( rSize );
1022 maMaxOutSize = rSize;
1025 bool ImplDockingWindowWrapper::IsFloatingMode() const
1027 return (mpFloatWin != nullptr);
1030 void ImplDockingWindowWrapper::SetDragArea( const tools::Rectangle& rRect )
1032 maDragArea = rRect;
1036 void ImplDockingWindowWrapper::Lock()
1038 mbLocked = true;
1039 // only toolbars support locking
1040 ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
1041 if( pToolBox )
1042 pToolBox->Lock( mbLocked );
1045 void ImplDockingWindowWrapper::Unlock()
1047 mbLocked = false;
1048 // only toolbars support locking
1049 ToolBox *pToolBox = dynamic_cast< ToolBox * >( GetWindow() );
1050 if( pToolBox )
1051 pToolBox->Lock( mbLocked );
1055 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */