1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <o3tl/safeint.hxx>
23 #include <sal/config.h>
24 #include <sal/log.hxx>
26 #include <vcl/layout.hxx>
27 #include <vcl/mnemonic.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/menu.hxx>
31 #include <vcl/event.hxx>
32 #include <vcl/syswin.hxx>
33 #include <vcl/taskpanelist.hxx>
34 #include <vcl/tabctrl.hxx>
35 #include <vcl/tabpage.hxx>
36 #include <vcl/virdev.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <o3tl/string_view.hxx>
42 #include <salframe.hxx>
47 using namespace ::com::sun::star::uno
;
49 class SystemWindow::ImplData
54 std::unique_ptr
<TaskPaneList
>
57 OUString maRepresentedURL
;
58 Link
<SystemWindow
&,void> maCloseHdl
;
61 SystemWindow::ImplData::ImplData()
63 mpTaskPaneList
= nullptr;
64 maMaxOutSize
= Size( SHRT_MAX
, SHRT_MAX
);
67 SystemWindow::SystemWindow(WindowType nType
, const char* pIdleDebugName
)
69 , mpImplData(new ImplData
)
70 , maLayoutIdle( pIdleDebugName
)
72 mpWindowImpl
->mbSysWin
= true;
73 mpWindowImpl
->mnActivateMode
= ActivateModeFlags::GrabFocus
;
75 //To-Do, reuse maResizeTimer
76 maLayoutIdle
.SetPriority(TaskPriority::RESIZE
);
77 maLayoutIdle
.SetInvokeHandler( LINK( this, SystemWindow
, ImplHandleLayoutTimerHdl
) );
80 void SystemWindow::loadUI(vcl::Window
* pParent
, const OUString
& rID
, const OUString
& rUIXMLDescription
,
81 const css::uno::Reference
<css::frame::XFrame
> &rFrame
)
83 mbIsDeferredInit
= true;
84 mpDialogParent
= pParent
; //should be unset in doDeferredInit
85 m_pUIBuilder
.reset( new VclBuilder(this, AllSettings::GetUIRootDir(), rUIXMLDescription
, rID
, rFrame
) );
88 SystemWindow::~SystemWindow()
93 void SystemWindow::dispose()
98 // Hack to make sure code called from base ~Window does not interpret this
99 // as a SystemWindow (which it no longer is by then):
100 mpWindowImpl
->mbSysWin
= false;
102 mpDialogParent
.clear();
107 static void ImplHandleControlAccelerator( const vcl::Window
* pWindow
, bool bShow
)
109 Control
*pControl
= dynamic_cast<Control
*>(pWindow
->ImplGetWindow());
110 if (pControl
&& pControl
->GetText().indexOf('~') != -1)
112 pControl
->SetShowAccelerator( bShow
);
113 pControl
->Invalidate(InvalidateFlags::Update
);
119 void processChildren(const vcl::Window
*pParent
, bool bShowAccel
)
121 // go through its children
122 vcl::Window
* pChild
= firstLogicalChildOfParent(pParent
);
125 if (pChild
->GetType() == WindowType::TABCONTROL
)
127 // find currently shown tab page
128 TabControl
* pTabControl
= static_cast<TabControl
*>(pChild
);
129 TabPage
* pTabPage
= pTabControl
->GetTabPage( pTabControl
->GetCurPageId() );
130 processChildren(pTabPage
, bShowAccel
);
132 else if (pChild
->GetType() == WindowType::TABPAGE
)
134 // bare tabpage without tabcontrol parent (options dialog)
135 processChildren(pChild
, bShowAccel
);
137 else if ((pChild
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) == WB_DIALOGCONTROL
)
139 // special controls that manage their children outside of widget layout
140 processChildren(pChild
, bShowAccel
);
144 ImplHandleControlAccelerator(pChild
, bShowAccel
);
146 pChild
= nextLogicalChildOfParent(pParent
, pChild
);
153 bool ToggleMnemonicsOnHierarchy(const CommandEvent
& rCEvent
, const vcl::Window
*pWindow
)
155 if (rCEvent
.GetCommand() == CommandEventId::ModKeyChange
&& ImplGetSVData()->maNWFData
.mbAutoAccel
)
157 const CommandModKeyData
*pCData
= rCEvent
.GetModKeyData();
158 const bool bShowAccel
= pCData
&& pCData
->IsMod2() && pCData
->IsDown();
159 processChildren(pWindow
, bShowAccel
);
166 bool SystemWindow::EventNotify( NotifyEvent
& rNEvt
)
168 if (rNEvt
.GetType() == NotifyEventType::COMMAND
)
169 ToggleMnemonicsOnHierarchy(*rNEvt
.GetCommandEvent(), this);
171 // capture KeyEvents for menu handling
172 if (rNEvt
.GetType() == NotifyEventType::KEYINPUT
||
173 rNEvt
.GetType() == NotifyEventType::COMMAND
)
175 MenuBar
* pMBar
= mpMenuBar
;
176 if ( !pMBar
&& ( GetType() == WindowType::FLOATINGWINDOW
) )
178 vcl::Window
* pWin
= ImplGetFrameWindow()->ImplGetWindow();
179 if( pWin
&& pWin
->IsSystemWindow() )
180 pMBar
= static_cast<SystemWindow
*>(pWin
)->GetMenuBar();
185 if (rNEvt
.GetType() == NotifyEventType::COMMAND
)
186 bDone
= pMBar
->ImplHandleCmdEvent(*rNEvt
.GetCommandEvent());
188 bDone
= pMBar
->ImplHandleKeyEvent(*rNEvt
.GetKeyEvent());
194 return Window::EventNotify( rNEvt
);
197 bool SystemWindow::PreNotify( NotifyEvent
& rNEvt
)
199 // capture KeyEvents for taskpane cycling
200 if ( rNEvt
.GetType() == NotifyEventType::KEYINPUT
)
202 if( rNEvt
.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6
&&
203 rNEvt
.GetKeyEvent()->GetKeyCode().IsMod1() &&
204 !rNEvt
.GetKeyEvent()->GetKeyCode().IsShift() )
206 // Ctrl-F6 goes directly to the document
207 GrabFocusToDocument();
212 TaskPaneList
*pTList
= mpImplData
->mpTaskPaneList
.get();
213 if( !pTList
&& ( GetType() == WindowType::FLOATINGWINDOW
) )
215 vcl::Window
* pWin
= ImplGetFrameWindow()->ImplGetWindow();
216 if( pWin
&& pWin
->IsSystemWindow() )
217 pTList
= static_cast<SystemWindow
*>(pWin
)->mpImplData
->mpTaskPaneList
.get();
221 // search topmost system window which is the one to handle dialog/toolbar cycling
222 SystemWindow
*pSysWin
= this;
223 vcl::Window
*pWin
= this;
226 pWin
= pWin
->GetParent();
227 if( pWin
&& pWin
->IsSystemWindow() )
228 pSysWin
= static_cast<SystemWindow
*>(pWin
);
230 pTList
= pSysWin
->mpImplData
->mpTaskPaneList
.get();
232 if( pTList
&& pTList
->HandleKeyEvent( *rNEvt
.GetKeyEvent() ) )
236 return Window::PreNotify( rNEvt
);
239 TaskPaneList
* SystemWindow::GetTaskPaneList()
243 if( mpImplData
->mpTaskPaneList
)
244 return mpImplData
->mpTaskPaneList
.get();
247 mpImplData
->mpTaskPaneList
.reset( new TaskPaneList
);
248 MenuBar
* pMBar
= mpMenuBar
;
249 if ( !pMBar
&& ( GetType() == WindowType::FLOATINGWINDOW
) )
251 vcl::Window
* pWin
= ImplGetFrameWindow()->ImplGetWindow();
252 if ( pWin
&& pWin
->IsSystemWindow() )
253 pMBar
= static_cast<SystemWindow
*>(pWin
)->GetMenuBar();
256 mpImplData
->mpTaskPaneList
->AddWindow( pMBar
->ImplGetWindow() );
257 return mpImplData
->mpTaskPaneList
.get();
261 bool SystemWindow::Close()
263 VclPtr
<vcl::Window
> xWindow
= this;
264 CallEventListeners( VclEventId::WindowClose
);
265 if ( xWindow
->isDisposed() )
268 if ( mpWindowImpl
->mxWindowPeer
.is() && IsCreatedWithToolkit() )
271 // Is Window not closeable, ignore close
272 vcl::Window
* pBorderWin
= ImplGetBorderWindow();
275 nStyle
= pBorderWin
->GetStyle();
278 if ( !(nStyle
& WB_CLOSEABLE
) )
286 void SystemWindow::TitleButtonClick( TitleButton
)
290 void SystemWindow::Resizing( Size
& )
294 void SystemWindow::SetRepresentedURL( const OUString
& i_rURL
)
296 bool bChanged
= (i_rURL
!= mpImplData
->maRepresentedURL
);
297 mpImplData
->maRepresentedURL
= i_rURL
;
298 if ( !mbSysChild
&& bChanged
)
300 const vcl::Window
* pWindow
= this;
301 while ( pWindow
->mpWindowImpl
->mpBorderWindow
)
302 pWindow
= pWindow
->mpWindowImpl
->mpBorderWindow
;
304 if ( pWindow
->mpWindowImpl
->mbFrame
)
305 pWindow
->mpWindowImpl
->mpFrame
->SetRepresentedURL( i_rURL
);
309 void SystemWindow::SetIcon( sal_uInt16 nIcon
)
311 if ( mnIcon
== nIcon
)
318 const vcl::Window
* pWindow
= this;
319 while ( pWindow
->mpWindowImpl
->mpBorderWindow
)
320 pWindow
= pWindow
->mpWindowImpl
->mpBorderWindow
;
322 if ( pWindow
->mpWindowImpl
->mbFrame
)
323 pWindow
->mpWindowImpl
->mpFrame
->SetIcon( nIcon
);
327 void SystemWindow::ShowTitleButton( TitleButton nButton
, bool bVisible
)
329 if ( nButton
== TitleButton::Docking
)
331 if ( mbDockBtn
!= bVisible
)
333 mbDockBtn
= bVisible
;
334 if ( mpWindowImpl
->mpBorderWindow
)
335 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetDockButton( bVisible
);
338 else if ( nButton
== TitleButton::Hide
)
340 if ( mbHideBtn
!= bVisible
)
342 mbHideBtn
= bVisible
;
343 if ( mpWindowImpl
->mpBorderWindow
)
344 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetHideButton( bVisible
);
347 else if ( nButton
== TitleButton::Menu
)
349 if ( mpWindowImpl
->mpBorderWindow
)
350 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMenuButton( bVisible
);
356 bool SystemWindow::IsTitleButtonVisible( TitleButton nButton
) const
358 if ( nButton
== TitleButton::Docking
)
360 else /* if ( nButton == TitleButton::Hide ) */
364 void SystemWindow::SetMinOutputSizePixel( const Size
& rSize
)
366 maMinOutSize
= rSize
;
367 if ( mpWindowImpl
->mpBorderWindow
)
369 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMinOutputSize( rSize
.Width(), rSize
.Height() );
370 if ( mpWindowImpl
->mpBorderWindow
->mpWindowImpl
->mbFrame
)
371 mpWindowImpl
->mpBorderWindow
->mpWindowImpl
->mpFrame
->SetMinClientSize( rSize
.Width(), rSize
.Height() );
373 else if ( mpWindowImpl
->mbFrame
)
374 mpWindowImpl
->mpFrame
->SetMinClientSize( rSize
.Width(), rSize
.Height() );
377 void SystemWindow::SetMaxOutputSizePixel( const Size
& rSize
)
380 if( aSize
.Width() > SHRT_MAX
|| aSize
.Width() <= 0 )
381 aSize
.setWidth( SHRT_MAX
);
382 if( aSize
.Height() > SHRT_MAX
|| aSize
.Height() <= 0 )
383 aSize
.setHeight( SHRT_MAX
);
385 mpImplData
->maMaxOutSize
= aSize
;
386 if ( mpWindowImpl
->mpBorderWindow
)
388 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMaxOutputSize( aSize
.Width(), aSize
.Height() );
389 if ( mpWindowImpl
->mpBorderWindow
->mpWindowImpl
->mbFrame
)
390 mpWindowImpl
->mpBorderWindow
->mpWindowImpl
->mpFrame
->SetMaxClientSize( aSize
.Width(), aSize
.Height() );
392 else if ( mpWindowImpl
->mbFrame
)
393 mpWindowImpl
->mpFrame
->SetMaxClientSize( aSize
.Width(), aSize
.Height() );
396 const Size
& SystemWindow::GetMaxOutputSizePixel() const
398 return mpImplData
->maMaxOutSize
;
401 vcl::WindowData::WindowData(std::u16string_view rStr
)
403 vcl::WindowDataMask nValidMask
= vcl::WindowDataMask::NONE
;
404 sal_Int32 nIndex
= 0;
406 std::u16string_view aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
407 if (!aTokenStr
.empty())
409 setX(o3tl::toInt32(aTokenStr
));
410 if (x() > -16384 && x() < 16384)
411 nValidMask
|= vcl::WindowDataMask::X
;
417 aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
418 if (!aTokenStr
.empty())
420 setY(o3tl::toInt32(aTokenStr
));
421 if (y() > -16384 && y() < 16384)
422 nValidMask
|= vcl::WindowDataMask::Y
;
428 aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
429 if (!aTokenStr
.empty())
431 sal_Int32 nWidth
= o3tl::toInt32(aTokenStr
);
436 if (width() > 0 && width() < 16384)
437 nValidMask
|= vcl::WindowDataMask::Width
;
443 aTokenStr
= o3tl::getToken(rStr
, 0, ';', nIndex
);
444 if (!aTokenStr
.empty())
446 sal_Int32 nHeight
= o3tl::toInt32(aTokenStr
);
451 if (height() > 0 && height() < 16384)
452 nValidMask
|= vcl::WindowDataMask::Height
;
458 aTokenStr
= o3tl::getToken(rStr
, 0, ';', nIndex
);
459 if (!aTokenStr
.empty())
461 // #94144# allow Minimize again, should be masked out when read from configuration
462 // 91625 - ignore Minimize
463 vcl::WindowState nState
= static_cast<vcl::WindowState
>(o3tl::toInt32(aTokenStr
));
464 //nState &= ~vcl::WindowState::Minimized;
466 nValidMask
|= vcl::WindowDataMask::State
;
469 setState(vcl::WindowState::NONE
);
471 // read maximized pos/size
472 aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
473 if (!aTokenStr
.empty())
475 SetMaximizedX(o3tl::toInt32(aTokenStr
));
476 if (GetMaximizedX() > -16384 && GetMaximizedX() < 16384)
477 nValidMask
|= vcl::WindowDataMask::MaximizedX
;
483 aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
484 if (!aTokenStr
.empty())
486 SetMaximizedY(o3tl::toInt32(aTokenStr
));
487 if (GetMaximizedY() > -16384 && GetMaximizedY() < 16384)
488 nValidMask
|= vcl::WindowDataMask::MaximizedY
;
494 aTokenStr
= o3tl::getToken(rStr
, 0, ',', nIndex
);
495 if (!aTokenStr
.empty())
497 SetMaximizedWidth(o3tl::toInt32(aTokenStr
));
498 if (GetMaximizedWidth() > 0 && GetMaximizedWidth() < 16384)
499 nValidMask
|= vcl::WindowDataMask::MaximizedWidth
;
501 SetMaximizedWidth(0);
504 SetMaximizedWidth(0);
505 aTokenStr
= o3tl::getToken(rStr
, 0, ';', nIndex
);
506 if (!aTokenStr
.empty())
508 SetMaximizedHeight(o3tl::toInt32(aTokenStr
));
509 if (GetMaximizedHeight() > 0 && GetMaximizedHeight() < 16384)
510 nValidMask
|= vcl::WindowDataMask::MaximizedHeight
;
512 SetMaximizedHeight(0);
515 SetMaximizedHeight(0);
521 OUString
vcl::WindowData::toStr() const
523 const vcl::WindowDataMask nValidMask
= mask();
524 if ( nValidMask
== vcl::WindowDataMask::NONE
)
527 OUStringBuffer
rStrBuf(64);
529 tools::Rectangle aRect
= posSize();
531 if (nValidMask
& vcl::WindowDataMask::X
)
532 rStrBuf
.append(static_cast<sal_Int32
>(aRect
.Left()));
534 if (nValidMask
& vcl::WindowDataMask::Y
)
535 rStrBuf
.append(static_cast<sal_Int32
>(aRect
.Top()));
537 if (nValidMask
& vcl::WindowDataMask::Width
)
538 rStrBuf
.append(static_cast<sal_Int32
>(aRect
.GetWidth()));
540 if (nValidMask
& vcl::WindowDataMask::Height
)
541 rStrBuf
.append(static_cast<sal_Int32
>(aRect
.GetHeight()));
542 rStrBuf
.append( ';' );
543 if (nValidMask
& vcl::WindowDataMask::State
)
545 // #94144# allow Minimize again, should be masked out when read from configuration
546 // 91625 - ignore Minimize
547 rStrBuf
.append(static_cast<sal_Int32
>(state()));
550 if (nValidMask
& vcl::WindowDataMask::MaximizedX
)
551 rStrBuf
.append(static_cast<sal_Int32
>(GetMaximizedX()));
553 if (nValidMask
& vcl::WindowDataMask::MaximizedY
)
554 rStrBuf
.append(static_cast<sal_Int32
>(GetMaximizedY()));
555 rStrBuf
.append( ',' );
556 if (nValidMask
& vcl::WindowDataMask::MaximizedWidth
)
557 rStrBuf
.append(static_cast<sal_Int32
>(GetMaximizedWidth()));
559 if (nValidMask
& vcl::WindowDataMask::MaximizedHeight
)
560 rStrBuf
.append(static_cast<sal_Int32
>(GetMaximizedHeight()));
563 return rStrBuf
.makeStringAndClear();
566 void SystemWindow::ImplMoveToScreen( tools::Long
& io_rX
, tools::Long
& io_rY
, tools::Long i_nWidth
, tools::Long i_nHeight
, vcl::Window
const * i_pConfigureWin
)
568 AbsoluteScreenPixelRectangle aScreenRect
= Application::GetScreenPosSizePixel( 0 );
569 for( unsigned int i
= 1; i
< Application::GetScreenCount(); i
++ )
570 aScreenRect
.Union( Application::GetScreenPosSizePixel( i
) );
571 // unfortunately most of the time width and height are not really known
579 if( io_rX
+ i_nWidth
< aScreenRect
.Left() )
582 io_rX
= aScreenRect
.Left();
584 // check right border
585 if( io_rX
> aScreenRect
.Right() - i_nWidth
)
588 io_rX
= aScreenRect
.Right() - i_nWidth
;
591 if( io_rY
+ i_nHeight
< aScreenRect
.Top() )
594 io_rY
= aScreenRect
.Top();
596 // check bottom border
597 if( io_rY
> aScreenRect
.Bottom() - i_nHeight
)
600 io_rY
= aScreenRect
.Bottom() - i_nHeight
;
602 vcl::Window
* pParent
= i_pConfigureWin
->GetParent();
603 if( bMove
&& pParent
)
605 // calculate absolute screen pos here, since that is what is contained in WindowData
606 Point
aParentAbsPos( pParent
->OutputToAbsoluteScreenPixel( Point(0,0) ) );
607 Size
aParentSizePixel( pParent
->GetOutputSizePixel() );
608 Point
aPos( (aParentSizePixel
.Width() - i_nWidth
) / 2,
609 (aParentSizePixel
.Height() - i_nHeight
) / 2 );
610 io_rX
= aParentAbsPos
.X() + aPos
.X();
611 io_rY
= aParentAbsPos
.Y() + aPos
.Y();
615 void SystemWindow::SetWindowState(const vcl::WindowData
& rData
)
617 const vcl::WindowDataMask nValidMask
= rData
.mask();
618 if ( nValidMask
== vcl::WindowDataMask::NONE
)
624 vcl::Window
* pWindow
= this;
625 while ( pWindow
->mpWindowImpl
->mpBorderWindow
)
626 pWindow
= pWindow
->mpWindowImpl
->mpBorderWindow
;
628 if ( pWindow
->mpWindowImpl
->mbFrame
)
630 const vcl::WindowState nState
= rData
.state();
631 vcl::WindowData aState
= rData
;
633 if (rData
.mask() & vcl::WindowDataMask::Size
)
635 // #i43799# adjust window state sizes if a minimal output size was set
636 // otherwise the frame and the client might get different sizes
637 if (maMinOutSize
.Width() > static_cast<tools::Long
>(aState
.width()))
638 aState
.setWidth(maMinOutSize
.Width());
639 if (maMinOutSize
.Height() > static_cast<tools::Long
>(aState
.width()))
640 aState
.setHeight(maMinOutSize
.Height());
643 // #94144# allow Minimize again, should be masked out when read from configuration
644 // 91625 - ignore Minimize
645 //nState &= ~(WindowState::Minimized);
646 aState
.rState() &= vcl::WindowState::SystemMask
;
648 // normalize window positions onto screen
649 tools::Long nX
= aState
.x(), nY
= aState
.y();
650 ImplMoveToScreen(nX
, nY
, aState
.width(), aState
.height(), pWindow
);
651 aState
.setPos({ nX
, nY
});
652 nX
= aState
.GetMaximizedX();
653 nY
= aState
.GetMaximizedY();
654 ImplMoveToScreen(nX
, nY
, aState
.GetMaximizedWidth(), aState
.GetMaximizedHeight(), pWindow
);
655 aState
.SetMaximizedX(nX
);
656 aState
.SetMaximizedY(nY
);
658 // #96568# avoid having multiple frames at the same screen location
659 // do the check only if not maximized
660 if( !((rData
.mask() & vcl::WindowDataMask::State
) && (nState
& vcl::WindowState::Maximized
)) )
661 if (rData
.mask() & vcl::WindowDataMask::PosSize
)
663 AbsoluteScreenPixelRectangle aDesktop
= GetDesktopRectPixel();
664 ImplSVData
*pSVData
= ImplGetSVData();
665 vcl::Window
*pWin
= pSVData
->maFrameData
.mpFirstFrame
;
666 bool bWrapped
= false;
669 if( !pWin
->ImplIsRealParentPath( this ) && ( pWin
!= this ) &&
670 pWin
->ImplGetWindow()->IsTopWindow() && pWin
->mpWindowImpl
->mbReallyVisible
)
672 SalFrameGeometry g
= pWin
->mpWindowImpl
->mpFrame
->GetGeometry();
673 if( std::abs(g
.x()-aState
.x()) < 2 && std::abs(g
.y()-aState
.y()) < 5 )
675 tools::Long displacement
= g
.topDecoration() ? g
.topDecoration() : 20;
676 if( static_cast<tools::Long
>(aState
.x() + displacement
+ aState
.width() + g
.rightDecoration()) > aDesktop
.Right() ||
677 static_cast<tools::Long
>(aState
.y() + displacement
+ aState
.height() + g
.bottomDecoration()) > aDesktop
.Bottom() )
679 // displacing would leave screen
680 aState
.setX(g
.leftDecoration() ? g
.leftDecoration() : 10); // should result in (0,0)
681 aState
.setY(displacement
);
683 static_cast<tools::Long
>(aState
.x() + displacement
+ aState
.width() + g
.rightDecoration()) > aDesktop
.Right() ||
684 static_cast<tools::Long
>(aState
.y() + displacement
+ aState
.height() + g
.bottomDecoration()) > aDesktop
.Bottom() )
685 break; // further displacement not possible -> break
686 // avoid endless testing
690 aState
.move(displacement
, displacement
);
691 pWin
= pSVData
->maFrameData
.mpFirstFrame
; // check new pos again
694 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
698 mpWindowImpl
->mpFrame
->SetWindowState( &aState
);
700 // do a synchronous resize for layout reasons
701 // but use rData only when the window is not to be maximized (#i38089#)
702 // otherwise we have no useful size information
703 if( (rData
.mask() & vcl::WindowDataMask::State
) && (nState
& vcl::WindowState::Maximized
) )
705 // query maximized size from frame
706 SalFrameGeometry aGeometry
= mpWindowImpl
->mpFrame
->GetGeometry();
708 // but use it only if it is different from the restore size (rData)
709 // as currently only on windows the exact size of a maximized window
710 // can be computed without actually showing the window
711 if (aGeometry
.width() != rData
.width() || aGeometry
.height() != rData
.height())
712 ImplHandleResize(pWindow
, aGeometry
.width(), aGeometry
.height());
715 if (rData
.mask() & vcl::WindowDataMask::Size
)
716 ImplHandleResize(pWindow
, aState
.width(), aState
.height()); // #i43799# use aState and not rData, see above
720 PosSizeFlags nPosSize
= PosSizeFlags::NONE
;
721 if ( nValidMask
& vcl::WindowDataMask::X
)
722 nPosSize
|= PosSizeFlags::X
;
723 if ( nValidMask
& vcl::WindowDataMask::Y
)
724 nPosSize
|= PosSizeFlags::Y
;
725 if ( nValidMask
& vcl::WindowDataMask::Width
)
726 nPosSize
|= PosSizeFlags::Width
;
727 if ( nValidMask
& vcl::WindowDataMask::Height
)
728 nPosSize
|= PosSizeFlags::Height
;
730 tools::Long nX
= rData
.x();
731 tools::Long nY
= rData
.y();
732 tools::Long nWidth
= rData
.width();
733 tools::Long nHeight
= rData
.height();
734 const SalFrameGeometry aGeom
= pWindow
->mpWindowImpl
->mpFrame
->GetGeometry();
737 if( nX
+ nWidth
> static_cast<tools::Long
>(aGeom
.width()) )
738 nX
= aGeom
.width() - nWidth
;
741 if( nY
+ nHeight
> static_cast<tools::Long
>(aGeom
.height()) )
742 nY
= aGeom
.height() - nHeight
;
743 setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nPosSize
);
746 // tdf#146648 if an explicit size state was set, then use it as the preferred
748 if (nValidMask
& vcl::WindowDataMask::Size
)
749 mbInitialLayoutSizeCalculated
= true;
752 void SystemWindow::GetWindowState(vcl::WindowData
& rData
) const
754 vcl::WindowDataMask nValidMask
= rData
.mask();
755 if ( nValidMask
== vcl::WindowDataMask::NONE
)
760 rData
.setMask( vcl::WindowDataMask::NONE
);
764 const vcl::Window
* pWindow
= this;
765 while ( pWindow
->mpWindowImpl
->mpBorderWindow
)
766 pWindow
= pWindow
->mpWindowImpl
->mpBorderWindow
;
768 if ( pWindow
->mpWindowImpl
->mbFrame
)
770 vcl::WindowData aState
;
771 if ( mpWindowImpl
->mpFrame
->GetWindowState( &aState
) )
773 // Limit mask only to what we've received, the rest is not set.
774 nValidMask
&= aState
.mask();
775 rData
.setMask( nValidMask
);
776 if ( nValidMask
& vcl::WindowDataMask::X
)
777 rData
.setX( aState
.x() );
778 if ( nValidMask
& vcl::WindowDataMask::Y
)
779 rData
.setY( aState
.y() );
780 if ( nValidMask
& vcl::WindowDataMask::Width
)
781 rData
.setWidth( aState
.width() );
782 if ( nValidMask
& vcl::WindowDataMask::Height
)
783 rData
.setHeight( aState
.height() );
784 if ( nValidMask
& vcl::WindowDataMask::MaximizedX
)
785 rData
.SetMaximizedX( aState
.GetMaximizedX() );
786 if ( nValidMask
& vcl::WindowDataMask::MaximizedY
)
787 rData
.SetMaximizedY( aState
.GetMaximizedY() );
788 if ( nValidMask
& vcl::WindowDataMask::MaximizedWidth
)
789 rData
.SetMaximizedWidth( aState
.GetMaximizedWidth() );
790 if ( nValidMask
& vcl::WindowDataMask::MaximizedHeight
)
791 rData
.SetMaximizedHeight( aState
.GetMaximizedHeight() );
792 if ( nValidMask
& vcl::WindowDataMask::State
)
794 // #94144# allow Minimize again, should be masked out when read from configuration
795 // 91625 - ignore Minimize
796 if (!(nValidMask
& vcl::WindowDataMask::Minimized
))
797 aState
.rState() &= ~vcl::WindowState::Minimized
;
798 rData
.setState(aState
.state());
800 rData
.setMask( nValidMask
);
803 rData
.setMask(vcl::WindowDataMask::NONE
);
807 Point aPos
= GetPosPixel();
808 Size aSize
= GetSizePixel();
809 vcl::WindowState nState
= vcl::WindowState::NONE
;
811 nValidMask
&= vcl::WindowDataMask::PosSizeState
;
812 rData
.setMask( nValidMask
);
813 if (nValidMask
& vcl::WindowDataMask::X
)
814 rData
.setX(aPos
.X());
815 if (nValidMask
& vcl::WindowDataMask::Y
)
816 rData
.setY(aPos
.Y());
817 if (nValidMask
& vcl::WindowDataMask::Width
)
818 rData
.setWidth(aSize
.Width());
819 if (nValidMask
& vcl::WindowDataMask::Height
)
820 rData
.setHeight(aSize
.Height());
821 if (nValidMask
& vcl::WindowDataMask::State
)
822 rData
.setState(nState
);
826 void SystemWindow::SetWindowState(std::u16string_view rStr
)
830 SetWindowState(vcl::WindowData(rStr
));
833 OUString
SystemWindow::GetWindowState(vcl::WindowDataMask nMask
) const
835 vcl::WindowData aData
;
836 aData
.setMask(nMask
);
837 GetWindowState(aData
);
838 return aData
.toStr();
841 void SystemWindow::SetMenuBar(MenuBar
* pMenuBar
)
843 if ( mpMenuBar
== pMenuBar
)
846 MenuBar
* pOldMenuBar
= mpMenuBar
;
847 vcl::Window
* pOldWindow
= nullptr;
848 VclPtr
<vcl::Window
> pNewWindow
;
849 mpMenuBar
= pMenuBar
;
851 if ( mpWindowImpl
->mpBorderWindow
&& (mpWindowImpl
->mpBorderWindow
->GetType() == WindowType::BORDERWINDOW
) )
854 pOldWindow
= pOldMenuBar
->ImplGetWindow();
856 pOldWindow
= nullptr;
859 CallEventListeners( VclEventId::WindowMenubarRemoved
, static_cast<void*>(pOldMenuBar
) );
860 pOldWindow
->SetAccessible( css::uno::Reference
< css::accessibility::XAccessible
>() );
864 SAL_WARN_IF( pMenuBar
->pWindow
, "vcl", "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
866 pNewWindow
= MenuBar::ImplCreate(mpWindowImpl
->mpBorderWindow
, pOldWindow
, pMenuBar
);
867 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMenuBarWindow(pNewWindow
);
869 CallEventListeners( VclEventId::WindowMenubarAdded
, static_cast<void*>(pMenuBar
) );
872 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMenuBarWindow( nullptr );
876 bool bDelete
= (pMenuBar
== nullptr);
877 if( bDelete
&& pOldWindow
)
879 if( mpImplData
->mpTaskPaneList
)
880 mpImplData
->mpTaskPaneList
->RemoveWindow( pOldWindow
);
882 MenuBar::ImplDestroy( pOldMenuBar
, bDelete
);
884 pOldWindow
= nullptr; // will be deleted in MenuBar::ImplDestroy,
891 pNewWindow
= pMenuBar
->ImplGetWindow();
893 pOldWindow
= pOldMenuBar
->ImplGetWindow();
896 // update taskpane list to make menubar accessible
897 if( mpImplData
->mpTaskPaneList
)
900 mpImplData
->mpTaskPaneList
->RemoveWindow( pOldWindow
);
902 mpImplData
->mpTaskPaneList
->AddWindow( pNewWindow
);
906 void SystemWindow::SetNotebookBar(const OUString
& rUIXMLDescription
,
907 const css::uno::Reference
<css::frame::XFrame
>& rFrame
,
908 const NotebookBarAddonsItem
& aNotebookBarAddonsItem
,
909 bool bReloadNotebookbar
)
911 if (rUIXMLDescription
!= maNotebookBarUIFile
|| bReloadNotebookbar
)
913 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())
914 ->SetNotebookBar(rUIXMLDescription
, rFrame
, aNotebookBarAddonsItem
);
915 maNotebookBarUIFile
= rUIXMLDescription
;
917 GetNotebookBar()->SetSystemWindow(this);
921 void SystemWindow::CloseNotebookBar()
923 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->CloseNotebookBar();
924 maNotebookBarUIFile
.clear();
927 VclPtr
<NotebookBar
> const & SystemWindow::GetNotebookBar() const
929 return static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->GetNotebookBar();
932 void SystemWindow::SetMenuBarMode( MenuBarMode nMode
)
934 if ( mnMenuBarMode
!= nMode
)
936 mnMenuBarMode
= nMode
;
937 if ( mpWindowImpl
->mpBorderWindow
&& (mpWindowImpl
->mpBorderWindow
->GetType() == WindowType::BORDERWINDOW
) )
939 if ( nMode
== MenuBarMode::Hide
)
940 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMenuBarMode( true );
942 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetMenuBarMode( false );
947 bool SystemWindow::ImplIsInTaskPaneList( vcl::Window
* pWin
)
949 if( mpImplData
&& mpImplData
->mpTaskPaneList
)
950 return mpImplData
->mpTaskPaneList
->IsInList( pWin
);
954 unsigned int SystemWindow::GetScreenNumber() const
956 return mpWindowImpl
->mpFrame
->GetUnmirroredGeometry().screen();
959 void SystemWindow::SetScreenNumber(unsigned int nDisplayScreen
)
961 mpWindowImpl
->mpFrame
->SetScreenNumber( nDisplayScreen
);
964 void SystemWindow::SetApplicationID(const OUString
&rApplicationID
)
966 mpWindowImpl
->mpFrame
->SetApplicationID( rApplicationID
);
969 void SystemWindow::SetCloseHdl(const Link
<SystemWindow
&,void>& rLink
)
971 mpImplData
->maCloseHdl
= rLink
;
974 const Link
<SystemWindow
&,void>& SystemWindow::GetCloseHdl() const
976 return mpImplData
->maCloseHdl
;
979 void SystemWindow::queue_resize(StateChangedType
/*eReason*/)
981 if (!isLayoutEnabled())
983 if (isCalculatingInitialLayoutSize())
985 InvalidateSizeCache();
986 if (hasPendingLayout())
988 maLayoutIdle
.Start();
991 void SystemWindow::Resize()
996 bool SystemWindow::isLayoutEnabled() const
998 //pre dtor called, and single child is a container => we're layout enabled
999 return mpImplData
&& ::isLayoutEnabled(this);
1002 Size
SystemWindow::GetOptimalSize() const
1004 if (!isLayoutEnabled())
1005 return Window::GetOptimalSize();
1007 Window
*pBox
= GetWindow(GetWindowType::FirstChild
);
1008 // tdf#141318 Do the same as SystemWindow::setOptimalLayoutSize in case we're called before initial layout
1009 const_cast<SystemWindow
*>(this)->settingOptimalLayoutSize(pBox
);
1010 Size aSize
= VclContainer::getLayoutRequisition(*pBox
);
1012 sal_Int32 nBorderWidth
= get_border_width();
1014 aSize
.AdjustHeight(2 * nBorderWidth
);
1015 aSize
.AdjustWidth(2 * nBorderWidth
);
1017 return Window::CalcWindowSize(aSize
);
1020 void SystemWindow::setPosSizeOnContainee(Size aSize
, Window
&rBox
)
1022 sal_Int32 nBorderWidth
= get_border_width();
1024 aSize
.AdjustWidth( -(2 * nBorderWidth
) );
1025 aSize
.AdjustHeight( -(2 * nBorderWidth
) );
1027 Point
aPos(nBorderWidth
, nBorderWidth
);
1028 VclContainer::setLayoutAllocation(rBox
, aPos
, CalcOutputSize(aSize
));
1031 IMPL_LINK_NOARG( SystemWindow
, ImplHandleLayoutTimerHdl
, Timer
*, void )
1033 Window
*pBox
= GetWindow(GetWindowType::FirstChild
);
1034 if (!isLayoutEnabled())
1036 SAL_WARN_IF(pBox
, "vcl.layout", "SystemWindow has become non-layout because extra children have been added directly to it.");
1040 setPosSizeOnContainee(GetSizePixel(), *pBox
);
1043 void SystemWindow::SetText(const OUString
& rStr
)
1045 setDeferredProperties();
1046 Window::SetText(rStr
);
1049 OUString
SystemWindow::GetText() const
1051 const_cast<SystemWindow
*>(this)->setDeferredProperties();
1052 return Window::GetText();
1055 void SystemWindow::settingOptimalLayoutSize(Window
* /*pBox*/)
1059 void SystemWindow::setOptimalLayoutSize(bool bAllowWindowShrink
)
1061 maLayoutIdle
.Stop();
1063 //resize SystemWindow to fit requisition on initial show
1064 Window
*pBox
= GetWindow(GetWindowType::FirstChild
);
1066 settingOptimalLayoutSize(pBox
);
1068 Size aSize
= get_preferred_size();
1070 Size
aMax(bestmaxFrameSizeForScreenSize(Size(GetDesktopRectPixel().GetSize())));
1072 aSize
.setWidth( std::min(aMax
.Width(), aSize
.Width()) );
1073 aSize
.setHeight( std::min(aMax
.Height(), aSize
.Height()) );
1075 SetMinOutputSizePixel(aSize
);
1077 if (!bAllowWindowShrink
)
1079 Size aCurrentSize
= GetSizePixel();
1080 aSize
.setWidth(std::max(aSize
.Width(), aCurrentSize
.Width()));
1081 aSize
.setHeight(std::max(aSize
.Height(), aCurrentSize
.Height()));
1084 SetSizePixel(aSize
);
1085 setPosSizeOnContainee(aSize
, *pBox
);
1088 void SystemWindow::DoInitialLayout()
1090 if (GetSettings().GetStyleSettings().GetAutoMnemonic())
1091 GenerateAutoMnemonicsOnHierarchy(this);
1093 if (isLayoutEnabled())
1095 mbIsCalculatingInitialLayoutSize
= true;
1096 setDeferredProperties();
1097 setOptimalLayoutSize(!mbInitialLayoutSizeCalculated
);
1098 mbInitialLayoutSizeCalculated
= true;
1099 mbIsCalculatingInitialLayoutSize
= false;
1103 void SystemWindow::doDeferredInit(WinBits nBits
)
1105 VclPtr
<vcl::Window
> pParent
= mpDialogParent
;
1106 mpDialogParent
.reset();
1107 ImplDeferredInit(pParent
, nBits
);
1108 mbIsDeferredInit
= false;
1111 void SystemWindow::ImplDeferredInit(vcl::Window
* /*pParent*/, WinBits
/*nBits*/)
1113 SAL_WARN("vcl.layout", "SystemWindow in layout without doDeferredInit impl");
1116 VclPtr
<VirtualDevice
> SystemWindow::createScreenshot()
1118 // same prerequisites as in Execute()
1119 setDeferredProperties();
1120 ImplAdjustNWFSizes();
1125 Size
aSize(GetOutputSizePixel());
1127 VclPtr
<VirtualDevice
> xOutput(VclPtr
<VirtualDevice
>::Create(DeviceFormat::WITHOUT_ALPHA
));
1128 xOutput
->SetOutputSizePixel(aSize
);
1131 xOutput
->DrawOutDev(aPos
, aSize
, aPos
, aSize
, *GetOutDev());
1136 void SystemWindow::PrePaint(vcl::RenderContext
& rRenderContext
)
1138 Window::PrePaint(rRenderContext
);
1139 mbPaintComplete
= false;
1142 void SystemWindow::PostPaint(vcl::RenderContext
& rRenderContext
)
1144 Window::PostPaint(rRenderContext
);
1145 mbPaintComplete
= true;
1148 void SystemWindow::ensureRepaint()
1152 mbPaintComplete
= false;
1154 while (!mbPaintComplete
&& !Application::IsQuit())
1156 Application::Yield();
1160 void SystemWindow::CollectMenuBarMnemonics(MnemonicGenerator
& rMnemonicGenerator
) const
1162 if (MenuBar
* pMenu
= GetMenuBar())
1164 sal_uInt16 nMenuItems
= pMenu
->GetItemCount();
1165 for ( sal_uInt16 i
= 0; i
< nMenuItems
; ++i
)
1166 rMnemonicGenerator
.RegisterMnemonic( pMenu
->GetItemText( pMenu
->GetItemId( i
) ) );
1170 int SystemWindow::GetMenuBarHeight() const
1172 if (MenuBar
* pMenuBar
= GetMenuBar())
1173 return pMenuBar
->GetMenuBarHeight();
1177 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */