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>
24 #include <helpwin.hxx>
26 #include <comphelper/lok.hxx>
27 #include <sal/log.hxx>
28 #include <vcl/layout.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <vcl/event.hxx>
32 #include <vcl/toolbox.hxx>
33 #include <vcl/floatwin.hxx>
34 #include <vcl/settings.hxx>
35 #include <vcl/IDialogRenderable.hxx>
37 class FloatingWindow::ImplData
42 VclPtr
<ToolBox
> mpBox
;
43 tools::Rectangle maItemEdgeClipRect
; // used to clip the common edge between a toolbar item and the border of this window
44 Point maPos
; // position of the floating window wrt. parent
45 Point maLOKTwipsPos
; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows).
48 FloatingWindow::ImplData::ImplData()
53 tools::Rectangle
& FloatingWindow::ImplGetItemEdgeClipRect()
55 return mpImplData
->maItemEdgeClipRect
;
58 void FloatingWindow::ImplInitFloating( vcl::Window
* pParent
, WinBits nStyle
)
60 mpImplData
.reset(new ImplData
);
62 mpWindowImpl
->mbFloatWin
= true;
66 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
69 pParent
= ImplGetSVData()->maFrameData
.mpAppWin
;
71 SAL_WARN_IF(!pParent
, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
73 // no Border, then we don't need a border window
76 mpWindowImpl
->mbOverlapWin
= true;
77 nStyle
|= WB_DIALOGCONTROL
;
78 ImplInit(pParent
, nStyle
, nullptr);
82 if (!(nStyle
& WB_NODIALOGCONTROL
))
83 nStyle
|= WB_DIALOGCONTROL
;
85 if (nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
| WB_ROLLABLE
| WB_CLOSEABLE
| WB_STANDALONE
)
86 && !(nStyle
& WB_OWNERDRAWDECORATION
))
88 WinBits nFloatWinStyle
= nStyle
;
89 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
90 // nFloatWinStyle |= WB_CLOSEABLE;
91 mpWindowImpl
->mbFrame
= true;
92 mpWindowImpl
->mbOverlapWin
= true;
93 ImplInit(pParent
, nFloatWinStyle
& ~WB_BORDER
, nullptr);
97 VclPtr
<ImplBorderWindow
> pBorderWin
;
98 BorderWindowStyle nBorderStyle
= BorderWindowStyle::Float
;
100 if (nStyle
& WB_OWNERDRAWDECORATION
)
101 nBorderStyle
|= BorderWindowStyle::Frame
;
103 nBorderStyle
|= BorderWindowStyle::Overlap
;
105 if ((nStyle
& WB_SYSTEMWINDOW
) && !(nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
)))
107 nBorderStyle
|= BorderWindowStyle::Frame
;
108 nStyle
|= WB_CLOSEABLE
; // make undecorated floaters closeable
110 pBorderWin
= VclPtr
<ImplBorderWindow
>::Create(pParent
, nStyle
, nBorderStyle
);
111 ImplInit(pBorderWin
, nStyle
& ~WB_BORDER
, nullptr);
112 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
113 pBorderWin
->GetBorder(mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
,
114 mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
115 pBorderWin
->SetDisplayActive(true);
116 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
117 mpWindowImpl
->mpRealParent
= pParent
;
120 SetActivateMode( ActivateModeFlags::NONE
);
122 mpNextFloat
= nullptr;
123 mpFirstPopupModeWin
= nullptr;
125 mnTitle
= (nStyle
& (WB_MOVEABLE
| WB_POPUP
)) ? FloatWinTitleType::Normal
: FloatWinTitleType::NONE
;
126 mnOldTitle
= mnTitle
;
127 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
128 mbInPopupMode
= false;
130 mbPopupModeCanceled
= false;
131 mbPopupModeTearOff
= false;
137 void FloatingWindow::ImplInitSettings()
139 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
142 if (IsControlBackground())
143 aColor
= GetControlBackground();
144 else if (Window::GetStyle() & WB_3DLOOK
)
145 aColor
= rStyleSettings
.GetFaceColor();
147 aColor
= rStyleSettings
.GetWindowColor();
148 SetBackground(aColor
);
151 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, WinBits nStyle
) :
152 SystemWindow(WindowType::FLOATINGWINDOW
)
154 ImplInitFloating(pParent
, nStyle
);
157 FloatingWindow::FloatingWindow(vcl::Window
* pParent
, const OString
& rID
, const OUString
& rUIXMLDescription
, const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
158 : SystemWindow(WindowType::FLOATINGWINDOW
)
159 , mpNextFloat(nullptr)
160 , mpFirstPopupModeWin(nullptr)
162 , mnPopupModeFlags(FloatWinPopupFlags::NONE
)
163 , mnTitle(FloatWinTitleType::Unknown
)
164 , mnOldTitle(FloatWinTitleType::Unknown
)
165 , mbInPopupMode(false)
167 , mbPopupModeCanceled(false)
168 , mbPopupModeTearOff(false)
173 loadUI(pParent
, rID
, rUIXMLDescription
, rFrame
);
176 //Find the real parent stashed in mpDialogParent.
177 void FloatingWindow::doDeferredInit(WinBits nBits
)
179 vcl::Window
*pParent
= mpDialogParent
;
180 mpDialogParent
= nullptr;
181 ImplInitFloating(pParent
, nBits
);
182 mbIsDeferredInit
= false;
185 void FloatingWindow::ApplySettings(vcl::RenderContext
& rRenderContext
)
187 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
190 if (Window::GetStyle() & WB_3DLOOK
)
191 aColor
= rStyleSettings
.GetFaceColor();
193 aColor
= rStyleSettings
.GetWindowColor();
195 ApplyControlBackground(rRenderContext
, aColor
);
198 FloatingWindow::~FloatingWindow()
204 void FloatingWindow::dispose()
206 ReleaseLOKNotifier();
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
);
226 mpFirstPopupModeWin
.clear();
227 mxPrevFocusWin
.clear();
228 SystemWindow::dispose();
231 Point
FloatingWindow::CalcFloatingPosition( vcl::Window
* pWindow
, const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
, sal_uInt16
& rArrangeIndex
)
233 return ImplCalcPos( pWindow
, rRect
, nFlags
, rArrangeIndex
);
236 Point
FloatingWindow::ImplCalcPos(vcl::Window
* pWindow
,
237 const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
,
238 sal_uInt16
& rArrangeIndex
, Point
* pLOKTwipsPos
)
240 // get window position
242 Size aSize
= ::isLayoutEnabled(pWindow
) ? pWindow
->get_preferred_size() : pWindow
->GetSizePixel();
243 tools::Rectangle aScreenRect
= pWindow
->ImplGetFrameWindow()->GetDesktopRectPixel();
244 FloatingWindow
*pFloatingWindow
= dynamic_cast<FloatingWindow
*>( pWindow
);
247 vcl::Window
* pW
= pWindow
;
248 if ( pW
->mpWindowImpl
->mpRealParent
)
249 pW
= pW
->mpWindowImpl
->mpRealParent
;
251 tools::Rectangle
normRect( rRect
); // rRect is already relative to top-level window
252 normRect
.SetPos( pW
->ScreenToOutputPixel( normRect
.TopLeft() ) );
254 bool bRTL
= AllSettings::GetLayoutRTL();
256 tools::Rectangle
devRect( pW
->OutputToAbsoluteScreenPixel( normRect
.TopLeft() ),
257 pW
->OutputToAbsoluteScreenPixel( normRect
.BottomRight() ) );
259 tools::Rectangle
devRectRTL( devRect
);
261 // create a rect that can be compared to desktop coordinates
262 devRectRTL
= pW
->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect
);
263 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
264 aScreenRect
= Application::GetScreenPosSizePixel(
265 Application::GetBestScreen( bRTL
? devRectRTL
: devRect
) );
267 FloatWinPopupFlags nArrangeAry
[5];
268 sal_uInt16 nArrangeAttempts
= 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 if (nFlags
& FloatWinPopupFlags::NoHorzPlacement
)
293 nArrangeAry
[2] = FloatWinPopupFlags::Up
;
294 nArrangeAttempts
= 3;
298 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
299 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
300 nArrangeAry
[4] = FloatWinPopupFlags::Up
;
305 nArrangeAry
[0] = FloatWinPopupFlags::Down
;
306 nArrangeAry
[1] = FloatWinPopupFlags::Up
;
307 if (nFlags
& FloatWinPopupFlags::NoHorzPlacement
)
309 nArrangeAry
[2] = FloatWinPopupFlags::Down
;
310 nArrangeAttempts
= 3;
314 nArrangeAry
[2] = FloatWinPopupFlags::Right
;
315 nArrangeAry
[3] = FloatWinPopupFlags::Left
;
316 nArrangeAry
[4] = FloatWinPopupFlags::Down
;
320 sal_uInt16 nArrangeIndex
= 0;
321 const bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
323 for ( ; nArrangeIndex
< nArrangeAttempts
; nArrangeIndex
++ )
326 switch ( nArrangeAry
[nArrangeIndex
] )
329 case FloatWinPopupFlags::Left
:
330 aPos
.setX( devRect
.Left()-aSize
.Width()+1 );
331 aPos
.setY( devRect
.Top() );
332 aPos
.AdjustY( -(pWindow
->mpWindowImpl
->mnTopBorder
) );
335 if( (devRectRTL
.Right()+aSize
.Width()) > aScreenRect
.Right() )
340 if ( aPos
.X() < aScreenRect
.Left() )
343 if (bBreak
|| bLOKActive
)
345 e1
= devRect
.TopLeft();
346 e2
= devRect
.BottomLeft();
347 // set non-zero width
349 // don't clip corners
354 case FloatWinPopupFlags::Right
:
355 aPos
= devRect
.TopRight();
356 aPos
.AdjustY( -(pWindow
->mpWindowImpl
->mnTopBorder
) );
359 if( (devRectRTL
.Left() - aSize
.Width()) < aScreenRect
.Left() )
364 if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
367 if (bBreak
|| bLOKActive
)
369 e1
= devRect
.TopRight();
370 e2
= devRect
.BottomRight();
371 // set non-zero width
373 // don't clip corners
378 case FloatWinPopupFlags::Up
:
379 aPos
.setX( devRect
.Left() );
380 aPos
.setY( devRect
.Top()-aSize
.Height()+1 );
381 if ( aPos
.Y() < aScreenRect
.Top() )
383 if (bBreak
|| bLOKActive
)
385 e1
= devRect
.TopLeft();
386 e2
= devRect
.TopRight();
387 // set non-zero height
389 // don't clip corners
394 case FloatWinPopupFlags::Down
:
395 aPos
= devRect
.BottomLeft();
396 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
398 if (bBreak
|| bLOKActive
)
400 e1
= devRect
.BottomLeft();
401 e2
= devRect
.BottomRight();
402 // set non-zero height
404 // don't clip corners
412 // no further adjustment for LibreOfficeKit
416 // adjust if necessary
419 if ( (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Left
) ||
420 (nArrangeAry
[nArrangeIndex
] == FloatWinPopupFlags::Right
) )
422 if ( aPos
.Y()+aSize
.Height() > aScreenRect
.Bottom() )
424 aPos
.setY( devRect
.Bottom()-aSize
.Height()+1 );
425 if ( aPos
.Y() < aScreenRect
.Top() )
426 aPos
.setY( aScreenRect
.Top() );
433 if( devRectRTL
.Right()-aSize
.Width()+1 < aScreenRect
.Left() )
434 aPos
.AdjustX( -(aScreenRect
.Left() - devRectRTL
.Right() + aSize
.Width() - 1) );
436 else if ( aPos
.X()+aSize
.Width() > aScreenRect
.Right() )
438 aPos
.setX( devRect
.Right()-aSize
.Width()+1 );
439 if ( aPos
.X() < aScreenRect
.Left() )
440 aPos
.setX( aScreenRect
.Left() );
448 if (nArrangeIndex
>= nArrangeAttempts
)
449 nArrangeIndex
= nArrangeAttempts
- 1;
451 rArrangeIndex
= nArrangeIndex
;
453 aPos
= pW
->AbsoluteScreenToOutputPixel( aPos
);
455 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
456 if( pFloatingWindow
&& pFloatingWindow
->mpImplData
->mpBox
)
458 pFloatingWindow
->mpImplData
->maItemEdgeClipRect
=
459 tools::Rectangle( e1
, e2
);
462 if (bLOKActive
&& pLOKTwipsPos
)
464 if (pW
->IsMapModeEnabled() || pW
->GetMapMode().GetMapUnit() == MapUnit::MapPixel
)
466 // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)),
467 // for pixel conversions when map mode is not enabled, we get
468 // a 20 twips per pixel conversion since LogicToLogic uses
469 // a fixed 72 dpi value, instead of a correctly computed output
470 // device dpi or at least the most commonly used 96 dpi value;
471 // and anyway the following is what we already do in
472 // ScGridWindow::LogicInvalidate when map mode is not enabled.
474 *pLOKTwipsPos
= pW
->PixelToLogic(aPos
, MapMode(MapUnit::MapTwip
));
478 *pLOKTwipsPos
= OutputDevice::LogicToLogic(aPos
, pW
->GetMapMode(), MapMode(MapUnit::MapTwip
));
482 // caller expects coordinates relative to top-level win
483 return pW
->OutputToScreenPixel( aPos
);
486 Point
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const Point
& rPos
)
488 Point
aAbsolute( rPos
);
490 const OutputDevice
*pWindowOutDev
= pReference
->GetOutDev();
492 // compare coordinates in absolute screen coordinates
493 if( pReference
->HasMirroredGraphics() )
495 if(!pReference
->IsRTLEnabled() )
496 pWindowOutDev
->ReMirror( aAbsolute
);
498 tools::Rectangle
aRect( pReference
->ScreenToOutputPixel(aAbsolute
), Size(1,1) ) ;
499 aRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect
);
500 aAbsolute
= aRect
.TopLeft();
503 aAbsolute
= pReference
->OutputToAbsoluteScreenPixel(
504 pReference
->ScreenToOutputPixel(rPos
) );
509 tools::Rectangle
FloatingWindow::ImplConvertToAbsPos(vcl::Window
* pReference
, const tools::Rectangle
& rRect
)
511 tools::Rectangle aFloatRect
= rRect
;
513 const OutputDevice
*pParentWinOutDev
= pReference
->GetOutDev();
515 // compare coordinates in absolute screen coordinates
516 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
517 if( pReference
->HasMirroredGraphics() )
519 if(!pReference
->IsRTLEnabled() )
520 pParentWinOutDev
->ReMirror(aFloatRect
);
522 aFloatRect
.SetPos(pReference
->ScreenToOutputPixel(aFloatRect
.TopLeft()));
523 aFloatRect
= pReference
->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect
);
526 aFloatRect
.SetPos(pReference
->OutputToAbsoluteScreenPixel(pReference
->ScreenToOutputPixel(rRect
.TopLeft())));
530 FloatingWindow
* FloatingWindow::ImplFloatHitTest( vcl::Window
* pReference
, const Point
& rPos
, bool& rbHitTestInsideRect
)
532 FloatingWindow
* pWin
= this;
533 rbHitTestInsideRect
= false;
535 Point
aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference
, rPos
));
539 // compute the floating window's size in absolute screen coordinates
541 // use the border window to have the exact position
542 vcl::Window
*pBorderWin
= pWin
->GetWindow( GetWindowType::Border
);
546 // the top-left corner in output coordinates ie (0,0)
547 tools::Rectangle
devRect( pBorderWin
->ImplOutputToUnmirroredAbsoluteScreenPixel( tools::Rectangle( Point(), pBorderWin
->GetSizePixel()) ) ) ;
548 if ( devRect
.IsInside( aAbsolute
) )
554 // test, if mouse is in rectangle, (this is typically the rect of the active
555 // toolbox item or similar)
556 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
557 // is already in absolute device coordinates
558 if ( pWin
->maFloatRect
.IsInside( aAbsolute
) )
560 rbHitTestInsideRect
= true;
564 pWin
= pWin
->mpNextFloat
;
571 FloatingWindow
* FloatingWindow::ImplFindLastLevelFloat()
573 FloatingWindow
* pWin
= this;
574 FloatingWindow
* pLastFoundWin
= pWin
;
578 if ( pWin
->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel
)
579 pLastFoundWin
= pWin
;
581 pWin
= pWin
->mpNextFloat
;
585 return pLastFoundWin
;
588 bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window
* pWindow
)
590 FloatingWindow
* pWin
= this;
594 if ( pWin
->mpFirstPopupModeWin
== pWindow
)
597 pWin
= pWin
->mpNextFloat
;
604 IMPL_LINK_NOARG(FloatingWindow
, ImplEndPopupModeHdl
, void*, void)
606 VclPtr
<FloatingWindow
> pThis(this);
608 mnPopupModeFlags
= FloatWinPopupFlags::NONE
;
613 bool FloatingWindow::EventNotify( NotifyEvent
& rNEvt
)
615 // call Base Class first for tab control
616 bool bRet
= SystemWindow::EventNotify( rNEvt
);
619 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
621 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
622 vcl::KeyCode aKeyCode
= pKEvt
->GetKeyCode();
623 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
625 if ( (nKeyCode
== KEY_ESCAPE
) && (GetStyle() & WB_CLOSEABLE
) )
636 void FloatingWindow::PixelInvalidate(const tools::Rectangle
* /*pRectangle*/)
638 if (VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier())
640 std::vector
<vcl::LOKPayloadItem
> aPayload
;
641 const tools::Rectangle
aRect(Point(0,0), Size(GetSizePixel().Width()+1, GetSizePixel().Height()+1));
642 aPayload
.push_back(std::make_pair(OString("rectangle"), aRect
.toString()));
643 const vcl::ILibreOfficeKitNotifier
* pNotifier
= pParent
->GetLOKNotifier();
644 pNotifier
->notifyWindow(GetLOKWindowId(), "invalidate", aPayload
);
648 void FloatingWindow::StateChanged( StateChangedType nType
)
650 if (nType
== StateChangedType::InitShow
)
655 SystemWindow::StateChanged( nType
);
657 VclPtr
<vcl::Window
> pParent
= GetParentWithLOKNotifier();
660 if (nType
== StateChangedType::InitShow
)
662 std::vector
<vcl::LOKPayloadItem
> aItems
;
665 // we are a toplevel window, let's so far pretend to be a
666 // dialog - but maybe we'll need a separate type for this
668 aItems
.emplace_back("type", "dialog");
669 aItems
.emplace_back("position", mpImplData
->maLOKTwipsPos
.toString()); // twips
673 SetLOKNotifier(pParent
->GetLOKNotifier());
674 if (dynamic_cast<HelpTextWindow
*>(this))
675 aItems
.emplace_back("type", "tooltip");
677 aItems
.emplace_back("type", "child");
679 aItems
.emplace_back("parentId", OString::number(pParent
->GetLOKWindowId()));
681 aItems
.emplace_back("position", mpImplData
->maPos
.toString()); // pixels
682 else // mpImplData->maPos is not set
683 aItems
.emplace_back("position", GetPosPixel().toString());
686 aItems
.emplace_back("size", GetSizePixel().toString());
687 GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems
);
689 else if (!IsVisible() && nType
== StateChangedType::Visible
)
691 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
693 pNotifier
->notifyWindow(GetLOKWindowId(), "close");
694 ReleaseLOKNotifier();
699 if ( nType
== StateChangedType::ControlBackground
)
706 void FloatingWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
708 SystemWindow::DataChanged( rDCEvt
);
710 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
711 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
718 void FloatingWindow::ImplCallPopupModeEnd()
720 // PopupMode is finished
721 mbInPopupMode
= false;
723 // call Handler asynchronously.
724 if ( mpImplData
&& !mnPostId
)
725 mnPostId
= Application::PostUserEvent(LINK(this, FloatingWindow
, ImplEndPopupModeHdl
));
728 void FloatingWindow::PopupModeEnd()
730 maPopupModeEndHdl
.Call( this );
733 void FloatingWindow::SetTitleType( FloatWinTitleType nTitle
)
735 if ( (mnTitle
== nTitle
) || !mpWindowImpl
->mpBorderWindow
)
739 Size aOutSize
= GetOutputSizePixel();
740 BorderWindowTitleType nTitleStyle
;
741 if ( nTitle
== FloatWinTitleType::Normal
)
742 nTitleStyle
= BorderWindowTitleType::Small
;
743 else if ( nTitle
== FloatWinTitleType::TearOff
)
744 nTitleStyle
= BorderWindowTitleType::Tearoff
;
745 else if ( nTitle
== FloatWinTitleType::Popup
)
746 nTitleStyle
= BorderWindowTitleType::Popup
;
747 else // nTitle == FloatWinTitleType::NONE
748 nTitleStyle
= BorderWindowTitleType::NONE
;
749 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetTitleType( nTitleStyle
, aOutSize
);
750 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
753 void FloatingWindow::StartPopupMode( const tools::Rectangle
& rRect
, FloatWinPopupFlags nFlags
)
759 mnOldTitle
= mnTitle
;
760 if ( ( mpWindowImpl
->mnStyle
& WB_POPUP
) && !GetText().isEmpty() )
761 SetTitleType( FloatWinTitleType::Popup
);
762 else if ( nFlags
& FloatWinPopupFlags::AllowTearOff
)
763 SetTitleType( FloatWinTitleType::TearOff
);
765 SetTitleType( FloatWinTitleType::NONE
);
767 // avoid close on focus change for decorated floating windows only
768 if( mpWindowImpl
->mbFrame
&& (GetStyle() & WB_MOVEABLE
) )
769 nFlags
|= FloatWinPopupFlags::NoAppFocusClose
;
771 // compute window position according to flags and arrangement
772 sal_uInt16 nArrangeIndex
;
774 mpImplData
->maPos
= ImplCalcPos(this, rRect
, nFlags
, nArrangeIndex
, &mpImplData
->maLOKTwipsPos
);
775 SetPosPixel( mpImplData
->maPos
);
776 ImplGetFrame()->PositionByToolkit(rRect
, nFlags
);
778 // set data and display window
779 // convert maFloatRect to absolute device coordinates
780 // so they can be compared across different frames
781 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
782 maFloatRect
= FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect
);
784 maFloatRect
.AdjustLeft( -2 );
785 maFloatRect
.AdjustTop( -2 );
786 maFloatRect
.AdjustRight(2 );
787 maFloatRect
.AdjustBottom(2 );
788 mnPopupModeFlags
= nFlags
;
789 mbInPopupMode
= true;
791 mbPopupModeCanceled
= false;
792 mbPopupModeTearOff
= false;
795 // add FloatingWindow to list of windows that are in popup mode
796 ImplSVData
* pSVData
= ImplGetSVData();
797 mpNextFloat
= pSVData
->mpWinData
->mpFirstFloat
;
798 pSVData
->mpWinData
->mpFirstFloat
= this;
799 if (nFlags
& FloatWinPopupFlags::GrabFocus
)
801 // force key input even without focus (useful for menus)
803 mxPrevFocusWin
= Window::SaveFocus();
804 mpWindowImpl
->mpFrameData
->mbHasFocus
= true;
807 Show( true, ShowFlags::NoActivate
);
810 void FloatingWindow::StartPopupMode( ToolBox
* pBox
, FloatWinPopupFlags nFlags
)
812 mpImplData
->mpBox
= pBox
;
814 // get selected button
815 sal_uInt16 nItemId
= pBox
->GetDownItemId();
818 pBox
->ImplFloatControl( true, this );
820 // retrieve some data from the ToolBox
821 tools::Rectangle aRect
= nItemId
? pBox
->GetItemRect( nItemId
) : pBox
->GetOverflowRect();
823 // convert to parent's screen coordinates
824 mpImplData
->maPos
= GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox
->OutputToAbsoluteScreenPixel( aRect
.TopLeft() ) ) );
825 aRect
.SetPos( mpImplData
->maPos
);
828 FloatWinPopupFlags::AllMouseButtonClose
|
829 FloatWinPopupFlags::NoMouseUpClose
;
831 // set Flags for positioning
832 if ( !(nFlags
& (FloatWinPopupFlags::Down
| FloatWinPopupFlags::Up
|
833 FloatWinPopupFlags::Left
| FloatWinPopupFlags::Right
)) )
835 if ( pBox
->IsHorizontal() )
836 nFlags
|= FloatWinPopupFlags::Down
;
838 nFlags
|= FloatWinPopupFlags::Right
;
841 // start FloatingMode
842 StartPopupMode( aRect
, nFlags
);
845 void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags
, const VclPtr
<vcl::Window
>& xFocusId
)
847 if ( !mbInPopupMode
)
850 ImplSVData
* pSVData
= ImplGetSVData();
852 mbInCleanUp
= true; // prevent killing this window due to focus change while working with it
854 if (!(nFlags
& FloatWinPopupEndFlags::NoCloseChildren
))
856 // stop the PopupMode also for all PopupMode windows created after us
857 std::vector
<VclPtr
<FloatingWindow
>> aCancelFloats
;
858 // stop the PopupMode also for all following PopupMode windows
859 for (auto pFloat
= pSVData
->mpWinData
->mpFirstFloat
;
860 pFloat
!= nullptr && pFloat
!= this;
861 pFloat
= pFloat
->mpNextFloat
)
862 aCancelFloats
.push_back(pFloat
);
863 for (auto & it
: aCancelFloats
)
864 it
->EndPopupMode(FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::NoCloseChildren
);
867 // delete window from the list
868 pSVData
->mpWinData
->mpFirstFloat
= mpNextFloat
;
869 mpNextFloat
= nullptr;
871 FloatWinPopupFlags nPopupModeFlags
= mnPopupModeFlags
;
872 mbPopupModeTearOff
= nFlags
& FloatWinPopupEndFlags::TearOff
&&
873 nPopupModeFlags
& FloatWinPopupFlags::AllowTearOff
;
875 // hide window again if it was not deleted
876 if (!mbPopupModeTearOff
)
877 Show( false, ShowFlags::NoFocusChange
);
879 if (HasChildPathFocus() && xFocusId
!= nullptr)
881 // restore focus to previous focus window if we still have the focus
882 Window::EndSaveFocus(xFocusId
);
884 else if ( pSVData
->mpWinData
->mpFocusWin
&& pSVData
->mpWinData
->mpFirstFloat
&&
885 ImplIsWindowOrChild( pSVData
->mpWinData
->mpFocusWin
) )
887 // maybe pass focus on to a suitable FloatingWindow
888 pSVData
->mpWinData
->mpFirstFloat
->GrabFocus();
891 mbPopupModeCanceled
= bool(nFlags
& FloatWinPopupEndFlags::Cancel
);
894 SetTitleType( mnOldTitle
);
896 // set ToolBox again to normal
897 if (mpImplData
&& mpImplData
->mpBox
)
899 mpImplData
->mpBox
->ImplFloatControl( false, this );
900 // if the parent ToolBox is in popup mode, it should be closed too.
901 if ( GetDockingManager()->IsInPopupMode( mpImplData
->mpBox
) )
902 nFlags
|= FloatWinPopupEndFlags::CloseAll
;
904 mpImplData
->mpBox
= nullptr;
907 // call PopupModeEnd-Handler depending on parameter
908 if ( !(nFlags
& FloatWinPopupEndFlags::DontCallHdl
) )
909 ImplCallPopupModeEnd();
911 // close all other windows depending on parameter
912 if ( nFlags
& FloatWinPopupEndFlags::CloseAll
)
914 if ( !(nPopupModeFlags
& FloatWinPopupFlags::NewLevel
) )
916 if (pSVData
->mpWinData
->mpFirstFloat
)
918 FloatingWindow
* pLastLevelFloat
= pSVData
->mpWinData
->mpFirstFloat
->ImplFindLastLevelFloat();
919 pLastLevelFloat
->EndPopupMode( FloatWinPopupEndFlags::Cancel
| FloatWinPopupEndFlags::CloseAll
);
927 void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags
)
929 ImplEndPopupMode(nFlags
, mxPrevFocusWin
);
932 void FloatingWindow::AddPopupModeWindow(vcl::Window
* pWindow
)
934 // !!! up-to-now only 1 window and not yet a list
935 mpFirstPopupModeWin
= pWindow
;
937 bool FloatingWindow::UpdatePositionData()
939 auto pWin
= ImplGetParent();
942 // Simulate Move, so the relative position of the floating window will be recalculated
943 pWin
->ImplCallMove();
950 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */