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 #include <helpwin.hxx>
25 
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>
36 
38 {
39 public:
40  ImplData();
41 
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
46 };
47 
49 {
50  mpBox = nullptr;
51 }
52 
54 {
55  return mpImplData->maItemEdgeClipRect;
56 }
57 
59 {
60  mpImplData.reset(new ImplData);
61 
62  mpWindowImpl->mbFloatWin = true;
63  mbInCleanUp = false;
64  mbGrabFocus = false;
65 
66  SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!");
67 
68  if (!pParent)
69  pParent = ImplGetSVData()->maFrameData.mpAppWin;
70 
71  SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
72 
73  // no Border, then we don't need a border window
74  if (!nStyle)
75  {
76  mpWindowImpl->mbOverlapWin = true;
77  nStyle |= WB_DIALOGCONTROL;
78  ImplInit(pParent, nStyle, nullptr);
79  }
80  else
81  {
82  if (!(nStyle & WB_NODIALOGCONTROL))
83  nStyle |= WB_DIALOGCONTROL;
84 
86  && !(nStyle & WB_OWNERDRAWDECORATION))
87  {
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);
94  }
95  else
96  {
97  VclPtr<ImplBorderWindow> pBorderWin;
99 
100  if (nStyle & WB_OWNERDRAWDECORATION)
101  nBorderStyle |= BorderWindowStyle::Frame;
102  else
103  nBorderStyle |= BorderWindowStyle::Overlap;
104 
105  if ((nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)))
106  {
107  nBorderStyle |= BorderWindowStyle::Frame;
108  nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
109  }
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;
118  }
119  }
121 
122  mpNextFloat = nullptr;
123  mpFirstPopupModeWin = nullptr;
124  mnPostId = nullptr;
128  mbInPopupMode = false;
129  mbPopupMode = false;
130  mbPopupModeCanceled = false;
131  mbPopupModeTearOff = false;
132  mbMouseDown = false;
133 
135 }
136 
138 {
139  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
140 
141  Color aColor;
142  if (IsControlBackground())
143  aColor = GetControlBackground();
144  else if (Window::GetStyle() & WB_3DLOOK)
145  aColor = rStyleSettings.GetFaceColor();
146  else
147  aColor = rStyleSettings.GetWindowColor();
148  SetBackground(aColor);
149 }
150 
153 {
154  ImplInitFloating(pParent, nStyle);
155 }
156 
157 FloatingWindow::FloatingWindow(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame)
159  , mpNextFloat(nullptr)
160  , mpFirstPopupModeWin(nullptr)
161  , mnPostId(nullptr)
162  , mnPopupModeFlags(FloatWinPopupFlags::NONE)
163  , mnTitle(FloatWinTitleType::Unknown)
164  , mnOldTitle(FloatWinTitleType::Unknown)
165  , mbInPopupMode(false)
166  , mbPopupMode(false)
167  , mbPopupModeCanceled(false)
168  , mbPopupModeTearOff(false)
169  , mbMouseDown(false)
170  , mbGrabFocus(false)
171  , mbInCleanUp(false)
172 {
173  loadUI(pParent, rID, rUIXMLDescription, rFrame);
174 }
175 
176 //Find the real parent stashed in mpDialogParent.
178 {
179  vcl::Window *pParent = mpDialogParent;
180  mpDialogParent = nullptr;
181  ImplInitFloating(pParent, nBits);
182  mbIsDeferredInit = false;
183 }
184 
186 {
187  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
188 
189  Color aColor;
190  if (Window::GetStyle() & WB_3DLOOK)
191  aColor = rStyleSettings.GetFaceColor();
192  else
193  aColor = rStyleSettings.GetWindowColor();
194 
195  ApplyControlBackground(rRenderContext, aColor);
196 }
197 
199 {
200  disposeOnce();
201  assert (!mnPostId);
202 }
203 
205 {
207 
208  if (mpImplData)
209  {
210  if( mbPopupModeCanceled )
211  // indicates that ESC key was pressed
212  // will be handled in Window::ImplGrabFocus()
214 
215  if ( IsInPopupMode() )
217 
218  if ( mnPostId )
220  mnPostId = nullptr;
221  }
222 
223  mpImplData.reset();
224 
225  mpNextFloat.clear();
229 }
230 
231 Point FloatingWindow::CalcFloatingPosition( vcl::Window* pWindow, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags, sal_uInt16& rArrangeIndex )
232 {
233  return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
234 }
235 
237  const tools::Rectangle& rRect, FloatWinPopupFlags nFlags,
238  sal_uInt16& rArrangeIndex, Point* pLOKTwipsPos)
239 {
240  // get window position
241  Point aPos;
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 );
245 
246  // convert...
247  vcl::Window* pW = pWindow;
248  if ( pW->mpWindowImpl->mpRealParent )
249  pW = pW->mpWindowImpl->mpRealParent;
250 
251  tools::Rectangle normRect( rRect ); // rRect is already relative to top-level window
252  normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
253 
254  bool bRTL = AllSettings::GetLayoutRTL();
255 
256  tools::Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
257  pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
258 
259  tools::Rectangle devRectRTL( devRect );
260  if( bRTL )
261  // create a rect that can be compared to desktop coordinates
262  devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
265  Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
266 
267  FloatWinPopupFlags nArrangeAry[5];
268  sal_uInt16 nArrangeAttempts = 5;
269  Point e1,e2; // the common edge between the item rect and the floating window
270 
271  if ( nFlags & FloatWinPopupFlags::Left )
272  {
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;
278  }
279  else if ( nFlags & FloatWinPopupFlags::Right )
280  {
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;
286  }
287  else if ( nFlags & FloatWinPopupFlags::Up )
288  {
289  nArrangeAry[0] = FloatWinPopupFlags::Up;
290  nArrangeAry[1] = FloatWinPopupFlags::Down;
292  {
293  nArrangeAry[2] = FloatWinPopupFlags::Up;
294  nArrangeAttempts = 3;
295  }
296  else
297  {
298  nArrangeAry[2] = FloatWinPopupFlags::Right;
299  nArrangeAry[3] = FloatWinPopupFlags::Left;
300  nArrangeAry[4] = FloatWinPopupFlags::Up;
301  }
302  }
303  else
304  {
305  nArrangeAry[0] = FloatWinPopupFlags::Down;
306  nArrangeAry[1] = FloatWinPopupFlags::Up;
308  {
309  nArrangeAry[2] = FloatWinPopupFlags::Down;
310  nArrangeAttempts = 3;
311  }
312  else
313  {
314  nArrangeAry[2] = FloatWinPopupFlags::Right;
315  nArrangeAry[3] = FloatWinPopupFlags::Left;
316  nArrangeAry[4] = FloatWinPopupFlags::Down;
317  }
318  }
319 
320  sal_uInt16 nArrangeIndex = 0;
321  const bool bLOKActive = comphelper::LibreOfficeKit::isActive();
322 
323  for ( ; nArrangeIndex < nArrangeAttempts; nArrangeIndex++ )
324  {
325  bool bBreak = true;
326  switch ( nArrangeAry[nArrangeIndex] )
327  {
328 
329  case FloatWinPopupFlags::Left:
330  aPos.setX( devRect.Left()-aSize.Width()+1 );
331  aPos.setY( devRect.Top() );
332  aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
333  if( bRTL )
334  {
335  if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
336  bBreak = false;
337  }
338  else
339  {
340  if ( aPos.X() < aScreenRect.Left() )
341  bBreak = false;
342  }
343  if (bBreak || bLOKActive)
344  {
345  e1 = devRect.TopLeft();
346  e2 = devRect.BottomLeft();
347  // set non-zero width
348  e2.AdjustX( 1 );
349  // don't clip corners
350  e1.AdjustY( 1 );
351  e2.AdjustY( -1 );
352  }
353  break;
354  case FloatWinPopupFlags::Right:
355  aPos = devRect.TopRight();
356  aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) );
357  if( bRTL )
358  {
359  if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
360  bBreak = false;
361  }
362  else
363  {
364  if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
365  bBreak = false;
366  }
367  if (bBreak || bLOKActive)
368  {
369  e1 = devRect.TopRight();
370  e2 = devRect.BottomRight();
371  // set non-zero width
372  e2.AdjustX( 1 );
373  // don't clip corners
374  e1.AdjustY( 1 );
375  e2.AdjustY( -1 );
376  }
377  break;
378  case FloatWinPopupFlags::Up:
379  aPos.setX( devRect.Left() );
380  aPos.setY( devRect.Top()-aSize.Height()+1 );
381  if ( aPos.Y() < aScreenRect.Top() )
382  bBreak = false;
383  if (bBreak || bLOKActive)
384  {
385  e1 = devRect.TopLeft();
386  e2 = devRect.TopRight();
387  // set non-zero height
388  e2.AdjustY( 1 );
389  // don't clip corners
390  e1.AdjustX( 1 );
391  e2.AdjustX( -1 );
392  }
393  break;
395  aPos = devRect.BottomLeft();
396  if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
397  bBreak = false;
398  if (bBreak || bLOKActive)
399  {
400  e1 = devRect.BottomLeft();
401  e2 = devRect.BottomRight();
402  // set non-zero height
403  e2.AdjustY( 1 );
404  // don't clip corners
405  e1.AdjustX( 1 );
406  e2.AdjustX( -1 );
407  }
408  break;
409  default: break;
410  }
411 
412  // no further adjustment for LibreOfficeKit
413  if (bLOKActive)
414  break;
415 
416  // adjust if necessary
417  if (bBreak)
418  {
419  if ( (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Left) ||
420  (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Right) )
421  {
422  if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
423  {
424  aPos.setY( devRect.Bottom()-aSize.Height()+1 );
425  if ( aPos.Y() < aScreenRect.Top() )
426  aPos.setY( aScreenRect.Top() );
427  }
428  }
429  else
430  {
431  if( bRTL )
432  {
433  if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
434  aPos.AdjustX( -(aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1) );
435  }
436  else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
437  {
438  aPos.setX( devRect.Right()-aSize.Width()+1 );
439  if ( aPos.X() < aScreenRect.Left() )
440  aPos.setX( aScreenRect.Left() );
441  }
442  }
443  }
444 
445  if ( bBreak )
446  break;
447  }
448  if (nArrangeIndex >= nArrangeAttempts)
449  nArrangeIndex = nArrangeAttempts - 1;
450 
451  rArrangeIndex = nArrangeIndex;
452 
453  aPos = pW->AbsoluteScreenToOutputPixel( aPos );
454 
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 )
457  {
458  pFloatingWindow->mpImplData->maItemEdgeClipRect =
459  tools::Rectangle( e1, e2 );
460  }
461 
462  if (bLOKActive && pLOKTwipsPos)
463  {
464  if (pW->IsMapModeEnabled() || pW->GetMapMode().GetMapUnit() == MapUnit::MapPixel)
465  {
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.
473 
474  *pLOKTwipsPos = pW->PixelToLogic(aPos, MapMode(MapUnit::MapTwip));
475  }
476  else
477  {
478  *pLOKTwipsPos = OutputDevice::LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip));
479  }
480  }
481 
482  // caller expects coordinates relative to top-level win
483  return pW->OutputToScreenPixel( aPos );
484 }
485 
487 {
488  Point aAbsolute( rPos );
489 
490  const OutputDevice *pWindowOutDev = pReference->GetOutDev();
491 
492  // compare coordinates in absolute screen coordinates
493  if( pReference->HasMirroredGraphics() )
494  {
495  if(!pReference->IsRTLEnabled() )
496  pWindowOutDev->ReMirror( aAbsolute );
497 
498  tools::Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
499  aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
500  aAbsolute = aRect.TopLeft();
501  }
502  else
503  aAbsolute = pReference->OutputToAbsoluteScreenPixel(
504  pReference->ScreenToOutputPixel(rPos) );
505 
506  return aAbsolute;
507 }
508 
510 {
511  tools::Rectangle aFloatRect = rRect;
512 
513  const OutputDevice *pParentWinOutDev = pReference->GetOutDev();
514 
515  // compare coordinates in absolute screen coordinates
516  // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
517  if( pReference->HasMirroredGraphics() )
518  {
519  if(!pReference->IsRTLEnabled() )
520  pParentWinOutDev->ReMirror(aFloatRect);
521 
522  aFloatRect.SetPos(pReference->ScreenToOutputPixel(aFloatRect.TopLeft()));
523  aFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(aFloatRect);
524  }
525  else
526  aFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
527  return aFloatRect;
528 }
529 
530 FloatingWindow* FloatingWindow::ImplFloatHitTest( vcl::Window* pReference, const Point& rPos, bool& rbHitTestInsideRect )
531 {
532  FloatingWindow* pWin = this;
533  rbHitTestInsideRect = false;
534 
535  Point aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference, rPos));
536 
537  do
538  {
539  // compute the floating window's size in absolute screen coordinates
540 
541  // use the border window to have the exact position
542  vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border );
543  if (!pBorderWin)
544  break;
545 
546  // the top-left corner in output coordinates ie (0,0)
548  if ( devRect.IsInside( aAbsolute ) )
549  {
550  // inside the window
551  return pWin;
552  }
553 
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 ) )
559  {
560  rbHitTestInsideRect = true;
561  return pWin;
562  }
563 
564  pWin = pWin->mpNextFloat;
565  }
566  while ( pWin );
567 
568  return nullptr;
569 }
570 
572 {
573  FloatingWindow* pWin = this;
574  FloatingWindow* pLastFoundWin = pWin;
575 
576  do
577  {
579  pLastFoundWin = pWin;
580 
581  pWin = pWin->mpNextFloat;
582  }
583  while ( pWin );
584 
585  return pLastFoundWin;
586 }
587 
589 {
590  FloatingWindow* pWin = this;
591 
592  do
593  {
594  if ( pWin->mpFirstPopupModeWin == pWindow )
595  return true;
596 
597  pWin = pWin->mpNextFloat;
598  }
599  while ( pWin );
600 
601  return false;
602 }
603 
604 IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void*, void)
605 {
606  VclPtr<FloatingWindow> pThis(this);
607  mnPostId = nullptr;
608  mnPopupModeFlags = FloatWinPopupFlags::NONE;
609  mbPopupMode = false;
610  PopupModeEnd();
611 }
612 
614 {
615  // call Base Class first for tab control
616  bool bRet = SystemWindow::EventNotify( rNEvt );
617  if ( !bRet )
618  {
619  if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
620  {
621  const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
622  vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
623  sal_uInt16 nKeyCode = aKeyCode.GetCode();
624 
625  if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
626  {
627  Close();
628  return true;
629  }
630  }
631  }
632 
633  return bRet;
634 }
635 
637 {
639  {
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);
645  }
646 }
647 
649 {
650  if (nType == StateChangedType::InitShow)
651  {
652  DoInitialLayout();
653  }
654 
656 
658  if (pParent)
659  {
660  if (nType == StateChangedType::InitShow)
661  {
662  std::vector<vcl::LOKPayloadItem> aItems;
663  if (pParent == this)
664  {
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
667  // later
668  aItems.emplace_back("type", "dialog");
669  aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips
670  }
671  else
672  {
673  SetLOKNotifier(pParent->GetLOKNotifier());
674  if (dynamic_cast<HelpTextWindow*>(this))
675  aItems.emplace_back("type", "tooltip");
676  else
677  aItems.emplace_back("type", "child");
678 
679  aItems.emplace_back("parentId", OString::number(pParent->GetLOKWindowId()));
680  if (mbInPopupMode)
681  aItems.emplace_back("position", mpImplData->maPos.toString()); // pixels
682  else // mpImplData->maPos is not set
683  aItems.emplace_back("position", GetPosPixel().toString());
684 
685  }
686  aItems.emplace_back("size", GetSizePixel().toString());
687  GetLOKNotifier()->notifyWindow(GetLOKWindowId(), "created", aItems);
688  }
689  else if (!IsVisible() && nType == StateChangedType::Visible)
690  {
691  if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
692  {
693  pNotifier->notifyWindow(GetLOKWindowId(), "close");
695  }
696  }
697  }
698 
700  {
702  Invalidate();
703  }
704 }
705 
707 {
708  SystemWindow::DataChanged( rDCEvt );
709 
710  if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
711  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
712  {
714  Invalidate();
715  }
716 }
717 
719 {
720  // PopupMode is finished
721  mbInPopupMode = false;
722 
723  // call Handler asynchronously.
724  if ( mpImplData && !mnPostId )
725  mnPostId = Application::PostUserEvent(LINK(this, FloatingWindow, ImplEndPopupModeHdl));
726 }
727 
729 {
730  maPopupModeEndHdl.Call( this );
731 }
732 
734 {
735  if ( (mnTitle == nTitle) || !mpWindowImpl->mpBorderWindow )
736  return;
737 
738  mnTitle = nTitle;
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 );
751 }
752 
754 {
755  if ( IsRollUp() )
756  RollDown();
757 
758  // remove title
760  if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() )
762  else if ( nFlags & FloatWinPopupFlags::AllowTearOff )
764  else
766 
767  // avoid close on focus change for decorated floating windows only
768  if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
770 
771  // compute window position according to flags and arrangement
772  sal_uInt16 nArrangeIndex;
773  DoInitialLayout();
774  mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos);
775  SetPosPixel( mpImplData->maPos );
776  ImplGetFrame()->PositionByToolkit(rRect, nFlags);
777 
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 !!!
783 
784  maFloatRect.AdjustLeft( -2 );
785  maFloatRect.AdjustTop( -2 );
788  mnPopupModeFlags = nFlags;
789  mbInPopupMode = true;
790  mbPopupMode = true;
791  mbPopupModeCanceled = false;
792  mbPopupModeTearOff = false;
793  mbMouseDown = false;
794 
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)
800  {
801  // force key input even without focus (useful for menus)
802  mbGrabFocus = true;
803  mxPrevFocusWin = Window::SaveFocus();
804  mpWindowImpl->mpFrameData->mbHasFocus = true;
805  GrabFocus();
806  }
807  Show( true, ShowFlags::NoActivate );
808 }
809 
811 {
812  mpImplData->mpBox = pBox;
813 
814  // get selected button
815  sal_uInt16 nItemId = pBox->GetDownItemId();
816 
817  if ( nItemId )
818  pBox->ImplFloatControl( true, this );
819 
820  // retrieve some data from the ToolBox
821  tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect();
822 
823  // convert to parent's screen coordinates
825  aRect.SetPos( mpImplData->maPos );
826 
827  nFlags |=
830 
831  // set Flags for positioning
834  {
835  if ( pBox->IsHorizontal() )
836  nFlags |= FloatWinPopupFlags::Down;
837  else
838  nFlags |= FloatWinPopupFlags::Right;
839  }
840 
841  // start FloatingMode
842  StartPopupMode( aRect, nFlags );
843 }
844 
846 {
847  if ( !mbInPopupMode )
848  return;
849 
850  ImplSVData* pSVData = ImplGetSVData();
851 
852  mbInCleanUp = true; // prevent killing this window due to focus change while working with it
853 
855  {
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);
865  }
866 
867  // delete window from the list
868  pSVData->mpWinData->mpFirstFloat = mpNextFloat;
869  mpNextFloat = nullptr;
870 
871  FloatWinPopupFlags nPopupModeFlags = mnPopupModeFlags;
873  nPopupModeFlags & FloatWinPopupFlags::AllowTearOff;
874 
875  // hide window again if it was not deleted
876  if (!mbPopupModeTearOff)
877  Show( false, ShowFlags::NoFocusChange );
878 
879  if (HasChildPathFocus() && xFocusId != nullptr)
880  {
881  // restore focus to previous focus window if we still have the focus
882  Window::EndSaveFocus(xFocusId);
883  }
884  else if ( pSVData->mpWinData->mpFocusWin && pSVData->mpWinData->mpFirstFloat &&
886  {
887  // maybe pass focus on to a suitable FloatingWindow
888  pSVData->mpWinData->mpFirstFloat->GrabFocus();
889  }
890 
892 
893  // redo title
895 
896  // set ToolBox again to normal
897  if (mpImplData && mpImplData->mpBox)
898  {
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 ) )
903 
904  mpImplData->mpBox = nullptr;
905  }
906 
907  // call PopupModeEnd-Handler depending on parameter
908  if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) )
910 
911  // close all other windows depending on parameter
912  if ( nFlags & FloatWinPopupEndFlags::CloseAll )
913  {
914  if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) )
915  {
916  if (pSVData->mpWinData->mpFirstFloat)
917  {
918  FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
919  pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
920  }
921  }
922  }
923 
924  mbInCleanUp = false;
925 }
926 
928 {
930 }
931 
933 {
934  // !!! up-to-now only 1 window and not yet a list
935  mpFirstPopupModeWin = pWindow;
936 }
938 {
939  auto pWin = ImplGetParent();
940  if (pWin)
941  {
942  // Simulate Move, so the relative position of the floating window will be recalculated
943  pWin->ImplCallMove();
944  return true;
945  }
946 
947  return false;
948 }
949 
950 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2786
WinBits const WB_ROLLABLE
Point TopLeft() 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:3222
void StartPopupMode(const tools::Rectangle &rRect, FloatWinPopupFlags nFlags)
Definition: floatwin.cxx:753
bool mbPopupMode
Definition: floatwin.hxx:89
WinBits const WB_SYSTEMWINDOW
VclPtr< vcl::Window > mpFocusWin
Definition: svdata.hxx:247
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
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
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:1514
virtual void StateChanged(StateChangedType nType) override
Definition: floatwin.cxx:648
bool IsRollUp() const
Definition: syswin.hxx:146
WinBits const WB_NODIALOGCONTROL
void PixelInvalidate(const tools::Rectangle *pRectangle) override
Notification about some rectangle of the output device got invalidated.
Definition: floatwin.cxx:636
SAL_DLLPRIVATE void ImplFloatControl(bool bStart, FloatingWindow *pWindow)
Definition: toolbox.cxx:2816
FloatingWindow(const FloatingWindow &)=delete
Point AbsoluteScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2857
SAL_DLLPRIVATE void ImplInitFloating(vcl::Window *pParent, WinBits nStyle)
Definition: floatwin.cxx:58
void SetDisplayActive(bool bActive)
Definition: brdwin.cxx:1933
const StyleSettings & GetStyleSettings() const
bool UpdatePositionData()
Definition: floatwin.cxx:937
const Color & GetFaceColor() const
Link< FloatingWindow *, void > maPopupModeEndHdl
Definition: floatwin.hxx:95
bool IsMapModeEnabled() const
Definition: outdev.hxx:1675
virtual Size GetSizePixel() const
Definition: window.cxx:2397
SAL_DLLPRIVATE vcl::Window * ImplGetFrameWindow() const
Definition: window2.cxx:901
virtual ~FloatingWindow() override
Definition: floatwin.cxx:198
void SetLOKNotifier(const vcl::ILibreOfficeKitNotifier *pNotifier, bool bParent=false)
Interface to register for dialog / window tunneling.
Definition: window.cxx:3147
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:999
const MapMode & GetMapMode() const
Definition: outdev.hxx:1681
sal_uInt16 GetCode() const
Definition: keycod.hxx:51
static bool IsUnifiedDisplay()
Determines if the screens that make up a display are separate or form one large display area...
Definition: svapp.cxx:1212
bool mbGrabFocus
Definition: floatwin.hxx:93
SAL_DLLPRIVATE tools::Rectangle ImplOutputToUnmirroredAbsoluteScreenPixel(const tools::Rectangle &rRect) const
Definition: window.cxx:2867
DataChangedEventType GetType() const
Definition: event.hxx:356
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:310
tools::Rectangle GetDesktopRectPixel() const
Definition: window.cxx:2791
SAL_DLLPRIVATE void ImplInitSettings()
Definition: floatwin.cxx:137
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:236
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:2982
Unknown
BorderWindowTitleType
Definition: brdwin.hxx:66
DialogControlFlags GetDialogControlFlags() const
Definition: window2.cxx:1057
NONE
tools::Rectangle const & GetOverflowRect() const
Definition: toolbox2.cxx:850
tools::Rectangle maFloatRect
Definition: floatwin.hxx:83
StateChangedType
Definition: window.hxx:317
FloatWinPopupEndFlags
Definition: floatwin.hxx:52
WinBits const WB_OWNERDRAWDECORATION
sal_Int64 WinBits
void SetBackground()
bool mbPopupModeTearOff
Definition: floatwin.hxx:91
SAL_DLLPRIVATE void ReMirror(Point &rPoint) const
Definition: outdev.cxx:599
tools::Long Left() const
VclPtr< vcl::Window > GetParentWithLOKNotifier()
Find the nearest parent with LOK Notifier; can be itself if this Window has LOK notifier set...
Definition: window.cxx:3227
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
AllSettingsFlags GetFlags() const
Definition: event.hxx:357
tools::Long Bottom() const
bool IsHorizontal() const
Definition: toolbox.hxx:333
VclPtr< ToolBox > mpBox
Definition: floatwin.cxx:42
FloatWinPopupFlags GetPopupModeFlags() const
Definition: floatwin.hxx:146
SAL_DLLPRIVATE tools::Rectangle & ImplGetItemEdgeClipRect()
Definition: floatwin.cxx:53
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Rectangle maItemEdgeClipRect
Definition: floatwin.cxx:43
IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void *, void)
Definition: floatwin.cxx:604
std::unique_ptr< ImplData > mpImplData
Definition: floatwin.hxx:82
tools::Rectangle GetItemRect(sal_uInt16 nItemId)
Definition: toolbox2.cxx:830
virtual bool Close()
Definition: syswin.cxx:266
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
Remove user event based on event ID.
Definition: svapp.cxx:1027
Point BottomRight() const
WinBits const WB_DIALOGCONTROL
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
void clear()
Definition: vclptr.hxx:190
static tools::Rectangle GetScreenPosSizePixel(unsigned int nScreen)
Get a screen's rectangular area.
Definition: svapp.cxx:1247
VclPtr< vcl::Window > mxPrevFocusWin
Definition: floatwin.hxx:81
bool IsRTLEnabled() const
Definition: outdev.hxx:1360
void SetActivateMode(ActivateModeFlags nMode)
Definition: window.cxx:2630
sal_uInt16 GetDownItemId() const
Definition: toolbox.hxx:354
Point maLOKTwipsPos
absolute position of the floating window in the document - in twips (for toplevel floating windows)...
Definition: floatwin.cxx:45
virtual void doDeferredInit(WinBits nBits) override
Definition: floatwin.cxx:177
VclPtr< WorkWindow > mpAppWin
Definition: svdata.hxx:239
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1164
static Point ImplConvertToAbsPos(vcl::Window *pReference, const Point &rPos)
Definition: floatwin.cxx:486
tools::Long Width() const
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:302
void AddPopupModeWindow(vcl::Window *pWindow)
Definition: floatwin.cxx:932
static bool GetLayoutRTL()
std::unique_ptr< WindowImpl > mpWindowImpl
Definition: window.hxx:519
SAL_DLLPRIVATE vcl::Window * ImplGetParent() const
Definition: window2.cxx:865
Size get_preferred_size() const
Definition: window2.cxx:1653
bool mbIsDeferredInit
Definition: syswin.hxx:82
MouseNotifyEvent GetType() const
Definition: event.hxx:302
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:231
SAL_DLLPRIVATE FloatingWindow * ImplFindLastLevelFloat()
Definition: floatwin.cxx:571
const AllSettings & GetSettings() const
Definition: outdev.hxx:417
FloatWinPopupFlags mnPopupModeFlags
Definition: floatwin.hxx:85
Size GetOutputSizePixel() const
Definition: outdev.hxx:440
MapUnit GetMapUnit() const
Definition: mapmod.cxx:168
static unsigned int GetScreenCount()
Get the number of screens available for the display.
Definition: svapp.cxx:1206
static SAL_DLLPRIVATE unsigned int GetBestScreen(const tools::Rectangle &)
Get the "best" screen.
Definition: svapp.cxx:1273
SAL_DLLPRIVATE bool ImplIsFloatPopupModeWindow(const vcl::Window *pWindow)
Definition: floatwin.cxx:588
virtual void PopupModeEnd()
Definition: floatwin.cxx:728
tools::Long Top() const
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2804
FloatWinPopupFlags
Definition: floatwin.hxx:31
void GrabFocus()
Definition: window.cxx:2954
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: floatwin.cxx:706
FloatWinTitleType
Definition: floatwin.hxx:66
vcl::Window * GetParent() const
Definition: window2.cxx:1097
Point OutputToAbsoluteScreenPixel(const Point &rPos) const
Definition: window.cxx:2847
tools::Long AdjustTop(tools::Long nVertMoveDelta)
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1039
SAL_DLLPRIVATE void ImplEndPopupMode(FloatWinPopupEndFlags nFlags, const VclPtr< vcl::Window > &xFocusId)
Definition: floatwin.cxx:845
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1049
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle, SystemParentData *pSystemParentData)
Definition: window.cxx:937
SAL_DLLPRIVATE void ImplCallPopupModeEnd()
Definition: floatwin.cxx:718
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:2419
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:613
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:2034
ImplSVFrameData maFrameData
Definition: svdata.hxx:391
bool IsVisible() const
Definition: window2.cxx:1102
virtual OUString GetText() const override
Definition: syswin.cxx:1109
::OutputDevice const * GetOutDev() const
Definition: window.cxx:578
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
tools::Long Height() const
const Color & GetWindowColor() const
BorderWindowStyle
Definition: brdwin.hxx:33
SAL_DLLPRIVATE bool ImplIsWindowOrChild(const vcl::Window *pWindow, bool bSystemWindow=false) const
Definition: stacking.cxx:703
VclPtr< FloatingWindow > mpFirstFloat
Definition: svdata.hxx:250
void ApplyControlBackground(vcl::RenderContext &rRenderContext, const Color &rDefaultColor)
Definition: window2.cxx:529
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
Definition: floatwin.cxx:185
VclPtr< vcl::Window > mpFirstPopupModeWin
Definition: floatwin.hxx:80
VclPtr< vcl::Window > mpDialogParent
Definition: syswin.hxx:83
SAL_DLLPRIVATE FloatingWindow * ImplFloatHitTest(vcl::Window *pReference, const Point &rPos, bool &rbHitTestInsideRect)
Definition: floatwin.cxx:530
virtual void StateChanged(StateChangedType nStateChange)
Definition: window.cxx:1936
const vcl::ILibreOfficeKitNotifier * GetLOKNotifier() const
Definition: window.cxx:3217
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void SetDialogControlFlags(DialogControlFlags nFlags)
Definition: window2.cxx:1052
WinBits GetStyle() const
Definition: window2.cxx:953
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2798
void ReleaseLOKNotifier()
Indicate that LOK is not going to use this dialog any more.
Definition: window.cxx:3185
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:204
WinBits const WB_POPUP
void SetTitleType(FloatWinTitleType nTitle)
Definition: floatwin.cxx:733
void EndPopupMode(FloatWinPopupEndFlags nFlags=FloatWinPopupEndFlags::NONE)
Definition: floatwin.cxx:927
bool mbInPopupMode
Definition: floatwin.hxx:88
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1257
bool isLayoutEnabled() const
Definition: syswin.cxx:1058
tools::Long Right() const
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:392
bool mbMouseDown
Definition: floatwin.hxx:92
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2183