LibreOffice Module vcl (master)  1
floatwin.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <svdata.hxx>
21 #include <brdwin.hxx>
22 #include <window.h>
23 #include <salframe.hxx>
24 
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>
35 
37 {
38 public:
39  ImplData();
40 
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
45 };
46 
48 {
49  mpBox = nullptr;
50 }
51 
53 {
54  return mpImplData->maItemEdgeClipRect;
55 }
56 
58 {
59  mpImplData.reset(new ImplData);
60 
61  mpWindowImpl->mbFloatWin = true;
62  mbInCleanUp = false;
63  mbGrabFocus = false;
64 
65  SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
66 
67  if (!pParent)
68  pParent = ImplGetSVData()->maFrameData.mpAppWin;
69 
70  SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
71 
72  // no Border, then we don't need a border window
73  if (!nStyle)
74  {
75  mpWindowImpl->mbOverlapWin = true;
76  nStyle |= WB_DIALOGCONTROL;
77  ImplInit(pParent, nStyle, nullptr);
78  }
79  else
80  {
81  if (!(nStyle & WB_NODIALOGCONTROL))
82  nStyle |= WB_DIALOGCONTROL;
83 
85  && !(nStyle & WB_OWNERDRAWDECORATION))
86  {
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);
93  }
94  else
95  {
96  VclPtr<ImplBorderWindow> pBorderWin;
98 
99  if (nStyle & WB_OWNERDRAWDECORATION)
100  nBorderStyle |= BorderWindowStyle::Frame;
101  else
102  nBorderStyle |= BorderWindowStyle::Overlap;
103 
104  if ((nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)))
105  {
106  nBorderStyle |= BorderWindowStyle::Frame;
107  nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
108  }
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;
117  }
118  }
120 
121  mpNextFloat = nullptr;
122  mpFirstPopupModeWin = nullptr;
123  mnPostId = nullptr;
127  mbInPopupMode = false;
128  mbPopupMode = false;
129  mbPopupModeCanceled = false;
130  mbPopupModeTearOff = false;
131  mbMouseDown = false;
132 
134 }
135 
137 {
138  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
139 
140  Color aColor;
141  if (IsControlBackground())
142  aColor = GetControlBackground();
143  else if (Window::GetStyle() & WB_3DLOOK)
144  aColor = rStyleSettings.GetFaceColor();
145  else
146  aColor = rStyleSettings.GetWindowColor();
147  SetBackground(aColor);
148 }
149 
152 {
153  ImplInitFloating(pParent, nStyle);
154 }
155 
156 FloatingWindow::FloatingWindow(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame)
158  , mpNextFloat(nullptr)
159  , mpFirstPopupModeWin(nullptr)
160  , mnPostId(nullptr)
161  , mnPopupModeFlags(FloatWinPopupFlags::NONE)
162  , mnTitle(FloatWinTitleType::Unknown)
163  , mnOldTitle(FloatWinTitleType::Unknown)
164  , mbInPopupMode(false)
165  , mbPopupMode(false)
166  , mbPopupModeCanceled(false)
167  , mbPopupModeTearOff(false)
168  , mbMouseDown(false)
169  , mbGrabFocus(false)
170  , mbInCleanUp(false)
171 {
172  loadUI(pParent, rID, rUIXMLDescription, rFrame);
173 }
174 
175 //Find the real parent stashed in mpDialogParent.
177 {
178  vcl::Window *pParent = mpDialogParent;
179  mpDialogParent = nullptr;
180  ImplInitFloating(pParent, nBits);
181  mbIsDeferredInit = false;
182 }
183 
185 {
186  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
187 
188  Color aColor;
189  if (Window::GetStyle() & WB_3DLOOK)
190  aColor = rStyleSettings.GetFaceColor();
191  else
192  aColor = rStyleSettings.GetWindowColor();
193 
194  ApplyControlBackground(rRenderContext, aColor);
195 }
196 
198 {
199  disposeOnce();
200  assert (!mnPostId);
201 }
202 
204 {
206 
207  if (mpImplData)
208  {
209  if( mbPopupModeCanceled )
210  // indicates that ESC key was pressed
211  // will be handled in Window::ImplGrabFocus()
213 
214  if ( IsInPopupMode() )
216 
217  if ( mnPostId )
219  mnPostId = nullptr;
220  }
221 
222  mpImplData.reset();
223 
224  mpNextFloat.clear();
228 }
229 
230 Point FloatingWindow::CalcFloatingPosition( vcl::Window* pWindow, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags, sal_uInt16& rArrangeIndex )
231 {
232  return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
233 }
234 
236  const tools::Rectangle& rRect, FloatWinPopupFlags nFlags,
237  sal_uInt16& rArrangeIndex, Point* pLOKTwipsPos)
238 {
239  // get window position
240  Point aPos;
241  Size aSize = ::isLayoutEnabled(pWindow) ? pWindow->get_preferred_size() : pWindow->GetSizePixel();
242  tools::Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
243  FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
244 
245  // convert...
246  vcl::Window* pW = pWindow;
247  if ( pW->mpWindowImpl->mpRealParent )
248  pW = pW->mpWindowImpl->mpRealParent;
249 
250  tools::Rectangle normRect( rRect ); // rRect is already relative to top-level window
251  normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
252 
253  bool bRTL = AllSettings::GetLayoutRTL();
254 
255  tools::Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
256  pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
257 
258  tools::Rectangle devRectRTL( devRect );
259  if( bRTL )
260  // create a rect that can be compared to desktop coordinates
261  devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
264  Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
265 
266  FloatWinPopupFlags nArrangeAry[5];
267  Point e1,e2; // the common edge between the item rect and the floating window
268 
269  if ( nFlags & FloatWinPopupFlags::Left )
270  {
271  nArrangeAry[0] = FloatWinPopupFlags::Left;
272  nArrangeAry[1] = FloatWinPopupFlags::Right;
273  nArrangeAry[2] = FloatWinPopupFlags::Up;
274  nArrangeAry[3] = FloatWinPopupFlags::Down;
275  nArrangeAry[4] = FloatWinPopupFlags::Left;
276  }
277  else if ( nFlags & FloatWinPopupFlags::Right )
278  {
279  nArrangeAry[0] = FloatWinPopupFlags::Right;
280  nArrangeAry[1] = FloatWinPopupFlags::Left;
281  nArrangeAry[2] = FloatWinPopupFlags::Up;
282  nArrangeAry[3] = FloatWinPopupFlags::Down;
283  nArrangeAry[4] = FloatWinPopupFlags::Right;
284  }
285  else if ( nFlags & FloatWinPopupFlags::Up )
286  {
287  nArrangeAry[0] = FloatWinPopupFlags::Up;
288  nArrangeAry[1] = FloatWinPopupFlags::Down;
289  nArrangeAry[2] = FloatWinPopupFlags::Right;
290  nArrangeAry[3] = FloatWinPopupFlags::Left;
291  nArrangeAry[4] = FloatWinPopupFlags::Up;
292  }
293  else
294  {
295  nArrangeAry[0] = FloatWinPopupFlags::Down;
296  nArrangeAry[1] = FloatWinPopupFlags::Up;
297  nArrangeAry[2] = FloatWinPopupFlags::Right;
298  nArrangeAry[3] = FloatWinPopupFlags::Left;
299  nArrangeAry[4] = FloatWinPopupFlags::Down;
300  }
301 
302  sal_uInt16 nArrangeIndex = 0;
303  const bool bLOKActive = comphelper::LibreOfficeKit::isActive();
304 
305  for ( ; nArrangeIndex < 5; nArrangeIndex++ )
306  {
307  bool bBreak = true;
308  switch ( nArrangeAry[nArrangeIndex] )
309  {
310 
311  case FloatWinPopupFlags::Left:
312  aPos.setX( devRect.Left()-aSize.Width()+1 );
313  aPos.setY( devRect.Top() );
314  aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
315  if( bRTL )
316  {
317  if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
318  bBreak = false;
319  }
320  else
321  {
322  if ( aPos.X() < aScreenRect.Left() )
323  bBreak = false;
324  }
325  if (bBreak || bLOKActive)
326  {
327  e1 = devRect.TopLeft();
328  e2 = devRect.BottomLeft();
329  // set non-zero width
330  e2.AdjustX( 1 );
331  // don't clip corners
332  e1.AdjustY( 1 );
333  e2.AdjustY( -1 );
334  }
335  break;
336  case FloatWinPopupFlags::Right:
337  aPos = devRect.TopRight();
338  aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
339  if( bRTL )
340  {
341  if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
342  bBreak = false;
343  }
344  else
345  {
346  if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
347  bBreak = false;
348  }
349  if (bBreak || bLOKActive)
350  {
351  e1 = devRect.TopRight();
352  e2 = devRect.BottomRight();
353  // set non-zero width
354  e2.AdjustX( 1 );
355  // don't clip corners
356  e1.AdjustY( 1 );
357  e2.AdjustY( -1 );
358  }
359  break;
360  case FloatWinPopupFlags::Up:
361  aPos.setX( devRect.Left() );
362  aPos.setY( devRect.Top()-aSize.Height()+1 );
363  if ( aPos.Y() < aScreenRect.Top() )
364  bBreak = false;
365  if (bBreak || bLOKActive)
366  {
367  e1 = devRect.TopLeft();
368  e2 = devRect.TopRight();
369  // set non-zero height
370  e2.AdjustY( 1 );
371  // don't clip corners
372  e1.AdjustX( 1 );
373  e2.AdjustX( -1 );
374  }
375  break;
377  aPos = devRect.BottomLeft();
378  if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
379  bBreak = false;
380  if (bBreak || bLOKActive)
381  {
382  e1 = devRect.BottomLeft();
383  e2 = devRect.BottomRight();
384  // set non-zero height
385  e2.AdjustY( 1 );
386  // don't clip corners
387  e1.AdjustX( 1 );
388  e2.AdjustX( -1 );
389  }
390  break;
391  default: break;
392  }
393 
394  // no further adjustment for LibreOfficeKit
395  if (bLOKActive)
396  break;
397 
398  // adjust if necessary
399  if (bBreak)
400  {
401  if ( (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Left) ||
402  (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Right) )
403  {
404  if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
405  {
406  aPos.setY( devRect.Bottom()-aSize.Height()+1 );
407  if ( aPos.Y() < aScreenRect.Top() )
408  aPos.setY( aScreenRect.Top() );
409  }
410  }
411  else
412  {
413  if( bRTL )
414  {
415  if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
416  aPos.AdjustX( -(aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1) );
417  }
418  else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
419  {
420  aPos.setX( devRect.Right()-aSize.Width()+1 );
421  if ( aPos.X() < aScreenRect.Left() )
422  aPos.setX( aScreenRect.Left() );
423  }
424  }
425  }
426 
427  if ( bBreak )
428  break;
429  }
430  if ( nArrangeIndex > 4 )
431  nArrangeIndex = 4;
432 
433  rArrangeIndex = nArrangeIndex;
434 
435  aPos = pW->AbsoluteScreenToOutputPixel( aPos );
436 
437  // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
438  if( pFloatingWindow && pFloatingWindow->mpImplData->mpBox )
439  {
440  pFloatingWindow->mpImplData->maItemEdgeClipRect =
441  tools::Rectangle( e1, e2 );
442  }
443 
444  if (bLOKActive && pLOKTwipsPos)
445  {
446  if (pW->IsMapModeEnabled() || pW->GetMapMode().GetMapUnit() == MapUnit::MapPixel)
447  {
448  // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)),
449  // for pixel conversions when map mode is not enabled, we get
450  // a 20 twips per pixel conversion since LogicToLogic uses
451  // a fixed 72 dpi value, instead of a correctly computed output
452  // device dpi or at least the most commonly used 96 dpi value;
453  // and anyway the following is what we already do in
454  // ScGridWindow::LogicInvalidate when map mode is not enabled.
455 
456  *pLOKTwipsPos = pW->PixelToLogic(aPos, MapMode(MapUnit::MapTwip));
457  }
458  else
459  {
460  *pLOKTwipsPos = OutputDevice::LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip));
461  }
462  }
463 
464  // caller expects coordinates relative to top-level win
465  return pW->OutputToScreenPixel( aPos );
466 }
467 
469 {
470  Point aAbsolute( rPos );
471 
472  const OutputDevice *pWindowOutDev = pReference->GetOutDev();
473 
474  // compare coordinates in absolute screen coordinates
475  if( pReference->HasMirroredGraphics() )
476  {
477  if(!pReference->IsRTLEnabled() )
478  pWindowOutDev->ReMirror( aAbsolute );
479 
480  tools::Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
481  aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
482  aAbsolute = aRect.TopLeft();
483  }
484  else
485  aAbsolute = pReference->OutputToAbsoluteScreenPixel(
486  pReference->ScreenToOutputPixel(rPos) );
487 
488  return aAbsolute;
489 }
490 
492 {
493  tools::Rectangle aFloatRect = rRect;
494 
495  const OutputDevice *pParentWinOutDev = pReference->GetOutDev();
496 
497  // compare coordinates in absolute screen coordinates
498  // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
499  if( pReference->HasMirroredGraphics() )
500  {
501  if(!pReference->IsRTLEnabled() )
502  pParentWinOutDev->ReMirror(aFloatRect);
503 
504  aFloatRect.SetPos(pReference->ScreenToOutputPixel(aFloatRect.TopLeft()));
505  aFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect);
506  }
507  else
508  aFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
509  return aFloatRect;
510 }
511 
512 FloatingWindow* FloatingWindow::ImplFloatHitTest( vcl::Window* pReference, const Point& rPos, bool& rbHitTestInsideRect )
513 {
514  FloatingWindow* pWin = this;
515  rbHitTestInsideRect = false;
516 
517  Point aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference, rPos));
518 
519  do
520  {
521  // compute the floating window's size in absolute screen coordinates
522 
523  // use the border window to have the exact position
524  vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border );
525  if (!pBorderWin)
526  break;
527 
528  // the top-left corner in output coordinates ie (0,0)
530  if ( devRect.IsInside( aAbsolute ) )
531  {
532  // inside the window
533  return pWin;
534  }
535 
536  // test, if mouse is in rectangle, (this is typically the rect of the active
537  // toolbox item or similar)
538  // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
539  // is already in absolute device coordinates
540  if ( pWin->maFloatRect.IsInside( aAbsolute ) )
541  {
542  rbHitTestInsideRect = true;
543  return pWin;
544  }
545 
546  pWin = pWin->mpNextFloat;
547  }
548  while ( pWin );
549 
550  return nullptr;
551 }
552 
554 {
555  FloatingWindow* pWin = this;
556  FloatingWindow* pLastFoundWin = pWin;
557 
558  do
559  {
561  pLastFoundWin = pWin;
562 
563  pWin = pWin->mpNextFloat;
564  }
565  while ( pWin );
566 
567  return pLastFoundWin;
568 }
569 
571 {
572  FloatingWindow* pWin = this;
573 
574  do
575  {
576  if ( pWin->mpFirstPopupModeWin == pWindow )
577  return true;
578 
579  pWin = pWin->mpNextFloat;
580  }
581  while ( pWin );
582 
583  return false;
584 }
585 
586 IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void*, void)
587 {
588  VclPtr<FloatingWindow> pThis(this);
589  mnPostId = nullptr;
590  mnPopupModeFlags = FloatWinPopupFlags::NONE;
591  mbPopupMode = false;
592  PopupModeEnd();
593 }
594 
596 {
597  // call Base Class first for tab control
598  bool bRet = SystemWindow::EventNotify( rNEvt );
599  if ( !bRet )
600  {
601  if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
602  {
603  const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
604  vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
605  sal_uInt16 nKeyCode = aKeyCode.GetCode();
606 
607  if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
608  {
609  Close();
610  return true;
611  }
612  }
613  }
614 
615  return bRet;
616 }
617 
619 {
621  {
622  std::vector<vcl::LOKPayloadItem> aPayload;
623  const tools::Rectangle aRect(Point(0,0), Size(GetSizePixel().Width()+1, GetSizePixel().Height()+1));
624  aPayload.push_back(std::make_pair(OString("rectangle"), aRect.toString()));
625  const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier();
626  pNotifier->notifyWindow(GetLOKWindowId(), "invalidate", aPayload);
627  }
628 }
629 
631 {
632  if (nType == StateChangedType::InitShow)
633  {
634  DoInitialLayout();
635  }
636 
638 
640  if (pParent)
641  {
642  if (nType == StateChangedType::InitShow)
643  {
644  std::vector<vcl::LOKPayloadItem> aItems;
645  if (pParent == this)
646  {
647  // we are a toplevel window, let's so far pretend to be a
648  // dialog - but maybe we'll need a separate type for this
649  // later
650  aItems.emplace_back("type", "dialog");
651  aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips
652  }
653  else
654  {
655  SetLOKNotifier(pParent->GetLOKNotifier());
656  aItems.emplace_back("type", "child");
657  aItems.emplace_back("parentId", OString::number(pParent->GetLOKWindowId()));
658  if (mbInPopupMode)
659  aItems.emplace_back("position", mpImplData->maPos.toString()); // pixels
660  else // mpImplData->maPos is not set
661  aItems.emplace_back("position", GetPosPixel().toString());
662 
663  }
664  aItems.emplace_back("size", GetSizePixel().toString());
665  GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems);
666  }
667  else if (!IsVisible() && nType == StateChangedType::Visible)
668  {
669  if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
670  {
671  pNotifier->notifyWindow(GetLOKWindowId(), "close");
673  }
674  }
675  }
676 
678  {
680  Invalidate();
681  }
682 }
683 
685 {
686  SystemWindow::DataChanged( rDCEvt );
687 
688  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
689  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
690  {
692  Invalidate();
693  }
694 }
695 
697 {
698  // PopupMode is finished
699  mbInPopupMode = false;
700 
701  // call Handler asynchronously.
702  if ( mpImplData && !mnPostId )
703  mnPostId = Application::PostUserEvent(LINK(this, FloatingWindow, ImplEndPopupModeHdl));
704 }
705 
707 {
708  maPopupModeEndHdl.Call( this );
709 }
710 
712 {
713  if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
714  {
715  mnTitle = nTitle;
716  Size aOutSize = GetOutputSizePixel();
717  BorderWindowTitleType nTitleStyle;
718  if ( nTitle == FloatWinTitleType::Normal )
719  nTitleStyle = BorderWindowTitleType::Small;
720  else if ( nTitle == FloatWinTitleType::TearOff )
721  nTitleStyle = BorderWindowTitleType::Tearoff;
722  else if ( nTitle == FloatWinTitleType::Popup )
723  nTitleStyle = BorderWindowTitleType::Popup;
724  else // nTitle == FloatWinTitleType::NONE
725  nTitleStyle = BorderWindowTitleType::NONE;
726  static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetTitleType( nTitleStyle, aOutSize );
727  static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
728  }
729 }
730 
732 {
733  if ( IsRollUp() )
734  RollDown();
735 
736  // remove title
738  if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() )
740  else if ( nFlags & FloatWinPopupFlags::AllowTearOff )
742  else
744 
745  // avoid close on focus change for decorated floating windows only
746  if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
748 
749  // compute window position according to flags and arrangement
750  sal_uInt16 nArrangeIndex;
751  DoInitialLayout();
752  mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos);
753  SetPosPixel( mpImplData->maPos );
754  ImplGetFrame()->PositionByToolkit(rRect, nFlags);
755 
756  // set data and display window
757  // convert maFloatRect to absolute device coordinates
758  // so they can be compared across different frames
759  // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
761 
762  maFloatRect.AdjustLeft( -2 );
763  maFloatRect.AdjustTop( -2 );
766  mnPopupModeFlags = nFlags;
767  mbInPopupMode = true;
768  mbPopupMode = true;
769  mbPopupModeCanceled = false;
770  mbPopupModeTearOff = false;
771  mbMouseDown = false;
772 
773  // add FloatingWindow to list of windows that are in popup mode
774  ImplSVData* pSVData = ImplGetSVData();
775  mpNextFloat = pSVData->mpWinData->mpFirstFloat;
776  pSVData->mpWinData->mpFirstFloat = this;
777  if (nFlags & FloatWinPopupFlags::GrabFocus)
778  {
779  // force key input even without focus (useful for menus)
780  mbGrabFocus = true;
781  mxPrevFocusWin = Window::SaveFocus();
782  mpWindowImpl->mpFrameData->mbHasFocus = true;
783  GrabFocus();
784  }
785  Show( true, ShowFlags::NoActivate );
786 }
787 
789 {
790  mpImplData->mpBox = pBox;
791 
792  // get selected button
793  sal_uInt16 nItemId = pBox->GetDownItemId();
794 
795  if ( nItemId )
796  pBox->ImplFloatControl( true, this );
797 
798  // retrieve some data from the ToolBox
799  tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect();
800 
801  // convert to parent's screen coordinates
803  aRect.SetPos( mpImplData->maPos );
804 
805  nFlags |=
808 
809  // set Flags for positioning
812  {
813  if ( pBox->IsHorizontal() )
814  nFlags |= FloatWinPopupFlags::Down;
815  else
816  nFlags |= FloatWinPopupFlags::Right;
817  }
818 
819  // start FloatingMode
820  StartPopupMode( aRect, nFlags );
821 }
822 
824 {
825  if ( !mbInPopupMode )
826  return;
827 
828  ImplSVData* pSVData = ImplGetSVData();
829 
830  mbInCleanUp = true; // prevent killing this window due to focus change while working with it
831 
833  {
834  // stop the PopupMode also for all PopupMode windows created after us
835  std::vector<VclPtr<FloatingWindow>> aCancelFloats;
836  // stop the PopupMode also for all following PopupMode windows
837  for (auto pFloat = pSVData->mpWinData->mpFirstFloat;
838  pFloat != nullptr && pFloat != this;
839  pFloat = pFloat->mpNextFloat)
840  aCancelFloats.push_back(pFloat);
841  for (auto & it : aCancelFloats)
842  it->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::NoCloseChildren);
843  }
844 
845  // delete window from the list
846  pSVData->mpWinData->mpFirstFloat = mpNextFloat;
847  mpNextFloat = nullptr;
848 
849  FloatWinPopupFlags nPopupModeFlags = mnPopupModeFlags;
851  nPopupModeFlags & FloatWinPopupFlags::AllowTearOff;
852 
853  // hide window again if it was not deleted
854  if (!mbPopupModeTearOff)
855  Show( false, ShowFlags::NoFocusChange );
856 
857  if (HasChildPathFocus() && xFocusId != nullptr)
858  {
859  // restore focus to previous focus window if we still have the focus
860  Window::EndSaveFocus(xFocusId);
861  }
862  else if ( pSVData->mpWinData->mpFocusWin && pSVData->mpWinData->mpFirstFloat &&
864  {
865  // maybe pass focus on to a suitable FloatingWindow
866  pSVData->mpWinData->mpFirstFloat->GrabFocus();
867  }
868 
870 
871  // redo title
873 
874  // set ToolBox again to normal
875  if (mpImplData && mpImplData->mpBox)
876  {
877  mpImplData->mpBox->ImplFloatControl( false, this );
878  // if the parent ToolBox is in popup mode, it should be closed too.
879  if ( GetDockingManager()->IsInPopupMode( mpImplData->mpBox ) )
881 
882  mpImplData->mpBox = nullptr;
883  }
884 
885  // call PopupModeEnd-Handler depending on parameter
886  if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) )
888 
889  // close all other windows depending on parameter
890  if ( nFlags & FloatWinPopupEndFlags::CloseAll )
891  {
892  if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) )
893  {
894  if (pSVData->mpWinData->mpFirstFloat)
895  {
896  FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
897  pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
898  }
899  }
900  }
901 
902  mbInCleanUp = false;
903 }
904 
906 {
908 }
909 
911 {
912  // !!! up-to-now only 1 window and not yet a list
913  mpFirstPopupModeWin = pWindow;
914 }
916 {
917  auto pWin = ImplGetParent();
918  if (pWin)
919  {
920  // Simulate Move, so the relative position of the floating window will be recalculated
921  pWin->ImplCallMove();
922  return true;
923  }
924 
925  return false;
926 }
927 
928 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2857
WinBits const WB_ROLLABLE
Point TopLeft() const
long Width() const
void SetPos(const Point &rPoint)
FloatWinTitleType mnOldTitle
Definition: floatwin.hxx:87
bool IsControlBackground() const
Definition: window2.cxx:1087
bool IsInPopupMode() const
Definition: floatwin.hxx:148
vcl::LOKWindowId GetLOKWindowId() const
Definition: window.cxx:3299
void StartPopupMode(const tools::Rectangle &rRect, FloatWinPopupFlags nFlags)
Definition: floatwin.cxx:731
bool mbPopupMode
Definition: floatwin.hxx:89
WinBits const WB_SYSTEMWINDOW
VclPtr< vcl::Window > mpFocusWin
Definition: svdata.hxx:248
void RollDown()
Definition: syswin.cxx:385
void loadUI(vcl::Window *pParent, const OString &rID, const OUString &rUIXMLDescription, const css::uno::Reference< css::frame::XFrame > &rFrame=css::uno::Reference< css::frame::XFrame >())
Definition: syswin.cxx:88
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: syswin.cxx:171
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1668
virtual void StateChanged(StateChangedType nType) override
Definition: floatwin.cxx:630
long Height() const
bool IsRollUp() const
Definition: syswin.hxx:147
WinBits const WB_NODIALOGCONTROL
void PixelInvalidate(const tools::Rectangle *pRectangle) override
Notification about some rectangle of the output device got invalidated.
Definition: floatwin.cxx:618
SAL_DLLPRIVATE void ImplFloatControl(bool bStart, FloatingWindow *pWindow)
Definition: toolbox.cxx:2829
FloatingWindow(const FloatingWindow &)=delete
long AdjustLeft(long nHorzMoveDelta)
Point AbsoluteScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2928
SAL_DLLPRIVATE void ImplInitFloating(vcl::Window *pParent, WinBits nStyle)
Definition: floatwin.cxx:57
void SetDisplayActive(bool bActive)
Definition: brdwin.cxx:1930
const StyleSettings & GetStyleSettings() const
bool UpdatePositionData()
Definition: floatwin.cxx:915
const Color & GetFaceColor() const
Link< FloatingWindow *, void > maPopupModeEndHdl
Definition: floatwin.hxx:95
bool IsMapModeEnabled() const
Definition: outdev.hxx:1676
virtual Size GetSizePixel() const
Definition: window.cxx:2415
SAL_DLLPRIVATE vcl::Window * ImplGetFrameWindow() const
Definition: window2.cxx:901
virtual ~FloatingWindow() override
Definition: floatwin.cxx:197
void SetLOKNotifier(const vcl::ILibreOfficeKitNotifier *pNotifier, bool bParent=false)
Interface to register for dialog / window tunneling.
Definition: window.cxx:3224
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
Post a user event to the default window.
Definition: svapp.cxx:1006
const MapMode & GetMapMode() const
Definition: outdev.hxx:1681
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
static bool IsUnifiedDisplay()
Determines if the screens that make up a display are separate or form one large display area...
Definition: svapp.cxx:1210
bool mbGrabFocus
Definition: floatwin.hxx:93
SAL_DLLPRIVATE tools::Rectangle ImplOutputToUnmirroredAbsoluteScreenPixel(const tools::Rectangle &rRect) const
Definition: window.cxx:2938
DataChangedEventType GetType() const
Definition: event.hxx:361
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:315
tools::Rectangle GetDesktopRectPixel() const
Definition: window.cxx:2862
SAL_DLLPRIVATE void ImplInitSettings()
Definition: floatwin.cxx:136
const Color & GetControlBackground() const
Definition: window2.cxx:1082
bool mbInCleanUp
Definition: floatwin.hxx:94
static Point ImplCalcPos(vcl::Window *pWindow, const tools::Rectangle &rRect, FloatWinPopupFlags nFlags, sal_uInt16 &rArrangeIndex, Point *pLOKTwipsPos=nullptr)
Definition: floatwin.cxx:235
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:3059
Unknown
BorderWindowTitleType
Definition: brdwin.hxx:66
long AdjustBottom(long nVertMoveDelta)
DialogControlFlags GetDialogControlFlags() const
Definition: window2.cxx:1057
NONE
tools::Rectangle const & GetOverflowRect() const
Definition: toolbox2.cxx:846
tools::Rectangle maFloatRect
Definition: floatwin.hxx:83
StateChangedType
Definition: window.hxx:311
FloatWinPopupEndFlags
Definition: floatwin.hxx:52
WinBits const WB_OWNERDRAWDECORATION
sal_Int64 WinBits
void SetBackground()
long Right() const
bool mbPopupModeTearOff
Definition: floatwin.hxx:91
SAL_DLLPRIVATE void ReMirror(Point &rPoint) const
Definition: outdev.cxx:613
VclPtr< vcl::Window > GetParentWithLOKNotifier()
Find the nearest parent with LOK Notifier; can be itself if this Window has LOK notifier set...
Definition: window.cxx:3304
AllSettingsFlags GetFlags() const
Definition: event.hxx:362
bool IsHorizontal() const
Definition: toolbox.hxx:336
VclPtr< ToolBox > mpBox
Definition: floatwin.cxx:41
FloatWinPopupFlags GetPopupModeFlags() const
Definition: floatwin.hxx:146
SAL_DLLPRIVATE tools::Rectangle & ImplGetItemEdgeClipRect()
Definition: floatwin.cxx:52
long Top() const
tools::Rectangle maItemEdgeClipRect
Definition: floatwin.cxx:42
IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void *, void)
Definition: floatwin.cxx:586
std::unique_ptr< ImplData > mpImplData
Definition: floatwin.hxx:82
tools::Rectangle GetItemRect(sal_uInt16 nItemId)
Definition: toolbox2.cxx:826
virtual bool Close()
Definition: syswin.cxx:266
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
Remove user event based on event ID.
Definition: svapp.cxx:1034
Point BottomRight() const
WinBits const WB_DIALOGCONTROL
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:75
void clear()
Definition: vclptr.hxx:190
static tools::Rectangle GetScreenPosSizePixel(unsigned int nScreen)
Get a screen's rectangular area.
Definition: svapp.cxx:1245
VclPtr< vcl::Window > mxPrevFocusWin
Definition: floatwin.hxx:81
bool IsRTLEnabled() const
Definition: outdev.hxx:1361
void SetActivateMode(ActivateModeFlags nMode)
Definition: window.cxx:2701
sal_uInt16 GetDownItemId() const
Definition: toolbox.hxx:357
Point maLOKTwipsPos
absolute position of the floating window in the document - in twips (for toplevel floating windows)...
Definition: floatwin.cxx:44
virtual void doDeferredInit(WinBits nBits) override
Definition: floatwin.cxx:176
VclPtr< WorkWindow > mpAppWin
Definition: svdata.hxx:240
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1160
static Point ImplConvertToAbsPos(vcl::Window *pReference, const Point &rPos)
Definition: floatwin.cxx:468
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
long Bottom() const
void AddPopupModeWindow(vcl::Window *pWindow)
Definition: floatwin.cxx:910
static bool GetLayoutRTL()
std::unique_ptr< WindowImpl > mpWindowImpl
Definition: window.hxx:511
SAL_DLLPRIVATE vcl::Window * ImplGetParent() const
Definition: window2.cxx:865
Size get_preferred_size() const
Definition: window2.cxx:1640
bool mbIsDeferredInit
Definition: syswin.hxx:83
MouseNotifyEvent GetType() const
Definition: event.hxx:307
VclPtr< FloatingWindow > mpNextFloat
Definition: floatwin.hxx:79
bool IsInside(const Point &rPOINT) const
static Point CalcFloatingPosition(vcl::Window *pWindow, const tools::Rectangle &rRect, FloatWinPopupFlags nFlags, sal_uInt16 &rArrangeIndex)
Definition: floatwin.cxx:230
SAL_DLLPRIVATE FloatingWindow * ImplFindLastLevelFloat()
Definition: floatwin.cxx:553
const AllSettings & GetSettings() const
Definition: outdev.hxx:420
FloatWinPopupFlags mnPopupModeFlags
Definition: floatwin.hxx:85
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
MapUnit GetMapUnit() const
Definition: mapmod.cxx:168
static unsigned int GetScreenCount()
Get the number of screens available for the display.
Definition: svapp.cxx:1204
static SAL_DLLPRIVATE unsigned int GetBestScreen(const tools::Rectangle &)
Get the "best" screen.
Definition: svapp.cxx:1271
SAL_DLLPRIVATE bool ImplIsFloatPopupModeWindow(const vcl::Window *pWindow)
Definition: floatwin.cxx:570
virtual void PopupModeEnd()
Definition: floatwin.cxx:706
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2875
FloatWinPopupFlags
Definition: floatwin.hxx:31
void GrabFocus()
Definition: window.cxx:3031
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: floatwin.cxx:684
FloatWinTitleType
Definition: floatwin.hxx:66
vcl::Window * GetParent() const
Definition: window2.cxx:1097
Point OutputToAbsoluteScreenPixel(const Point &rPos) const
Definition: window.cxx:2918
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1046
SAL_DLLPRIVATE void ImplEndPopupMode(FloatWinPopupEndFlags nFlags, const VclPtr< vcl::Window > &xFocusId)
Definition: floatwin.cxx:823
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1179
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle, SystemParentData *pSystemParentData)
Definition: window.cxx:932
SAL_DLLPRIVATE void ImplCallPopupModeEnd()
Definition: floatwin.cxx:696
WinBits const WB_3DLOOK
WinBits const WB_SIZEABLE
WinBits const WB_STANDALONE
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: window.cxx:2437
SalFrame * ImplGetFrame() const
Definition: window2.cxx:848
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:54
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: syswin.cxx:101
ImplSVEvent * mnPostId
Definition: floatwin.hxx:84
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: floatwin.cxx:595
long AdjustRight(long nHorzMoveDelta)
WindowType
#define SAL_WARN_IF(condition, area, stream)
bool mbPopupModeCanceled
Definition: floatwin.hxx:90
WinBits const WB_BORDER
constexpr sal_uInt16 KEY_ESCAPE
Definition: keycodes.hxx:120
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: brdwin.cxx:2031
ImplSVFrameData maFrameData
Definition: svdata.hxx:395
bool IsVisible() const
Definition: window2.cxx:1102
virtual OUString GetText() const override
Definition: syswin.cxx:1109
::OutputDevice const * GetOutDev() const
Definition: window.cxx:572
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
virtual void PositionByToolkit(const tools::Rectangle &, FloatWinPopupFlags)
Definition: salframe.hxx:173
FloatWinTitleType mnTitle
Definition: floatwin.hxx:86
long AdjustTop(long nVertMoveDelta)
const Color & GetWindowColor() const
BorderWindowStyle
Definition: brdwin.hxx:33
SAL_DLLPRIVATE bool ImplIsWindowOrChild(const vcl::Window *pWindow, bool bSystemWindow=false) const
Definition: stacking.cxx:710
long Left() const
VclPtr< FloatingWindow > mpFirstFloat
Definition: svdata.hxx:251
void ApplyControlBackground(vcl::RenderContext &rRenderContext, const Color &rDefaultColor)
Definition: window2.cxx:529
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
Definition: floatwin.cxx:184
VclPtr< vcl::Window > mpFirstPopupModeWin
Definition: floatwin.hxx:80
VclPtr< vcl::Window > mpDialogParent
Definition: syswin.hxx:84
SAL_DLLPRIVATE FloatingWindow * ImplFloatHitTest(vcl::Window *pReference, const Point &rPos, bool &rbHitTestInsideRect)
Definition: floatwin.cxx:512
virtual void StateChanged(StateChangedType nStateChange)
Definition: window.cxx:1954
const vcl::ILibreOfficeKitNotifier * GetLOKNotifier() const
Definition: window.cxx:3294
void SetDialogControlFlags(DialogControlFlags nFlags)
Definition: window2.cxx:1052
WinBits GetStyle() const
Definition: window2.cxx:953
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2869
void ReleaseLOKNotifier()
Indicate that LOK is not going to use this dialog any more.
Definition: window.cxx:3262
WinBits const WB_CLOSEABLE
WinBits const WB_MOVEABLE
rtl::OString toString() const
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: floatwin.cxx:203
WinBits const WB_POPUP
void SetTitleType(FloatWinTitleType nTitle)
Definition: floatwin.cxx:711
void EndPopupMode(FloatWinPopupEndFlags nFlags=FloatWinPopupEndFlags::NONE)
Definition: floatwin.cxx:905
bool mbInPopupMode
Definition: floatwin.hxx:88
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1257
bool isLayoutEnabled() const
Definition: syswin.cxx:1058
SAL_DLLPRIVATE void DoInitialLayout()
Definition: syswin.cxx:1140
bool HasMirroredGraphics() const override
static DockingManager * GetDockingManager()
Definition: window2.cxx:803
virtual void DataChanged(const DataChangedEvent &rDCEvt)
Definition: event.cxx:35
OUString toString(OptionInfo const *info)
ImplSVWinData * mpWinData
Definition: svdata.hxx:396
bool mbMouseDown
Definition: floatwin.hxx:92
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2201