bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / syswin.cxx
blobce463c6b55515a01aa934f654d61a96e4800e77e
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 <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
24 #include <vcl/accel.hxx>
25 #include <vcl/layout.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/menu.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/syswin.hxx>
31 #include <vcl/taskpanelist.hxx>
32 #include <vcl/tabctrl.hxx>
33 #include <vcl/tabpage.hxx>
34 #include <vcl/virdev.hxx>
36 #include <rtl/strbuf.hxx>
38 #include <salframe.hxx>
39 #include <svdata.hxx>
40 #include <brdwin.hxx>
41 #include <window.h>
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::lang;
46 class SystemWindow::ImplData
48 public:
49 ImplData();
51 std::unique_ptr<TaskPaneList>
52 mpTaskPaneList;
53 Size maMaxOutSize;
54 OUString maRepresentedURL;
55 Link<SystemWindow&,void> maCloseHdl;
58 SystemWindow::ImplData::ImplData()
60 mpTaskPaneList = nullptr;
61 maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
64 SystemWindow::SystemWindow(WindowType nType)
65 : Window(nType)
66 , mbRollUp(false)
67 , mbDockBtn(false)
68 , mbHideBtn(false)
69 , mbSysChild(false)
70 , mbIsCalculatingInitialLayoutSize(false)
71 , mbPaintComplete(false)
72 , mnMenuBarMode(MenuBarMode::Normal)
73 , mnIcon(0)
74 , mpImplData(new ImplData)
75 , mbIsDeferredInit(false)
77 mpWindowImpl->mbSysWin = true;
78 mpWindowImpl->mnActivateMode = ActivateModeFlags::GrabFocus;
80 //To-Do, reuse maResizeTimer
81 maLayoutIdle.SetPriority(TaskPriority::RESIZE);
82 maLayoutIdle.SetInvokeHandler( LINK( this, SystemWindow, ImplHandleLayoutTimerHdl ) );
83 maLayoutIdle.SetDebugName( "vcl::SystemWindow maLayoutIdle" );
86 void SystemWindow::loadUI(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription,
87 const css::uno::Reference<css::frame::XFrame> &rFrame)
89 mbIsDeferredInit = true;
90 mpDialogParent = pParent; //should be unset in doDeferredInit
91 m_pUIBuilder.reset( new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame) );
94 SystemWindow::~SystemWindow()
96 disposeOnce();
99 void SystemWindow::dispose()
101 maLayoutIdle.Stop();
102 mpImplData.reset();
104 // Hack to make sure code called from base ~Window does not interpret this
105 // as a SystemWindow (which it no longer is by then):
106 mpWindowImpl->mbSysWin = false;
107 disposeBuilder();
108 mpDialogParent.clear();
109 mpMenuBar.clear();
110 Window::dispose();
113 static void ImplHandleControlAccelerator( const vcl::Window* pWindow, bool bShow )
115 Control *pControl = dynamic_cast<Control*>(pWindow->ImplGetWindow());
116 if (pControl && pControl->GetText().indexOf('~') != -1)
118 pControl->SetShowAccelerator( bShow );
119 pControl->Invalidate(InvalidateFlags::Update);
123 namespace
125 void processChildren(const vcl::Window *pParent, bool bShowAccel)
127 // go through its children
128 vcl::Window* pChild = firstLogicalChildOfParent(pParent);
129 while (pChild)
131 if (pChild->GetType() == WindowType::TABCONTROL)
133 // find currently shown tab page
134 TabControl* pTabControl = static_cast<TabControl*>(pChild);
135 TabPage* pTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
136 processChildren(pTabPage, bShowAccel);
138 else if (pChild->GetType() == WindowType::TABPAGE)
140 // bare tabpage without tabcontrol parent (options dialog)
141 processChildren(pChild, bShowAccel);
143 else if ((pChild->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL)
145 // special controls that manage their children outside of widget layout
146 processChildren(pChild, bShowAccel);
148 else
150 ImplHandleControlAccelerator(pChild, bShowAccel);
152 pChild = nextLogicalChildOfParent(pParent, pChild);
157 bool Accelerator::ToggleMnemonicsOnHierarchy(const CommandEvent& rCEvent, const vcl::Window *pWindow)
159 if (rCEvent.GetCommand() == CommandEventId::ModKeyChange && ImplGetSVData()->maNWFData.mbAutoAccel)
161 const CommandModKeyData *pCData = rCEvent.GetModKeyData();
162 const bool bShowAccel = pCData && pCData->IsMod2() && pCData->IsDown();
163 processChildren(pWindow, bShowAccel);
164 return true;
166 return false;
169 bool SystemWindow::EventNotify( NotifyEvent& rNEvt )
171 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
172 Accelerator::ToggleMnemonicsOnHierarchy(*rNEvt.GetCommandEvent(), this);
174 // capture KeyEvents for menu handling
175 if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ||
176 rNEvt.GetType() == MouseNotifyEvent::COMMAND)
178 MenuBar* pMBar = mpMenuBar;
179 if ( !pMBar && ( GetType() == WindowType::FLOATINGWINDOW ) )
181 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
182 if( pWin && pWin->IsSystemWindow() )
183 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
185 bool bDone(false);
186 if (pMBar)
188 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
189 bDone = pMBar->ImplHandleCmdEvent(*rNEvt.GetCommandEvent());
190 else
191 bDone = pMBar->ImplHandleKeyEvent(*rNEvt.GetKeyEvent());
193 if (bDone)
194 return true;
197 return Window::EventNotify( rNEvt );
200 bool SystemWindow::PreNotify( NotifyEvent& rNEvt )
202 // capture KeyEvents for taskpane cycling
203 if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
205 if( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6 &&
206 rNEvt.GetKeyEvent()->GetKeyCode().IsMod1() &&
207 !rNEvt.GetKeyEvent()->GetKeyCode().IsShift() )
209 // Ctrl-F6 goes directly to the document
210 GrabFocusToDocument();
211 return true;
213 else
215 TaskPaneList *pTList = mpImplData->mpTaskPaneList.get();
216 if( !pTList && ( GetType() == WindowType::FLOATINGWINDOW ) )
218 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
219 if( pWin && pWin->IsSystemWindow() )
220 pTList = static_cast<SystemWindow*>(pWin)->mpImplData->mpTaskPaneList.get();
222 if( !pTList )
224 // search topmost system window which is the one to handle dialog/toolbar cycling
225 SystemWindow *pSysWin = this;
226 vcl::Window *pWin = this;
227 while( pWin )
229 pWin = pWin->GetParent();
230 if( pWin && pWin->IsSystemWindow() )
231 pSysWin = static_cast<SystemWindow*>(pWin);
233 pTList = pSysWin->mpImplData->mpTaskPaneList.get();
235 if( pTList && pTList->HandleKeyEvent( *rNEvt.GetKeyEvent() ) )
236 return true;
239 return Window::PreNotify( rNEvt );
242 TaskPaneList* SystemWindow::GetTaskPaneList()
244 if( !mpImplData )
245 return nullptr;
246 if( mpImplData->mpTaskPaneList )
247 return mpImplData->mpTaskPaneList.get();
248 else
250 mpImplData->mpTaskPaneList.reset( new TaskPaneList );
251 MenuBar* pMBar = mpMenuBar;
252 if ( !pMBar && ( GetType() == WindowType::FLOATINGWINDOW ) )
254 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
255 if ( pWin && pWin->IsSystemWindow() )
256 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
258 if( pMBar )
259 mpImplData->mpTaskPaneList->AddWindow( pMBar->ImplGetWindow() );
260 return mpImplData->mpTaskPaneList.get();
264 bool SystemWindow::Close()
266 VclPtr<vcl::Window> xWindow = this;
267 CallEventListeners( VclEventId::WindowClose );
268 if ( xWindow->IsDisposed() )
269 return false;
271 if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
272 return false;
274 // Is Window not closeable, ignore close
275 vcl::Window* pBorderWin = ImplGetBorderWindow();
276 WinBits nStyle;
277 if ( pBorderWin )
278 nStyle = pBorderWin->GetStyle();
279 else
280 nStyle = GetStyle();
281 if ( !(nStyle & WB_CLOSEABLE) )
282 return false;
284 Hide();
286 return true;
289 void SystemWindow::TitleButtonClick( TitleButton )
293 void SystemWindow::Resizing( Size& )
297 void SystemWindow::SetRepresentedURL( const OUString& i_rURL )
299 bool bChanged = (i_rURL != mpImplData->maRepresentedURL);
300 mpImplData->maRepresentedURL = i_rURL;
301 if ( !mbSysChild && bChanged )
303 const vcl::Window* pWindow = this;
304 while ( pWindow->mpWindowImpl->mpBorderWindow )
305 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
307 if ( pWindow->mpWindowImpl->mbFrame )
308 pWindow->mpWindowImpl->mpFrame->SetRepresentedURL( i_rURL );
312 void SystemWindow::SetIcon( sal_uInt16 nIcon )
314 if ( mnIcon == nIcon )
315 return;
317 mnIcon = nIcon;
319 if ( !mbSysChild )
321 const vcl::Window* pWindow = this;
322 while ( pWindow->mpWindowImpl->mpBorderWindow )
323 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
325 if ( pWindow->mpWindowImpl->mbFrame )
326 pWindow->mpWindowImpl->mpFrame->SetIcon( nIcon );
330 void SystemWindow::ShowTitleButton( TitleButton nButton, bool bVisible )
332 if ( nButton == TitleButton::Docking )
334 if ( mbDockBtn != bVisible )
336 mbDockBtn = bVisible;
337 if ( mpWindowImpl->mpBorderWindow )
338 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetDockButton( bVisible );
341 else if ( nButton == TitleButton::Hide )
343 if ( mbHideBtn != bVisible )
345 mbHideBtn = bVisible;
346 if ( mpWindowImpl->mpBorderWindow )
347 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetHideButton( bVisible );
350 else if ( nButton == TitleButton::Menu )
352 if ( mpWindowImpl->mpBorderWindow )
353 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuButton( bVisible );
355 else
356 return;
359 bool SystemWindow::IsTitleButtonVisible( TitleButton nButton ) const
361 if ( nButton == TitleButton::Docking )
362 return mbDockBtn;
363 else /* if ( nButton == TitleButton::Hide ) */
364 return mbHideBtn;
367 void SystemWindow::RollUp()
369 if ( !mbRollUp )
371 maOrgSize = GetOutputSizePixel();
372 Size aSize = maRollUpOutSize;
373 if ( !aSize.Width() )
374 aSize.setWidth( GetOutputSizePixel().Width() );
375 mbRollUp = true;
376 if ( mpWindowImpl->mpBorderWindow )
377 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetRollUp( true, aSize );
378 else
379 SetOutputSizePixel( aSize );
383 void SystemWindow::RollDown()
385 if ( mbRollUp )
387 mbRollUp = false;
388 if ( mpWindowImpl->mpBorderWindow )
389 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetRollUp( false, maOrgSize );
390 else
391 SetOutputSizePixel( maOrgSize );
395 void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
397 maMinOutSize = rSize;
398 if ( mpWindowImpl->mpBorderWindow )
400 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMinOutputSize( rSize.Width(), rSize.Height() );
401 if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
402 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
404 else if ( mpWindowImpl->mbFrame )
405 mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
408 void SystemWindow::SetMaxOutputSizePixel( const Size& rSize )
410 Size aSize( rSize );
411 if( aSize.Width() > SHRT_MAX || aSize.Width() <= 0 )
412 aSize.setWidth( SHRT_MAX );
413 if( aSize.Height() > SHRT_MAX || aSize.Height() <= 0 )
414 aSize.setHeight( SHRT_MAX );
416 mpImplData->maMaxOutSize = aSize;
417 if ( mpWindowImpl->mpBorderWindow )
419 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMaxOutputSize( aSize.Width(), aSize.Height() );
420 if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
421 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
423 else if ( mpWindowImpl->mbFrame )
424 mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
427 const Size& SystemWindow::GetMaxOutputSizePixel() const
429 return mpImplData->maMaxOutSize;
432 void ImplWindowStateFromStr(WindowStateData& rData,
433 const OString& rStr)
435 WindowStateMask nValidMask = WindowStateMask::NONE;
436 sal_Int32 nIndex = 0;
438 OString aTokenStr = rStr.getToken(0, ',', nIndex);
439 if (!aTokenStr.isEmpty())
441 rData.SetX(aTokenStr.toInt32());
442 if( rData.GetX() > -16384 && rData.GetX() < 16384 )
443 nValidMask |= WindowStateMask::X;
444 else
445 rData.SetX( 0 );
447 else
448 rData.SetX( 0 );
449 aTokenStr = rStr.getToken(0, ',', nIndex);
450 if (!aTokenStr.isEmpty())
452 rData.SetY(aTokenStr.toInt32());
453 if( rData.GetY() > -16384 && rData.GetY() < 16384 )
454 nValidMask |= WindowStateMask::Y;
455 else
456 rData.SetY( 0 );
458 else
459 rData.SetY( 0 );
460 aTokenStr = rStr.getToken(0, ',', nIndex);
461 if (!aTokenStr.isEmpty())
463 rData.SetWidth(aTokenStr.toInt32());
464 if( rData.GetWidth() > 0 && rData.GetWidth() < 16384 )
465 nValidMask |= WindowStateMask::Width;
466 else
467 rData.SetWidth( 0 );
469 else
470 rData.SetWidth( 0 );
471 aTokenStr = rStr.getToken(0, ';', nIndex);
472 if (!aTokenStr.isEmpty())
474 rData.SetHeight(aTokenStr.toInt32());
475 if( rData.GetHeight() > 0 && rData.GetHeight() < 16384 )
476 nValidMask |= WindowStateMask::Height;
477 else
478 rData.SetHeight( 0 );
480 else
481 rData.SetHeight( 0 );
482 aTokenStr = rStr.getToken(0, ';', nIndex);
483 if (!aTokenStr.isEmpty())
485 // #94144# allow Minimize again, should be masked out when read from configuration
486 // 91625 - ignore Minimize
487 WindowStateState nState = static_cast<WindowStateState>(aTokenStr.toInt32());
488 //nState &= ~(WindowStateState::Minimized);
489 rData.SetState( nState );
490 nValidMask |= WindowStateMask::State;
492 else
493 rData.SetState( WindowStateState::NONE );
495 // read maximized pos/size
496 aTokenStr = rStr.getToken(0, ',', nIndex);
497 if (!aTokenStr.isEmpty())
499 rData.SetMaximizedX(aTokenStr.toInt32());
500 if( rData.GetMaximizedX() > -16384 && rData.GetMaximizedX() < 16384 )
501 nValidMask |= WindowStateMask::MaximizedX;
502 else
503 rData.SetMaximizedX( 0 );
505 else
506 rData.SetMaximizedX( 0 );
507 aTokenStr = rStr.getToken(0, ',', nIndex);
508 if (!aTokenStr.isEmpty())
510 rData.SetMaximizedY(aTokenStr.toInt32());
511 if( rData.GetMaximizedY() > -16384 && rData.GetMaximizedY() < 16384 )
512 nValidMask |= WindowStateMask::MaximizedY;
513 else
514 rData.SetMaximizedY( 0 );
516 else
517 rData.SetMaximizedY( 0 );
518 aTokenStr = rStr.getToken(0, ',', nIndex);
519 if (!aTokenStr.isEmpty())
521 rData.SetMaximizedWidth(aTokenStr.toInt32());
522 if( rData.GetMaximizedWidth() > 0 && rData.GetMaximizedWidth() < 16384 )
523 nValidMask |= WindowStateMask::MaximizedWidth;
524 else
525 rData.SetMaximizedWidth( 0 );
527 else
528 rData.SetMaximizedWidth( 0 );
529 aTokenStr = rStr.getToken(0, ';', nIndex);
530 if (!aTokenStr.isEmpty())
532 rData.SetMaximizedHeight(aTokenStr.toInt32());
533 if( rData.GetMaximizedHeight() > 0 && rData.GetMaximizedHeight() < 16384 )
534 nValidMask |= WindowStateMask::MaximizedHeight;
535 else
536 rData.SetMaximizedHeight( 0 );
538 else
539 rData.SetMaximizedHeight( 0 );
541 // mark valid fields
542 rData.SetMask( nValidMask );
545 OString WindowStateData::ToStr() const
547 const WindowStateMask nValidMask = GetMask();
548 if ( nValidMask == WindowStateMask::NONE )
549 return OString();
551 OStringBuffer rStrBuf(64);
553 if ( nValidMask & WindowStateMask::X )
554 rStrBuf.append(static_cast<sal_Int32>(GetX()));
555 rStrBuf.append(',');
556 if ( nValidMask & WindowStateMask::Y )
557 rStrBuf.append(static_cast<sal_Int32>(GetY()));
558 rStrBuf.append(',');
559 if ( nValidMask & WindowStateMask::Width )
560 rStrBuf.append(static_cast<sal_Int32>(GetWidth()));
561 rStrBuf.append(',');
562 if ( nValidMask & WindowStateMask::Height )
563 rStrBuf.append(static_cast<sal_Int32>(GetHeight()));
564 rStrBuf.append( ';' );
565 if ( nValidMask & WindowStateMask::State )
567 // #94144# allow Minimize again, should be masked out when read from configuration
568 // 91625 - ignore Minimize
569 WindowStateState nState = GetState();
570 rStrBuf.append(static_cast<sal_Int32>(nState));
572 rStrBuf.append(';');
573 if ( nValidMask & WindowStateMask::MaximizedX )
574 rStrBuf.append(static_cast<sal_Int32>(GetMaximizedX()));
575 rStrBuf.append(',');
576 if ( nValidMask & WindowStateMask::MaximizedY )
577 rStrBuf.append(static_cast<sal_Int32>(GetMaximizedY()));
578 rStrBuf.append( ',' );
579 if ( nValidMask & WindowStateMask::MaximizedWidth )
580 rStrBuf.append(static_cast<sal_Int32>(GetMaximizedWidth()));
581 rStrBuf.append(',');
582 if ( nValidMask & WindowStateMask::MaximizedHeight )
583 rStrBuf.append(static_cast<sal_Int32>(GetMaximizedHeight()));
584 rStrBuf.append(';');
586 return rStrBuf.makeStringAndClear();
589 void SystemWindow::ImplMoveToScreen( long& io_rX, long& io_rY, long i_nWidth, long i_nHeight, vcl::Window const * i_pConfigureWin )
591 tools::Rectangle aScreenRect;
592 if( !Application::IsUnifiedDisplay() )
593 aScreenRect = Application::GetScreenPosSizePixel( GetScreenNumber() );
594 else
596 aScreenRect = Application::GetScreenPosSizePixel( 0 );
597 for( unsigned int i = 1; i < Application::GetScreenCount(); i++ )
598 aScreenRect.Union( Application::GetScreenPosSizePixel( i ) );
600 // unfortunately most of the time width and height are not really known
601 if( i_nWidth < 1 )
602 i_nWidth = 50;
603 if( i_nHeight < 1 )
604 i_nHeight = 50;
606 // check left border
607 bool bMove = false;
608 if( io_rX + i_nWidth < aScreenRect.Left() )
610 bMove = true;
611 io_rX = aScreenRect.Left();
613 // check right border
614 if( io_rX > aScreenRect.Right() - i_nWidth )
616 bMove = true;
617 io_rX = aScreenRect.Right() - i_nWidth;
619 // check top border
620 if( io_rY + i_nHeight < aScreenRect.Top() )
622 bMove = true;
623 io_rY = aScreenRect.Top();
625 // check bottom border
626 if( io_rY > aScreenRect.Bottom() - i_nHeight )
628 bMove = true;
629 io_rY = aScreenRect.Bottom() - i_nHeight;
631 vcl::Window* pParent = i_pConfigureWin->GetParent();
632 if( bMove && pParent )
634 // calculate absolute screen pos here, since that is what is contained in WindowState
635 Point aParentAbsPos( pParent->OutputToAbsoluteScreenPixel( Point(0,0) ) );
636 Size aParentSizePixel( pParent->GetOutputSizePixel() );
637 Point aPos( (aParentSizePixel.Width() - i_nWidth) / 2,
638 (aParentSizePixel.Height() - i_nHeight) / 2 );
639 io_rX = aParentAbsPos.X() + aPos.X();
640 io_rY = aParentAbsPos.Y() + aPos.Y();
644 void SystemWindow::SetWindowStateData( const WindowStateData& rData )
646 const WindowStateMask nValidMask = rData.GetMask();
647 if ( nValidMask == WindowStateMask::NONE )
648 return;
650 if ( mbSysChild )
651 return;
653 vcl::Window* pWindow = this;
654 while ( pWindow->mpWindowImpl->mpBorderWindow )
655 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
657 if ( pWindow->mpWindowImpl->mbFrame )
659 const WindowStateState nState = rData.GetState();
660 SalFrameState aState;
661 aState.mnMask = rData.GetMask();
662 aState.mnX = rData.GetX();
663 aState.mnY = rData.GetY();
664 aState.mnWidth = rData.GetWidth();
665 aState.mnHeight = rData.GetHeight();
667 if( rData.GetMask() & (WindowStateMask::Width|WindowStateMask::Height) )
669 // #i43799# adjust window state sizes if a minimal output size was set
670 // otherwise the frame and the client might get different sizes
671 if( maMinOutSize.Width() > aState.mnWidth )
672 aState.mnWidth = maMinOutSize.Width();
673 if( maMinOutSize.Height() > aState.mnHeight )
674 aState.mnHeight = maMinOutSize.Height();
677 aState.mnMaximizedX = rData.GetMaximizedX();
678 aState.mnMaximizedY = rData.GetMaximizedY();
679 aState.mnMaximizedWidth = rData.GetMaximizedWidth();
680 aState.mnMaximizedHeight = rData.GetMaximizedHeight();
681 // #94144# allow Minimize again, should be masked out when read from configuration
682 // 91625 - ignore Minimize
683 //nState &= ~(WindowStateState::Minimized);
684 aState.mnState = nState & WindowStateState::SystemMask;
686 // normalize window positions onto screen
687 ImplMoveToScreen( aState.mnX, aState.mnY, aState.mnWidth, aState.mnHeight, pWindow );
688 ImplMoveToScreen( aState.mnMaximizedX, aState.mnMaximizedY, aState.mnMaximizedWidth, aState.mnMaximizedHeight, pWindow );
690 // #96568# avoid having multiple frames at the same screen location
691 // do the check only if not maximized
692 if( !((rData.GetMask() & WindowStateMask::State) && (nState & WindowStateState::Maximized)) )
693 if( rData.GetMask() & (WindowStateMask::Pos|WindowStateMask::Width|WindowStateMask::Height) )
695 tools::Rectangle aDesktop = GetDesktopRectPixel();
696 ImplSVData *pSVData = ImplGetSVData();
697 vcl::Window *pWin = pSVData->maWinData.mpFirstFrame;
698 bool bWrapped = false;
699 while( pWin )
701 if( !pWin->ImplIsRealParentPath( this ) && ( pWin != this ) &&
702 pWin->ImplGetWindow()->IsTopWindow() && pWin->mpWindowImpl->mbReallyVisible )
704 SalFrameGeometry g = pWin->mpWindowImpl->mpFrame->GetGeometry();
705 if( std::abs(g.nX-aState.mnX) < 2 && std::abs(g.nY-aState.mnY) < 5 )
707 long displacement = g.nTopDecoration ? g.nTopDecoration : 20;
708 if( static_cast<unsigned long>(aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > static_cast<unsigned long>(aDesktop.Right()) ||
709 static_cast<unsigned long>(aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > static_cast<unsigned long>(aDesktop.Bottom()) )
711 // displacing would leave screen
712 aState.mnX = g.nLeftDecoration ? g.nLeftDecoration : 10; // should result in (0,0)
713 aState.mnY = displacement;
714 if( bWrapped ||
715 static_cast<unsigned long>(aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > static_cast<unsigned long>(aDesktop.Right()) ||
716 static_cast<unsigned long>(aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > static_cast<unsigned long>(aDesktop.Bottom()) )
717 break; // further displacement not possible -> break
718 // avoid endless testing
719 bWrapped = true;
721 else
723 // displace
724 aState.mnX += displacement;
725 aState.mnY += displacement;
727 pWin = pSVData->maWinData.mpFirstFrame; // check new pos again
730 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
734 mpWindowImpl->mpFrame->SetWindowState( &aState );
736 // do a synchronous resize for layout reasons
737 // but use rData only when the window is not to be maximized (#i38089#)
738 // otherwise we have no useful size information
739 if( (rData.GetMask() & WindowStateMask::State) && (nState & WindowStateState::Maximized) )
741 // query maximized size from frame
742 SalFrameGeometry aGeometry = mpWindowImpl->mpFrame->GetGeometry();
744 // but use it only if it is different from the restore size (rData)
745 // as currently only on windows the exact size of a maximized window
746 // can be computed without actually showing the window
747 if( aGeometry.nWidth != rData.GetWidth() || aGeometry.nHeight != rData.GetHeight() )
748 ImplHandleResize( pWindow, aGeometry.nWidth, aGeometry.nHeight );
750 else
751 if( rData.GetMask() & (WindowStateMask::Width|WindowStateMask::Height) )
752 ImplHandleResize( pWindow, aState.mnWidth, aState.mnHeight ); // #i43799# use aState and not rData, see above
754 else
756 PosSizeFlags nPosSize = PosSizeFlags::NONE;
757 if ( nValidMask & WindowStateMask::X )
758 nPosSize |= PosSizeFlags::X;
759 if ( nValidMask & WindowStateMask::Y )
760 nPosSize |= PosSizeFlags::Y;
761 if ( nValidMask & WindowStateMask::Width )
762 nPosSize |= PosSizeFlags::Width;
763 if ( nValidMask & WindowStateMask::Height )
764 nPosSize |= PosSizeFlags::Height;
766 if( IsRollUp() )
767 RollDown();
769 long nX = rData.GetX();
770 long nY = rData.GetY();
771 long nWidth = rData.GetWidth();
772 long nHeight = rData.GetHeight();
773 const SalFrameGeometry& rGeom = pWindow->mpWindowImpl->mpFrame->GetGeometry();
774 if( nX < 0 )
775 nX = 0;
776 if( nX + nWidth > static_cast<long>(rGeom.nWidth) )
777 nX = rGeom.nWidth - nWidth;
778 if( nY < 0 )
779 nY = 0;
780 if( nY + nHeight > static_cast<long>(rGeom.nHeight) )
781 nY = rGeom.nHeight - nHeight;
782 setPosSizePixel( nX, nY, nWidth, nHeight, nPosSize );
783 maOrgSize = Size( nWidth, nHeight );
785 // 91625 - ignore Minimize
786 if ( nValidMask & WindowStateMask::State )
788 const WindowStateState nState = rData.GetState();
789 if ( nState & WindowStateState::Rollup )
790 RollUp();
791 else
792 RollDown();
797 void SystemWindow::GetWindowStateData( WindowStateData& rData ) const
799 WindowStateMask nValidMask = rData.GetMask();
800 if ( nValidMask == WindowStateMask::NONE )
801 return;
803 if ( mbSysChild )
804 return;
806 const vcl::Window* pWindow = this;
807 while ( pWindow->mpWindowImpl->mpBorderWindow )
808 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
810 if ( pWindow->mpWindowImpl->mbFrame )
812 SalFrameState aState;
813 aState.mnMask = WindowStateMask::All;
814 if ( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
816 if ( nValidMask & WindowStateMask::X )
817 rData.SetX( aState.mnX );
818 if ( nValidMask & WindowStateMask::Y )
819 rData.SetY( aState.mnY );
820 if ( nValidMask & WindowStateMask::Width )
821 rData.SetWidth( aState.mnWidth );
822 if ( nValidMask & WindowStateMask::Height )
823 rData.SetHeight( aState.mnHeight );
824 if ( aState.mnMask & WindowStateMask::MaximizedX )
826 rData.SetMaximizedX( aState.mnMaximizedX );
827 nValidMask |= WindowStateMask::MaximizedX;
829 if ( aState.mnMask & WindowStateMask::MaximizedY )
831 rData.SetMaximizedY( aState.mnMaximizedY );
832 nValidMask |= WindowStateMask::MaximizedY;
834 if ( aState.mnMask & WindowStateMask::MaximizedWidth )
836 rData.SetMaximizedWidth( aState.mnMaximizedWidth );
837 nValidMask |= WindowStateMask::MaximizedWidth;
839 if ( aState.mnMask & WindowStateMask::MaximizedHeight )
841 rData.SetMaximizedHeight( aState.mnMaximizedHeight );
842 nValidMask |= WindowStateMask::MaximizedHeight;
844 if ( nValidMask & WindowStateMask::State )
846 // #94144# allow Minimize again, should be masked out when read from configuration
847 // 91625 - ignore Minimize
848 if ( !(nValidMask&WindowStateMask::Minimized) )
849 aState.mnState &= ~WindowStateState::Minimized;
850 rData.SetState( aState.mnState );
852 rData.SetMask( nValidMask );
854 else
855 rData.SetMask( WindowStateMask::NONE );
857 else
859 Point aPos = GetPosPixel();
860 Size aSize = GetSizePixel();
861 WindowStateState nState = WindowStateState::NONE;
863 if ( IsRollUp() )
865 aSize.AdjustHeight(maOrgSize.Height() );
866 nState = WindowStateState::Rollup;
869 if ( nValidMask & WindowStateMask::X )
870 rData.SetX( aPos.X() );
871 if ( nValidMask & WindowStateMask::Y )
872 rData.SetY( aPos.Y() );
873 if ( nValidMask & WindowStateMask::Width )
874 rData.SetWidth( aSize.Width() );
875 if ( nValidMask & WindowStateMask::Height )
876 rData.SetHeight( aSize.Height() );
877 if ( nValidMask & WindowStateMask::State )
878 rData.SetState( nState );
882 void SystemWindow::SetWindowState(const OString& rStr)
884 if (rStr.isEmpty())
885 return;
887 WindowStateData aData;
888 ImplWindowStateFromStr( aData, rStr );
889 SetWindowStateData( aData );
892 OString SystemWindow::GetWindowState( WindowStateMask nMask ) const
894 WindowStateData aData;
895 aData.SetMask( nMask );
896 GetWindowStateData( aData );
898 return aData.ToStr();
901 void SystemWindow::SetMenuBar(MenuBar* pMenuBar)
903 if ( mpMenuBar != pMenuBar )
905 MenuBar* pOldMenuBar = mpMenuBar;
906 vcl::Window* pOldWindow = nullptr;
907 VclPtr<vcl::Window> pNewWindow;
908 mpMenuBar = pMenuBar;
910 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) )
912 if ( pOldMenuBar )
913 pOldWindow = pOldMenuBar->ImplGetWindow();
914 else
915 pOldWindow = nullptr;
916 if ( pOldWindow )
918 CallEventListeners( VclEventId::WindowMenubarRemoved, static_cast<void*>(pOldMenuBar) );
919 pOldWindow->SetAccessible( css::uno::Reference< css::accessibility::XAccessible >() );
921 if ( pMenuBar )
923 SAL_WARN_IF( pMenuBar->pWindow, "vcl", "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
925 pNewWindow = MenuBar::ImplCreate(mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar);
926 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow(pNewWindow);
928 CallEventListeners( VclEventId::WindowMenubarAdded, static_cast<void*>(pMenuBar) );
930 else
931 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow( nullptr );
932 ImplToBottomChild();
933 if ( pOldMenuBar )
935 bool bDelete = (pMenuBar == nullptr);
936 if( bDelete && pOldWindow )
938 if( mpImplData->mpTaskPaneList )
939 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
941 MenuBar::ImplDestroy( pOldMenuBar, bDelete );
942 if( bDelete )
943 pOldWindow = nullptr; // will be deleted in MenuBar::ImplDestroy,
947 else
949 if( pMenuBar )
950 pNewWindow = pMenuBar->ImplGetWindow();
951 if( pOldMenuBar )
952 pOldWindow = pOldMenuBar->ImplGetWindow();
955 // update taskpane list to make menubar accessible
956 if( mpImplData->mpTaskPaneList )
958 if( pOldWindow )
959 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
960 if( pNewWindow )
961 mpImplData->mpTaskPaneList->AddWindow( pNewWindow );
966 void SystemWindow::SetNotebookBar(const OUString& rUIXMLDescription,
967 const css::uno::Reference<css::frame::XFrame>& rFrame,
968 const NotebookBarAddonsItem& aNotebookBarAddonsItem,
969 bool bReloadNotebookbar)
971 if (rUIXMLDescription != maNotebookBarUIFile || bReloadNotebookbar)
973 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())
974 ->SetNotebookBar(rUIXMLDescription, rFrame, aNotebookBarAddonsItem);
975 maNotebookBarUIFile = rUIXMLDescription;
976 if(GetNotebookBar())
977 GetNotebookBar()->SetSystemWindow(this);
981 void SystemWindow::CloseNotebookBar()
983 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CloseNotebookBar();
984 maNotebookBarUIFile.clear();
987 VclPtr<NotebookBar> const & SystemWindow::GetNotebookBar() const
989 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetNotebookBar();
992 void SystemWindow::SetMenuBarMode( MenuBarMode nMode )
994 if ( mnMenuBarMode != nMode )
996 mnMenuBarMode = nMode;
997 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) )
999 if ( nMode == MenuBarMode::Hide )
1000 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarMode( true );
1001 else
1002 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarMode( false );
1007 bool SystemWindow::ImplIsInTaskPaneList( vcl::Window* pWin )
1009 if( mpImplData && mpImplData->mpTaskPaneList )
1010 return mpImplData->mpTaskPaneList->IsInList( pWin );
1011 return false;
1014 unsigned int SystemWindow::GetScreenNumber() const
1016 return mpWindowImpl->mpFrame->maGeometry.nDisplayScreenNumber;
1019 void SystemWindow::SetScreenNumber(unsigned int nDisplayScreen)
1021 mpWindowImpl->mpFrame->SetScreenNumber( nDisplayScreen );
1024 void SystemWindow::SetApplicationID(const OUString &rApplicationID)
1026 mpWindowImpl->mpFrame->SetApplicationID( rApplicationID );
1029 void SystemWindow::SetCloseHdl(const Link<SystemWindow&,void>& rLink)
1031 mpImplData->maCloseHdl = rLink;
1034 const Link<SystemWindow&,void>& SystemWindow::GetCloseHdl() const
1036 return mpImplData->maCloseHdl;
1039 void SystemWindow::queue_resize(StateChangedType /*eReason*/)
1041 if (!isLayoutEnabled())
1042 return;
1043 if (isCalculatingInitialLayoutSize())
1044 return;
1045 InvalidateSizeCache();
1046 if (hasPendingLayout())
1047 return;
1048 maLayoutIdle.Start();
1051 void SystemWindow::Resize()
1053 queue_resize();
1056 bool SystemWindow::isLayoutEnabled() const
1058 //pre dtor called, and single child is a container => we're layout enabled
1059 return mpImplData && ::isLayoutEnabled(this);
1062 Size SystemWindow::GetOptimalSize() const
1064 if (!isLayoutEnabled())
1065 return Window::GetOptimalSize();
1067 Size aSize = VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
1069 sal_Int32 nBorderWidth = get_border_width();
1071 aSize.AdjustHeight(2 * nBorderWidth );
1072 aSize.AdjustWidth(2 * nBorderWidth );
1074 return Window::CalcWindowSize(aSize);
1077 void SystemWindow::setPosSizeOnContainee(Size aSize, Window &rBox)
1079 sal_Int32 nBorderWidth = get_border_width();
1081 aSize.AdjustWidth( -(2 * nBorderWidth) );
1082 aSize.AdjustHeight( -(2 * nBorderWidth) );
1084 Point aPos(nBorderWidth, nBorderWidth);
1085 VclContainer::setLayoutAllocation(rBox, aPos, CalcOutputSize(aSize));
1088 IMPL_LINK_NOARG( SystemWindow, ImplHandleLayoutTimerHdl, Timer*, void )
1090 if (!isLayoutEnabled())
1092 SAL_WARN("vcl.layout", "SystemWindow has become non-layout because extra children have been added directly to it.");
1093 return;
1096 Window *pBox = GetWindow(GetWindowType::FirstChild);
1097 assert(pBox);
1098 setPosSizeOnContainee(GetSizePixel(), *pBox);
1101 void SystemWindow::SetText(const OUString& rStr)
1103 setDeferredProperties();
1104 Window::SetText(rStr);
1107 OUString SystemWindow::GetText() const
1109 const_cast<SystemWindow*>(this)->setDeferredProperties();
1110 return Window::GetText();
1113 void SystemWindow::settingOptimalLayoutSize(Window* /*pBox*/)
1117 void SystemWindow::setOptimalLayoutSize()
1119 maLayoutIdle.Stop();
1121 //resize SystemWindow to fit requisition on initial show
1122 Window *pBox = GetWindow(GetWindowType::FirstChild);
1124 settingOptimalLayoutSize(pBox);
1126 Size aSize = get_preferred_size();
1128 Size aMax(bestmaxFrameSizeForScreenSize(GetDesktopRectPixel().GetSize()));
1130 aSize.setWidth( std::min(aMax.Width(), aSize.Width()) );
1131 aSize.setHeight( std::min(aMax.Height(), aSize.Height()) );
1133 SetMinOutputSizePixel(aSize);
1134 SetSizePixel(aSize);
1135 setPosSizeOnContainee(aSize, *pBox);
1138 void SystemWindow::DoInitialLayout()
1140 if (GetSettings().GetStyleSettings().GetAutoMnemonic())
1141 Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
1143 if (isLayoutEnabled())
1145 mbIsCalculatingInitialLayoutSize = true;
1146 setDeferredProperties();
1147 setOptimalLayoutSize();
1148 mbIsCalculatingInitialLayoutSize = false;
1152 void SystemWindow::doDeferredInit(WinBits /*nBits*/)
1154 SAL_WARN("vcl.layout", "SystemWindow in layout without doDeferredInit impl");
1157 void SystemWindow::createScreenshot(VirtualDevice& rOutput)
1159 // same prerequisites as in Execute()
1160 setDeferredProperties();
1161 ImplAdjustNWFSizes();
1162 Show();
1163 ToTop();
1164 ensureRepaint();
1166 Point aPos;
1167 Size aSize(GetOutputSizePixel());
1169 rOutput.SetOutputSizePixel(aSize);
1170 rOutput.DrawOutDev(aPos, aSize, aPos, aSize, *this);
1173 void SystemWindow::PrePaint(vcl::RenderContext& rRenderContext)
1175 Window::PrePaint(rRenderContext);
1176 mbPaintComplete = false;
1179 void SystemWindow::PostPaint(vcl::RenderContext& rRenderContext)
1181 Window::PostPaint(rRenderContext);
1182 mbPaintComplete = true;
1185 void SystemWindow::ensureRepaint()
1187 // ensure repaint
1188 Invalidate();
1189 mbPaintComplete = false;
1191 while (!mbPaintComplete)
1193 Application::Yield();
1197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */