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 <comphelper/lok.hxx>
26 #include <sal/log.hxx>
27 #include <vcl/layout.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/wrkwin.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/toolbox.hxx>
32 #include <vcl/floatwin.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/IDialogRenderable.hxx>
36 class FloatingWindow::ImplData
41 VclPtr
<ToolBox
> mpBox
;
42 tools::Rectangle maItemEdgeClipRect
; // used to clip the common edge between a toolbar item and the border of this window
43 Point maPos
; // position of the floating window wrt. parent
44 Point maLOKTwipsPos
; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows).
47 FloatingWindow::ImplData::ImplData()
52 tools::Rectangle
& FloatingWindow::ImplGetItemEdgeClipRect()
54 return mpImplData
->maItemEdgeClipRect
;
57 void FloatingWindow::ImplInitFloating( vcl::Window
* pParent
, WinBits nStyle
)
59 mpImplData
.reset(new ImplData
);
61 mpWindowImpl
->mbFloatWin
= true;
65 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
68 pParent
= ImplGetSVData()->maWinData
.mpAppWin
;
70 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
72 // no Border, then we don't need a border window
75 mpWindowImpl
->mbOverlapWin
= true;
76 nStyle
|= WB_DIALOGCONTROL
;
77 ImplInit(pParent
, nStyle
, nullptr);
81 if (!(nStyle
& WB_NODIALOGCONTROL
))
82 nStyle
|= WB_DIALOGCONTROL
;
84 if (nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
| WB_ROLLABLE
| WB_CLOSEABLE
| WB_STANDALONE
)
85 && !(nStyle
& WB_OWNERDRAWDECORATION
))
87 WinBits nFloatWinStyle
= nStyle
;
88 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
89 // nFloatWinStyle |= WB_CLOSEABLE;
90 mpWindowImpl
->mbFrame
= true;
91 mpWindowImpl
->mbOverlapWin
= true;
92 ImplInit(pParent
, nFloatWinStyle
& ~WB_BORDER
, nullptr);
96 VclPtr
<ImplBorderWindow
> pBorderWin
;
97 BorderWindowStyle nBorderStyle
= BorderWindowStyle::Float
;
99 if (nStyle
& WB_OWNERDRAWDECORATION
)
100 nBorderStyle
|= BorderWindowStyle::Frame
;
102 nBorderStyle
|= BorderWindowStyle::Overlap
;
104 if ((nStyle
& WB_SYSTEMWINDOW
) && !(nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
)))
106 nBorderStyle
|= BorderWindowStyle::Frame
;
107 nStyle
|= WB_CLOSEABLE
; // make undecorated floaters closeable
109 pBorderWin
= VclPtr
<ImplBorderWindow
>::Create(pParent
, nStyle
, nBorderStyle
);
110 ImplInit(pBorderWin
, nStyle
& ~WB_BORDER
, nullptr);
111 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
112 pBorderWin
->GetBorder(mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
,
113 mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
114 pBorderWin
->SetDisplayActive(true);
115 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
116 mpWindowImpl
->mpRealParent
= pParent
;
119 SetActivateMode( ActivateModeFlags::NONE
);
121 mpNextFloat
= nullptr;
122 mpFirstPopupModeWin
= nullptr;
124 mnTitle
= (nStyle
& (WB_MOVEABLE
| WB_POPUP
)) ? FloatWinTitleType::Normal
: FloatWinTitleType::NONE
;
125 mnOldTitle
= mnTitle
;
126 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
127 mbInPopupMode
= false;
129 mbPopupModeCanceled
= false;
130 mbPopupModeTearOff
= false;
136 void FloatingWindow::ImplInitSettings()
138 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
141 if (IsControlBackground())
142 aColor
= GetControlBackground();
143 else if (Window::GetStyle() & WB_3DLOOK
)
144 aColor
= rStyleSettings
.GetFaceColor();
146 aColor
= rStyleSettings
.GetWindowColor();
147 SetBackground(aColor
);
150 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, WinBits nStyle
) :
151 SystemWindow(WindowType::FLOATINGWINDOW
)
153 ImplInitFloating(pParent
, nStyle
);
156 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
, const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
157 : SystemWindow(WindowType::FLOATINGWINDOW
)
158 , mpNextFloat(nullptr)
159 , mpFirstPopupModeWin(nullptr)
161 , mnPopupModeFlags(FloatWinPopupFlags::NONE
)
162 , mnTitle(FloatWinTitleType::Unknown
)
163 , mnOldTitle(FloatWinTitleType::Unknown
)
164 , mbInPopupMode(false)
166 , mbPopupModeCanceled(false)
167 , mbPopupModeTearOff(false)
172 loadUI(pParent
, rID
, rUIXMLDescription
, rFrame
);
175 //Find the real parent stashed in mpDialogParent.
176 void FloatingWindow::doDeferredInit(WinBits nBits
)
178 vcl::Window
*pParent
= mpDialogParent
;
179 mpDialogParent
= nullptr;
180 ImplInitFloating(pParent
, nBits
);
181 mbIsDeferredInit
= false;
184 void FloatingWindow::ApplySettings(vcl::RenderContext
& rRenderContext
)
186 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
189 if (Window::GetStyle() & WB_3DLOOK
)
190 aColor
= rStyleSettings
.GetFaceColor();
192 aColor
= rStyleSettings
.GetWindowColor();
194 ApplyControlBackground(rRenderContext
, aColor
);
197 FloatingWindow::~FloatingWindow()
203 void FloatingWindow::dispose()
207 if( mbPopupModeCanceled
)
208 // indicates that ESC key was pressed
209 // will be handled in Window::ImplGrabFocus()
210 SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel
);
212 if ( IsInPopupMode() )
213 EndPopupMode( FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::CloseAll
| FloatWinPopupEndFlags::DontCallHdl
);
216 Application::RemoveUserEvent( mnPostId
);
223 mpFirstPopupModeWin
.clear();
224 mxPrevFocusWin
.clear();
225 SystemWindow::dispose();
228 Point
FloatingWindow::CalcFloatingPosition( vcl::Window
* pWindow
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
, sal_uInt16
& rArrangeIndex
)
230 return ImplCalcPos( pWindow
, rRect
, nFlags
, rArrangeIndex
);
233 Point
FloatingWindow::ImplCalcPos(vcl::Window
* pWindow
,
234 const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
,
235 sal_uInt16
& rArrangeIndex
, Point
* pLOKTwipsPos
)
237 // get window position
239 Size aSize
= ::isLayoutEnabled(pWindow
) ? pWindow
->get_preferred_size() : pWindow
->GetSizePixel();
240 tools::Rectangle aScreenRect
= pWindow
->ImplGetFrameWindow()->GetDesktopRectPixel();
241 FloatingWindow
*pFloatingWindow
= dynamic_cast<FloatingWindow
*>( pWindow
);
244 vcl::Window
* pW
= pWindow
;
245 if ( pW
->mpWindowImpl
->mpRealParent
)
246 pW
= pW
->mpWindowImpl
->mpRealParent
;
248 tools::Rectangle
normRect( rRect
); // rRect is already relative to top-level window
249 normRect
.SetPos( pW
->ScreenToOutputPixel( normRect
.TopLeft() ) );
251 bool bRTL
= AllSettings::GetLayoutRTL();
253 tools::Rectangle
devRect( pW
->OutputToAbsoluteScreenPixel( normRect
.TopLeft() ),
254 pW
->OutputToAbsoluteScreenPixel( normRect
.BottomRight() ) );
256 tools::Rectangle
devRectRTL( devRect
);
258 // create a rect that can be compared to desktop coordinates
259 devRectRTL
= pW
->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect
);
260 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
261 aScreenRect
= Application::GetScreenPosSizePixel(
262 Application::GetBestScreen( bRTL
? devRectRTL
: devRect
) );
264 FloatWinPopupFlags nArrangeAry
[5];
265 Point e1
,e2
; // the common edge between the item rect and the floating window
267 if ( nFlags
& FloatWinPopupFlags::Left
)
269 nArrangeAry
[0] = FloatWinPopupFlags::Left
;
270 nArrangeAry
[1] = FloatWinPopupFlags::Right
;
271 nArrangeAry
[2] = FloatWinPopupFlags::Up
;
272 nArrangeAry
[3] = FloatWinPopupFlags::Down
;
273 nArrangeAry
[4] = FloatWinPopupFlags::Left
;
275 else if ( nFlags
& FloatWinPopupFlags::Right
)
277 nArrangeAry
[0] = FloatWinPopupFlags::Right
;
278 nArrangeAry
[1] = FloatWinPopupFlags::Left
;
279 nArrangeAry
[2] = FloatWinPopupFlags::Up
;
280 nArrangeAry
[3] = FloatWinPopupFlags::Down
;
281 nArrangeAry
[4] = FloatWinPopupFlags::Right
;
283 else if ( nFlags
& FloatWinPopupFlags::Up
)
285 nArrangeAry
[0] = FloatWinPopupFlags::Up
;
286 nArrangeAry
[1] = FloatWinPopupFlags::Down
;
287 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
288 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
289 nArrangeAry
[4] = FloatWinPopupFlags::Up
;
293 nArrangeAry
[0] = FloatWinPopupFlags::Down
;
294 nArrangeAry
[1] = FloatWinPopupFlags::Up
;
295 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
296 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
297 nArrangeAry
[4] = FloatWinPopupFlags::Down
;
300 sal_uInt16 nArrangeIndex
= 0;
301 const bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
303 for ( ; nArrangeIndex
< 5; nArrangeIndex
++ )
306 switch ( nArrangeAry
[nArrangeIndex
] )
309 case FloatWinPopupFlags::Left
:
310 aPos
.setX( devRect
.Left()-aSize
.Width()+1 );
311 aPos
.setY( devRect
.Top() );
312 aPos
.AdjustY( -(pWindow
->mpWindowImpl
->mnTopBorder
) );
315 if( (devRectRTL
.Right()+aSize
.Width()) > aScreenRect
.Right() )
320 if ( aPos
.X() < aScreenRect
.Left() )
323 if (bBreak
|| bLOKActive
)
325 e1
= devRect
.TopLeft();
326 e2
= devRect
.BottomLeft();
327 // set non-zero width
329 // don't clip corners
334 case FloatWinPopupFlags::Right
:
335 aPos
= devRect
.TopRight();
336 aPos
.AdjustY( -(pWindow
->mpWindowImpl
->mnTopBorder
) );
339 if( (devRectRTL
.Left() - aSize
.Width()) < aScreenRect
.Left() )
344 if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
347 if (bBreak
|| bLOKActive
)
349 e1
= devRect
.TopRight();
350 e2
= devRect
.BottomRight();
351 // set non-zero width
353 // don't clip corners
358 case FloatWinPopupFlags::Up
:
359 aPos
.setX( devRect
.Left() );
360 aPos
.setY( devRect
.Top()-aSize
.Height()+1 );
361 if ( aPos
.Y() < aScreenRect
.Top() )
363 if (bBreak
|| bLOKActive
)
365 e1
= devRect
.TopLeft();
366 e2
= devRect
.TopRight();
367 // set non-zero height
369 // don't clip corners
374 case FloatWinPopupFlags::Down
:
375 aPos
= devRect
.BottomLeft();
376 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
378 if (bBreak
|| bLOKActive
)
380 e1
= devRect
.BottomLeft();
381 e2
= devRect
.BottomRight();
382 // set non-zero height
384 // don't clip corners
392 // no further adjustment for LibreOfficeKit
396 // adjust if necessary
399 if ( (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Left
) ||
400 (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Right
) )
402 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
404 aPos
.setY( devRect
.Bottom()-aSize
.Height()+1 );
405 if ( aPos
.Y() < aScreenRect
.Top() )
406 aPos
.setY( aScreenRect
.Top() );
413 if( devRectRTL
.Right()-aSize
.Width()+1 < aScreenRect
.Left() )
414 aPos
.AdjustX( -(aScreenRect
.Left() - devRectRTL
.Right() + aSize
.Width() - 1) );
416 else if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
418 aPos
.setX( devRect
.Right()-aSize
.Width()+1 );
419 if ( aPos
.X() < aScreenRect
.Left() )
420 aPos
.setX( aScreenRect
.Left() );
428 if ( nArrangeIndex
> 4 )
431 rArrangeIndex
= nArrangeIndex
;
433 aPos
= pW
->AbsoluteScreenToOutputPixel( aPos
);
435 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
436 if( pFloatingWindow
&& pFloatingWindow
->mpImplData
->mpBox
)
438 pFloatingWindow
->mpImplData
->maItemEdgeClipRect
=
439 tools::Rectangle( e1
, e2
);
442 if (bLOKActive
&& pLOKTwipsPos
)
444 if (pW
->IsMapModeEnabled() || pW
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
446 // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)),
447 // for pixel conversions when map mode is not enabled, we get
448 // a 20 twips per pixel conversion since LogicToLogic uses
449 // a fixed 72 dpi value, instead of a correctly computed output
450 // device dpi or at least the most commonly used 96 dpi value;
451 // and anyway the following is what we already do in
452 // ScGridWindow::LogicInvalidate when map mode is not enabled.
454 *pLOKTwipsPos
= pW
->PixelToLogic(aPos
, MapMode(MapUnit::MapTwip
));
458 *pLOKTwipsPos
= OutputDevice::LogicToLogic(aPos
, pW
->GetMapMode(), MapMode(MapUnit::MapTwip
));
462 // caller expects coordinates relative to top-level win
463 return pW
->OutputToScreenPixel( aPos
);
466 Point
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const Point
& rPos
)
468 Point
aAbsolute( rPos
);
470 const OutputDevice
*pWindowOutDev
= pReference
->GetOutDev();
472 // compare coordinates in absolute screen coordinates
473 if( pReference
->HasMirroredGraphics() )
475 if(!pReference
->IsRTLEnabled() )
476 pWindowOutDev
->ReMirror( aAbsolute
);
478 tools::Rectangle
aRect( pReference
->ScreenToOutputPixel(aAbsolute
), Size(1,1) ) ;
479 aRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect
);
480 aAbsolute
= aRect
.TopLeft();
483 aAbsolute
= pReference
->OutputToAbsoluteScreenPixel(
484 pReference
->ScreenToOutputPixel(rPos
) );
489 tools::Rectangle
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const tools::Rectangle
& rRect
)
491 tools::Rectangle aFloatRect
= rRect
;
493 const OutputDevice
*pParentWinOutDev
= pReference
->GetOutDev();
495 // compare coordinates in absolute screen coordinates
496 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
497 if( pReference
->HasMirroredGraphics() )
499 if(!pReference
->IsRTLEnabled() )
500 pParentWinOutDev
->ReMirror(aFloatRect
);
502 aFloatRect
.SetPos(pReference
->ScreenToOutputPixel(aFloatRect
.TopLeft()));
503 aFloatRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect
);
506 aFloatRect
.SetPos(pReference
->OutputToAbsoluteScreenPixel(pReference
->ScreenToOutputPixel(rRect
.TopLeft())));
510 FloatingWindow
* FloatingWindow::ImplFloatHitTest( vcl::Window
* pReference
, const Point
& rPos
, bool& rbHitTestInsideRect
)
512 FloatingWindow
* pWin
= this;
513 rbHitTestInsideRect
= false;
515 Point
aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference
, rPos
));
519 // compute the floating window's size in absolute screen coordinates
521 // use the border window to have the exact position
522 vcl::Window
*pBorderWin
= pWin
->GetWindow( GetWindowType::Border
);
524 // the top-left corner in output coordinates ie (0,0)
525 tools::Rectangle
devRect( pBorderWin
->ImplOutputToUnmirroredAbsoluteScreenPixel( tools::Rectangle( Point(), pBorderWin
->GetSizePixel()) ) ) ;
526 if ( devRect
.IsInside( aAbsolute
) )
532 // test, if mouse is in rectangle, (this is typically the rect of the active
533 // toolbox item or similar)
534 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
535 // is already in absolute device coordinates
536 if ( pWin
->maFloatRect
.IsInside( aAbsolute
) )
538 rbHitTestInsideRect
= true;
542 pWin
= pWin
->mpNextFloat
;
549 FloatingWindow
* FloatingWindow::ImplFindLastLevelFloat()
551 FloatingWindow
* pWin
= this;
552 FloatingWindow
* pLastFoundWin
= pWin
;
556 if ( pWin
->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel
)
557 pLastFoundWin
= pWin
;
559 pWin
= pWin
->mpNextFloat
;
563 return pLastFoundWin
;
566 bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window
* pWindow
)
568 FloatingWindow
* pWin
= this;
572 if ( pWin
->mpFirstPopupModeWin
== pWindow
)
575 pWin
= pWin
->mpNextFloat
;
582 IMPL_LINK_NOARG(FloatingWindow
, ImplEndPopupModeHdl
, void*, void)
584 VclPtr
<FloatingWindow
> pThis(this);
586 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
591 bool FloatingWindow::EventNotify( NotifyEvent
& rNEvt
)
593 // call Base Class first for tab control
594 bool bRet
= SystemWindow::EventNotify( rNEvt
);
597 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
599 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
600 vcl::KeyCode aKeyCode
= pKEvt
->GetKeyCode();
601 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
603 if ( (nKeyCode
== KEY_ESCAPE
) && (GetStyle() & WB_CLOSEABLE
) )
614 void FloatingWindow::PixelInvalidate(const tools::Rectangle
* /*pRectangle*/)
616 if (VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier())
618 std::vector
<vcl::LOKPayloadItem
> aPayload
;
619 const tools::Rectangle
aRect(Point(0,0), Size(GetSizePixel().Width()+1, GetSizePixel().Height()+1));
620 aPayload
.push_back(std::make_pair(OString("rectangle"), aRect
.toString()));
621 const vcl::ILibreOfficeKitNotifier
* pNotifier
= pParent
->GetLOKNotifier();
622 pNotifier
->notifyWindow(GetLOKWindowId(), "invalidate", aPayload
);
626 void FloatingWindow::StateChanged( StateChangedType nType
)
628 if (nType
== StateChangedType::InitShow
)
633 SystemWindow::StateChanged( nType
);
635 VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier();
638 if (nType
== StateChangedType::InitShow
)
640 std::vector
<vcl::LOKPayloadItem
> aItems
;
643 // we are a toplevel window, let's so far pretend to be a
644 // dialog - but maybe we'll need a separate type for this
646 aItems
.emplace_back("type", "dialog");
647 aItems
.emplace_back("position", mpImplData
->maLOKTwipsPos
.toString()); // twips
651 SetLOKNotifier(pParent
->GetLOKNotifier());
652 aItems
.emplace_back("type", "child");
653 aItems
.emplace_back("parentId", OString::number(pParent
->GetLOKWindowId()));
654 aItems
.emplace_back("position", mpImplData
->maPos
.toString()); // pixels
656 aItems
.emplace_back("size", GetSizePixel().toString());
657 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems
);
659 else if (!IsVisible() && nType
== StateChangedType::Visible
)
661 assert(GetLOKNotifier());
662 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "close");
663 ReleaseLOKNotifier();
667 if ( nType
== StateChangedType::ControlBackground
)
674 void FloatingWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
676 SystemWindow::DataChanged( rDCEvt
);
678 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
679 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
686 void FloatingWindow::ImplCallPopupModeEnd()
688 // PopupMode is finished
689 mbInPopupMode
= false;
691 // call Handler asynchronously.
692 if ( mpImplData
&& !mnPostId
)
693 mnPostId
= Application::PostUserEvent(LINK(this, FloatingWindow
, ImplEndPopupModeHdl
));
696 void FloatingWindow::PopupModeEnd()
698 maPopupModeEndHdl
.Call( this );
701 void FloatingWindow::SetTitleType( FloatWinTitleType nTitle
)
703 if ( (mnTitle
!= nTitle
) && mpWindowImpl
->mpBorderWindow
)
706 Size aOutSize
= GetOutputSizePixel();
707 BorderWindowTitleType nTitleStyle
;
708 if ( nTitle
== FloatWinTitleType::Normal
)
709 nTitleStyle
= BorderWindowTitleType::Small
;
710 else if ( nTitle
== FloatWinTitleType::TearOff
)
711 nTitleStyle
= BorderWindowTitleType::Tearoff
;
712 else if ( nTitle
== FloatWinTitleType::Popup
)
713 nTitleStyle
= BorderWindowTitleType::Popup
;
714 else // nTitle == FloatWinTitleType::NONE
715 nTitleStyle
= BorderWindowTitleType::NONE
;
716 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetTitleType( nTitleStyle
, aOutSize
);
717 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
721 void FloatingWindow::StartPopupMode( const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
727 mnOldTitle
= mnTitle
;
728 if ( ( mpWindowImpl
->mnStyle
& WB_POPUP
) && !GetText().isEmpty() )
729 SetTitleType( FloatWinTitleType::Popup
);
730 else if ( nFlags
& FloatWinPopupFlags::AllowTearOff
)
731 SetTitleType( FloatWinTitleType::TearOff
);
733 SetTitleType( FloatWinTitleType::NONE
);
735 // avoid close on focus change for decorated floating windows only
736 if( mpWindowImpl
->mbFrame
&& (GetStyle() & WB_MOVEABLE
) )
737 nFlags
|= FloatWinPopupFlags::NoAppFocusClose
;
739 // compute window position according to flags and arrangement
740 sal_uInt16 nArrangeIndex
;
742 mpImplData
->maPos
= ImplCalcPos(this, rRect
, nFlags
, nArrangeIndex
, &mpImplData
->maLOKTwipsPos
);
743 SetPosPixel( mpImplData
->maPos
);
744 ImplGetFrame()->PositionByToolkit(rRect
, nFlags
);
746 // set data and display window
747 // convert maFloatRect to absolute device coordinates
748 // so they can be compared across different frames
749 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
750 maFloatRect
= FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect
);
752 maFloatRect
.AdjustLeft( -2 );
753 maFloatRect
.AdjustTop( -2 );
754 maFloatRect
.AdjustRight(2 );
755 maFloatRect
.AdjustBottom(2 );
756 mnPopupModeFlags
= nFlags
;
757 mbInPopupMode
= true;
759 mbPopupModeCanceled
= false;
760 mbPopupModeTearOff
= false;
763 // add FloatingWindow to list of windows that are in popup mode
764 ImplSVData
* pSVData
= ImplGetSVData();
765 mpNextFloat
= pSVData
->maWinData
.mpFirstFloat
;
766 pSVData
->maWinData
.mpFirstFloat
= this;
767 if (nFlags
& FloatWinPopupFlags::GrabFocus
)
769 // force key input even without focus (useful for menus)
771 mxPrevFocusWin
= Window::SaveFocus();
772 mpWindowImpl
->mpFrameData
->mbHasFocus
= true;
775 Show( true, ShowFlags::NoActivate
);
778 void FloatingWindow::StartPopupMode( ToolBox
* pBox
, FloatWinPopupFlags nFlags
)
780 mpImplData
->mpBox
= pBox
;
782 // get selected button
783 sal_uInt16 nItemId
= pBox
->GetDownItemId();
786 pBox
->ImplFloatControl( true, this );
788 // retrieve some data from the ToolBox
789 tools::Rectangle aRect
= nItemId
? pBox
->GetItemRect( nItemId
) : pBox
->GetOverflowRect();
791 // convert to parent's screen coordinates
792 mpImplData
->maPos
= GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox
->OutputToAbsoluteScreenPixel( aRect
.TopLeft() ) ) );
793 aRect
.SetPos( mpImplData
->maPos
);
796 FloatWinPopupFlags::AllMouseButtonClose
|
797 FloatWinPopupFlags::NoMouseUpClose
;
799 // set Flags for positioning
800 if ( !(nFlags
& (FloatWinPopupFlags::Down
| FloatWinPopupFlags::Up
|
801 FloatWinPopupFlags::Left
| FloatWinPopupFlags::Right
)) )
803 if ( pBox
->IsHorizontal() )
804 nFlags
|= FloatWinPopupFlags::Down
;
806 nFlags
|= FloatWinPopupFlags::Right
;
809 // start FloatingMode
810 StartPopupMode( aRect
, nFlags
);
813 void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags
, const VclPtr
<vcl::Window
>& xFocusId
)
815 if ( !mbInPopupMode
)
818 ImplSVData
* pSVData
= ImplGetSVData();
820 mbInCleanUp
= true; // prevent killing this window due to focus change while working with it
822 // stop the PopupMode also for all following PopupMode windows
823 while ( pSVData
->maWinData
.mpFirstFloat
&& pSVData
->maWinData
.mpFirstFloat
.get() != this )
824 pSVData
->maWinData
.mpFirstFloat
->EndPopupMode( FloatWinPopupEndFlags::Cancel
);
826 // delete window from the list
827 pSVData
->maWinData
.mpFirstFloat
= mpNextFloat
;
828 mpNextFloat
= nullptr;
830 FloatWinPopupFlags nPopupModeFlags
= mnPopupModeFlags
;
831 mbPopupModeTearOff
= nFlags
& FloatWinPopupEndFlags::TearOff
&&
832 nPopupModeFlags
& FloatWinPopupFlags::AllowTearOff
;
834 // hide window again if it was not deleted
835 if (!mbPopupModeTearOff
)
836 Show( false, ShowFlags::NoFocusChange
);
838 if (HasChildPathFocus() && xFocusId
!= nullptr)
840 // restore focus to previous focus window if we still have the focus
841 Window::EndSaveFocus(xFocusId
);
843 else if ( pSVData
->maWinData
.mpFocusWin
&& pSVData
->maWinData
.mpFirstFloat
&&
844 ImplIsWindowOrChild( pSVData
->maWinData
.mpFocusWin
) )
846 // maybe pass focus on to a suitable FloatingWindow
847 pSVData
->maWinData
.mpFirstFloat
->GrabFocus();
850 mbPopupModeCanceled
= bool(nFlags
& FloatWinPopupEndFlags::Cancel
);
853 SetTitleType( mnOldTitle
);
855 // set ToolBox again to normal
856 if (mpImplData
&& mpImplData
->mpBox
)
858 mpImplData
->mpBox
->ImplFloatControl( false, this );
859 // if the parent ToolBox is in popup mode, it should be closed too.
860 if ( GetDockingManager()->IsInPopupMode( mpImplData
->mpBox
) )
861 nFlags
|= FloatWinPopupEndFlags::CloseAll
;
863 mpImplData
->mpBox
= nullptr;
866 // call PopupModeEnd-Handler depending on parameter
867 if ( !(nFlags
& FloatWinPopupEndFlags::DontCallHdl
) )
868 ImplCallPopupModeEnd();
870 // close all other windows depending on parameter
871 if ( nFlags
& FloatWinPopupEndFlags::CloseAll
)
873 if ( !(nPopupModeFlags
& FloatWinPopupFlags::NewLevel
) )
875 if ( pSVData
->maWinData
.mpFirstFloat
)
877 FloatingWindow
* pLastLevelFloat
= pSVData
->maWinData
.mpFirstFloat
->ImplFindLastLevelFloat();
878 pLastLevelFloat
->EndPopupMode( FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::CloseAll
);
886 void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags
)
888 ImplEndPopupMode(nFlags
, mxPrevFocusWin
);
891 void FloatingWindow::AddPopupModeWindow(vcl::Window
* pWindow
)
893 // !!! up-to-now only 1 window and not yet a list
894 mpFirstPopupModeWin
= pWindow
;
896 bool FloatingWindow::UpdatePositionData()
898 auto pWin
= ImplGetParent();
901 // Simulate Move, so the relative position of the floating window will be recalculated
902 pWin
->ImplCallMove();
909 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */