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