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 .
23 #include <salframe.hxx>
25 #include <vcl/layout.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/wrkwin.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/toolbox.hxx>
30 #include <vcl/floatwin.hxx>
31 #include <vcl/settings.hxx>
33 #include <comphelper/lok.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/IDialogRenderable.hxx>
38 class FloatingWindow::ImplData
43 VclPtr
<ToolBox
> mpBox
;
44 Rectangle maItemEdgeClipRect
; // used to clip the common edge between a toolbar item and the border of this window
45 Point maPos
; // position of the floating window wrt. parent
46 Point maLOKTwipsPos
; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows).
49 FloatingWindow::ImplData::ImplData()
54 Rectangle
& FloatingWindow::ImplGetItemEdgeClipRect()
56 return mpImplData
->maItemEdgeClipRect
;
59 void FloatingWindow::ImplInit( vcl::Window
* pParent
, WinBits nStyle
)
61 mpImplData
= new ImplData
;
63 mpWindowImpl
->mbFloatWin
= true;
67 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
70 pParent
= ImplGetSVData()->maWinData
.mpAppWin
;
72 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
74 // no Border, then we don't need a border window
77 mpWindowImpl
->mbOverlapWin
= true;
78 nStyle
|= WB_DIALOGCONTROL
;
79 SystemWindow::ImplInit(pParent
, nStyle
, nullptr);
83 if (!(nStyle
& WB_NODIALOGCONTROL
))
84 nStyle
|= WB_DIALOGCONTROL
;
86 if (nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
| WB_ROLLABLE
| WB_CLOSEABLE
| WB_STANDALONE
)
87 && !(nStyle
& WB_OWNERDRAWDECORATION
))
89 WinBits nFloatWinStyle
= nStyle
;
90 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
91 // nFloatWinStyle |= WB_CLOSEABLE;
92 mpWindowImpl
->mbFrame
= true;
93 mpWindowImpl
->mbOverlapWin
= true;
94 SystemWindow::ImplInit(pParent
, nFloatWinStyle
& ~WB_BORDER
, nullptr);
98 VclPtr
<ImplBorderWindow
> pBorderWin
;
99 BorderWindowStyle nBorderStyle
= BorderWindowStyle::Border
| BorderWindowStyle::Float
;
101 if (nStyle
& WB_OWNERDRAWDECORATION
)
102 nBorderStyle
|= BorderWindowStyle::Frame
;
104 nBorderStyle
|= BorderWindowStyle::Overlap
;
106 if ((nStyle
& WB_SYSTEMWINDOW
) && !(nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
)))
108 nBorderStyle
|= BorderWindowStyle::Frame
;
109 nStyle
|= WB_CLOSEABLE
; // make undecorated floaters closeable
111 pBorderWin
= VclPtr
<ImplBorderWindow
>::Create(pParent
, nStyle
, nBorderStyle
);
112 SystemWindow::ImplInit(pBorderWin
, nStyle
& ~WB_BORDER
, nullptr);
113 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
114 pBorderWin
->GetBorder(mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
,
115 mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
116 pBorderWin
->SetDisplayActive(true);
117 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
118 mpWindowImpl
->mpRealParent
= pParent
;
121 SetActivateMode( ActivateModeFlags::NONE
);
123 mpNextFloat
= nullptr;
124 mpFirstPopupModeWin
= nullptr;
126 mnTitle
= (nStyle
& (WB_MOVEABLE
| WB_POPUP
)) ? FloatWinTitleType::Normal
: FloatWinTitleType::NONE
;
127 mnOldTitle
= mnTitle
;
128 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
129 mbInPopupMode
= false;
131 mbPopupModeCanceled
= false;
132 mbPopupModeTearOff
= false;
138 void FloatingWindow::ImplInitSettings()
140 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
143 if (IsControlBackground())
144 aColor
= GetControlBackground();
145 else if (Window::GetStyle() & WB_3DLOOK
)
146 aColor
= rStyleSettings
.GetFaceColor();
148 aColor
= rStyleSettings
.GetWindowColor();
149 SetBackground(aColor
);
152 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, WinBits nStyle
) :
153 SystemWindow(WINDOW_FLOATINGWINDOW
)
155 ImplInit(pParent
, nStyle
);
158 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
, const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
159 : SystemWindow(WINDOW_FLOATINGWINDOW
)
160 , mpNextFloat(nullptr)
161 , mpFirstPopupModeWin(nullptr)
162 , mpImplData(nullptr)
164 , mnPopupModeFlags(FloatWinPopupFlags::NONE
)
165 , mnTitle(FloatWinTitleType::Unknown
)
166 , mnOldTitle(FloatWinTitleType::Unknown
)
167 , mbInPopupMode(false)
169 , mbPopupModeCanceled(false)
170 , mbPopupModeTearOff(false)
175 loadUI(pParent
, rID
, rUIXMLDescription
, rFrame
);
178 //Find the real parent stashed in mpDialogParent.
179 void FloatingWindow::doDeferredInit(WinBits nBits
)
181 vcl::Window
*pParent
= mpDialogParent
;
182 mpDialogParent
= nullptr;
183 ImplInit(pParent
, nBits
);
184 mbIsDefferedInit
= false;
187 void FloatingWindow::ApplySettings(vcl::RenderContext
& rRenderContext
)
189 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
192 if (Window::GetStyle() & WB_3DLOOK
)
193 aColor
= rStyleSettings
.GetFaceColor();
195 aColor
= rStyleSettings
.GetWindowColor();
197 ApplyControlBackground(rRenderContext
, aColor
);
200 FloatingWindow::~FloatingWindow()
206 void FloatingWindow::dispose()
210 if( mbPopupModeCanceled
)
211 // indicates that ESC key was pressed
212 // will be handled in Window::ImplGrabFocus()
213 SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel
);
215 if ( IsInPopupMode() )
216 EndPopupMode( FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::CloseAll
| FloatWinPopupEndFlags::DontCallHdl
);
219 Application::RemoveUserEvent( mnPostId
);
224 mpImplData
= nullptr;
227 mpFirstPopupModeWin
.clear();
228 mxPrevFocusWin
.clear();
229 SystemWindow::dispose();
232 Point
FloatingWindow::CalcFloatingPosition( vcl::Window
* pWindow
, const Rectangle
& rRect
, FloatWinPopupFlags nFlags
, sal_uInt16
& rArrangeIndex
)
234 return ImplCalcPos( pWindow
, rRect
, nFlags
, rArrangeIndex
);
237 Point
FloatingWindow::ImplCalcPos(vcl::Window
* pWindow
,
238 const Rectangle
& rRect
, FloatWinPopupFlags nFlags
,
239 sal_uInt16
& rArrangeIndex
, Point
* pLOKTwipsPos
)
241 // get window position
243 Size aSize
= ::isLayoutEnabled(pWindow
) ? pWindow
->get_preferred_size() : pWindow
->GetSizePixel();
244 Rectangle aScreenRect
= pWindow
->ImplGetFrameWindow()->GetDesktopRectPixel();
245 FloatingWindow
*pFloatingWindow
= dynamic_cast<FloatingWindow
*>( pWindow
);
248 vcl::Window
* pW
= pWindow
;
249 if ( pW
->mpWindowImpl
->mpRealParent
)
250 pW
= pW
->mpWindowImpl
->mpRealParent
;
252 Rectangle
normRect( rRect
); // rRect is already relative to top-level window
253 normRect
.SetPos( pW
->ScreenToOutputPixel( normRect
.TopLeft() ) );
255 bool bRTL
= AllSettings::GetLayoutRTL();
257 Rectangle
devRect( pW
->OutputToAbsoluteScreenPixel( normRect
.TopLeft() ),
258 pW
->OutputToAbsoluteScreenPixel( normRect
.BottomRight() ) );
260 Rectangle
devRectRTL( devRect
);
262 // create a rect that can be compared to desktop coordinates
263 devRectRTL
= pW
->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect
);
264 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
265 aScreenRect
= Application::GetScreenPosSizePixel(
266 Application::GetBestScreen( bRTL
? devRectRTL
: devRect
) );
268 FloatWinPopupFlags nArrangeAry
[5];
269 Point e1
,e2
; // the common edge between the item rect and the floating window
271 if ( nFlags
& FloatWinPopupFlags::Left
)
273 nArrangeAry
[0] = FloatWinPopupFlags::Left
;
274 nArrangeAry
[1] = FloatWinPopupFlags::Right
;
275 nArrangeAry
[2] = FloatWinPopupFlags::Up
;
276 nArrangeAry
[3] = FloatWinPopupFlags::Down
;
277 nArrangeAry
[4] = FloatWinPopupFlags::Left
;
279 else if ( nFlags
& FloatWinPopupFlags::Right
)
281 nArrangeAry
[0] = FloatWinPopupFlags::Right
;
282 nArrangeAry
[1] = FloatWinPopupFlags::Left
;
283 nArrangeAry
[2] = FloatWinPopupFlags::Up
;
284 nArrangeAry
[3] = FloatWinPopupFlags::Down
;
285 nArrangeAry
[4] = FloatWinPopupFlags::Right
;
287 else if ( nFlags
& FloatWinPopupFlags::Up
)
289 nArrangeAry
[0] = FloatWinPopupFlags::Up
;
290 nArrangeAry
[1] = FloatWinPopupFlags::Down
;
291 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
292 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
293 nArrangeAry
[4] = FloatWinPopupFlags::Up
;
297 nArrangeAry
[0] = FloatWinPopupFlags::Down
;
298 nArrangeAry
[1] = FloatWinPopupFlags::Up
;
299 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
300 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
301 nArrangeAry
[4] = FloatWinPopupFlags::Down
;
304 sal_uInt16 nArrangeIndex
= 0;
305 const bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
307 for ( ; nArrangeIndex
< 5; nArrangeIndex
++ )
310 switch ( nArrangeAry
[nArrangeIndex
] )
313 case FloatWinPopupFlags::Left
:
314 aPos
.X() = devRect
.Left()-aSize
.Width()+1;
315 aPos
.Y() = devRect
.Top();
316 aPos
.Y() -= pWindow
->mpWindowImpl
->mnTopBorder
;
317 if( bRTL
) // --- RTL --- we're comparing screen coordinates here
319 if( (devRectRTL
.Right()+aSize
.Width()) > aScreenRect
.Right() )
324 if ( aPos
.X() < aScreenRect
.Left() )
327 if (bBreak
|| bLOKActive
)
329 e1
= devRect
.TopLeft();
330 e2
= devRect
.BottomLeft();
331 // set non-zero width
333 // don't clip corners
338 case FloatWinPopupFlags::Right
:
339 aPos
= devRect
.TopRight();
340 aPos
.Y() -= pWindow
->mpWindowImpl
->mnTopBorder
;
341 if( bRTL
) // --- RTL --- we're comparing screen coordinates here
343 if( (devRectRTL
.Left() - aSize
.Width()) < aScreenRect
.Left() )
348 if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
351 if (bBreak
|| bLOKActive
)
353 e1
= devRect
.TopRight();
354 e2
= devRect
.BottomRight();
355 // set non-zero width
357 // don't clip corners
362 case FloatWinPopupFlags::Up
:
363 aPos
.X() = devRect
.Left();
364 aPos
.Y() = devRect
.Top()-aSize
.Height()+1;
365 if ( aPos
.Y() < aScreenRect
.Top() )
367 if (bBreak
|| bLOKActive
)
369 e1
= devRect
.TopLeft();
370 e2
= devRect
.TopRight();
371 // set non-zero height
373 // don't clip corners
378 case FloatWinPopupFlags::Down
:
379 aPos
= devRect
.BottomLeft();
380 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
382 if (bBreak
|| bLOKActive
)
384 e1
= devRect
.BottomLeft();
385 e2
= devRect
.BottomRight();
386 // set non-zero height
388 // don't clip corners
396 // no further adjustement for LibreOfficeKit
400 // adjust if necessary
403 if ( (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Left
) ||
404 (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Right
) )
406 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
408 aPos
.Y() = devRect
.Bottom()-aSize
.Height()+1;
409 if ( aPos
.Y() < aScreenRect
.Top() )
410 aPos
.Y() = aScreenRect
.Top();
415 if( bRTL
) // --- RTL --- we're comparing screen coordinates here
417 if( devRectRTL
.Right()-aSize
.Width()+1 < aScreenRect
.Left() )
418 aPos
.X() -= aScreenRect
.Left() - devRectRTL
.Right() + aSize
.Width() - 1;
420 else if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
422 aPos
.X() = devRect
.Right()-aSize
.Width()+1;
423 if ( aPos
.X() < aScreenRect
.Left() )
424 aPos
.X() = aScreenRect
.Left();
432 if ( nArrangeIndex
> 4 )
435 rArrangeIndex
= nArrangeIndex
;
437 aPos
= pW
->AbsoluteScreenToOutputPixel( aPos
);
439 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
440 if( pFloatingWindow
)
442 pFloatingWindow
->mpImplData
->maItemEdgeClipRect
=
446 if (bLOKActive
&& pLOKTwipsPos
)
448 if (pW
->IsMapModeEnabled() || pW
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
450 // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)),
451 // for pixel conversions when map mode is not enabled, we gets
452 // a 20 twips per pixel conversion since LogicToLogic uses
453 // a fixed 72 dpi value, instead of a correctly computed output
454 // device dpi or at least the most commonly used 96 dpi value;
455 // and anyway the following is what we already do in
456 // ScGridWindow::LogicInvalidate when map mode is not enabled.
458 *pLOKTwipsPos
= pW
->PixelToLogic(aPos
, MapMode(MapUnit::MapTwip
));
462 *pLOKTwipsPos
= pW
->LogicToLogic(aPos
, pW
->GetMapMode(), MapMode(MapUnit::MapTwip
));
466 // caller expects coordinates relative to top-level win
467 return pW
->OutputToScreenPixel( aPos
);
470 Point
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const Point
& rPos
)
472 Point
aAbsolute( rPos
);
474 const OutputDevice
*pWindowOutDev
= pReference
->GetOutDev();
476 // compare coordinates in absolute screen coordinates
477 if( pReference
->HasMirroredGraphics() )
479 if(!pReference
->IsRTLEnabled() )
480 // --- RTL --- re-mirror back to get device coordinates
481 pWindowOutDev
->ReMirror( aAbsolute
);
483 Rectangle
aRect( pReference
->ScreenToOutputPixel(aAbsolute
), Size(1,1) ) ;
484 aRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect
);
485 aAbsolute
= aRect
.TopLeft();
488 aAbsolute
= Point( pReference
->OutputToAbsoluteScreenPixel(
489 pReference
->ScreenToOutputPixel(rPos
) ) );
494 Rectangle
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const Rectangle
& rRect
)
496 Rectangle aFloatRect
= rRect
;
498 const OutputDevice
*pParentWinOutDev
= pReference
->GetOutDev();
500 // compare coordinates in absolute screen coordinates
501 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
502 if( pReference
->HasMirroredGraphics() )
504 if(!pReference
->IsRTLEnabled() )
505 // --- RTL --- re-mirror back to get device coordinates
506 pParentWinOutDev
->ReMirror(aFloatRect
);
508 aFloatRect
.SetPos(pReference
->ScreenToOutputPixel(aFloatRect
.TopLeft()));
509 aFloatRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect
);
512 aFloatRect
.SetPos(pReference
->OutputToAbsoluteScreenPixel(pReference
->ScreenToOutputPixel(rRect
.TopLeft())));
516 FloatingWindow
* FloatingWindow::ImplFloatHitTest( vcl::Window
* pReference
, const Point
& rPos
, HitTest
& rHitTest
)
518 FloatingWindow
* pWin
= this;
520 Point
aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference
, rPos
));
524 // compute the floating window's size in absolute screen coordinates
526 // use the border window to have the exact position
527 vcl::Window
*pBorderWin
= pWin
->GetWindow( GetWindowType::Border
);
529 Point aPt
; // the top-left corner in output coordinates ie (0,0)
530 Rectangle
devRect( pBorderWin
->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt
, pBorderWin
->GetSizePixel()) ) ) ;
531 if ( devRect
.IsInside( aAbsolute
) )
533 rHitTest
= HITTEST_WINDOW
;
537 // test, if mouse is in rectangle, (this is typically the rect of the active
538 // toolbox item or similar)
539 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
540 // is already in absolute device coordinates
541 if ( pWin
->maFloatRect
.IsInside( aAbsolute
) )
543 rHitTest
= HITTEST_RECT
;
547 pWin
= pWin
->mpNextFloat
;
551 rHitTest
= HITTEST_OUTSIDE
;
555 FloatingWindow
* FloatingWindow::ImplFindLastLevelFloat()
557 FloatingWindow
* pWin
= this;
558 FloatingWindow
* pLastFoundWin
= pWin
;
562 if ( pWin
->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel
)
563 pLastFoundWin
= pWin
;
565 pWin
= pWin
->mpNextFloat
;
569 return pLastFoundWin
;
572 bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window
* pWindow
)
574 FloatingWindow
* pWin
= this;
578 if ( pWin
->mpFirstPopupModeWin
== pWindow
)
581 pWin
= pWin
->mpNextFloat
;
588 IMPL_LINK_NOARG(FloatingWindow
, ImplEndPopupModeHdl
, void*, void)
590 VclPtr
<FloatingWindow
> pThis(this);
592 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
597 bool FloatingWindow::EventNotify( NotifyEvent
& rNEvt
)
599 // call Base Class first for tab control
600 bool bRet
= SystemWindow::EventNotify( rNEvt
);
603 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
605 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
606 vcl::KeyCode aKeyCode
= pKEvt
->GetKeyCode();
607 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
609 if ( (nKeyCode
== KEY_ESCAPE
) && (GetStyle() & WB_CLOSEABLE
) )
620 void FloatingWindow::LogicInvalidate(const Rectangle
* /*pRectangle*/)
622 if (VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier())
624 const vcl::ILibreOfficeKitNotifier
* pNotifier
= pParent
->GetLOKNotifier();
625 pNotifier
->notifyWindow(GetLOKWindowId(), "invalidate");
629 void FloatingWindow::StateChanged( StateChangedType nType
)
631 if (nType
== StateChangedType::InitShow
)
636 SystemWindow::StateChanged( nType
);
638 VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier();
641 if (nType
== StateChangedType::InitShow
)
643 std::vector
<vcl::LOKPayloadItem
> aItems
;
646 // we are a toplevel window, let's so far pretend to be a
647 // dialog - but maybe we'll need a separate type for this
649 aItems
.emplace_back("type", "dialog");
650 aItems
.emplace_back("position", mpImplData
->maLOKTwipsPos
.toString()); // twips
654 SetLOKNotifier(pParent
->GetLOKNotifier());
655 aItems
.emplace_back("type", "child");
656 aItems
.emplace_back("parentId", OString::number(pParent
->GetLOKWindowId()));
657 aItems
.emplace_back("position", mpImplData
->maPos
.toString()); // pixels
659 aItems
.emplace_back("size", GetSizePixel().toString());
660 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems
);
662 else if (!IsVisible() && nType
== StateChangedType::Visible
)
664 assert(GetLOKNotifier());
665 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "close");
666 ReleaseLOKNotifier();
670 if ( nType
== StateChangedType::ControlBackground
)
677 void FloatingWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
679 SystemWindow::DataChanged( rDCEvt
);
681 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
682 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
689 void FloatingWindow::ImplCallPopupModeEnd()
691 // PopupMode is finished
692 mbInPopupMode
= false;
694 // call Handler asynchronously.
695 if ( mpImplData
&& !mnPostId
)
696 mnPostId
= Application::PostUserEvent(LINK(this, FloatingWindow
, ImplEndPopupModeHdl
));
699 void FloatingWindow::PopupModeEnd()
701 maPopupModeEndHdl
.Call( this );
704 void FloatingWindow::SetTitleType( FloatWinTitleType nTitle
)
706 if ( (mnTitle
!= nTitle
) && mpWindowImpl
->mpBorderWindow
)
709 Size aOutSize
= GetOutputSizePixel();
710 BorderWindowTitleType nTitleStyle
;
711 if ( nTitle
== FloatWinTitleType::Normal
)
712 nTitleStyle
= BorderWindowTitleType::Small
;
713 else if ( nTitle
== FloatWinTitleType::TearOff
)
714 nTitleStyle
= BorderWindowTitleType::Tearoff
;
715 else if ( nTitle
== FloatWinTitleType::Popup
)
716 nTitleStyle
= BorderWindowTitleType::Popup
;
717 else // nTitle == FloatWinTitleType::NONE
718 nTitleStyle
= BorderWindowTitleType::NONE
;
719 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetTitleType( nTitleStyle
, aOutSize
);
720 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
724 void FloatingWindow::StartPopupMode( const Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
730 mnOldTitle
= mnTitle
;
731 if ( ( mpWindowImpl
->mnStyle
& WB_POPUP
) && !GetText().isEmpty() )
732 SetTitleType( FloatWinTitleType::Popup
);
733 else if ( nFlags
& FloatWinPopupFlags::AllowTearOff
)
734 SetTitleType( FloatWinTitleType::TearOff
);
736 SetTitleType( FloatWinTitleType::NONE
);
738 // avoid close on focus change for decorated floating windows only
739 if( mpWindowImpl
->mbFrame
&& (GetStyle() & WB_MOVEABLE
) )
740 nFlags
|= FloatWinPopupFlags::NoAppFocusClose
;
742 // compute window position according to flags and arrangement
743 sal_uInt16 nArrangeIndex
;
744 mpImplData
->maPos
= ImplCalcPos(this, rRect
, nFlags
, nArrangeIndex
, &mpImplData
->maLOKTwipsPos
);
745 SetPosPixel( mpImplData
->maPos
);
747 // set data and display window
748 // convert maFloatRect to absolute device coordinates
749 // so they can be compared across different frames
750 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
751 maFloatRect
= FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect
);
753 maFloatRect
.Left() -= 2;
754 maFloatRect
.Top() -= 2;
755 maFloatRect
.Right() += 2;
756 maFloatRect
.Bottom() += 2;
757 mnPopupModeFlags
= nFlags
;
758 mbInPopupMode
= true;
760 mbPopupModeCanceled
= false;
761 mbPopupModeTearOff
= false;
764 // add FloatingWindow to list of windows that are in popup mode
765 ImplSVData
* pSVData
= ImplGetSVData();
766 mpNextFloat
= pSVData
->maWinData
.mpFirstFloat
;
767 pSVData
->maWinData
.mpFirstFloat
= this;
768 if (nFlags
& FloatWinPopupFlags::GrabFocus
)
770 // force key input even without focus (useful for menus)
772 mxPrevFocusWin
= Window::SaveFocus();
773 mpWindowImpl
->mpFrameData
->mbHasFocus
= true;
776 Show( true, ShowFlags::NoActivate
);
779 void FloatingWindow::StartPopupMode( ToolBox
* pBox
, FloatWinPopupFlags nFlags
)
781 // get selected button
782 sal_uInt16 nItemId
= pBox
->GetDownItemId();
786 mpImplData
->mpBox
= pBox
;
787 pBox
->ImplFloatControl( true, this );
789 // retrieve some data from the ToolBox
790 Rectangle aRect
= pBox
->GetItemRect( nItemId
);
792 // convert to parent's screen coordinates
793 mpImplData
->maPos
= GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox
->OutputToAbsoluteScreenPixel( aRect
.TopLeft() ) ) );
794 aRect
.SetPos( mpImplData
->maPos
);
797 FloatWinPopupFlags::AllMouseButtonClose
|
798 FloatWinPopupFlags::NoMouseUpClose
;
800 // set Flags for positioning
801 if ( !(nFlags
& (FloatWinPopupFlags::Down
| FloatWinPopupFlags::Up
|
802 FloatWinPopupFlags::Left
| FloatWinPopupFlags::Right
)) )
804 if ( pBox
->IsHorizontal() )
805 nFlags
|= FloatWinPopupFlags::Down
;
807 nFlags
|= FloatWinPopupFlags::Right
;
810 // start FloatingMode
811 StartPopupMode( aRect
, nFlags
);
814 void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags
, const VclPtr
<vcl::Window
>& xFocusId
)
816 if ( !mbInPopupMode
)
819 ImplSVData
* pSVData
= ImplGetSVData();
821 mbInCleanUp
= true; // prevent killing this window due to focus change while working with it
823 // stop the PopupMode also for all following PopupMode windows
824 while ( pSVData
->maWinData
.mpFirstFloat
&& pSVData
->maWinData
.mpFirstFloat
.get() != this )
825 pSVData
->maWinData
.mpFirstFloat
->EndPopupMode( FloatWinPopupEndFlags::Cancel
);
827 // delete window from the list
828 pSVData
->maWinData
.mpFirstFloat
= mpNextFloat
;
829 mpNextFloat
= nullptr;
831 FloatWinPopupFlags nPopupModeFlags
= mnPopupModeFlags
;
833 // hide window again if it was not deleted
834 if ( !(nFlags
& FloatWinPopupEndFlags::TearOff
) ||
835 !(nPopupModeFlags
& FloatWinPopupFlags::AllowTearOff
) )
837 Show( false, ShowFlags::NoFocusChange
);
839 if (HasChildPathFocus() && xFocusId
!= nullptr)
841 // restore focus to previous focus window if we still have the focus
842 Window::EndSaveFocus(xFocusId
);
844 else if ( pSVData
->maWinData
.mpFocusWin
&& pSVData
->maWinData
.mpFirstFloat
&&
845 ImplIsWindowOrChild( pSVData
->maWinData
.mpFocusWin
) )
847 // maybe pass focus on to a suitable FloatingWindow
848 pSVData
->maWinData
.mpFirstFloat
->GrabFocus();
850 mbPopupModeTearOff
= false;
854 mbPopupModeTearOff
= true;
857 mbPopupModeCanceled
= bool(nFlags
& FloatWinPopupEndFlags::Cancel
);
860 SetTitleType( mnOldTitle
);
862 // set ToolBox again to normal
863 if (mpImplData
&& mpImplData
->mpBox
)
865 mpImplData
->mpBox
->ImplFloatControl( false, this );
866 mpImplData
->mpBox
= nullptr;
869 // call PopupModeEnd-Handler depending on parameter
870 if ( !(nFlags
& FloatWinPopupEndFlags::DontCallHdl
) )
871 ImplCallPopupModeEnd();
873 // close all other windows depending on parameter
874 if ( nFlags
& FloatWinPopupEndFlags::CloseAll
)
876 if ( !(nPopupModeFlags
& FloatWinPopupFlags::NewLevel
) )
878 if ( pSVData
->maWinData
.mpFirstFloat
)
880 FloatingWindow
* pLastLevelFloat
= pSVData
->maWinData
.mpFirstFloat
->ImplFindLastLevelFloat();
881 pLastLevelFloat
->EndPopupMode( FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::CloseAll
);
889 void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags
)
891 ImplEndPopupMode(nFlags
, mxPrevFocusWin
);
894 void FloatingWindow::AddPopupModeWindow( vcl::Window
* pWindow
)
896 // !!! up-to-now only 1 window and not yet a list
897 mpFirstPopupModeWin
= pWindow
;
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */