build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / syswin.cxx
blobf5650b291be861535bcc6b98f3b23b5abe4a1fee
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <cstdlib>
24 #include <tools/debug.hxx>
26 #include <vcl/layout.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/menu.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/syswin.hxx>
32 #include <vcl/taskpanelist.hxx>
33 #include <vcl/unowrap.hxx>
34 #include <vcl/tabctrl.hxx>
35 #include <vcl/tabpage.hxx>
36 #include <vcl/mnemonic.hxx>
38 #include <rtl/strbuf.hxx>
40 #include <salframe.hxx>
41 #include <svdata.hxx>
42 #include <brdwin.hxx>
43 #include <window.h>
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
48 class SystemWindow::ImplData
50 public:
51 ImplData();
53 std::unique_ptr<TaskPaneList>
54 mpTaskPaneList;
55 Size maMaxOutSize;
56 OUString maRepresentedURL;
57 Link<SystemWindow&,void> maCloseHdl;
60 SystemWindow::ImplData::ImplData()
62 mpTaskPaneList = nullptr;
63 maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
66 SystemWindow::SystemWindow(WindowType nType)
67 : Window(nType)
68 , mbPinned(false)
69 , mbRollUp(false)
70 , mbRollFunc(false)
71 , mbDockBtn(false)
72 , mbHideBtn(false)
73 , mbSysChild(false)
74 , mbIsCalculatingInitialLayoutSize(false)
75 , mnMenuBarMode(MenuBarMode::Normal)
76 , mnIcon(0)
77 , mpImplData(new ImplData)
78 , mbIsDefferedInit(false)
80 mpWindowImpl->mbSysWin = true;
81 mpWindowImpl->mnActivateMode = ActivateModeFlags::GrabFocus;
83 //To-Do, reuse maResizeTimer
84 maLayoutIdle.SetPriority(SchedulerPriority::RESIZE);
85 maLayoutIdle.SetIdleHdl( LINK( this, SystemWindow, ImplHandleLayoutTimerHdl ) );
86 maLayoutIdle.SetDebugName( "vcl::SystemWindow maLayoutIdle" );
89 void SystemWindow::loadUI(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription,
90 const css::uno::Reference<css::frame::XFrame> &rFrame)
92 mbIsDefferedInit = true;
93 mpDialogParent = pParent; //should be unset in doDeferredInit
94 m_pUIBuilder.reset( new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame) );
97 SystemWindow::~SystemWindow()
99 disposeOnce();
102 void SystemWindow::dispose()
104 maLayoutIdle.Stop();
105 delete mpImplData;
106 mpImplData = nullptr;
108 // Hack to make sure code called from base ~Window does not interpret this
109 // as a SystemWindow (which it no longer is by then):
110 mpWindowImpl->mbSysWin = false;
111 disposeBuilder();
112 mpDialogParent.clear();
113 mpMenuBar.clear();
114 Window::dispose();
117 void ImplHandleControlAccelerator( vcl::Window* pWindow, bool bShow )
119 Control *pControl = dynamic_cast<Control*>(pWindow->ImplGetWindow());
120 if (pControl && pControl->GetText().indexOf('~') != -1)
122 pControl->SetShowAccelerator( bShow );
123 pControl->Invalidate(InvalidateFlags::Update);
127 namespace
129 void processChildren(vcl::Window *pParent, bool bShowAccel)
131 // go through its children
132 vcl::Window* pChild = firstLogicalChildOfParent(pParent);
133 while (pChild)
135 if (pChild->GetType() == WINDOW_TABCONTROL)
137 // find currently shown tab page
138 TabControl* pTabControl = static_cast<TabControl*>(pChild);
139 TabPage* pTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
140 processChildren(pTabPage, bShowAccel);
142 else if (pChild->GetType() == WINDOW_TABPAGE)
144 // bare tabpage without tabcontrol parent (options dialog)
145 processChildren(pChild, bShowAccel);
147 else if ((pChild->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL)
149 // special controls that manage their children outside of widget layout
150 processChildren(pChild, bShowAccel);
152 else
154 ImplHandleControlAccelerator(pChild, bShowAccel);
156 pChild = nextLogicalChildOfParent(pParent, pChild);
161 bool Accelerator::ToggleMnemonicsOnHierarchy(const CommandEvent& rCEvent, vcl::Window *pWindow)
163 if (rCEvent.GetCommand() == CommandEventId::ModKeyChange && ImplGetSVData()->maNWFData.mbAutoAccel)
165 const CommandModKeyData *pCData = rCEvent.GetModKeyData();
166 const bool bShowAccel = pCData && pCData->IsMod2() && pCData->IsDown();
167 processChildren(pWindow, bShowAccel);
168 return true;
170 return false;
173 bool SystemWindow::EventNotify( NotifyEvent& rNEvt )
175 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
176 Accelerator::ToggleMnemonicsOnHierarchy(*rNEvt.GetCommandEvent(), this);
178 // capture KeyEvents for menu handling
179 if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ||
180 rNEvt.GetType() == MouseNotifyEvent::COMMAND)
182 MenuBar* pMBar = mpMenuBar;
183 if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
185 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
186 if( pWin && pWin->IsSystemWindow() )
187 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
189 bool bDone(false);
190 if (pMBar)
192 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
193 bDone = pMBar->ImplHandleCmdEvent(*rNEvt.GetCommandEvent());
194 else
195 bDone = pMBar->ImplHandleKeyEvent(*rNEvt.GetKeyEvent());
197 if (bDone)
198 return true;
201 return Window::EventNotify( rNEvt );
204 bool SystemWindow::PreNotify( NotifyEvent& rNEvt )
206 // capture KeyEvents for taskpane cycling
207 if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
209 if( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6 &&
210 rNEvt.GetKeyEvent()->GetKeyCode().IsMod1() &&
211 !rNEvt.GetKeyEvent()->GetKeyCode().IsShift() )
213 // Ctrl-F6 goes directly to the document
214 GrabFocusToDocument();
215 return true;
217 else
219 TaskPaneList *pTList = mpImplData->mpTaskPaneList.get();
220 if( !pTList && ( GetType() == WINDOW_FLOATINGWINDOW ) )
222 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
223 if( pWin && pWin->IsSystemWindow() )
224 pTList = static_cast<SystemWindow*>(pWin)->mpImplData->mpTaskPaneList.get();
226 if( !pTList )
228 // search topmost system window which is the one to handle dialog/toolbar cycling
229 SystemWindow *pSysWin = this;
230 vcl::Window *pWin = this;
231 while( pWin )
233 pWin = pWin->GetParent();
234 if( pWin && pWin->IsSystemWindow() )
235 pSysWin = static_cast<SystemWindow*>(pWin);
237 pTList = pSysWin->mpImplData->mpTaskPaneList.get();
239 if( pTList && pTList->HandleKeyEvent( *rNEvt.GetKeyEvent() ) )
240 return true;
243 return Window::PreNotify( rNEvt );
246 TaskPaneList* SystemWindow::GetTaskPaneList()
248 if( !mpImplData )
249 return nullptr;
250 if( mpImplData->mpTaskPaneList )
251 return mpImplData->mpTaskPaneList.get();
252 else
254 mpImplData->mpTaskPaneList.reset( new TaskPaneList );
255 MenuBar* pMBar = mpMenuBar;
256 if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
258 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
259 if ( pWin && pWin->IsSystemWindow() )
260 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
262 if( pMBar )
263 mpImplData->mpTaskPaneList->AddWindow( pMBar->ImplGetWindow() );
264 return mpImplData->mpTaskPaneList.get();
268 bool SystemWindow::Close()
270 VclPtr<vcl::Window> xWindow = this;
271 CallEventListeners( VCLEVENT_WINDOW_CLOSE );
272 if ( xWindow->IsDisposed() )
273 return false;
275 if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
276 return false;
278 // Is Window not closeable, ignore close
279 vcl::Window* pBorderWin = ImplGetBorderWindow();
280 WinBits nStyle;
281 if ( pBorderWin )
282 nStyle = pBorderWin->GetStyle();
283 else
284 nStyle = GetStyle();
285 if ( !(nStyle & WB_CLOSEABLE) )
286 return false;
288 Hide();
290 return true;
293 void SystemWindow::TitleButtonClick( TitleButton )
297 void SystemWindow::Resizing( Size& )
301 void SystemWindow::SetRepresentedURL( const OUString& i_rURL )
303 bool bChanged = (i_rURL != mpImplData->maRepresentedURL);
304 mpImplData->maRepresentedURL = i_rURL;
305 if ( !mbSysChild && bChanged )
307 const vcl::Window* pWindow = this;
308 while ( pWindow->mpWindowImpl->mpBorderWindow )
309 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
311 if ( pWindow->mpWindowImpl->mbFrame )
312 pWindow->mpWindowImpl->mpFrame->SetRepresentedURL( i_rURL );
316 void SystemWindow::SetIcon( sal_uInt16 nIcon )
318 if ( mnIcon == nIcon )
319 return;
321 mnIcon = nIcon;
323 if ( !mbSysChild )
325 const vcl::Window* pWindow = this;
326 while ( pWindow->mpWindowImpl->mpBorderWindow )
327 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
329 if ( pWindow->mpWindowImpl->mbFrame )
330 pWindow->mpWindowImpl->mpFrame->SetIcon( nIcon );
334 void SystemWindow::ShowTitleButton( TitleButton nButton, bool bVisible )
336 if ( nButton == TitleButton::Docking )
338 if ( mbDockBtn != bVisible )
340 mbDockBtn = bVisible;
341 if ( mpWindowImpl->mpBorderWindow )
342 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetDockButton( bVisible );
345 else if ( nButton == TitleButton::Hide )
347 if ( mbHideBtn != bVisible )
349 mbHideBtn = bVisible;
350 if ( mpWindowImpl->mpBorderWindow )
351 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetHideButton( bVisible );
354 else if ( nButton == TitleButton::Menu )
356 if ( mpWindowImpl->mpBorderWindow )
357 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuButton( bVisible );
359 else
360 return;
363 bool SystemWindow::IsTitleButtonVisible( TitleButton nButton ) const
365 if ( nButton == TitleButton::Docking )
366 return mbDockBtn;
367 else /* if ( nButton == TitleButton::Hide ) */
368 return mbHideBtn;
371 void SystemWindow::SetPin( bool bPin )
373 if ( bPin != mbPinned )
375 mbPinned = bPin;
376 if ( mpWindowImpl->mpBorderWindow )
377 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetPin( bPin );
381 void SystemWindow::RollUp()
383 if ( !mbRollUp )
385 maOrgSize = GetOutputSizePixel();
386 mbRollFunc = true;
387 Size aSize = maRollUpOutSize;
388 if ( !aSize.Width() )
389 aSize.Width() = GetOutputSizePixel().Width();
390 mbRollUp = true;
391 if ( mpWindowImpl->mpBorderWindow )
392 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetRollUp( true, aSize );
393 else
394 SetOutputSizePixel( aSize );
395 mbRollFunc = false;
399 void SystemWindow::RollDown()
401 if ( mbRollUp )
403 mbRollUp = false;
404 if ( mpWindowImpl->mpBorderWindow )
405 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetRollUp( false, maOrgSize );
406 else
407 SetOutputSizePixel( maOrgSize );
411 void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
413 maMinOutSize = rSize;
414 if ( mpWindowImpl->mpBorderWindow )
416 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMinOutputSize( rSize.Width(), rSize.Height() );
417 if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
418 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
420 else if ( mpWindowImpl->mbFrame )
421 mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
424 void SystemWindow::SetMaxOutputSizePixel( const Size& rSize )
426 Size aSize( rSize );
427 if( aSize.Width() > SHRT_MAX || aSize.Width() <= 0 )
428 aSize.Width() = SHRT_MAX;
429 if( aSize.Height() > SHRT_MAX || aSize.Height() <= 0 )
430 aSize.Height() = SHRT_MAX;
432 mpImplData->maMaxOutSize = aSize;
433 if ( mpWindowImpl->mpBorderWindow )
435 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMaxOutputSize( aSize.Width(), aSize.Height() );
436 if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
437 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
439 else if ( mpWindowImpl->mbFrame )
440 mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
443 const Size& SystemWindow::GetMaxOutputSizePixel() const
445 return mpImplData->maMaxOutSize;
448 static void ImplWindowStateFromStr(WindowStateData& rData,
449 const OString& rStr)
451 WindowStateMask nValidMask = WindowStateMask::NONE;
452 sal_Int32 nIndex = 0;
453 OString aTokenStr;
455 aTokenStr = rStr.getToken(0, ',', nIndex);
456 if (!aTokenStr.isEmpty())
458 rData.SetX(aTokenStr.toInt32());
459 if( rData.GetX() > -16384 && rData.GetX() < 16384 )
460 nValidMask |= WindowStateMask::X;
461 else
462 rData.SetX( 0 );
464 else
465 rData.SetX( 0 );
466 aTokenStr = rStr.getToken(0, ',', nIndex);
467 if (!aTokenStr.isEmpty())
469 rData.SetY(aTokenStr.toInt32());
470 if( rData.GetY() > -16384 && rData.GetY() < 16384 )
471 nValidMask |= WindowStateMask::Y;
472 else
473 rData.SetY( 0 );
475 else
476 rData.SetY( 0 );
477 aTokenStr = rStr.getToken(0, ',', nIndex);
478 if (!aTokenStr.isEmpty())
480 rData.SetWidth(aTokenStr.toInt32());
481 if( rData.GetWidth() > 0 && rData.GetWidth() < 16384 )
482 nValidMask |= WindowStateMask::Width;
483 else
484 rData.SetWidth( 0 );
486 else
487 rData.SetWidth( 0 );
488 aTokenStr = rStr.getToken(0, ';', nIndex);
489 if (!aTokenStr.isEmpty())
491 rData.SetHeight(aTokenStr.toInt32());
492 if( rData.GetHeight() > 0 && rData.GetHeight() < 16384 )
493 nValidMask |= WindowStateMask::Height;
494 else
495 rData.SetHeight( 0 );
497 else
498 rData.SetHeight( 0 );
499 aTokenStr = rStr.getToken(0, ';', nIndex);
500 if (!aTokenStr.isEmpty())
502 // #94144# allow Minimize again, should be masked out when read from configuration
503 // 91625 - ignore Minimize
504 WindowStateState nState = (WindowStateState)aTokenStr.toInt32();
505 //nState &= ~(WindowStateState::Minimized);
506 rData.SetState( nState );
507 nValidMask |= WindowStateMask::State;
509 else
510 rData.SetState( WindowStateState::NONE );
512 // read maximized pos/size
513 aTokenStr = rStr.getToken(0, ',', nIndex);
514 if (!aTokenStr.isEmpty())
516 rData.SetMaximizedX(aTokenStr.toInt32());
517 if( rData.GetMaximizedX() > -16384 && rData.GetMaximizedX() < 16384 )
518 nValidMask |= WindowStateMask::MaximizedX;
519 else
520 rData.SetMaximizedX( 0 );
522 else
523 rData.SetMaximizedX( 0 );
524 aTokenStr = rStr.getToken(0, ',', nIndex);
525 if (!aTokenStr.isEmpty())
527 rData.SetMaximizedY(aTokenStr.toInt32());
528 if( rData.GetMaximizedY() > -16384 && rData.GetMaximizedY() < 16384 )
529 nValidMask |= WindowStateMask::MaximizedY;
530 else
531 rData.SetMaximizedY( 0 );
533 else
534 rData.SetMaximizedY( 0 );
535 aTokenStr = rStr.getToken(0, ',', nIndex);
536 if (!aTokenStr.isEmpty())
538 rData.SetMaximizedWidth(aTokenStr.toInt32());
539 if( rData.GetMaximizedWidth() > 0 && rData.GetMaximizedWidth() < 16384 )
540 nValidMask |= WindowStateMask::MaximizedWidth;
541 else
542 rData.SetMaximizedWidth( 0 );
544 else
545 rData.SetMaximizedWidth( 0 );
546 aTokenStr = rStr.getToken(0, ';', nIndex);
547 if (!aTokenStr.isEmpty())
549 rData.SetMaximizedHeight(aTokenStr.toInt32());
550 if( rData.GetMaximizedHeight() > 0 && rData.GetMaximizedHeight() < 16384 )
551 nValidMask |= WindowStateMask::MaximizedHeight;
552 else
553 rData.SetMaximizedHeight( 0 );
555 else
556 rData.SetMaximizedHeight( 0 );
558 // mark valid fields
559 rData.SetMask( nValidMask );
562 static OString ImplWindowStateToStr(const WindowStateData& rData)
564 const WindowStateMask nValidMask = rData.GetMask();
565 if ( nValidMask == WindowStateMask::NONE )
566 return OString();
568 OStringBuffer rStrBuf;
570 if ( nValidMask & WindowStateMask::X )
571 rStrBuf.append(static_cast<sal_Int32>(rData.GetX()));
572 rStrBuf.append(',');
573 if ( nValidMask & WindowStateMask::Y )
574 rStrBuf.append(static_cast<sal_Int32>(rData.GetY()));
575 rStrBuf.append(',');
576 if ( nValidMask & WindowStateMask::Width )
577 rStrBuf.append(static_cast<sal_Int32>(rData.GetWidth()));
578 rStrBuf.append(',');
579 if ( nValidMask & WindowStateMask::Height )
580 rStrBuf.append(static_cast<sal_Int32>(rData.GetHeight()));
581 rStrBuf.append( ';' );
582 if ( nValidMask & WindowStateMask::State )
584 // #94144# allow Minimize again, should be masked out when read from configuration
585 // 91625 - ignore Minimize
586 WindowStateState nState = rData.GetState();
587 rStrBuf.append(static_cast<sal_Int32>(nState));
589 rStrBuf.append(';');
590 if ( nValidMask & WindowStateMask::MaximizedX )
591 rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedX()));
592 rStrBuf.append(',');
593 if ( nValidMask & WindowStateMask::MaximizedY )
594 rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedY()));
595 rStrBuf.append( ',' );
596 if ( nValidMask & WindowStateMask::MaximizedWidth )
597 rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedWidth()));
598 rStrBuf.append(',');
599 if ( nValidMask & WindowStateMask::MaximizedHeight )
600 rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedHeight()));
601 rStrBuf.append(';');
603 return rStrBuf.makeStringAndClear();
606 void SystemWindow::ImplMoveToScreen( long& io_rX, long& io_rY, long i_nWidth, long i_nHeight, vcl::Window* i_pConfigureWin )
608 Rectangle aScreenRect;
609 if( !Application::IsUnifiedDisplay() )
610 aScreenRect = Application::GetScreenPosSizePixel( GetScreenNumber() );
611 else
613 aScreenRect = Application::GetScreenPosSizePixel( 0 );
614 for( unsigned int i = 1; i < Application::GetScreenCount(); i++ )
615 aScreenRect.Union( Application::GetScreenPosSizePixel( i ) );
617 // unfortunately most of the time width and height are not really known
618 if( i_nWidth < 1 )
619 i_nWidth = 50;
620 if( i_nHeight < 1 )
621 i_nHeight = 50;
623 // check left border
624 bool bMove = false;
625 if( io_rX + i_nWidth < aScreenRect.Left() )
627 bMove = true;
628 io_rX = aScreenRect.Left();
630 // check right border
631 if( io_rX > aScreenRect.Right() - i_nWidth )
633 bMove = true;
634 io_rX = aScreenRect.Right() - i_nWidth;
636 // check top border
637 if( io_rY + i_nHeight < aScreenRect.Top() )
639 bMove = true;
640 io_rY = aScreenRect.Top();
642 // check bottom border
643 if( io_rY > aScreenRect.Bottom() - i_nHeight )
645 bMove = true;
646 io_rY = aScreenRect.Bottom() - i_nHeight;
648 vcl::Window* pParent = i_pConfigureWin->GetParent();
649 if( bMove && pParent )
651 // calculate absolute screen pos here, since that is what is contained in WindowState
652 Point aParentAbsPos( pParent->OutputToAbsoluteScreenPixel( Point(0,0) ) );
653 Size aParentSizePixel( pParent->GetOutputSizePixel() );
654 Point aPos( (aParentSizePixel.Width() - i_nWidth) / 2,
655 (aParentSizePixel.Height() - i_nHeight) / 2 );
656 io_rX = aParentAbsPos.X() + aPos.X();
657 io_rY = aParentAbsPos.Y() + aPos.Y();
661 void SystemWindow::SetWindowStateData( const WindowStateData& rData )
663 const WindowStateMask nValidMask = rData.GetMask();
664 if ( nValidMask == WindowStateMask::NONE )
665 return;
667 if ( mbSysChild )
668 return;
670 vcl::Window* pWindow = this;
671 while ( pWindow->mpWindowImpl->mpBorderWindow )
672 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
674 if ( pWindow->mpWindowImpl->mbFrame )
676 const WindowStateState nState = rData.GetState();
677 SalFrameState aState;
678 aState.mnMask = rData.GetMask();
679 aState.mnX = rData.GetX();
680 aState.mnY = rData.GetY();
681 aState.mnWidth = rData.GetWidth();
682 aState.mnHeight = rData.GetHeight();
684 if( rData.GetMask() & (WindowStateMask::Width|WindowStateMask::Height) )
686 // #i43799# adjust window state sizes if a minimal output size was set
687 // otherwise the frame and the client might get different sizes
688 if( maMinOutSize.Width() > aState.mnWidth )
689 aState.mnWidth = maMinOutSize.Width();
690 if( maMinOutSize.Height() > aState.mnHeight )
691 aState.mnHeight = maMinOutSize.Height();
694 aState.mnMaximizedX = rData.GetMaximizedX();
695 aState.mnMaximizedY = rData.GetMaximizedY();
696 aState.mnMaximizedWidth = rData.GetMaximizedWidth();
697 aState.mnMaximizedHeight = rData.GetMaximizedHeight();
698 // #94144# allow Minimize again, should be masked out when read from configuration
699 // 91625 - ignore Minimize
700 //nState &= ~(WindowStateState::Minimized);
701 aState.mnState = nState & WindowStateState::SystemMask;
703 // normalize window positions onto screen
704 ImplMoveToScreen( aState.mnX, aState.mnY, aState.mnWidth, aState.mnHeight, pWindow );
705 ImplMoveToScreen( aState.mnMaximizedX, aState.mnMaximizedY, aState.mnMaximizedWidth, aState.mnMaximizedHeight, pWindow );
707 // #96568# avoid having multiple frames at the same screen location
708 // do the check only if not maximized
709 if( !((rData.GetMask() & WindowStateMask::State) && (nState & WindowStateState::Maximized)) )
710 if( rData.GetMask() & (WindowStateMask::Pos|WindowStateMask::Width|WindowStateMask::Height) )
712 Rectangle aDesktop = GetDesktopRectPixel();
713 ImplSVData *pSVData = ImplGetSVData();
714 vcl::Window *pWin = pSVData->maWinData.mpFirstFrame;
715 bool bWrapped = false;
716 while( pWin )
718 if( !pWin->ImplIsRealParentPath( this ) && ( pWin != this ) &&
719 pWin->ImplGetWindow()->IsTopWindow() && pWin->mpWindowImpl->mbReallyVisible )
721 SalFrameGeometry g = pWin->mpWindowImpl->mpFrame->GetGeometry();
722 if( std::abs(g.nX-aState.mnX) < 2 && std::abs(g.nY-aState.mnY) < 5 )
724 long displacement = g.nTopDecoration ? g.nTopDecoration : 20;
725 if( (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.Right() ||
726 (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.Bottom() )
728 // displacing would leave screen
729 aState.mnX = g.nLeftDecoration ? g.nLeftDecoration : 10; // should result in (0,0)
730 aState.mnY = displacement;
731 if( bWrapped ||
732 (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.Right() ||
733 (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.Bottom() )
734 break; // further displacement not possible -> break
735 // avoid endless testing
736 bWrapped = true;
738 else
740 // displace
741 aState.mnX += displacement;
742 aState.mnY += displacement;
744 pWin = pSVData->maWinData.mpFirstFrame; // check new pos again
747 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
751 mpWindowImpl->mpFrame->SetWindowState( &aState );
753 // do a synchronous resize for layout reasons
754 // but use rData only when the window is not to be maximized (#i38089#)
755 // otherwise we have no useful size information
756 if( (rData.GetMask() & WindowStateMask::State) && (nState & WindowStateState::Maximized) )
758 // query maximized size from frame
759 SalFrameGeometry aGeometry = mpWindowImpl->mpFrame->GetGeometry();
761 // but use it only if it is different from the restore size (rData)
762 // as currently only on windows the exact size of a maximized window
763 // can be computed without actually showing the window
764 if( aGeometry.nWidth != rData.GetWidth() || aGeometry.nHeight != rData.GetHeight() )
765 ImplHandleResize( pWindow, aGeometry.nWidth, aGeometry.nHeight );
767 else
768 if( rData.GetMask() & (WindowStateMask::Width|WindowStateMask::Height) )
769 ImplHandleResize( pWindow, aState.mnWidth, aState.mnHeight ); // #i43799# use aState and not rData, see above
771 else
773 PosSizeFlags nPosSize = PosSizeFlags::NONE;
774 if ( nValidMask & WindowStateMask::X )
775 nPosSize |= PosSizeFlags::X;
776 if ( nValidMask & WindowStateMask::Y )
777 nPosSize |= PosSizeFlags::Y;
778 if ( nValidMask & WindowStateMask::Width )
779 nPosSize |= PosSizeFlags::Width;
780 if ( nValidMask & WindowStateMask::Height )
781 nPosSize |= PosSizeFlags::Height;
783 if( IsRollUp() )
784 RollDown();
786 long nX = rData.GetX();
787 long nY = rData.GetY();
788 long nWidth = rData.GetWidth();
789 long nHeight = rData.GetHeight();
790 const SalFrameGeometry& rGeom = pWindow->mpWindowImpl->mpFrame->GetGeometry();
791 if( nX < 0 )
792 nX = 0;
793 if( nX + nWidth > (long) rGeom.nWidth )
794 nX = rGeom.nWidth - nWidth;
795 if( nY < 0 )
796 nY = 0;
797 if( nY + nHeight > (long) rGeom.nHeight )
798 nY = rGeom.nHeight - nHeight;
799 setPosSizePixel( nX, nY, nWidth, nHeight, nPosSize );
800 maOrgSize = Size( nWidth, nHeight );
802 // 91625 - ignore Minimize
803 if ( nValidMask & WindowStateMask::State )
805 const WindowStateState nState = rData.GetState();
806 if ( nState & WindowStateState::Rollup )
807 RollUp();
808 else
809 RollDown();
814 void SystemWindow::GetWindowStateData( WindowStateData& rData ) const
816 WindowStateMask nValidMask = rData.GetMask();
817 if ( nValidMask == WindowStateMask::NONE )
818 return;
820 if ( mbSysChild )
821 return;
823 const vcl::Window* pWindow = this;
824 while ( pWindow->mpWindowImpl->mpBorderWindow )
825 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
827 if ( pWindow->mpWindowImpl->mbFrame )
829 SalFrameState aState;
830 aState.mnMask = WindowStateMask::All;
831 if ( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
833 if ( nValidMask & WindowStateMask::X )
834 rData.SetX( aState.mnX );
835 if ( nValidMask & WindowStateMask::Y )
836 rData.SetY( aState.mnY );
837 if ( nValidMask & WindowStateMask::Width )
838 rData.SetWidth( aState.mnWidth );
839 if ( nValidMask & WindowStateMask::Height )
840 rData.SetHeight( aState.mnHeight );
841 if ( aState.mnMask & WindowStateMask::MaximizedX )
843 rData.SetMaximizedX( aState.mnMaximizedX );
844 nValidMask |= WindowStateMask::MaximizedX;
846 if ( aState.mnMask & WindowStateMask::MaximizedY )
848 rData.SetMaximizedY( aState.mnMaximizedY );
849 nValidMask |= WindowStateMask::MaximizedY;
851 if ( aState.mnMask & WindowStateMask::MaximizedWidth )
853 rData.SetMaximizedWidth( aState.mnMaximizedWidth );
854 nValidMask |= WindowStateMask::MaximizedWidth;
856 if ( aState.mnMask & WindowStateMask::MaximizedHeight )
858 rData.SetMaximizedHeight( aState.mnMaximizedHeight );
859 nValidMask |= WindowStateMask::MaximizedHeight;
861 if ( nValidMask & WindowStateMask::State )
863 // #94144# allow Minimize again, should be masked out when read from configuration
864 // 91625 - ignore Minimize
865 if ( !(nValidMask&WindowStateMask::Minimized) )
866 aState.mnState &= ~(WindowStateState::Minimized);
867 rData.SetState( aState.mnState );
869 rData.SetMask( nValidMask );
871 else
872 rData.SetMask( WindowStateMask::NONE );
874 else
876 Point aPos = GetPosPixel();
877 Size aSize = GetSizePixel();
878 WindowStateState nState = WindowStateState::NONE;
880 if ( IsRollUp() )
882 aSize.Height() += maOrgSize.Height();
883 nState = WindowStateState::Rollup;
886 if ( nValidMask & WindowStateMask::X )
887 rData.SetX( aPos.X() );
888 if ( nValidMask & WindowStateMask::Y )
889 rData.SetY( aPos.Y() );
890 if ( nValidMask & WindowStateMask::Width )
891 rData.SetWidth( aSize.Width() );
892 if ( nValidMask & WindowStateMask::Height )
893 rData.SetHeight( aSize.Height() );
894 if ( nValidMask & WindowStateMask::State )
895 rData.SetState( nState );
899 void SystemWindow::SetWindowState(const OString& rStr)
901 if (rStr.isEmpty())
902 return;
904 WindowStateData aData;
905 ImplWindowStateFromStr( aData, rStr );
906 SetWindowStateData( aData );
909 OString SystemWindow::GetWindowState( WindowStateMask nMask ) const
911 WindowStateData aData;
912 aData.SetMask( nMask );
913 GetWindowStateData( aData );
915 return ImplWindowStateToStr(aData);
918 void SystemWindow::SetMenuBar(MenuBar* pMenuBar)
920 if ( mpMenuBar != pMenuBar )
922 MenuBar* pOldMenuBar = mpMenuBar;
923 vcl::Window* pOldWindow = nullptr;
924 VclPtr<vcl::Window> pNewWindow;
925 mpMenuBar = pMenuBar;
927 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
929 if ( pOldMenuBar )
930 pOldWindow = pOldMenuBar->ImplGetWindow();
931 else
932 pOldWindow = nullptr;
933 if ( pOldWindow )
935 CallEventListeners( VCLEVENT_WINDOW_MENUBARREMOVED, static_cast<void*>(pOldMenuBar) );
936 pOldWindow->SetAccessible( css::uno::Reference< css::accessibility::XAccessible >() );
938 if ( pMenuBar )
940 SAL_WARN_IF( pMenuBar->pWindow, "vcl", "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
942 pNewWindow = MenuBar::ImplCreate(mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar);
943 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow(pNewWindow);
945 CallEventListeners( VCLEVENT_WINDOW_MENUBARADDED, static_cast<void*>(pMenuBar) );
947 else
948 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow( nullptr );
949 ImplToBottomChild();
950 if ( pOldMenuBar )
952 bool bDelete = (pMenuBar == nullptr);
953 if( bDelete && pOldWindow )
955 if( mpImplData->mpTaskPaneList )
956 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
958 MenuBar::ImplDestroy( pOldMenuBar, bDelete );
959 if( bDelete )
960 pOldWindow = nullptr; // will be deleted in MenuBar::ImplDestroy,
964 else
966 if( pMenuBar )
967 pNewWindow = pMenuBar->ImplGetWindow();
968 if( pOldMenuBar )
969 pOldWindow = pOldMenuBar->ImplGetWindow();
972 // update taskpane list to make menubar accessible
973 if( mpImplData->mpTaskPaneList )
975 if( pOldWindow )
976 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
977 if( pNewWindow )
978 mpImplData->mpTaskPaneList->AddWindow( pNewWindow );
983 void SystemWindow::SetNotebookBar(const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame>& rFrame)
985 if (rUIXMLDescription != maNotebookBarUIFile)
987 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetNotebookBar(rUIXMLDescription, rFrame);
988 maNotebookBarUIFile = rUIXMLDescription;
992 void SystemWindow::CloseNotebookBar()
994 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CloseNotebookBar();
995 maNotebookBarUIFile.clear();
998 VclPtr<NotebookBar> SystemWindow::GetNotebookBar() const
1000 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetNotebookBar();
1003 void SystemWindow::SetMenuBarMode( MenuBarMode nMode )
1005 if ( mnMenuBarMode != nMode )
1007 mnMenuBarMode = nMode;
1008 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
1010 if ( nMode == MenuBarMode::Hide )
1011 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarMode( true );
1012 else
1013 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarMode( false );
1018 bool SystemWindow::ImplIsInTaskPaneList( vcl::Window* pWin )
1020 if( mpImplData && mpImplData->mpTaskPaneList )
1021 return mpImplData->mpTaskPaneList->IsInList( pWin );
1022 return false;
1025 unsigned int SystemWindow::GetScreenNumber() const
1027 return mpWindowImpl->mpFrame->maGeometry.nDisplayScreenNumber;
1030 void SystemWindow::SetScreenNumber(unsigned int nDisplayScreen)
1032 mpWindowImpl->mpFrame->SetScreenNumber( nDisplayScreen );
1035 void SystemWindow::SetApplicationID(const OUString &rApplicationID)
1037 mpWindowImpl->mpFrame->SetApplicationID( rApplicationID );
1040 void SystemWindow::SetCloseHdl(const Link<SystemWindow&,void>& rLink)
1042 mpImplData->maCloseHdl = rLink;
1045 const Link<SystemWindow&,void>& SystemWindow::GetCloseHdl() const
1047 return mpImplData->maCloseHdl;
1050 void SystemWindow::queue_resize(StateChangedType /*eReason*/)
1052 if (!isLayoutEnabled())
1053 return;
1054 if (isCalculatingInitialLayoutSize())
1055 return;
1056 InvalidateSizeCache();
1057 if (hasPendingLayout())
1058 return;
1059 maLayoutIdle.Start();
1062 void SystemWindow::Resize()
1064 queue_resize();
1067 bool SystemWindow::isLayoutEnabled() const
1069 //pre dtor called, and single child is a container => we're layout enabled
1070 return mpImplData && ::isLayoutEnabled(this);
1073 Size SystemWindow::GetOptimalSize() const
1075 if (!isLayoutEnabled())
1076 return Window::GetOptimalSize();
1078 Size aSize = VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
1080 sal_Int32 nBorderWidth = get_border_width();
1082 aSize.Height() += 2 * nBorderWidth;
1083 aSize.Width() += 2 * nBorderWidth;
1085 return Window::CalcWindowSize(aSize);
1088 void SystemWindow::setPosSizeOnContainee(Size aSize, Window &rBox)
1090 sal_Int32 nBorderWidth = get_border_width();
1092 aSize.Width() -= 2 * nBorderWidth;
1093 aSize.Height() -= 2 * nBorderWidth;
1095 Point aPos(nBorderWidth, nBorderWidth);
1096 VclContainer::setLayoutAllocation(rBox, aPos, CalcOutputSize(aSize));
1099 IMPL_LINK_NOARG( SystemWindow, ImplHandleLayoutTimerHdl, Idle*, void )
1101 if (!isLayoutEnabled())
1103 SAL_WARN("vcl.layout", "SystemWindow has become non-layout because extra children have been added directly to it.");
1104 return;
1107 Window *pBox = GetWindow(GetWindowType::FirstChild);
1108 assert(pBox);
1109 setPosSizeOnContainee(GetSizePixel(), *pBox);
1112 void SystemWindow::SetText(const OUString& rStr)
1114 setDeferredProperties();
1115 Window::SetText(rStr);
1118 OUString SystemWindow::GetText() const
1120 const_cast<SystemWindow*>(this)->setDeferredProperties();
1121 return Window::GetText();
1124 void SystemWindow::settingOptimalLayoutSize(Window* /*pBox*/)
1128 void SystemWindow::setOptimalLayoutSize()
1130 maLayoutIdle.Stop();
1132 //resize SystemWindow to fit requisition on initial show
1133 Window *pBox = GetWindow(GetWindowType::FirstChild);
1135 settingOptimalLayoutSize(pBox);
1137 Size aSize = get_preferred_size();
1139 Size aMax(bestmaxFrameSizeForScreenSize(GetDesktopRectPixel().GetSize()));
1141 aSize.Width() = std::min(aMax.Width(), aSize.Width());
1142 aSize.Height() = std::min(aMax.Height(), aSize.Height());
1144 SetMinOutputSizePixel(aSize);
1145 SetSizePixel(aSize);
1146 setPosSizeOnContainee(aSize, *pBox);
1149 void SystemWindow::DoInitialLayout()
1151 if (GetSettings().GetStyleSettings().GetAutoMnemonic())
1152 Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
1154 if (isLayoutEnabled())
1156 mbIsCalculatingInitialLayoutSize = true;
1157 setDeferredProperties();
1158 setOptimalLayoutSize();
1159 mbIsCalculatingInitialLayoutSize = false;
1163 void SystemWindow::doDeferredInit(WinBits /*nBits*/)
1165 SAL_WARN("vcl.layout", "SystemWindow in layout without doDeferredInit impl");
1168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */