1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23
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>
35
36 #include <rtl/strbuf.hxx>
37
38 #include <salframe.hxx>
39 #include <svdata.hxx>
40 #include <brdwin.hxx>
41 #include <window.h>
42
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::lang;
45
46 class SystemWindow::ImplData
47 {
48 public:
49 ImplData();
50
51 std::unique_ptr<TaskPaneList>
52 mpTaskPaneList;
53 Size maMaxOutSize;
54 OUString maRepresentedURL;
55 Link<SystemWindow&,void> maCloseHdl;
56 };
57
ImplData()58 SystemWindow::ImplData::ImplData()
59 {
60 mpTaskPaneList = nullptr;
61 maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
62 }
63
SystemWindow(WindowType nType)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)
76 {
77 mpWindowImpl->mbSysWin = true;
78 mpWindowImpl->mnActivateMode = ActivateModeFlags::GrabFocus;
79
80 //To-Do, reuse maResizeTimer
81 maLayoutIdle.SetPriority(TaskPriority::RESIZE);
82 maLayoutIdle.SetInvokeHandler( LINK( this, SystemWindow, ImplHandleLayoutTimerHdl ) );
83 maLayoutIdle.SetDebugName( "vcl::SystemWindow maLayoutIdle" );
84 }
85
loadUI(vcl::Window * pParent,const OString & rID,const OUString & rUIXMLDescription,const css::uno::Reference<css::frame::XFrame> & rFrame)86 void SystemWindow::loadUI(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription,
87 const css::uno::Reference<css::frame::XFrame> &rFrame)
88 {
89 mbIsDeferredInit = true;
90 mpDialogParent = pParent; //should be unset in doDeferredInit
91 m_pUIBuilder.reset( new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame) );
92 }
93
~SystemWindow()94 SystemWindow::~SystemWindow()
95 {
96 disposeOnce();
97 }
98
dispose()99 void SystemWindow::dispose()
100 {
101 maLayoutIdle.Stop();
102 mpImplData.reset();
103
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();
111 }
112
ImplHandleControlAccelerator(const vcl::Window * pWindow,bool bShow)113 static void ImplHandleControlAccelerator( const vcl::Window* pWindow, bool bShow )
114 {
115 Control *pControl = dynamic_cast<Control*>(pWindow->ImplGetWindow());
116 if (pControl && pControl->GetText().indexOf('~') != -1)
117 {
118 pControl->SetShowAccelerator( bShow );
119 pControl->Invalidate(InvalidateFlags::Update);
120 }
121 }
122
123 namespace
124 {
processChildren(const vcl::Window * pParent,bool bShowAccel)125 void processChildren(const vcl::Window *pParent, bool bShowAccel)
126 {
127 // go through its children
128 vcl::Window* pChild = firstLogicalChildOfParent(pParent);
129 while (pChild)
130 {
131 if (pChild->GetType() == WindowType::TABCONTROL)
132 {
133 // find currently shown tab page
134 TabControl* pTabControl = static_cast<TabControl*>(pChild);
135 TabPage* pTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
136 processChildren(pTabPage, bShowAccel);
137 }
138 else if (pChild->GetType() == WindowType::TABPAGE)
139 {
140 // bare tabpage without tabcontrol parent (options dialog)
141 processChildren(pChild, bShowAccel);
142 }
143 else if ((pChild->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL)
144 {
145 // special controls that manage their children outside of widget layout
146 processChildren(pChild, bShowAccel);
147 }
148 else
149 {
150 ImplHandleControlAccelerator(pChild, bShowAccel);
151 }
152 pChild = nextLogicalChildOfParent(pParent, pChild);
153 }
154 }
155 }
156
ToggleMnemonicsOnHierarchy(const CommandEvent & rCEvent,const vcl::Window * pWindow)157 bool Accelerator::ToggleMnemonicsOnHierarchy(const CommandEvent& rCEvent, const vcl::Window *pWindow)
158 {
159 if (rCEvent.GetCommand() == CommandEventId::ModKeyChange && ImplGetSVData()->maNWFData.mbAutoAccel)
160 {
161 const CommandModKeyData *pCData = rCEvent.GetModKeyData();
162 const bool bShowAccel = pCData && pCData->IsMod2() && pCData->IsDown();
163 processChildren(pWindow, bShowAccel);
164 return true;
165 }
166 return false;
167 }
168
EventNotify(NotifyEvent & rNEvt)169 bool SystemWindow::EventNotify( NotifyEvent& rNEvt )
170 {
171 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
172 Accelerator::ToggleMnemonicsOnHierarchy(*rNEvt.GetCommandEvent(), this);
173
174 // capture KeyEvents for menu handling
175 if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ||
176 rNEvt.GetType() == MouseNotifyEvent::COMMAND)
177 {
178 MenuBar* pMBar = mpMenuBar;
179 if ( !pMBar && ( GetType() == WindowType::FLOATINGWINDOW ) )
180 {
181 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
182 if( pWin && pWin->IsSystemWindow() )
183 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
184 }
185 bool bDone(false);
186 if (pMBar)
187 {
188 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
189 bDone = pMBar->ImplHandleCmdEvent(*rNEvt.GetCommandEvent());
190 else
191 bDone = pMBar->ImplHandleKeyEvent(*rNEvt.GetKeyEvent());
192 }
193 if (bDone)
194 return true;
195 }
196
197 return Window::EventNotify( rNEvt );
198 }
199
PreNotify(NotifyEvent & rNEvt)200 bool SystemWindow::PreNotify( NotifyEvent& rNEvt )
201 {
202 // capture KeyEvents for taskpane cycling
203 if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
204 {
205 if( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6 &&
206 rNEvt.GetKeyEvent()->GetKeyCode().IsMod1() &&
207 !rNEvt.GetKeyEvent()->GetKeyCode().IsShift() )
208 {
209 // Ctrl-F6 goes directly to the document
210 GrabFocusToDocument();
211 return true;
212 }
213 else
214 {
215 TaskPaneList *pTList = mpImplData->mpTaskPaneList.get();
216 if( !pTList && ( GetType() == WindowType::FLOATINGWINDOW ) )
217 {
218 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
219 if( pWin && pWin->IsSystemWindow() )
220 pTList = static_cast<SystemWindow*>(pWin)->mpImplData->mpTaskPaneList.get();
221 }
222 if( !pTList )
223 {
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 )
228 {
229 pWin = pWin->GetParent();
230 if( pWin && pWin->IsSystemWindow() )
231 pSysWin = static_cast<SystemWindow*>(pWin);
232 }
233 pTList = pSysWin->mpImplData->mpTaskPaneList.get();
234 }
235 if( pTList && pTList->HandleKeyEvent( *rNEvt.GetKeyEvent() ) )
236 return true;
237 }
238 }
239 return Window::PreNotify( rNEvt );
240 }
241
GetTaskPaneList()242 TaskPaneList* SystemWindow::GetTaskPaneList()
243 {
244 if( !mpImplData )
245 return nullptr;
246 if( mpImplData->mpTaskPaneList )
247 return mpImplData->mpTaskPaneList.get();
248 else
249 {
250 mpImplData->mpTaskPaneList.reset( new TaskPaneList );
251 MenuBar* pMBar = mpMenuBar;
252 if ( !pMBar && ( GetType() == WindowType::FLOATINGWINDOW ) )
253 {
254 vcl::Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
255 if ( pWin && pWin->IsSystemWindow() )
256 pMBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
257 }
258 if( pMBar )
259 mpImplData->mpTaskPaneList->AddWindow( pMBar->ImplGetWindow() );
260 return mpImplData->mpTaskPaneList.get();
261 }
262 }
263
Close()264 bool SystemWindow::Close()
265 {
266 VclPtr<vcl::Window> xWindow = this;
267 CallEventListeners( VclEventId::WindowClose );
268 if ( xWindow->IsDisposed() )
269 return false;
270
271 if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
272 return false;
273
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;
283
284 Hide();
285
286 return true;
287 }
288
TitleButtonClick(TitleButton)289 void SystemWindow::TitleButtonClick( TitleButton )
290 {
291 }
292
Resizing(Size &)293 void SystemWindow::Resizing( Size& )
294 {
295 }
296
SetRepresentedURL(const OUString & i_rURL)297 void SystemWindow::SetRepresentedURL( const OUString& i_rURL )
298 {
299 bool bChanged = (i_rURL != mpImplData->maRepresentedURL);
300 mpImplData->maRepresentedURL = i_rURL;
301 if ( !mbSysChild && bChanged )
302 {
303 const vcl::Window* pWindow = this;
304 while ( pWindow->mpWindowImpl->mpBorderWindow )
305 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
306
307 if ( pWindow->mpWindowImpl->mbFrame )
308 pWindow->mpWindowImpl->mpFrame->SetRepresentedURL( i_rURL );
309 }
310 }
311
SetIcon(sal_uInt16 nIcon)312 void SystemWindow::SetIcon( sal_uInt16 nIcon )
313 {
314 if ( mnIcon == nIcon )
315 return;
316
317 mnIcon = nIcon;
318
319 if ( !mbSysChild )
320 {
321 const vcl::Window* pWindow = this;
322 while ( pWindow->mpWindowImpl->mpBorderWindow )
323 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
324
325 if ( pWindow->mpWindowImpl->mbFrame )
326 pWindow->mpWindowImpl->mpFrame->SetIcon( nIcon );
327 }
328 }
329
ShowTitleButton(TitleButton nButton,bool bVisible)330 void SystemWindow::ShowTitleButton( TitleButton nButton, bool bVisible )
331 {
332 if ( nButton == TitleButton::Docking )
333 {
334 if ( mbDockBtn != bVisible )
335 {
336 mbDockBtn = bVisible;
337 if ( mpWindowImpl->mpBorderWindow )
338 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetDockButton( bVisible );
339 }
340 }
341 else if ( nButton == TitleButton::Hide )
342 {
343 if ( mbHideBtn != bVisible )
344 {
345 mbHideBtn = bVisible;
346 if ( mpWindowImpl->mpBorderWindow )
347 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetHideButton( bVisible );
348 }
349 }
350 else if ( nButton == TitleButton::Menu )
351 {
352 if ( mpWindowImpl->mpBorderWindow )
353 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuButton( bVisible );
354 }
355 else
356 return;
357 }
358
IsTitleButtonVisible(TitleButton nButton) const359 bool SystemWindow::IsTitleButtonVisible( TitleButton nButton ) const
360 {
361 if ( nButton == TitleButton::Docking )
362 return mbDockBtn;
363 else /* if ( nButton == TitleButton::Hide ) */
364 return mbHideBtn;
365 }
366
RollUp()367 void SystemWindow::RollUp()
368 {
369 if ( !mbRollUp )
370 {
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 );
380 }
381 }
382
RollDown()383 void SystemWindow::RollDown()
384 {
385 if ( mbRollUp )
386 {
387 mbRollUp = false;
388 if ( mpWindowImpl->mpBorderWindow )
389 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetRollUp( false, maOrgSize );
390 else
391 SetOutputSizePixel( maOrgSize );
392 }
393 }
394
SetMinOutputSizePixel(const Size & rSize)395 void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
396 {
397 maMinOutSize = rSize;
398 if ( mpWindowImpl->mpBorderWindow )
399 {
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() );
403 }
404 else if ( mpWindowImpl->mbFrame )
405 mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
406 }
407
SetMaxOutputSizePixel(const Size & rSize)408 void SystemWindow::SetMaxOutputSizePixel( const Size& rSize )
409 {
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 );
415
416 mpImplData->maMaxOutSize = aSize;
417 if ( mpWindowImpl->mpBorderWindow )
418 {
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() );
422 }
423 else if ( mpWindowImpl->mbFrame )
424 mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
425 }
426
GetMaxOutputSizePixel() const427 const Size& SystemWindow::GetMaxOutputSizePixel() const
428 {
429 return mpImplData->maMaxOutSize;
430 }
431
ImplWindowStateFromStr(WindowStateData & rData,const OString & rStr)432 void ImplWindowStateFromStr(WindowStateData& rData,
433 const OString& rStr)
434 {
435 WindowStateMask nValidMask = WindowStateMask::NONE;
436 sal_Int32 nIndex = 0;
437
438 OString aTokenStr = rStr.getToken(0, ',', nIndex);
439 if (!aTokenStr.isEmpty())
440 {
441 rData.SetX(aTokenStr.toInt32());
442 if( rData.GetX() > -16384 && rData.GetX() < 16384 )
443 nValidMask |= WindowStateMask::X;
444 else
445 rData.SetX( 0 );
446 }
447 else
448 rData.SetX( 0 );
449 aTokenStr = rStr.getToken(0, ',', nIndex);
450 if (!aTokenStr.isEmpty())
451 {
452 rData.SetY(aTokenStr.toInt32());
453 if( rData.GetY() > -16384 && rData.GetY() < 16384 )
454 nValidMask |= WindowStateMask::Y;
455 else
456 rData.SetY( 0 );
457 }
458 else
459 rData.SetY( 0 );
460 aTokenStr = rStr.getToken(0, ',', nIndex);
461 if (!aTokenStr.isEmpty())
462 {
463 rData.SetWidth(aTokenStr.toInt32());
464 if( rData.GetWidth() > 0 && rData.GetWidth() < 16384 )
465 nValidMask |= WindowStateMask::Width;
466 else
467 rData.SetWidth( 0 );
468 }
469 else
470 rData.SetWidth( 0 );
471 aTokenStr = rStr.getToken(0, ';', nIndex);
472 if (!aTokenStr.isEmpty())
473 {
474 rData.SetHeight(aTokenStr.toInt32());
475 if( rData.GetHeight() > 0 && rData.GetHeight() < 16384 )
476 nValidMask |= WindowStateMask::Height;
477 else
478 rData.SetHeight( 0 );
479 }
480 else
481 rData.SetHeight( 0 );
482 aTokenStr = rStr.getToken(0, ';', nIndex);
483 if (!aTokenStr.isEmpty())
484 {
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;
491 }
492 else
493 rData.SetState( WindowStateState::NONE );
494
495 // read maximized pos/size
496 aTokenStr = rStr.getToken(0, ',', nIndex);
497 if (!aTokenStr.isEmpty())
498 {
499 rData.SetMaximizedX(aTokenStr.toInt32());
500 if( rData.GetMaximizedX() > -16384 && rData.GetMaximizedX() < 16384 )
501 nValidMask |= WindowStateMask::MaximizedX;
502 else
503 rData.SetMaximizedX( 0 );
504 }
505 else
506 rData.SetMaximizedX( 0 );
507 aTokenStr = rStr.getToken(0, ',', nIndex);
508 if (!aTokenStr.isEmpty())
509 {
510 rData.SetMaximizedY(aTokenStr.toInt32());
511 if( rData.GetMaximizedY() > -16384 && rData.GetMaximizedY() < 16384 )
512 nValidMask |= WindowStateMask::MaximizedY;
513 else
514 rData.SetMaximizedY( 0 );
515 }
516 else
517 rData.SetMaximizedY( 0 );
518 aTokenStr = rStr.getToken(0, ',', nIndex);
519 if (!aTokenStr.isEmpty())
520 {
521 rData.SetMaximizedWidth(aTokenStr.toInt32());
522 if( rData.GetMaximizedWidth() > 0 && rData.GetMaximizedWidth() < 16384 )
523 nValidMask |= WindowStateMask::MaximizedWidth;
524 else
525 rData.SetMaximizedWidth( 0 );
526 }
527 else
528 rData.SetMaximizedWidth( 0 );
529 aTokenStr = rStr.getToken(0, ';', nIndex);
530 if (!aTokenStr.isEmpty())
531 {
532 rData.SetMaximizedHeight(aTokenStr.toInt32());
533 if( rData.GetMaximizedHeight() > 0 && rData.GetMaximizedHeight() < 16384 )
534 nValidMask |= WindowStateMask::MaximizedHeight;
535 else
536 rData.SetMaximizedHeight( 0 );
537 }
538 else
539 rData.SetMaximizedHeight( 0 );
540
541 // mark valid fields
542 rData.SetMask( nValidMask );
543 }
544
ToStr() const545 OString WindowStateData::ToStr() const
546 {
547 const WindowStateMask nValidMask = GetMask();
548 if ( nValidMask == WindowStateMask::NONE )
549 return OString();
550
551 OStringBuffer rStrBuf(64);
552
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 )
566 {
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));
571 }
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(';');
585
586 return rStrBuf.makeStringAndClear();
587 }
588
ImplMoveToScreen(long & io_rX,long & io_rY,long i_nWidth,long i_nHeight,vcl::Window const * i_pConfigureWin)589 void SystemWindow::ImplMoveToScreen( long& io_rX, long& io_rY, long i_nWidth, long i_nHeight, vcl::Window const * i_pConfigureWin )
590 {
591 tools::Rectangle aScreenRect;
592 if( !Application::IsUnifiedDisplay() )
593 aScreenRect = Application::GetScreenPosSizePixel( GetScreenNumber() );
594 else
595 {
596 aScreenRect = Application::GetScreenPosSizePixel( 0 );
597 for( unsigned int i = 1; i < Application::GetScreenCount(); i++ )
598 aScreenRect.Union( Application::GetScreenPosSizePixel( i ) );
599 }
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;
605
606 // check left border
607 bool bMove = false;
608 if( io_rX + i_nWidth < aScreenRect.Left() )
609 {
610 bMove = true;
611 io_rX = aScreenRect.Left();
612 }
613 // check right border
614 if( io_rX > aScreenRect.Right() - i_nWidth )
615 {
616 bMove = true;
617 io_rX = aScreenRect.Right() - i_nWidth;
618 }
619 // check top border
620 if( io_rY + i_nHeight < aScreenRect.Top() )
621 {
622 bMove = true;
623 io_rY = aScreenRect.Top();
624 }
625 // check bottom border
626 if( io_rY > aScreenRect.Bottom() - i_nHeight )
627 {
628 bMove = true;
629 io_rY = aScreenRect.Bottom() - i_nHeight;
630 }
631 vcl::Window* pParent = i_pConfigureWin->GetParent();
632 if( bMove && pParent )
633 {
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();
641 }
642 }
643
SetWindowStateData(const WindowStateData & rData)644 void SystemWindow::SetWindowStateData( const WindowStateData& rData )
645 {
646 const WindowStateMask nValidMask = rData.GetMask();
647 if ( nValidMask == WindowStateMask::NONE )
648 return;
649
650 if ( mbSysChild )
651 return;
652
653 vcl::Window* pWindow = this;
654 while ( pWindow->mpWindowImpl->mpBorderWindow )
655 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
656
657 if ( pWindow->mpWindowImpl->mbFrame )
658 {
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();
666
667 if( rData.GetMask() & (WindowStateMask::Width|WindowStateMask::Height) )
668 {
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();
675 }
676
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;
685
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 );
689
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) )
694 {
695 tools::Rectangle aDesktop = GetDesktopRectPixel();
696 ImplSVData *pSVData = ImplGetSVData();
697 vcl::Window *pWin = pSVData->maWinData.mpFirstFrame;
698 bool bWrapped = false;
699 while( pWin )
700 {
701 if( !pWin->ImplIsRealParentPath( this ) && ( pWin != this ) &&
702 pWin->ImplGetWindow()->IsTopWindow() && pWin->mpWindowImpl->mbReallyVisible )
703 {
704 SalFrameGeometry g = pWin->mpWindowImpl->mpFrame->GetGeometry();
705 if( std::abs(g.nX-aState.mnX) < 2 && std::abs(g.nY-aState.mnY) < 5 )
706 {
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()) )
710 {
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;
720 }
721 else
722 {
723 // displace
724 aState.mnX += displacement;
725 aState.mnY += displacement;
726 }
727 pWin = pSVData->maWinData.mpFirstFrame; // check new pos again
728 }
729 }
730 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
731 }
732 }
733
734 mpWindowImpl->mpFrame->SetWindowState( &aState );
735
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) )
740 {
741 // query maximized size from frame
742 SalFrameGeometry aGeometry = mpWindowImpl->mpFrame->GetGeometry();
743
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 );
749 }
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
753 }
754 else
755 {
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;
765
766 if( IsRollUp() )
767 RollDown();
768
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 );
784
785 // 91625 - ignore Minimize
786 if ( nValidMask & WindowStateMask::State )
787 {
788 const WindowStateState nState = rData.GetState();
789 if ( nState & WindowStateState::Rollup )
790 RollUp();
791 else
792 RollDown();
793 }
794 }
795 }
796
GetWindowStateData(WindowStateData & rData) const797 void SystemWindow::GetWindowStateData( WindowStateData& rData ) const
798 {
799 WindowStateMask nValidMask = rData.GetMask();
800 if ( nValidMask == WindowStateMask::NONE )
801 return;
802
803 if ( mbSysChild )
804 return;
805
806 const vcl::Window* pWindow = this;
807 while ( pWindow->mpWindowImpl->mpBorderWindow )
808 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
809
810 if ( pWindow->mpWindowImpl->mbFrame )
811 {
812 SalFrameState aState;
813 aState.mnMask = WindowStateMask::All;
814 if ( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
815 {
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 )
825 {
826 rData.SetMaximizedX( aState.mnMaximizedX );
827 nValidMask |= WindowStateMask::MaximizedX;
828 }
829 if ( aState.mnMask & WindowStateMask::MaximizedY )
830 {
831 rData.SetMaximizedY( aState.mnMaximizedY );
832 nValidMask |= WindowStateMask::MaximizedY;
833 }
834 if ( aState.mnMask & WindowStateMask::MaximizedWidth )
835 {
836 rData.SetMaximizedWidth( aState.mnMaximizedWidth );
837 nValidMask |= WindowStateMask::MaximizedWidth;
838 }
839 if ( aState.mnMask & WindowStateMask::MaximizedHeight )
840 {
841 rData.SetMaximizedHeight( aState.mnMaximizedHeight );
842 nValidMask |= WindowStateMask::MaximizedHeight;
843 }
844 if ( nValidMask & WindowStateMask::State )
845 {
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 );
851 }
852 rData.SetMask( nValidMask );
853 }
854 else
855 rData.SetMask( WindowStateMask::NONE );
856 }
857 else
858 {
859 Point aPos = GetPosPixel();
860 Size aSize = GetSizePixel();
861 WindowStateState nState = WindowStateState::NONE;
862
863 if ( IsRollUp() )
864 {
865 aSize.AdjustHeight(maOrgSize.Height() );
866 nState = WindowStateState::Rollup;
867 }
868
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 );
879 }
880 }
881
SetWindowState(const OString & rStr)882 void SystemWindow::SetWindowState(const OString& rStr)
883 {
884 if (rStr.isEmpty())
885 return;
886
887 WindowStateData aData;
888 ImplWindowStateFromStr( aData, rStr );
889 SetWindowStateData( aData );
890 }
891
GetWindowState(WindowStateMask nMask) const892 OString SystemWindow::GetWindowState( WindowStateMask nMask ) const
893 {
894 WindowStateData aData;
895 aData.SetMask( nMask );
896 GetWindowStateData( aData );
897
898 return aData.ToStr();
899 }
900
SetMenuBar(MenuBar * pMenuBar)901 void SystemWindow::SetMenuBar(MenuBar* pMenuBar)
902 {
903 if ( mpMenuBar != pMenuBar )
904 {
905 MenuBar* pOldMenuBar = mpMenuBar;
906 vcl::Window* pOldWindow = nullptr;
907 VclPtr<vcl::Window> pNewWindow;
908 mpMenuBar = pMenuBar;
909
910 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) )
911 {
912 if ( pOldMenuBar )
913 pOldWindow = pOldMenuBar->ImplGetWindow();
914 else
915 pOldWindow = nullptr;
916 if ( pOldWindow )
917 {
918 CallEventListeners( VclEventId::WindowMenubarRemoved, static_cast<void*>(pOldMenuBar) );
919 pOldWindow->SetAccessible( css::uno::Reference< css::accessibility::XAccessible >() );
920 }
921 if ( pMenuBar )
922 {
923 SAL_WARN_IF( pMenuBar->pWindow, "vcl", "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
924
925 pNewWindow = MenuBar::ImplCreate(mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar);
926 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow(pNewWindow);
927
928 CallEventListeners( VclEventId::WindowMenubarAdded, static_cast<void*>(pMenuBar) );
929 }
930 else
931 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetMenuBarWindow( nullptr );
932 ImplToBottomChild();
933 if ( pOldMenuBar )
934 {
935 bool bDelete = (pMenuBar == nullptr);
936 if( bDelete && pOldWindow )
937 {
938 if( mpImplData->mpTaskPaneList )
939 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
940 }
941 MenuBar::ImplDestroy( pOldMenuBar, bDelete );
942 if( bDelete )
943 pOldWindow = nullptr; // will be deleted in MenuBar::ImplDestroy,
944 }
945
946 }
947 else
948 {
949 if( pMenuBar )
950 pNewWindow = pMenuBar->ImplGetWindow();
951 if( pOldMenuBar )
952 pOldWindow = pOldMenuBar->ImplGetWindow();
953 }
954
955 // update taskpane list to make menubar accessible
956 if( mpImplData->mpTaskPaneList )
957 {
958 if( pOldWindow )
959 mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
960 if( pNewWindow )
961 mpImplData->mpTaskPaneList->AddWindow( pNewWindow );
962 }
963 }
964 }
965
SetNotebookBar(const OUString & rUIXMLDescription,const css::uno::Reference<css::frame::XFrame> & rFrame,const NotebookBarAddonsItem & aNotebookBarAddonsItem,bool bReloadNotebookbar)966 void SystemWindow::SetNotebookBar(const OUString& rUIXMLDescription,
967 const css::uno::Reference<css::frame::XFrame>& rFrame,
968 const NotebookBarAddonsItem& aNotebookBarAddonsItem,
969 bool bReloadNotebookbar)
970 {
971 if (rUIXMLDescription != maNotebookBarUIFile || bReloadNotebookbar)
972 {
973 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())
974 ->SetNotebookBar(rUIXMLDescription, rFrame, aNotebookBarAddonsItem);
975 maNotebookBarUIFile = rUIXMLDescription;
976 if(GetNotebookBar())
977 GetNotebookBar()->SetSystemWindow(this);
978 }
979 }
980
CloseNotebookBar()981 void SystemWindow::CloseNotebookBar()
982 {
983 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CloseNotebookBar();
984 maNotebookBarUIFile.clear();
985 }
986
GetNotebookBar() const987 VclPtr<NotebookBar> const & SystemWindow::GetNotebookBar() const
988 {
989 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetNotebookBar();
990 }
991
SetMenuBarMode(MenuBarMode nMode)992 void SystemWindow::SetMenuBarMode( MenuBarMode nMode )
993 {
994 if ( mnMenuBarMode != nMode )
995 {
996 mnMenuBarMode = nMode;
997 if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) )
998 {
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 );
1003 }
1004 }
1005 }
1006
ImplIsInTaskPaneList(vcl::Window * pWin)1007 bool SystemWindow::ImplIsInTaskPaneList( vcl::Window* pWin )
1008 {
1009 if( mpImplData && mpImplData->mpTaskPaneList )
1010 return mpImplData->mpTaskPaneList->IsInList( pWin );
1011 return false;
1012 }
1013
GetScreenNumber() const1014 unsigned int SystemWindow::GetScreenNumber() const
1015 {
1016 return mpWindowImpl->mpFrame->maGeometry.nDisplayScreenNumber;
1017 }
1018
SetScreenNumber(unsigned int nDisplayScreen)1019 void SystemWindow::SetScreenNumber(unsigned int nDisplayScreen)
1020 {
1021 mpWindowImpl->mpFrame->SetScreenNumber( nDisplayScreen );
1022 }
1023
SetApplicationID(const OUString & rApplicationID)1024 void SystemWindow::SetApplicationID(const OUString &rApplicationID)
1025 {
1026 mpWindowImpl->mpFrame->SetApplicationID( rApplicationID );
1027 }
1028
SetCloseHdl(const Link<SystemWindow &,void> & rLink)1029 void SystemWindow::SetCloseHdl(const Link<SystemWindow&,void>& rLink)
1030 {
1031 mpImplData->maCloseHdl = rLink;
1032 }
1033
GetCloseHdl() const1034 const Link<SystemWindow&,void>& SystemWindow::GetCloseHdl() const
1035 {
1036 return mpImplData->maCloseHdl;
1037 }
1038
queue_resize(StateChangedType)1039 void SystemWindow::queue_resize(StateChangedType /*eReason*/)
1040 {
1041 if (!isLayoutEnabled())
1042 return;
1043 if (isCalculatingInitialLayoutSize())
1044 return;
1045 InvalidateSizeCache();
1046 if (hasPendingLayout())
1047 return;
1048 maLayoutIdle.Start();
1049 }
1050
Resize()1051 void SystemWindow::Resize()
1052 {
1053 queue_resize();
1054 }
1055
isLayoutEnabled() const1056 bool SystemWindow::isLayoutEnabled() const
1057 {
1058 //pre dtor called, and single child is a container => we're layout enabled
1059 return mpImplData && ::isLayoutEnabled(this);
1060 }
1061
GetOptimalSize() const1062 Size SystemWindow::GetOptimalSize() const
1063 {
1064 if (!isLayoutEnabled())
1065 return Window::GetOptimalSize();
1066
1067 Size aSize = VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
1068
1069 sal_Int32 nBorderWidth = get_border_width();
1070
1071 aSize.AdjustHeight(2 * nBorderWidth );
1072 aSize.AdjustWidth(2 * nBorderWidth );
1073
1074 return Window::CalcWindowSize(aSize);
1075 }
1076
setPosSizeOnContainee(Size aSize,Window & rBox)1077 void SystemWindow::setPosSizeOnContainee(Size aSize, Window &rBox)
1078 {
1079 sal_Int32 nBorderWidth = get_border_width();
1080
1081 aSize.AdjustWidth( -(2 * nBorderWidth) );
1082 aSize.AdjustHeight( -(2 * nBorderWidth) );
1083
1084 Point aPos(nBorderWidth, nBorderWidth);
1085 VclContainer::setLayoutAllocation(rBox, aPos, CalcOutputSize(aSize));
1086 }
1087
IMPL_LINK_NOARG(SystemWindow,ImplHandleLayoutTimerHdl,Timer *,void)1088 IMPL_LINK_NOARG( SystemWindow, ImplHandleLayoutTimerHdl, Timer*, void )
1089 {
1090 if (!isLayoutEnabled())
1091 {
1092 SAL_WARN("vcl.layout", "SystemWindow has become non-layout because extra children have been added directly to it.");
1093 return;
1094 }
1095
1096 Window *pBox = GetWindow(GetWindowType::FirstChild);
1097 assert(pBox);
1098 setPosSizeOnContainee(GetSizePixel(), *pBox);
1099 }
1100
SetText(const OUString & rStr)1101 void SystemWindow::SetText(const OUString& rStr)
1102 {
1103 setDeferredProperties();
1104 Window::SetText(rStr);
1105 }
1106
GetText() const1107 OUString SystemWindow::GetText() const
1108 {
1109 const_cast<SystemWindow*>(this)->setDeferredProperties();
1110 return Window::GetText();
1111 }
1112
settingOptimalLayoutSize(Window *)1113 void SystemWindow::settingOptimalLayoutSize(Window* /*pBox*/)
1114 {
1115 }
1116
setOptimalLayoutSize()1117 void SystemWindow::setOptimalLayoutSize()
1118 {
1119 maLayoutIdle.Stop();
1120
1121 //resize SystemWindow to fit requisition on initial show
1122 Window *pBox = GetWindow(GetWindowType::FirstChild);
1123
1124 settingOptimalLayoutSize(pBox);
1125
1126 Size aSize = get_preferred_size();
1127
1128 Size aMax(bestmaxFrameSizeForScreenSize(GetDesktopRectPixel().GetSize()));
1129
1130 aSize.setWidth( std::min(aMax.Width(), aSize.Width()) );
1131 aSize.setHeight( std::min(aMax.Height(), aSize.Height()) );
1132
1133 SetMinOutputSizePixel(aSize);
1134 SetSizePixel(aSize);
1135 setPosSizeOnContainee(aSize, *pBox);
1136 }
1137
DoInitialLayout()1138 void SystemWindow::DoInitialLayout()
1139 {
1140 if (GetSettings().GetStyleSettings().GetAutoMnemonic())
1141 Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
1142
1143 if (isLayoutEnabled())
1144 {
1145 mbIsCalculatingInitialLayoutSize = true;
1146 setDeferredProperties();
1147 setOptimalLayoutSize();
1148 mbIsCalculatingInitialLayoutSize = false;
1149 }
1150 }
1151
doDeferredInit(WinBits)1152 void SystemWindow::doDeferredInit(WinBits /*nBits*/)
1153 {
1154 SAL_WARN("vcl.layout", "SystemWindow in layout without doDeferredInit impl");
1155 }
1156
createScreenshot(VirtualDevice & rOutput)1157 void SystemWindow::createScreenshot(VirtualDevice& rOutput)
1158 {
1159 // same prerequisites as in Execute()
1160 setDeferredProperties();
1161 ImplAdjustNWFSizes();
1162 Show();
1163 ToTop();
1164 ensureRepaint();
1165
1166 Point aPos;
1167 Size aSize(GetOutputSizePixel());
1168
1169 rOutput.SetOutputSizePixel(aSize);
1170 rOutput.DrawOutDev(aPos, aSize, aPos, aSize, *this);
1171 }
1172
PrePaint(vcl::RenderContext & rRenderContext)1173 void SystemWindow::PrePaint(vcl::RenderContext& rRenderContext)
1174 {
1175 Window::PrePaint(rRenderContext);
1176 mbPaintComplete = false;
1177 }
1178
PostPaint(vcl::RenderContext & rRenderContext)1179 void SystemWindow::PostPaint(vcl::RenderContext& rRenderContext)
1180 {
1181 Window::PostPaint(rRenderContext);
1182 mbPaintComplete = true;
1183 }
1184
ensureRepaint()1185 void SystemWindow::ensureRepaint()
1186 {
1187 // ensure repaint
1188 Invalidate();
1189 mbPaintComplete = false;
1190
1191 while (!mbPaintComplete)
1192 {
1193 Application::Yield();
1194 }
1195 }
1196
1197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1198