build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / floatwin.cxx
blob8a5d5dcc62fd0a2f3708463602cfea011e477129
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 <svdata.hxx>
21 #include <brdwin.hxx>
22 #include <window.h>
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>
34 #include <tools/rc.h>
35 #include <tools/debug.hxx>
36 #include <vcl/IDialogRenderable.hxx>
38 class FloatingWindow::ImplData
40 public:
41 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()
51 mpBox = nullptr;
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;
64 mbInCleanUp = false;
65 mbGrabFocus = false;
67 SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
69 if (!pParent)
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
75 if (!nStyle)
77 mpWindowImpl->mbOverlapWin = true;
78 nStyle |= WB_DIALOGCONTROL;
79 SystemWindow::ImplInit(pParent, nStyle, nullptr);
81 else
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);
96 else
98 VclPtr<ImplBorderWindow> pBorderWin;
99 BorderWindowStyle nBorderStyle = BorderWindowStyle::Border | BorderWindowStyle::Float;
101 if (nStyle & WB_OWNERDRAWDECORATION)
102 nBorderStyle |= BorderWindowStyle::Frame;
103 else
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;
125 mnPostId = nullptr;
126 mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FloatWinTitleType::Normal : FloatWinTitleType::NONE;
127 mnOldTitle = mnTitle;
128 mnPopupModeFlags = FloatWinPopupFlags::NONE;
129 mbInPopupMode = false;
130 mbPopupMode = false;
131 mbPopupModeCanceled = false;
132 mbPopupModeTearOff = false;
133 mbMouseDown = false;
135 ImplInitSettings();
138 void FloatingWindow::ImplInitSettings()
140 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
142 Color aColor;
143 if (IsControlBackground())
144 aColor = GetControlBackground();
145 else if (Window::GetStyle() & WB_3DLOOK)
146 aColor = rStyleSettings.GetFaceColor();
147 else
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)
163 , mnPostId(nullptr)
164 , mnPopupModeFlags(FloatWinPopupFlags::NONE)
165 , mnTitle(FloatWinTitleType::Unknown)
166 , mnOldTitle(FloatWinTitleType::Unknown)
167 , mbInPopupMode(false)
168 , mbPopupMode(false)
169 , mbPopupModeCanceled(false)
170 , mbPopupModeTearOff(false)
171 , mbMouseDown(false)
172 , mbGrabFocus(false)
173 , mbInCleanUp(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();
191 Color aColor;
192 if (Window::GetStyle() & WB_3DLOOK)
193 aColor = rStyleSettings.GetFaceColor();
194 else
195 aColor = rStyleSettings.GetWindowColor();
197 ApplyControlBackground(rRenderContext, aColor);
200 FloatingWindow::~FloatingWindow()
202 disposeOnce();
203 assert (!mnPostId);
206 void FloatingWindow::dispose()
208 if (mpImplData)
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 );
218 if ( mnPostId )
219 Application::RemoveUserEvent( mnPostId );
220 mnPostId = nullptr;
223 delete mpImplData;
224 mpImplData = nullptr;
226 mpNextFloat.clear();
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
242 Point aPos;
243 Size aSize = ::isLayoutEnabled(pWindow) ? pWindow->get_preferred_size() : pWindow->GetSizePixel();
244 Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
245 FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
247 // convert....
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 );
261 if( bRTL )
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;
295 else
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++ )
309 bool bBreak = true;
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() )
320 bBreak = false;
322 else
324 if ( aPos.X() < aScreenRect.Left() )
325 bBreak = false;
327 if (bBreak || bLOKActive)
329 e1 = devRect.TopLeft();
330 e2 = devRect.BottomLeft();
331 // set non-zero width
332 e2.X()++;
333 // don't clip corners
334 e1.Y()++;
335 e2.Y()--;
337 break;
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() )
344 bBreak = false;
346 else
348 if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
349 bBreak = false;
351 if (bBreak || bLOKActive)
353 e1 = devRect.TopRight();
354 e2 = devRect.BottomRight();
355 // set non-zero width
356 e2.X()++;
357 // don't clip corners
358 e1.Y()++;
359 e2.Y()--;
361 break;
362 case FloatWinPopupFlags::Up:
363 aPos.X() = devRect.Left();
364 aPos.Y() = devRect.Top()-aSize.Height()+1;
365 if ( aPos.Y() < aScreenRect.Top() )
366 bBreak = false;
367 if (bBreak || bLOKActive)
369 e1 = devRect.TopLeft();
370 e2 = devRect.TopRight();
371 // set non-zero height
372 e2.Y()++;
373 // don't clip corners
374 e1.X()++;
375 e2.X()--;
377 break;
378 case FloatWinPopupFlags::Down:
379 aPos = devRect.BottomLeft();
380 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
381 bBreak = false;
382 if (bBreak || bLOKActive)
384 e1 = devRect.BottomLeft();
385 e2 = devRect.BottomRight();
386 // set non-zero height
387 e2.Y()++;
388 // don't clip corners
389 e1.X()++;
390 e2.X()--;
392 break;
393 default: break;
396 // no further adjustement for LibreOfficeKit
397 if (bLOKActive)
398 break;
400 // adjust if necessary
401 if (bBreak)
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();
413 else
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();
429 if ( bBreak )
430 break;
432 if ( nArrangeIndex > 4 )
433 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 =
443 Rectangle( e1, e2 );
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));
460 else
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();
487 else
488 aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
489 pReference->ScreenToOutputPixel(rPos) ) );
491 return aAbsolute;
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);
511 else
512 aFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
513 return aFloatRect;
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;
534 return pWin;
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;
544 return pWin;
547 pWin = pWin->mpNextFloat;
549 while ( pWin );
551 rHitTest = HITTEST_OUTSIDE;
552 return nullptr;
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;
567 while ( pWin );
569 return pLastFoundWin;
572 bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window* pWindow )
574 FloatingWindow* pWin = this;
578 if ( pWin->mpFirstPopupModeWin == pWindow )
579 return true;
581 pWin = pWin->mpNextFloat;
583 while ( pWin );
585 return false;
588 IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void*, void)
590 VclPtr<FloatingWindow> pThis(this);
591 mnPostId = nullptr;
592 mnPopupModeFlags = FloatWinPopupFlags::NONE;
593 mbPopupMode = false;
594 PopupModeEnd();
597 bool FloatingWindow::EventNotify( NotifyEvent& rNEvt )
599 // call Base Class first for tab control
600 bool bRet = SystemWindow::EventNotify( rNEvt );
601 if ( !bRet )
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) )
611 Close();
612 return true;
617 return bRet;
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)
633 DoInitialLayout();
636 SystemWindow::StateChanged( nType );
638 VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier();
639 if (pParent)
641 if (nType == StateChangedType::InitShow)
643 std::vector<vcl::LOKPayloadItem> aItems;
644 if (pParent == this)
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
648 // later
649 aItems.emplace_back("type", "dialog");
650 aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips
652 else
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 )
672 ImplInitSettings();
673 Invalidate();
677 void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
679 SystemWindow::DataChanged( rDCEvt );
681 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
682 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
684 ImplInitSettings();
685 Invalidate();
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 )
708 mnTitle = nTitle;
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 )
726 if ( IsRollUp() )
727 RollDown();
729 // remove title
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 );
735 else
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;
759 mbPopupMode = true;
760 mbPopupModeCanceled = false;
761 mbPopupModeTearOff = false;
762 mbMouseDown = 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)
771 mbGrabFocus = true;
772 mxPrevFocusWin = Window::SaveFocus();
773 mpWindowImpl->mpFrameData->mbHasFocus = true;
774 GrabFocus();
776 Show( true, ShowFlags::NoActivate );
779 void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags )
781 // get selected button
782 sal_uInt16 nItemId = pBox->GetDownItemId();
783 if ( !nItemId )
784 return;
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 );
796 nFlags |=
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;
806 else
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 )
817 return;
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;
852 else
854 mbPopupModeTearOff = true;
857 mbPopupModeCanceled = bool(nFlags & FloatWinPopupEndFlags::Cancel);
859 // redo title
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 );
886 mbInCleanUp = false;
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: */