build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / window.cxx
blobe665b48af9dc3a6c276b71d440e677334dbc9812
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 <config_features.h>
21 #include <rtl/strbuf.hxx>
22 #include <tools/rc.h>
24 #include <sal/types.h>
25 #include <vcl/salgtype.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/help.hxx>
28 #include <vcl/cursor.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/vclevent.hxx>
31 #include <vcl/window.hxx>
32 #include <vcl/syswin.hxx>
33 #include <vcl/syschild.hxx>
34 #include <vcl/dockwin.hxx>
35 #include <vcl/wall.hxx>
36 #include <vcl/fixed.hxx>
37 #include <vcl/gradient.hxx>
38 #include <vcl/button.hxx>
39 #include <vcl/taskpanelist.hxx>
40 #include <vcl/dialog.hxx>
41 #include <vcl/unowrap.hxx>
42 #include <vcl/gdimtf.hxx>
43 #include <vcl/lazydelete.hxx>
44 #include <vcl/virdev.hxx>
45 #include <vcl/settings.hxx>
46 #include <vcl/sysdata.hxx>
47 #include <vcl/IDialogRenderable.hxx>
49 #include <vcl/uitest/uiobject.hxx>
50 #include <vcl/uitest/uitest.hxx>
52 #include <salframe.hxx>
53 #include <salobj.hxx>
54 #include <salinst.hxx>
55 #include <salgdi.hxx>
56 #include <svdata.hxx>
57 #include <window.h>
58 #include <toolbox.h>
59 #include <outdev.h>
60 #include <brdwin.hxx>
61 #include <helpwin.hxx>
62 #include "dndlistenercontainer.hxx"
64 #include <com/sun/star/awt/XDisplayConnection.hpp>
65 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
66 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
67 #include <com/sun/star/rendering/CanvasFactory.hpp>
68 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
69 #include <comphelper/lok.hxx>
70 #include <comphelper/processfactory.hxx>
71 #include <unotools/configmgr.hxx>
73 #include <cassert>
74 #include <set>
75 #include <typeinfo>
77 #ifdef _WIN32 // see #140456#
78 #include <win/salframe.h>
79 #endif
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::lang;
84 using namespace ::com::sun::star::datatransfer::clipboard;
85 using namespace ::com::sun::star::datatransfer::dnd;
87 namespace vcl {
89 Window::Window( WindowType nType ) :
90 mpWindowImpl(new WindowImpl( nType ))
92 meOutDevType = OUTDEV_WINDOW;
94 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
95 mbEnableRTL = AllSettings::GetLayoutRTL();
98 Window::Window( vcl::Window* pParent, WinBits nStyle ) :
99 mpWindowImpl(new WindowImpl( WINDOW_WINDOW ))
101 meOutDevType = OUTDEV_WINDOW;
103 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
104 mbEnableRTL = AllSettings::GetLayoutRTL();
106 ImplInit( pParent, nStyle, nullptr );
109 #if OSL_DEBUG_LEVEL > 0
110 namespace
112 OString lcl_createWindowInfo(const vcl::Window* pWindow)
114 // skip border windows, they do not carry information that
115 // would help with diagnosing the problem
116 const vcl::Window* pTempWin( pWindow );
117 while ( pTempWin && pTempWin->GetType() == WINDOW_BORDERWINDOW ) {
118 pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
120 // check if pTempWin is not null, otherwise use the
121 // original address
122 if ( pTempWin ) {
123 pWindow = pTempWin;
126 OStringBuffer aErrorString;
127 aErrorString.append(' ');
128 aErrorString.append(typeid( *pWindow ).name());
129 aErrorString.append("(");
130 aErrorString.append(
131 OUStringToOString(
132 pWindow->GetText(),
133 RTL_TEXTENCODING_UTF8
136 aErrorString.append(")");
137 return aErrorString.makeStringAndClear();
140 #endif
142 bool Window::IsDisposed() const
144 return !mpWindowImpl;
147 void Window::dispose()
149 assert( mpWindowImpl );
150 assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
151 assert( (!mpWindowImpl->mpParent ||
152 !mpWindowImpl->mpParent->IsDisposed()) &&
153 "vcl::Window child should have its parent disposed first" );
155 // remove Key and Mouse events issued by Application::PostKey/MouseEvent
156 Application::RemoveMouseAndKeyEvents( this );
158 // Dispose of the canvas implementation (which, currently, has an
159 // own wrapper window as a child to this one.
160 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
161 if( xCanvas.is() )
163 Reference < XComponent > xCanvasComponent( xCanvas, UNO_QUERY );
164 if( xCanvasComponent.is() )
165 xCanvasComponent->dispose();
168 mpWindowImpl->mbInDispose = true;
170 CallEventListeners( VCLEVENT_OBJECT_DYING );
172 // do not send child events for frames that were registered as native frames
173 if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
174 if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
175 GetAccessibleParentWindow()->CallEventListeners( VCLEVENT_WINDOW_CHILDDESTROYED, this );
177 // remove associated data structures from dockingmanager
178 ImplGetDockingManager()->RemoveWindow( this );
180 // remove ownerdraw decorated windows from list in the top-most frame window
181 if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
183 ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList();
184 auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) );
185 if( p != rList.end() )
186 rList.erase( p );
189 // shutdown drag and drop
190 Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
192 if( xDnDComponent.is() )
193 xDnDComponent->dispose();
195 if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
199 // deregister drop target listener
200 if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
202 Reference< XDragGestureRecognizer > xDragGestureRecognizer =
203 Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
204 if( xDragGestureRecognizer.is() )
206 xDragGestureRecognizer->removeDragGestureListener(
207 Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
210 mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
211 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
214 // shutdown drag and drop for this frame window
215 Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
217 // DNDEventDispatcher does not hold a reference of the DropTarget,
218 // so it's ok if it does not support XComponent
219 if( xComponent.is() )
220 xComponent->dispose();
222 catch (const Exception&)
224 // can be safely ignored here.
228 UnoWrapperBase* pWrapper = Application::GetUnoWrapper( false );
229 if ( pWrapper )
230 pWrapper->WindowDestroyed( this );
232 // MT: Must be called after WindowDestroyed!
233 // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
234 // But accessibility implementations from applications need this dispose.
235 if ( mpWindowImpl->mxAccessible.is() )
237 Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY );
238 if ( xC.is() )
239 xC->dispose();
242 ImplSVData* pSVData = ImplGetSVData();
244 if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
245 ImplDestroyHelpWindow( true );
247 SAL_WARN_IF( pSVData->maWinData.mpTrackWin.get() == this, "vcl",
248 "Window::~Window(): Window is in TrackingMode" );
249 SAL_WARN_IF(IsMouseCaptured(), "vcl",
250 "Window::~Window(): Window has the mouse captured");
252 // due to old compatibility
253 if ( pSVData->maWinData.mpTrackWin == this )
254 EndTracking();
255 if (IsMouseCaptured())
256 ReleaseMouse();
258 #if OSL_DEBUG_LEVEL > 0
259 if ( true ) // always perform these tests in debug builds
261 OStringBuffer aErrorStr;
262 bool bError = false;
263 vcl::Window* pTempWin;
265 if ( mpWindowImpl->mpFirstChild )
267 OStringBuffer aTempStr("Window (");
268 aTempStr.append(lcl_createWindowInfo(this));
269 aTempStr.append(") with live children destroyed: ");
270 pTempWin = mpWindowImpl->mpFirstChild;
271 while ( pTempWin )
273 aTempStr.append(lcl_createWindowInfo(pTempWin));
274 pTempWin = pTempWin->mpWindowImpl->mpNext;
276 OSL_FAIL( aTempStr.getStr() );
277 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
280 if (mpWindowImpl->mpFrameData != nullptr)
282 pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
283 while ( pTempWin )
285 if ( ImplIsRealParentPath( pTempWin ) )
287 bError = true;
288 aErrorStr.append(lcl_createWindowInfo(pTempWin));
290 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
292 if ( bError )
294 OStringBuffer aTempStr;
295 aTempStr.append("Window (");
296 aTempStr.append(lcl_createWindowInfo(this));
297 aTempStr.append(") with live SystemWindows destroyed: ");
298 aTempStr.append(aErrorStr.toString());
299 OSL_FAIL(aTempStr.getStr());
300 // abort in debug builds, must be fixed!
301 Application::Abort(OStringToOUString(
302 aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
306 bError = false;
307 pTempWin = pSVData->maWinData.mpFirstFrame;
308 while ( pTempWin )
310 if ( ImplIsRealParentPath( pTempWin ) )
312 bError = true;
313 aErrorStr.append(lcl_createWindowInfo(pTempWin));
315 pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
317 if ( bError )
319 OStringBuffer aTempStr( "Window (" );
320 aTempStr.append(lcl_createWindowInfo(this));
321 aTempStr.append(") with live SystemWindows destroyed: ");
322 aTempStr.append(aErrorStr.toString());
323 OSL_FAIL( aTempStr.getStr() );
324 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
327 if ( mpWindowImpl->mpFirstOverlap )
329 OStringBuffer aTempStr("Window (");
330 aTempStr.append(lcl_createWindowInfo(this));
331 aTempStr.append(") with live SystemWindows destroyed: ");
332 pTempWin = mpWindowImpl->mpFirstOverlap;
333 while ( pTempWin )
335 aTempStr.append(lcl_createWindowInfo(pTempWin));
336 pTempWin = pTempWin->mpWindowImpl->mpNext;
338 OSL_FAIL( aTempStr.getStr() );
339 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
342 vcl::Window* pMyParent = GetParent();
343 SystemWindow* pMySysWin = nullptr;
345 while ( pMyParent )
347 if ( pMyParent->IsSystemWindow() )
349 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
351 pMyParent = pMyParent->GetParent();
353 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
355 OStringBuffer aTempStr("Window (");
356 aTempStr.append(lcl_createWindowInfo(this));
357 aTempStr.append(") still in TaskPanelList!");
358 OSL_FAIL( aTempStr.getStr() );
359 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
362 #endif
364 if( mpWindowImpl->mbIsInTaskPaneList )
366 vcl::Window* pMyParent = GetParent();
367 SystemWindow* pMySysWin = nullptr;
369 while ( pMyParent )
371 if ( pMyParent->IsSystemWindow() )
373 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
375 pMyParent = pMyParent->GetParent();
377 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
379 pMySysWin->GetTaskPaneList()->RemoveWindow( this );
381 else
383 OStringBuffer aTempStr("Window (");
384 aTempStr.append(OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
385 aTempStr.append(") not found in TaskPanelList!");
386 OSL_FAIL( aTempStr.getStr() );
390 // remove from size-group if necessary
391 remove_from_all_size_groups();
393 // clear mnemonic labels
394 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
395 for (auto aI = aMnemonicLabels.begin(); aI != aMnemonicLabels.end(); ++aI)
397 remove_mnemonic_label(*aI);
400 // hide window in order to trigger the Paint-Handling
401 Hide();
403 // announce the window is to be destroyed
405 NotifyEvent aNEvt( MouseNotifyEvent::DESTROY, this );
406 CompatNotify( aNEvt );
409 // EndExtTextInputMode
410 if ( pSVData->maWinData.mpExtTextInputWin == this )
412 EndExtTextInput();
413 if ( pSVData->maWinData.mpExtTextInputWin == this )
414 pSVData->maWinData.mpExtTextInputWin = nullptr;
417 // check if the focus window is our child
418 bool bHasFocussedChild = false;
419 if( pSVData->maWinData.mpFocusWin && ImplIsRealParentPath( pSVData->maWinData.mpFocusWin ) )
421 // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
422 bHasFocussedChild = true;
423 #if OSL_DEBUG_LEVEL > 0
424 OStringBuffer aTempStr("Window (");
425 aTempStr.append(OUStringToOString(GetText(),
426 RTL_TEXTENCODING_UTF8)).
427 append(") with focussed child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !");
428 OSL_FAIL( aTempStr.getStr() );
429 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8 )); // abort in debug build version, this must be fixed!
430 #endif
433 // if we get focus pass focus to another window
434 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
435 if ( pSVData->maWinData.mpFocusWin == this
436 || bHasFocussedChild ) // #122232#, see above, try some cleanup
438 if ( mpWindowImpl->mbFrame )
440 pSVData->maWinData.mpFocusWin = nullptr;
441 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
443 else
445 vcl::Window* pParent = GetParent();
446 vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
447 // when windows overlap, give focus to the parent
448 // of the next FrameWindow
449 if ( pBorderWindow )
451 if ( pBorderWindow->ImplIsOverlapWindow() )
452 pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
454 else if ( ImplIsOverlapWindow() )
455 pParent = mpWindowImpl->mpOverlapWindow;
457 if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
458 pParent->GrabFocus();
459 else
460 mpWindowImpl->mpFrameWindow->GrabFocus();
462 // If the focus was set back to 'this' set it to nothing
463 if ( pSVData->maWinData.mpFocusWin == this )
465 pSVData->maWinData.mpFocusWin = nullptr;
466 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
471 if ( pOverlapWindow != nullptr &&
472 pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
473 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
475 // reset hint for DefModalDialogParent
476 if( pSVData->maWinData.mpActiveApplicationFrame == this )
477 pSVData->maWinData.mpActiveApplicationFrame = nullptr;
479 // reset hint of what was the last wheeled window
480 if( pSVData->maWinData.mpLastWheelWindow == this )
481 pSVData->maWinData.mpLastWheelWindow = nullptr;
483 // reset marked windows
484 if ( mpWindowImpl->mpFrameData != nullptr )
486 if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
487 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
488 if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
489 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
490 if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
491 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
494 // reset Deactivate-Window
495 if ( pSVData->maWinData.mpLastDeacWin == this )
496 pSVData->maWinData.mpLastDeacWin = nullptr;
498 if ( mpWindowImpl->mpFrameData )
500 if ( mpWindowImpl->mpFrameData->mnFocusId )
501 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
502 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
503 if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
504 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
505 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
508 // release SalGraphics
509 OutputDevice *pOutDev = GetOutDev();
510 pOutDev->ReleaseGraphics();
512 // remove window from the lists
513 ImplRemoveWindow( true );
515 // de-register as "top window child" at our parent, if necessary
516 if ( mpWindowImpl->mbFrame )
518 bool bIsTopWindow = mpWindowImpl->mpWinData && ( mpWindowImpl->mpWinData->mnIsTopWindow == 1 );
519 if ( mpWindowImpl->mpRealParent && bIsTopWindow )
521 ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
523 auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
524 pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
525 SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl", "Window::~Window: inconsistency in top window chain!" );
526 if ( myPos != pParentWinData->maTopWindowChildren.end() )
527 pParentWinData->maTopWindowChildren.erase( myPos );
531 delete mpWindowImpl->mpWinData;
532 mpWindowImpl->mpWinData = nullptr;
534 // remove BorderWindow or Frame window data
535 mpWindowImpl->mpBorderWindow.disposeAndClear();
536 if ( mpWindowImpl->mbFrame )
538 if ( pSVData->maWinData.mpFirstFrame == this )
539 pSVData->maWinData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
540 else
542 sal_Int32 nWindows = 0;
543 vcl::Window* pSysWin = pSVData->maWinData.mpFirstFrame;
544 while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
546 pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
547 nWindows++;
550 if ( pSysWin )
552 assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
553 pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
555 else // if it is not in the list, we can't remove it.
556 SAL_WARN("vcl", "Window " << this << " marked as frame window, "
557 "is missing from list of " << nWindows << " frames");
559 if (mpWindowImpl->mpFrame) // otherwise exception during init
561 mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
562 pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
564 assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
565 assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
567 delete mpWindowImpl->mpFrameData;
568 mpWindowImpl->mpFrameData = nullptr;
571 // should be the last statements
572 mpWindowImpl.reset();
574 OutputDevice::dispose();
577 Window::~Window()
579 // FIXME: we should kill all LazyDeletor usage.
580 vcl::LazyDeletor::Undelete( this );
581 disposeOnce();
584 // We will eventually being removing the inheritance of OutputDevice
585 // from Window. It will be replaced with a transient relationship such
586 // that the OutputDevice is only live for the scope of the Paint method.
587 // In the meantime this can help move us towards a Window use an
588 // OutputDevice, not being one.
590 ::OutputDevice const* Window::GetOutDev() const
592 return this;
595 ::OutputDevice* Window::GetOutDev()
597 return this;
600 } /* namespace vcl */
602 WindowImpl::WindowImpl( WindowType nType )
604 maZoom = Fraction( 1, 1 );
605 maWinRegion = vcl::Region(true);
606 maWinClipRegion = vcl::Region(true);
607 mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
608 mpFrameData = nullptr; // Frame Data
609 mpFrame = nullptr; // Pointer to frame window
610 mpSysObj = nullptr;
611 mpFrameWindow = nullptr; // window to top level parent (same as frame window)
612 mpOverlapWindow = nullptr; // first overlap parent
613 mpBorderWindow = nullptr; // Border-Window
614 mpClientWindow = nullptr; // Client-Window of a FrameWindow
615 mpParent = nullptr; // parent (incl. BorderWindow)
616 mpRealParent = nullptr; // real parent (excl. BorderWindow)
617 mpFirstChild = nullptr; // first child window
618 mpLastChild = nullptr; // last child window
619 mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
620 mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
621 mpPrev = nullptr; // prev window
622 mpNext = nullptr; // next window
623 mpNextOverlap = nullptr; // next overlap window of frame
624 mpLastFocusWindow = nullptr; // window for focus restore
625 mpDlgCtrlDownWindow = nullptr; // window for dialog control
626 mnEventListenersIteratingCount = 0;
627 mnChildEventListenersIteratingCount = 0;
628 mpCursor = nullptr; // cursor
629 mpControlFont = nullptr; // font properties
630 mpVCLXWindow = nullptr;
631 mpAccessibleInfos = nullptr;
632 maControlForeground = Color( COL_TRANSPARENT ); // no foreground set
633 maControlBackground = Color( COL_TRANSPARENT ); // no background set
634 mnLeftBorder = 0; // left border
635 mnTopBorder = 0; // top border
636 mnRightBorder = 0; // right border
637 mnBottomBorder = 0; // bottom border
638 mnWidthRequest = -1; // width request
639 mnHeightRequest = -1; // height request
640 mnOptimalWidthCache = -1; // optimal width cache
641 mnOptimalHeightCache = -1; // optimal height cache
642 mnX = 0; // X-Position to Parent
643 mnY = 0; // Y-Position to Parent
644 mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
645 mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
646 mpPaintRegion = nullptr; // Paint-ClipRegion
647 mnStyle = 0; // style (init in ImplInitWindow)
648 mnPrevStyle = 0; // prevstyle (set in SetStyle)
649 mnExtendedStyle = 0; // extended style (init in ImplInitWindow)
650 mnPrevExtendedStyle = 0; // prevstyle (set in SetExtendedStyle)
651 mnType = nType; // type
652 mnGetFocusFlags = GetFocusFlags::NONE; // Flags fuer GetFocus()-Aufruf
653 mnWaitCount = 0; // Wait-Count (>1 == Warte-MousePointer)
654 mnPaintFlags = 0; // Flags for ImplCallPaint
655 mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
656 mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
657 mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
658 mnLockCount = 0; // LockCount
659 meAlwaysInputMode = AlwaysInputNone; // neither AlwaysEnableInput nor AlwaysDisableInput called
660 meHalign = VclAlign::Fill;
661 meValign = VclAlign::Fill;
662 mePackType = VclPackType::Start;
663 mnPadding = 0;
664 mnGridHeight = 1;
665 mnGridLeftAttach = -1;
666 mnGridTopAttach = -1;
667 mnGridWidth = 1;
668 mnBorderWidth = 0;
669 mnMarginLeft = 0;
670 mnMarginRight = 0;
671 mnMarginTop = 0;
672 mnMarginBottom = 0;
673 mbFrame = false; // true: Window is a frame window
674 mbBorderWin = false; // true: Window is a border window
675 mbOverlapWin = false; // true: Window is a overlap window
676 mbSysWin = false; // true: SystemWindow is the base class
677 mbDialog = false; // true: Dialog is the base class
678 mbDockWin = false; // true: DockingWindow is the base class
679 mbFloatWin = false; // true: FloatingWindow is the base class
680 mbPushButton = false; // true: PushButton is the base class
681 mbToolBox = false; // true: ToolBox is the base class
682 mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
683 mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
684 mbSplitter = false; // true: Splitter is the base class
685 mbVisible = false; // true: Show( true ) called
686 mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
687 mbDisabled = false; // true: Enable( false ) called
688 mbInputDisabled = false; // true: EnableInput( false ) called
689 mbNoUpdate = false; // true: SetUpdateMode( false ) called
690 mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
691 mbActive = false; // true: Window Active
692 mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
693 mbReallyShown = false; // true: this and all parents to an overlapped window are shown
694 mbInInitShow = false; // true: we are in InitShow
695 mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
696 mbNoPtrVisible = false; // true: ShowPointer( false ) called
697 mbMouseMove = false; // true: BaseMouseMove called
698 mbPaintFrame = false; // true: Paint is visible, but not painted
699 mbInPaint = false; // true: Inside PaintHdl
700 mbMouseButtonDown = false; // true: BaseMouseButtonDown called
701 mbMouseButtonUp = false; // true: BaseMouseButtonUp called
702 mbKeyInput = false; // true: BaseKeyInput called
703 mbKeyUp = false; // true: BaseKeyUp called
704 mbCommand = false; // true: BaseCommand called
705 mbDefPos = true; // true: Position is not Set
706 mbDefSize = true; // true: Size is not Set
707 mbCallMove = true; // true: Move must be called by Show
708 mbCallResize = true; // true: Resize must be called by Show
709 mbWaitSystemResize = true; // true: Wait for System-Resize
710 mbInitWinClipRegion = true; // true: Calc Window Clip Region
711 mbInitChildRegion = false; // true: InitChildClipRegion
712 mbWinRegion = false; // true: Window Region
713 mbClipChildren = false; // true: Child-window should be clipped
714 mbClipSiblings = false; // true: Adjacent Child-window should be clipped
715 mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
716 mbPaintTransparent = false; // true: Paints should be executed on the Parent
717 mbMouseTransparent = false; // true: Window is transparent for Mouse
718 mbDlgCtrlStart = false; // true: From here on own Dialog-Control
719 mbFocusVisible = false; // true: Focus Visible
720 mbUseNativeFocus = false;
721 mbNativeFocusVisible = false; // true: native Focus Visible
722 mbInShowFocus = false; // prevent recursion
723 mbInHideFocus = false; // prevent recursion
724 mbTrackVisible = false; // true: Tracking Visible
725 mbControlForeground = false; // true: Foreground-Property set
726 mbControlBackground = false; // true: Background-Property set
727 mbAlwaysOnTop = false; // true: always visible for all others windows
728 mbCompoundControl = false; // true: Composite Control => Listener...
729 mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
730 mbPaintDisabled = false; // true: Paint should not be executed
731 mbAllResize = false; // true: Also sent ResizeEvents with 0,0
732 mbInDispose = false; // true: We're still in Window::dispose()
733 mbExtTextInput = false; // true: ExtTextInput-Mode is active
734 mbInFocusHdl = false; // true: Within GetFocus-Handler
735 mbCreatedWithToolkit = false;
736 mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
737 mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
738 mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
739 mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
740 mbCallHandlersDuringInputDisabled = false; // true: call event handlers even if input is disabled
741 mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
742 mbFakeFocusSet = false; // true: pretend as if the window has focus.
743 mbHexpand = false;
744 mbVexpand = false;
745 mbExpand = false;
746 mbFill = true;
747 mbSecondary = false;
748 mbNonHomogeneous = false;
749 static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
750 mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
751 mpLOKNotifier = nullptr;
752 mnLOKWindowId = 0;
753 mbLOKParentNotifier = false;
756 WindowImpl::~WindowImpl()
758 delete mpChildClipRegion;
759 delete mpAccessibleInfos;
760 delete mpControlFont;
763 ImplWinData::ImplWinData() :
764 mpExtOldText(nullptr),
765 mpExtOldAttrAry(nullptr),
766 mpCursorRect(nullptr),
767 mnCursorExtWidth(0),
768 mbVertical(false),
769 mpCompositionCharRects(nullptr),
770 mnCompositionCharRects(0),
771 mpFocusRect(nullptr),
772 mpTrackRect(nullptr),
773 mnTrackFlags(ShowTrackFlags::NONE),
774 mnIsTopWindow((sal_uInt16) ~0), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
775 mbMouseOver(false),
776 mbEnableNativeWidget(false)
780 ImplWinData::~ImplWinData()
782 delete mpExtOldText;
783 delete mpExtOldAttrAry;
784 delete mpCursorRect;
785 delete[] mpCompositionCharRects;
786 delete mpFocusRect;
787 delete mpTrackRect;
791 namespace vcl {
793 bool Window::AcquireGraphics() const
795 DBG_TESTSOLARMUTEX();
797 if ( mpGraphics )
798 return true;
800 mbInitLineColor = true;
801 mbInitFillColor = true;
802 mbInitFont = true;
803 mbInitTextColor = true;
804 mbInitClipRegion = true;
806 ImplSVData* pSVData = ImplGetSVData();
808 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
809 // try harder if no wingraphics was available directly
810 if ( !mpGraphics )
812 // find another output device in the same frame
813 OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
814 while ( pReleaseOutDev )
816 if ( static_cast<vcl::Window*>(pReleaseOutDev)->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame )
817 break;
818 pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
821 if ( pReleaseOutDev )
823 // steal the wingraphics from the other outdev
824 mpGraphics = pReleaseOutDev->mpGraphics;
825 pReleaseOutDev->ReleaseGraphics( false );
827 else
829 // if needed retry after releasing least recently used wingraphics
830 while ( !mpGraphics )
832 if ( !pSVData->maGDIData.mpLastWinGraphics )
833 break;
834 pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
835 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
840 // update global LRU list of wingraphics
841 if ( mpGraphics )
843 mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
844 pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::Window*>(this);
845 if ( mpNextGraphics )
846 mpNextGraphics->mpPrevGraphics = const_cast<vcl::Window*>(this);
847 if ( !pSVData->maGDIData.mpLastWinGraphics )
848 pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::Window*>(this);
851 if ( mpGraphics )
853 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp) );
854 mpGraphics->setAntiAliasB2DDraw(bool(mnAntialiasing & AntialiasingFlags::EnableB2dDraw));
857 return mpGraphics != nullptr;
860 void Window::ReleaseGraphics( bool bRelease )
862 DBG_TESTSOLARMUTEX();
864 if ( !mpGraphics )
865 return;
867 // release the fonts of the physically released graphics device
868 if( bRelease )
869 ImplReleaseFonts();
871 ImplSVData* pSVData = ImplGetSVData();
873 vcl::Window* pWindow = this;
875 if ( bRelease )
876 pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
877 // remove from global LRU list of window graphics
878 if ( mpPrevGraphics )
879 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
880 else
881 pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
882 if ( mpNextGraphics )
883 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
884 else
885 pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
887 mpGraphics = nullptr;
888 mpPrevGraphics = nullptr;
889 mpNextGraphics = nullptr;
892 static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
894 sal_Int32 nResult = 100;
896 #ifndef MACOSX
897 // Setting of HiDPI is unfortunately all only a heuristic; and to add
898 // insult to an injury, the system is constantly lying to us about
899 // the DPI and whatnot
900 // eg. fdo#77059 - set the value from which we do consider the
901 // screen hi-dpi to greater than 168
902 if (nDPI > 216) // 96 * 2 + 96 / 4
903 nResult = 250;
904 else if (nDPI > 168) // 96 * 2 - 96 / 4
905 nResult = 200;
906 else if (nDPI > 120) // 96 * 1.5 - 96 / 4
907 nResult = 150;
908 #else
909 (void)nDPI;
910 #endif
912 return nResult;
915 void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
917 SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WINDOW_FIXEDIMAGE, "vcl",
918 "Window::Window(): pParent == NULL" );
920 ImplSVData* pSVData = ImplGetSVData();
921 vcl::Window* pRealParent = pParent;
923 // inherit 3D look
924 if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
925 nStyle |= WB_3DLOOK;
927 // create border window if necessary
928 if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
929 && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
931 BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
932 if( (nStyle & WB_SYSTEMCHILDWINDOW) )
934 // handle WB_SYSTEMCHILDWINDOW
935 // these should be analogous to a top level frame; meaning they
936 // should have a border window with style BorderWindowStyle::Frame
937 // which controls their size
938 nBorderTypeStyle |= BorderWindowStyle::Frame;
939 nStyle |= WB_BORDER;
941 VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
942 static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
943 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
944 mpWindowImpl->mpBorderWindow = pBorderWin;
945 pParent = mpWindowImpl->mpBorderWindow;
947 else if( !mpWindowImpl->mbFrame && ! pParent )
949 mpWindowImpl->mbOverlapWin = true;
950 mpWindowImpl->mbFrame = true;
953 // insert window in list
954 ImplInsertWindow( pParent );
955 mpWindowImpl->mnStyle = nStyle;
957 if( pParent && ! mpWindowImpl->mbFrame )
958 mbEnableRTL = AllSettings::GetLayoutRTL();
960 // test for frame creation
961 if ( mpWindowImpl->mbFrame )
963 // create frame
964 SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
966 if ( nStyle & WB_MOVEABLE )
967 nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
968 if ( nStyle & WB_SIZEABLE )
969 nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
970 if ( nStyle & WB_CLOSEABLE )
971 nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
972 if ( nStyle & WB_APP )
973 nFrameStyle |= SalFrameStyleFlags::DEFAULT;
974 // check for undecorated floating window
975 if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
976 ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
977 ( mpWindowImpl->mbFloatWin || ((GetType() == WINDOW_BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
978 // 2. borderwindows of floaters with ownerdraw decoration
979 ( ((GetType() == WINDOW_BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) ) )
981 nFrameStyle = SalFrameStyleFlags::FLOAT;
982 if( nStyle & WB_OWNERDRAWDECORATION )
983 nFrameStyle |= (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW);
985 else if( mpWindowImpl->mbFloatWin )
986 nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
988 if( nStyle & WB_INTROWIN )
989 nFrameStyle |= SalFrameStyleFlags::INTRO;
990 if( nStyle & WB_TOOLTIPWIN )
991 nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
993 if( nStyle & WB_NOSHADOW )
994 nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
996 if( nStyle & WB_SYSTEMCHILDWINDOW )
997 nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
999 switch (mpWindowImpl->mnType)
1001 case WINDOW_DIALOG:
1002 case WINDOW_TABDIALOG:
1003 case WINDOW_MODALDIALOG:
1004 case WINDOW_MODELESSDIALOG:
1005 case WINDOW_MESSBOX:
1006 case WINDOW_INFOBOX:
1007 case WINDOW_WARNINGBOX:
1008 case WINDOW_ERRORBOX:
1009 case WINDOW_QUERYBOX:
1010 nFrameStyle |= SalFrameStyleFlags::DIALOG;
1011 break;
1012 default:
1013 break;
1016 SalFrame* pParentFrame = nullptr;
1017 if ( pParent )
1018 pParentFrame = pParent->mpWindowImpl->mpFrame;
1019 SalFrame* pFrame;
1020 if ( pSystemParentData )
1021 pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG );
1022 else
1023 pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
1024 if ( !pFrame )
1026 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
1027 throw RuntimeException(
1028 "Could not create system window!",
1029 Reference< XInterface >() );
1032 pFrame->SetCallback( this, ImplWindowFrameProc );
1034 // set window frame data
1035 mpWindowImpl->mpFrameData = new ImplFrameData;
1036 mpWindowImpl->mpFrame = pFrame;
1037 mpWindowImpl->mpFrameWindow = this;
1038 mpWindowImpl->mpOverlapWindow = this;
1040 // set frame data
1041 assert (pSVData->maWinData.mpFirstFrame.get() != this);
1042 mpWindowImpl->mpFrameData->mpNextFrame = pSVData->maWinData.mpFirstFrame;
1043 pSVData->maWinData.mpFirstFrame = this;
1044 mpWindowImpl->mpFrameData->mpFirstOverlap = nullptr;
1045 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
1046 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
1047 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
1048 mpWindowImpl->mpFrameData->mpFontCollection = pSVData->maGDIData.mpScreenFontList;
1049 mpWindowImpl->mpFrameData->mpFontCache = pSVData->maGDIData.mpScreenFontCache;
1050 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
1051 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
1052 mpWindowImpl->mpFrameData->mnLastMouseX = -1;
1053 mpWindowImpl->mpFrameData->mnLastMouseY = -1;
1054 mpWindowImpl->mpFrameData->mnBeforeLastMouseX = -1;
1055 mpWindowImpl->mpFrameData->mnBeforeLastMouseY = -1;
1056 mpWindowImpl->mpFrameData->mnFirstMouseX = -1;
1057 mpWindowImpl->mpFrameData->mnFirstMouseY = -1;
1058 mpWindowImpl->mpFrameData->mnLastMouseWinX = -1;
1059 mpWindowImpl->mpFrameData->mnLastMouseWinY = -1;
1060 mpWindowImpl->mpFrameData->mnModalMode = 0;
1061 mpWindowImpl->mpFrameData->mnMouseDownTime = 0;
1062 mpWindowImpl->mpFrameData->mnClickCount = 0;
1063 mpWindowImpl->mpFrameData->mnFirstMouseCode = 0;
1064 mpWindowImpl->mpFrameData->mnMouseCode = 0;
1065 mpWindowImpl->mpFrameData->mnMouseMode = MouseEventModifiers::NONE;
1066 mpWindowImpl->mpFrameData->meMapUnit = MapUnit::MapPixel;
1067 mpWindowImpl->mpFrameData->mbHasFocus = false;
1068 mpWindowImpl->mpFrameData->mbInMouseMove = false;
1069 mpWindowImpl->mpFrameData->mbMouseIn = false;
1070 mpWindowImpl->mpFrameData->mbStartDragCalled = false;
1071 mpWindowImpl->mpFrameData->mbNeedSysWindow = false;
1072 mpWindowImpl->mpFrameData->mbMinimized = false;
1073 mpWindowImpl->mpFrameData->mbStartFocusState = false;
1074 mpWindowImpl->mpFrameData->mbInSysObjFocusHdl = false;
1075 mpWindowImpl->mpFrameData->mbInSysObjToTopHdl = false;
1076 mpWindowImpl->mpFrameData->mbSysObjFocus = false;
1077 mpWindowImpl->mpFrameData->maPaintIdle.SetPriority( SchedulerPriority::REPAINT );
1078 mpWindowImpl->mpFrameData->maPaintIdle.SetIdleHdl( LINK( this, Window, ImplHandlePaintHdl ) );
1079 mpWindowImpl->mpFrameData->maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" );
1080 mpWindowImpl->mpFrameData->maResizeIdle.SetPriority( SchedulerPriority::RESIZE );
1081 mpWindowImpl->mpFrameData->maResizeIdle.SetIdleHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) );
1082 mpWindowImpl->mpFrameData->maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" );
1083 mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = false;
1084 if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
1085 RequestDoubleBuffering(true);
1086 mpWindowImpl->mpFrameData->mbInBufferedPaint = false;
1088 if ( pRealParent && IsTopWindow() )
1090 ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
1091 pParentWinData->maTopWindowChildren.push_back( this );
1095 // init data
1096 mpWindowImpl->mpRealParent = pRealParent;
1098 // #99318: make sure fontcache and list is available before call to SetSettings
1099 mpFontCollection = mpWindowImpl->mpFrameData->mpFontCollection;
1100 mpFontCache = mpWindowImpl->mpFrameData->mpFontCache;
1102 if ( mpWindowImpl->mbFrame )
1104 if ( pParent )
1106 mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
1107 mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
1109 else
1111 OutputDevice *pOutDev = GetOutDev();
1112 if ( pOutDev->AcquireGraphics() )
1114 mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
1118 // add ownerdraw decorated frame windows to list in the top-most frame window
1119 // so they can be hidden on lose focus
1120 if( nStyle & WB_OWNERDRAWDECORATION )
1121 ImplGetOwnerDrawList().push_back( this );
1123 // delay settings initialization until first "real" frame
1124 // this relies on the IntroWindow not needing any system settings
1125 if ( !pSVData->maAppData.mbSettingsInit &&
1126 ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
1129 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
1130 ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
1131 OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
1132 pSVData->maAppData.mbSettingsInit = true;
1135 // If we create a Window with default size, query this
1136 // size directly, because we want resize all Controls to
1137 // the correct size before we display the window
1138 if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
1139 mpWindowImpl->mpFrame->GetClientSize( mnOutWidth, mnOutHeight );
1141 else
1143 if ( pParent )
1145 if ( !ImplIsOverlapWindow() )
1147 mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
1148 mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
1149 mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
1152 if (!utl::ConfigManager::IsAvoidConfig())
1153 OutputDevice::SetSettings( pParent->GetSettings() );
1158 // setup the scale factor for Hi-DPI displays
1159 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1160 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1161 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1163 if (!utl::ConfigManager::IsAvoidConfig())
1165 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1166 maFont = rStyleSettings.GetAppFont();
1168 if ( nStyle & WB_3DLOOK )
1170 SetTextColor( rStyleSettings.GetButtonTextColor() );
1171 SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
1173 else
1175 SetTextColor( rStyleSettings.GetWindowTextColor() );
1176 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
1179 else
1181 maFont = GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
1184 ImplPointToLogic(*this, maFont);
1186 (void)ImplUpdatePos();
1188 // calculate app font res (except for the Intro Window or the default window)
1189 if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
1190 ImplInitAppFontData( this );
1192 if ( GetAccessibleParentWindow() && GetParent() != Application::GetDefDialogParent() )
1193 GetAccessibleParentWindow()->CallEventListeners( VCLEVENT_WINDOW_CHILDCREATED, this );
1196 void Window::ImplInitAppFontData( vcl::Window* pWindow )
1198 ImplSVData* pSVData = ImplGetSVData();
1199 long nTextHeight = pWindow->GetTextHeight();
1200 long nTextWidth = pWindow->approximate_char_width() * 8;
1201 long nSymHeight = nTextHeight*4;
1202 // Make the basis wider if the font is too narrow
1203 // such that the dialog looks symmetrical and does not become too narrow.
1204 // Add some extra space when the dialog has the same width,
1205 // as a little more space is better.
1206 if ( nSymHeight > nTextWidth )
1207 nTextWidth = nSymHeight;
1208 else if ( nSymHeight+5 > nTextWidth )
1209 nTextWidth = nSymHeight+5;
1210 pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
1211 pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
1213 #ifdef MACOSX
1214 // FIXME: this is currently only on OS X, check with other
1215 // platforms
1216 if( pSVData->maNWFData.mbNoFocusRects )
1218 // try to find out whether there is a large correction
1219 // of control sizes, if yes, make app font scalings larger
1220 // so dialog positioning is not completely off
1221 ImplControlValue aControlValue;
1222 Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
1223 Rectangle aBoundingRgn( aCtrlRegion );
1224 Rectangle aContentRgn( aCtrlRegion );
1225 if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
1226 ControlState::ENABLED, aControlValue, OUString(),
1227 aBoundingRgn, aContentRgn ) )
1229 // comment: the magical +6 is for the extra border in bordered
1230 // (which is the standard) edit fields
1231 if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
1232 pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
1235 #endif
1238 ImplWinData* Window::ImplGetWinData() const
1240 if ( !mpWindowImpl->mpWinData )
1242 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
1244 const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData = new ImplWinData;
1245 mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
1248 return mpWindowImpl->mpWinData;
1252 void Window::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
1254 if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
1255 return;
1257 if (bWindowInvalidate)
1259 const Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
1260 Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
1262 ImplMoveAllInvalidateRegions(aSrcRect,
1263 aPosAry.mnDestX-aPosAry.mnSrcX,
1264 aPosAry.mnDestY-aPosAry.mnSrcY,
1265 false);
1267 mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
1268 aPosAry.mnSrcX, aPosAry.mnSrcY,
1269 aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
1270 this);
1272 return;
1275 OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
1278 SalGraphics* Window::ImplGetFrameGraphics() const
1280 if ( mpWindowImpl->mpFrameWindow->mpGraphics )
1282 mpWindowImpl->mpFrameWindow->mbInitClipRegion = true;
1284 else
1286 OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow;
1287 if ( ! pFrameWinOutDev->AcquireGraphics() )
1289 return nullptr;
1292 mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
1293 return mpWindowImpl->mpFrameWindow->mpGraphics;
1296 void Window::ImplSetReallyVisible()
1298 // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
1299 // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
1300 // mbReallyShown is a useful indicator
1301 if( !mpWindowImpl->mbReallyShown )
1302 ImplCallInitShow();
1304 bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
1306 mbDevOutput = true;
1307 mpWindowImpl->mbReallyVisible = true;
1308 mpWindowImpl->mbReallyShown = true;
1310 // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
1311 // For this, the data member of the event must not be NULL.
1312 // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
1313 // we're doing it when the visibility really changes
1314 if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
1315 CallEventListeners( VCLEVENT_WINDOW_SHOW, this );
1316 // TODO. It's kind of a hack that we're re-using the VCLEVENT_WINDOW_SHOW. Normally, we should
1317 // introduce another event which explicitly triggers the Accessibility implementations.
1319 vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
1320 while ( pWindow )
1322 if ( pWindow->mpWindowImpl->mbVisible )
1323 pWindow->ImplSetReallyVisible();
1324 pWindow = pWindow->mpWindowImpl->mpNext;
1327 pWindow = mpWindowImpl->mpFirstChild;
1328 while ( pWindow )
1330 if ( pWindow->mpWindowImpl->mbVisible )
1331 pWindow->ImplSetReallyVisible();
1332 pWindow = pWindow->mpWindowImpl->mpNext;
1336 void Window::ImplInitResolutionSettings()
1338 // recalculate AppFont-resolution and DPI-resolution
1339 if (mpWindowImpl->mbFrame)
1341 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1342 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1344 // setup the scale factor for Hi-DPI displays
1345 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1346 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1347 SetPointFont(*this, rStyleSettings.GetAppFont());
1349 else if ( mpWindowImpl->mpParent )
1351 mnDPIX = mpWindowImpl->mpParent->mnDPIX;
1352 mnDPIY = mpWindowImpl->mpParent->mnDPIY;
1353 mnDPIScalePercentage = mpWindowImpl->mpParent->mnDPIScalePercentage;
1356 // update the recalculated values for logical units
1357 // and also tools belonging to the values
1358 if (IsMapModeEnabled())
1360 MapMode aMapMode = GetMapMode();
1361 SetMapMode();
1362 SetMapMode( aMapMode );
1366 void Window::ImplPointToLogic(vcl::RenderContext& rRenderContext, vcl::Font& rFont) const
1368 Size aSize = rFont.GetFontSize();
1370 if (aSize.Width())
1372 aSize.Width() *= mpWindowImpl->mpFrameData->mnDPIX;
1373 aSize.Width() += 72 / 2;
1374 aSize.Width() /= 72;
1376 aSize.Height() *= mpWindowImpl->mpFrameData->mnDPIY;
1377 aSize.Height() += 72/2;
1378 aSize.Height() /= 72;
1380 if (rRenderContext.IsMapModeEnabled())
1381 aSize = rRenderContext.PixelToLogic(aSize);
1383 rFont.SetFontSize(aSize);
1386 void Window::ImplLogicToPoint(vcl::RenderContext& rRenderContext, vcl::Font& rFont) const
1388 Size aSize = rFont.GetFontSize();
1390 if (rRenderContext.IsMapModeEnabled())
1391 aSize = rRenderContext.LogicToPixel(aSize);
1393 if (aSize.Width())
1395 aSize.Width() *= 72;
1396 aSize.Width() += mpWindowImpl->mpFrameData->mnDPIX / 2;
1397 aSize.Width() /= mpWindowImpl->mpFrameData->mnDPIX;
1399 aSize.Height() *= 72;
1400 aSize.Height() += mpWindowImpl->mpFrameData->mnDPIY / 2;
1401 aSize.Height() /= mpWindowImpl->mpFrameData->mnDPIY;
1403 rFont.SetFontSize(aSize);
1406 bool Window::ImplUpdatePos()
1408 bool bSysChild = false;
1410 if ( ImplIsOverlapWindow() )
1412 mnOutOffX = mpWindowImpl->mnX;
1413 mnOutOffY = mpWindowImpl->mnY;
1415 else
1417 vcl::Window* pParent = ImplGetParent();
1419 mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
1420 mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
1423 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1424 while ( pChild )
1426 if ( pChild->ImplUpdatePos() )
1427 bSysChild = true;
1428 pChild = pChild->mpWindowImpl->mpNext;
1431 if ( mpWindowImpl->mpSysObj )
1432 bSysChild = true;
1434 return bSysChild;
1437 void Window::ImplUpdateSysObjPos()
1439 if ( mpWindowImpl->mpSysObj )
1440 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1442 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1443 while ( pChild )
1445 pChild->ImplUpdateSysObjPos();
1446 pChild = pChild->mpWindowImpl->mpNext;
1450 void Window::ImplPosSizeWindow( long nX, long nY,
1451 long nWidth, long nHeight, PosSizeFlags nFlags )
1453 bool bNewPos = false;
1454 bool bNewSize = false;
1455 bool bCopyBits = false;
1456 long nOldOutOffX = mnOutOffX;
1457 long nOldOutOffY = mnOutOffY;
1458 long nOldOutWidth = mnOutWidth;
1459 long nOldOutHeight = mnOutHeight;
1460 vcl::Region* pOverlapRegion = nullptr;
1461 vcl::Region* pOldRegion = nullptr;
1463 if ( IsReallyVisible() )
1465 Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
1466 Size( nOldOutWidth, nOldOutHeight ) );
1467 pOldRegion = new vcl::Region( aOldWinRect );
1468 if ( mpWindowImpl->mbWinRegion )
1469 pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1471 if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
1472 !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
1473 !HasPaintEvent() )
1474 bCopyBits = true;
1477 bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
1478 if ( nFlags & PosSizeFlags::Width )
1480 if(!( nFlags & PosSizeFlags::X ))
1482 nX = mpWindowImpl->mnX;
1483 nFlags |= PosSizeFlags::X;
1484 bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
1487 if ( nWidth < 0 )
1488 nWidth = 0;
1489 if ( nWidth != mnOutWidth )
1491 mnOutWidth = nWidth;
1492 bNewSize = true;
1493 bCopyBits = false;
1496 if ( nFlags & PosSizeFlags::Height )
1498 if ( nHeight < 0 )
1499 nHeight = 0;
1500 if ( nHeight != mnOutHeight )
1502 mnOutHeight = nHeight;
1503 bNewSize = true;
1504 bCopyBits = false;
1508 if ( nFlags & PosSizeFlags::X )
1510 long nOrgX = nX;
1511 // --- RTL --- (compare the screen coordinates)
1512 Point aPtDev( Point( nX+mnOutOffX, 0 ) );
1513 OutputDevice *pOutDev = GetOutDev();
1514 if( pOutDev->HasMirroredGraphics() )
1516 mpGraphics->mirror( aPtDev.X(), this );
1518 // #106948# always mirror our pos if our parent is not mirroring, even
1519 // if we are also not mirroring
1520 // --- RTL --- check if parent is in different coordinates
1521 if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1523 // --- RTL --- (re-mirror at parent window)
1524 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1526 /* #i99166# An LTR window in RTL UI that gets sized only would be
1527 expected to not moved its upper left point
1529 if( bnXRecycled )
1531 if( ImplIsAntiparallel() )
1533 aPtDev.X() = mpWindowImpl->mnAbsScreenX;
1534 nOrgX = mpWindowImpl->maPos.X();
1538 else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1540 // mirrored window in LTR UI
1542 // --- RTL --- (re-mirror at parent window)
1543 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1547 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1548 if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
1550 if ( bCopyBits && !pOverlapRegion )
1552 pOverlapRegion = new vcl::Region();
1553 ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
1554 Size( mnOutWidth, mnOutHeight ) ),
1555 *pOverlapRegion, false, true );
1557 mpWindowImpl->mnX = nX;
1558 mpWindowImpl->maPos.X() = nOrgX;
1559 mpWindowImpl->mnAbsScreenX = aPtDev.X(); // --- RTL --- (store real screen pos)
1560 bNewPos = true;
1563 if ( nFlags & PosSizeFlags::Y )
1565 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1566 if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
1568 if ( bCopyBits && !pOverlapRegion )
1570 pOverlapRegion = new vcl::Region();
1571 ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
1572 Size( mnOutWidth, mnOutHeight ) ),
1573 *pOverlapRegion, false, true );
1575 mpWindowImpl->mnY = nY;
1576 mpWindowImpl->maPos.Y() = nY;
1577 bNewPos = true;
1581 if ( bNewPos || bNewSize )
1583 bool bUpdateSysObjPos = false;
1584 if ( bNewPos )
1585 bUpdateSysObjPos = ImplUpdatePos();
1587 // the borderwindow always specifies the position for its client window
1588 if ( mpWindowImpl->mpBorderWindow )
1589 mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
1591 if ( mpWindowImpl->mpClientWindow )
1593 mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
1594 mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
1595 mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
1596 mnOutHeight-mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
1597 PosSizeFlags::X | PosSizeFlags::Y |
1598 PosSizeFlags::Width | PosSizeFlags::Height );
1599 // If we have a client window, then this is the position
1600 // of the Application's floating windows
1601 mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
1602 if ( bNewPos )
1604 if ( mpWindowImpl->mpClientWindow->IsVisible() )
1606 mpWindowImpl->mpClientWindow->ImplCallMove();
1608 else
1610 mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
1615 // Move()/Resize() will be called only for Show(), such that
1616 // at least one is called before Show()
1617 if ( IsVisible() )
1619 if ( bNewPos )
1621 ImplCallMove();
1623 if ( bNewSize )
1625 ImplCallResize();
1628 else
1630 if ( bNewPos )
1631 mpWindowImpl->mbCallMove = true;
1632 if ( bNewSize )
1633 mpWindowImpl->mbCallResize = true;
1636 bool bUpdateSysObjClip = false;
1637 if ( IsReallyVisible() )
1639 if ( bNewPos || bNewSize )
1641 // set Clip-Flag
1642 bUpdateSysObjClip = !ImplSetClipFlag( true );
1645 // invalidate window content ?
1646 if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
1648 if ( bNewPos )
1650 bool bInvalidate = false;
1651 bool bParentPaint = true;
1652 if ( !ImplIsOverlapWindow() )
1653 bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
1654 if ( bCopyBits && bParentPaint && !HasPaintEvent() )
1656 Point aPoint( mnOutOffX, mnOutOffY );
1657 vcl::Region aRegion( Rectangle( aPoint,
1658 Size( mnOutWidth, mnOutHeight ) ) );
1659 if ( mpWindowImpl->mbWinRegion )
1660 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1661 ImplClipBoundaries( aRegion, false, true );
1662 if ( !pOverlapRegion->IsEmpty() )
1664 pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
1665 aRegion.Exclude( *pOverlapRegion );
1667 if ( !aRegion.IsEmpty() )
1669 // adapt Paint areas
1670 ImplMoveAllInvalidateRegions( Rectangle( Point( nOldOutOffX, nOldOutOffY ),
1671 Size( nOldOutWidth, nOldOutHeight ) ),
1672 mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
1673 true );
1674 SalGraphics* pGraphics = ImplGetFrameGraphics();
1675 if ( pGraphics )
1678 OutputDevice *pOutDev = GetOutDev();
1679 const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics );
1680 if ( bSelectClipRegion )
1682 pGraphics->CopyArea( mnOutOffX, mnOutOffY,
1683 nOldOutOffX, nOldOutOffY,
1684 nOldOutWidth, nOldOutHeight,
1685 this );
1687 else
1688 bInvalidate = true;
1690 else
1691 bInvalidate = true;
1692 if ( !bInvalidate )
1694 if ( !pOverlapRegion->IsEmpty() )
1695 ImplInvalidateFrameRegion( pOverlapRegion, InvalidateFlags::Children );
1698 else
1699 bInvalidate = true;
1701 else
1702 bInvalidate = true;
1703 if ( bInvalidate )
1704 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
1706 else
1708 Point aPoint( mnOutOffX, mnOutOffY );
1709 vcl::Region aRegion( Rectangle( aPoint,
1710 Size( mnOutWidth, mnOutHeight ) ) );
1711 aRegion.Exclude( *pOldRegion );
1712 if ( mpWindowImpl->mbWinRegion )
1713 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1714 ImplClipBoundaries( aRegion, false, true );
1715 if ( !aRegion.IsEmpty() )
1716 ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
1720 // invalidate Parent or Overlaps
1721 if ( bNewPos ||
1722 (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
1724 vcl::Region aRegion( *pOldRegion );
1725 if ( !mpWindowImpl->mbPaintTransparent )
1726 ImplExcludeWindowRegion( aRegion );
1727 ImplClipBoundaries( aRegion, false, true );
1728 if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
1729 ImplInvalidateParentFrameRegion( aRegion );
1733 // adapt system objects
1734 if ( bUpdateSysObjClip )
1735 ImplUpdateSysObjClip();
1736 if ( bUpdateSysObjPos )
1737 ImplUpdateSysObjPos();
1738 if ( bNewSize && mpWindowImpl->mpSysObj )
1739 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1742 delete pOverlapRegion;
1743 delete pOldRegion;
1746 void Window::ImplNewInputContext()
1748 ImplSVData* pSVData = ImplGetSVData();
1749 vcl::Window* pFocusWin = pSVData->maWinData.mpFocusWin;
1750 if ( !pFocusWin )
1751 return;
1753 // Is InputContext changed?
1754 const InputContext& rInputContext = pFocusWin->GetInputContext();
1755 if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
1756 return;
1758 pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
1760 SalInputContext aNewContext;
1761 const vcl::Font& rFont = rInputContext.GetFont();
1762 const OUString& rFontName = rFont.GetFamilyName();
1763 LogicalFontInstance* pFontInstance = nullptr;
1764 aNewContext.mpFont = nullptr;
1765 if (!rFontName.isEmpty())
1767 OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
1768 Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() );
1769 if ( !aSize.Height() )
1771 // only set default sizes if the font height in logical
1772 // coordinates equals 0
1773 if ( rFont.GetFontSize().Height() )
1774 aSize.Height() = 1;
1775 else
1776 aSize.Height() = (12*pFocusWin->mnDPIY)/72;
1778 pFontInstance = pFocusWin->mpFontCache->GetFontInstance( pFocusWin->mpFontCollection,
1779 rFont, aSize, static_cast<float>(aSize.Height()) );
1780 if ( pFontInstance )
1781 aNewContext.mpFont = &pFontInstance->maFontSelData;
1783 aNewContext.meLanguage = rFont.GetLanguage();
1784 aNewContext.mnOptions = rInputContext.GetOptions();
1785 pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
1787 if ( pFontInstance )
1788 pFocusWin->mpFontCache->Release( pFontInstance );
1791 void Window::doLazyDelete()
1793 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this);
1794 DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(this);
1795 if( pSysWin || ( pDockWin && pDockWin->IsFloatingMode() ) )
1797 Show( false );
1798 SetParent( ImplGetDefaultWindow() );
1800 vcl::LazyDeletor::Delete( this );
1803 KeyIndicatorState Window::GetIndicatorState() const
1805 return mpWindowImpl->mpFrame->GetIndicatorState();
1808 void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
1810 mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
1813 void Window::KeyInput( const KeyEvent& rKEvt )
1815 KeyCode cod = rKEvt.GetKeyCode ();
1816 bool accel = ImplGetSVData()->maNWFData.mbEnableAccel;
1817 bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
1819 // do not respond to accelerators unless Alt is held */
1820 if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
1822 if (!accel) return;
1823 if (autoacc && cod.GetModifier () != KEY_MOD2) return;
1826 NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt );
1827 if ( !CompatNotify( aNEvt ) )
1828 mpWindowImpl->mbKeyInput = true;
1831 void Window::KeyUp( const KeyEvent& rKEvt )
1833 NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt );
1834 if ( !CompatNotify( aNEvt ) )
1835 mpWindowImpl->mbKeyUp = true;
1838 void Window::Draw( OutputDevice*, const Point&, const Size&, DrawFlags )
1842 void Window::Move() {}
1844 void Window::Resize() {}
1846 void Window::Activate() {}
1848 void Window::Deactivate() {}
1850 void Window::GetFocus()
1852 if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
1854 VclPtr<vcl::Window> xWindow(this);
1855 mpWindowImpl->mpLastFocusWindow->GrabFocus();
1856 if( xWindow->IsDisposed() )
1857 return;
1860 NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
1861 CompatNotify( aNEvt );
1864 void Window::LoseFocus()
1866 NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this );
1867 CompatNotify( aNEvt );
1870 void Window::RequestHelp( const HelpEvent& rHEvt )
1872 // if Balloon-Help is requested, show the balloon
1873 // with help text set
1874 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1876 OUString rStr = GetHelpText();
1877 if ( rStr.isEmpty() )
1878 rStr = GetQuickHelpText();
1879 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1880 ImplGetParent()->RequestHelp( rHEvt );
1881 else
1883 Point aPos = GetPosPixel();
1884 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1885 aPos = ImplGetParent()->OutputToScreenPixel( aPos );
1886 Rectangle aRect( aPos, GetSizePixel() );
1888 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
1891 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1893 const OUString& rStr = GetQuickHelpText();
1894 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1895 ImplGetParent()->RequestHelp( rHEvt );
1896 else
1898 Point aPos = GetPosPixel();
1899 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1900 aPos = ImplGetParent()->OutputToScreenPixel( aPos );
1901 Rectangle aRect( aPos, GetSizePixel() );
1902 OUString aHelpText;
1903 if ( !rStr.isEmpty() )
1904 aHelpText = GetHelpText();
1905 Help::ShowQuickHelp( this, aRect, rStr, aHelpText, QuickHelpFlags::CtrlText );
1908 else
1910 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
1911 if ( aStrHelpId.isEmpty() && ImplGetParent() )
1912 ImplGetParent()->RequestHelp( rHEvt );
1913 else
1915 Help* pHelp = Application::GetHelp();
1916 if ( pHelp )
1918 if( !aStrHelpId.isEmpty() )
1919 pHelp->Start( aStrHelpId, this );
1920 else
1921 pHelp->Start( OOO_HELP_INDEX, this );
1927 void Window::Command( const CommandEvent& rCEvt )
1929 CallEventListeners( VCLEVENT_WINDOW_COMMAND, const_cast<CommandEvent *>(&rCEvt) );
1931 NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt );
1932 if ( !CompatNotify( aNEvt ) )
1933 mpWindowImpl->mbCommand = true;
1936 void Window::Tracking( const TrackingEvent& rTEvt )
1939 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1940 if( pWrapper )
1941 pWrapper->Tracking( rTEvt );
1944 void Window::StateChanged(StateChangedType eType)
1946 switch (eType)
1948 //stuff that doesn't invalidate the layout
1949 case StateChangedType::ControlForeground:
1950 case StateChangedType::ControlBackground:
1951 case StateChangedType::Transparent:
1952 case StateChangedType::UpdateMode:
1953 case StateChangedType::ReadOnly:
1954 case StateChangedType::Enable:
1955 case StateChangedType::State:
1956 case StateChangedType::Data:
1957 case StateChangedType::InitShow:
1958 case StateChangedType::ControlFocus:
1959 break;
1960 //stuff that does invalidate the layout
1961 default:
1962 queue_resize(eType);
1963 break;
1967 bool Window::IsLocked() const
1969 if ( mpWindowImpl->mnLockCount != 0 )
1970 return true;
1972 VclPtr<vcl::Window> pChild = mpWindowImpl->mpFirstChild;
1973 while ( pChild )
1975 if ( pChild->IsLocked() )
1976 return true;
1977 pChild = pChild->mpWindowImpl->mpNext;
1980 return false;
1983 void Window::SetStyle( WinBits nStyle )
1985 if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
1987 mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
1988 mpWindowImpl->mnStyle = nStyle;
1989 CompatStateChanged( StateChangedType::Style );
1993 void Window::SetExtendedStyle( WinBits nExtendedStyle )
1996 if ( mpWindowImpl->mnExtendedStyle != nExtendedStyle )
1998 vcl::Window* pWindow = ImplGetBorderWindow();
1999 if( ! pWindow )
2000 pWindow = this;
2001 if( pWindow->mpWindowImpl->mbFrame )
2003 SalExtStyle nExt = 0;
2004 if( (nExtendedStyle & WB_EXT_DOCUMENT) )
2005 nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
2006 if( (nExtendedStyle & WB_EXT_DOCMODIFIED) )
2007 nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
2009 pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
2011 mpWindowImpl->mnPrevExtendedStyle = mpWindowImpl->mnExtendedStyle;
2012 mpWindowImpl->mnExtendedStyle = nExtendedStyle;
2013 CompatStateChanged( StateChangedType::ExtendedStyle );
2017 void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
2020 if ( mpWindowImpl->mpBorderWindow )
2022 if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
2023 ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
2024 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
2027 // this is a little awkward: some controls (e.g. svtools ProgressBar)
2028 // cannot avoid getting constructed with WB_BORDER but want to disable
2029 // borders in case of NWF drawing. So they need a method to remove their border window
2030 VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow;
2031 // remove us as border window's client
2032 pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
2033 mpWindowImpl->mpBorderWindow = nullptr;
2034 mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
2035 // reparent us above the border window
2036 SetParent( pBorderWin->mpWindowImpl->mpParent );
2037 // set us to the position and size of our previous border
2038 Point aBorderPos( pBorderWin->GetPosPixel() );
2039 Size aBorderSize( pBorderWin->GetSizePixel() );
2040 setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
2041 // release border window
2042 pBorderWin.disposeAndClear();
2044 // set new style bits
2045 SetStyle( GetStyle() & (~WB_BORDER) );
2047 else
2049 if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
2050 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
2051 else
2052 mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
2057 WindowBorderStyle Window::GetBorderStyle() const
2060 if ( mpWindowImpl->mpBorderWindow )
2062 if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
2063 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
2064 else
2065 return mpWindowImpl->mpBorderWindow->GetBorderStyle();
2068 return WindowBorderStyle::NONE;
2071 long Window::CalcTitleWidth() const
2074 if ( mpWindowImpl->mpBorderWindow )
2076 if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
2077 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
2078 else
2079 return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
2081 else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
2083 // we guess the width for frame windows as we do not know the
2084 // border of external dialogs
2085 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2086 vcl::Font aFont = GetFont();
2087 const_cast<vcl::Window*>(this)->SetPointFont(*const_cast<Window*>(this), rStyleSettings.GetTitleFont());
2088 long nTitleWidth = GetTextWidth( GetText() );
2089 const_cast<vcl::Window*>(this)->SetFont( aFont );
2090 nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
2091 nTitleWidth += rStyleSettings.GetBorderSize() * 2;
2092 nTitleWidth += 10;
2093 return nTitleWidth;
2096 return 0;
2099 void Window::SetInputContext( const InputContext& rInputContext )
2102 mpWindowImpl->maInputContext = rInputContext;
2103 if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
2104 ImplNewInputContext();
2107 void Window::PostExtTextInputEvent(int nType, const OUString& rText)
2109 switch (nType)
2111 case VCLEVENT_WINDOW_EXTTEXTINPUT:
2113 std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]);
2114 for (int i = 0; i < rText.getLength(); ++i) {
2115 pAttr[i] = ExtTextInputAttr::Underline;
2117 SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE };
2118 ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent);
2119 SalExtTextInputPosEvent evt;
2120 ImplWindowFrameProc(this, SalEvent::ExtTextInputPos, &evt);
2122 break;
2123 case VCLEVENT_WINDOW_ENDEXTTEXTINPUT:
2124 ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr);
2125 break;
2126 default:
2127 assert(false);
2131 void Window::EndExtTextInput()
2133 if ( mpWindowImpl->mbExtTextInput )
2134 ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
2137 void Window::SetCursorRect( const Rectangle* pRect, long nExtTextInputWidth )
2140 ImplWinData* pWinData = ImplGetWinData();
2141 if ( pWinData->mpCursorRect )
2143 if ( pRect )
2144 *pWinData->mpCursorRect = *pRect;
2145 else
2147 delete pWinData->mpCursorRect;
2148 pWinData->mpCursorRect = nullptr;
2151 else
2153 if ( pRect )
2154 pWinData->mpCursorRect = new Rectangle( *pRect );
2157 pWinData->mnCursorExtWidth = nExtTextInputWidth;
2161 const Rectangle* Window::GetCursorRect() const
2164 ImplWinData* pWinData = ImplGetWinData();
2165 return pWinData->mpCursorRect;
2168 long Window::GetCursorExtTextInputWidth() const
2171 ImplWinData* pWinData = ImplGetWinData();
2172 return pWinData->mnCursorExtWidth;
2175 void Window::SetCompositionCharRect( const Rectangle* pRect, long nCompositionLength, bool bVertical ) {
2177 ImplWinData* pWinData = ImplGetWinData();
2178 delete[] pWinData->mpCompositionCharRects;
2179 pWinData->mbVertical = bVertical;
2180 pWinData->mpCompositionCharRects = nullptr;
2181 pWinData->mnCompositionCharRects = nCompositionLength;
2182 if ( pRect && (nCompositionLength > 0) )
2184 pWinData->mpCompositionCharRects = new Rectangle[nCompositionLength];
2185 for (long i = 0; i < nCompositionLength; ++i)
2186 pWinData->mpCompositionCharRects[i] = pRect[i];
2190 void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
2192 rAllChildren.push_back( this );
2194 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2195 while ( pChild )
2197 pChild->CollectChildren( rAllChildren );
2198 pChild = pChild->mpWindowImpl->mpNext;
2202 void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
2204 vcl::Font aFont = rFont;
2205 ImplPointToLogic(rRenderContext, aFont);
2206 rRenderContext.SetFont(aFont);
2209 vcl::Font Window::GetPointFont(vcl::RenderContext& rRenderContext) const
2211 vcl::Font aFont = rRenderContext.GetFont();
2212 ImplLogicToPoint(rRenderContext, aFont);
2213 return aFont;
2216 void Window::Show(bool bVisible, ShowFlags nFlags)
2218 if ( IsDisposed() || mpWindowImpl->mbVisible == bVisible )
2219 return;
2221 VclPtr<vcl::Window> xWindow(this);
2223 bool bRealVisibilityChanged = false;
2224 mpWindowImpl->mbVisible = bVisible;
2226 if ( !bVisible )
2228 ImplHideAllOverlaps();
2229 if( xWindow->IsDisposed() )
2230 return;
2232 if ( mpWindowImpl->mpBorderWindow )
2234 bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
2235 if ( mpWindowImpl->mbNoParentUpdate )
2236 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
2237 mpWindowImpl->mpBorderWindow->Show( false, nFlags );
2238 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
2240 else if ( mpWindowImpl->mbFrame )
2242 mpWindowImpl->mbSuppressAccessibilityEvents = true;
2243 mpWindowImpl->mpFrame->Show( false );
2246 CompatStateChanged( StateChangedType::Visible );
2248 if ( mpWindowImpl->mbReallyVisible )
2250 if ( mpWindowImpl->mbInitWinClipRegion )
2251 ImplInitWinClipRegion();
2253 vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
2255 if( xWindow->IsDisposed() )
2256 return;
2258 bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
2259 ImplResetReallyVisible();
2260 ImplSetClipFlag();
2262 if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
2264 // convert focus
2265 if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
2267 if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
2268 mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
2269 ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
2271 mpWindowImpl->mpOverlapWindow->GrabFocus();
2275 if ( !mpWindowImpl->mbFrame )
2277 if( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget )
2280 * #i48371# native theming: some themes draw outside the control
2281 * area we tell them to (bad thing, but we cannot do much about it ).
2282 * On hiding these controls they get invalidated with their window rectangle
2283 * which leads to the parts outside the control area being left and not
2284 * invalidated. Workaround: invalidate an area on the parent, too
2286 const int workaround_border = 5;
2287 Rectangle aBounds( aInvRegion.GetBoundRect() );
2288 aBounds.Left() -= workaround_border;
2289 aBounds.Top() -= workaround_border;
2290 aBounds.Right() += workaround_border;
2291 aBounds.Bottom() += workaround_border;
2292 aInvRegion = aBounds;
2294 if ( !mpWindowImpl->mbNoParentUpdate && !(nFlags & ShowFlags::NoParentUpdate) )
2296 if ( !aInvRegion.IsEmpty() )
2297 ImplInvalidateParentFrameRegion( aInvRegion );
2299 ImplGenerateMouseMove();
2303 else
2305 // inherit native widget flag for form controls
2306 // required here, because frames never show up in the child hierarchy - which should be fixed....
2307 // eg, the drop down of a combobox which is a system floating window
2308 if( mpWindowImpl->mbFrame && GetParent() && GetParent()->IsCompoundControl() &&
2309 GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() )
2311 EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
2314 if ( mpWindowImpl->mbCallMove )
2316 ImplCallMove();
2318 if ( mpWindowImpl->mbCallResize )
2320 ImplCallResize();
2323 CompatStateChanged( StateChangedType::Visible );
2325 vcl::Window* pTestParent;
2326 if ( ImplIsOverlapWindow() )
2327 pTestParent = mpWindowImpl->mpOverlapWindow;
2328 else
2329 pTestParent = ImplGetParent();
2330 if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
2332 // if a window becomes visible, send all child windows a StateChange,
2333 // such that these can initialise themselves
2334 ImplCallInitShow();
2336 // If it is a SystemWindow it automatically pops up on top of
2337 // all other windows if needed.
2338 if ( ImplIsOverlapWindow() && !(nFlags & ShowFlags::NoActivate) )
2340 ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE );
2341 ImplFocusToTop( ToTopFlags::NONE, false );
2344 // adjust mpWindowImpl->mbReallyVisible
2345 bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
2346 ImplSetReallyVisible();
2348 // assure clip rectangles will be recalculated
2349 ImplSetClipFlag();
2351 if ( !mpWindowImpl->mbFrame )
2353 InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
2354 if( ! IsPaintTransparent() )
2355 nInvalidateFlags |= InvalidateFlags::NoTransparent;
2356 ImplInvalidate( nullptr, nInvalidateFlags );
2357 ImplGenerateMouseMove();
2361 if ( mpWindowImpl->mpBorderWindow )
2362 mpWindowImpl->mpBorderWindow->Show( true, nFlags );
2363 else if ( mpWindowImpl->mbFrame )
2365 // #106431#, hide SplashScreen
2366 ImplSVData* pSVData = ImplGetSVData();
2367 if ( !pSVData->mpIntroWindow )
2369 // The right way would be just to call this (not even in the 'if')
2370 GetpApp()->InitFinished();
2372 else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
2374 // ... but the VCL splash is broken, and it needs this
2375 // (for ./soffice .uno:NewDoc)
2376 pSVData->mpIntroWindow->Hide();
2379 //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
2380 mpWindowImpl->mbSuppressAccessibilityEvents = false;
2382 mpWindowImpl->mbPaintFrame = true;
2383 if (!Application::GetSettings().GetMiscSettings().GetPseudoHeadless())
2385 bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
2386 mpWindowImpl->mpFrame->Show( true, bNoActivate );
2388 if( xWindow->IsDisposed() )
2389 return;
2391 // Query the correct size of the window, if we are waiting for
2392 // a system resize
2393 if ( mpWindowImpl->mbWaitSystemResize )
2395 long nOutWidth;
2396 long nOutHeight;
2397 mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
2398 ImplHandleResize( this, nOutWidth, nOutHeight );
2401 if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel())
2402 // Make sure that the buffer size matches the window size, even if no resize was needed.
2403 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
2406 if( xWindow->IsDisposed() )
2407 return;
2409 ImplShowAllOverlaps();
2412 if( xWindow->IsDisposed() )
2413 return;
2415 // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
2416 // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
2417 // we re-use the SHOW/HIDE events this way, with this particular semantics).
2418 // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
2419 // now only notify with a NULL data pointer, for all other clients except the access bridge.
2420 if ( !bRealVisibilityChanged )
2421 CallEventListeners( mpWindowImpl->mbVisible ? VCLEVENT_WINDOW_SHOW : VCLEVENT_WINDOW_HIDE );
2422 if( xWindow->IsDisposed() )
2423 return;
2427 Size Window::GetSizePixel() const
2429 if (!mpWindowImpl)
2431 SAL_WARN("vcl.layout", "WTF no windowimpl");
2432 return Size(0,0);
2435 // #i43257# trigger pending resize handler to assure correct window sizes
2436 if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
2438 VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
2439 mpWindowImpl->mpFrameData->maResizeIdle.Stop();
2440 mpWindowImpl->mpFrameData->maResizeIdle.GetIdleHdl().Call( nullptr );
2441 if( xWindow->IsDisposed() )
2442 return Size(0,0);
2445 return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
2446 mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
2449 void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2450 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2452 rLeftBorder = mpWindowImpl->mnLeftBorder;
2453 rTopBorder = mpWindowImpl->mnTopBorder;
2454 rRightBorder = mpWindowImpl->mnRightBorder;
2455 rBottomBorder = mpWindowImpl->mnBottomBorder;
2458 void Window::Enable( bool bEnable, bool bChild )
2460 if ( IsDisposed() )
2461 return;
2463 if ( !bEnable )
2465 // the tracking mode will be stopped or the capture will be stolen
2466 // when a window is disabled,
2467 if ( IsTracking() )
2468 EndTracking( TrackingEventFlags::Cancel );
2469 if ( IsMouseCaptured() )
2470 ReleaseMouse();
2471 // try to pass focus to the next control
2472 // if the window has focus and is contained in the dialog control
2473 // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow().
2474 // Otherwise ImplDlgCtrlNextWindow() should be used
2475 if ( HasFocus() )
2476 ImplDlgCtrlNextWindow();
2479 if ( mpWindowImpl->mpBorderWindow )
2481 mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
2482 if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
2483 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2484 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
2487 // #i56102# restore app focus win in case the
2488 // window was disabled when the frame focus changed
2489 ImplSVData* pSVData = ImplGetSVData();
2490 if( bEnable &&
2491 pSVData->maWinData.mpFocusWin == nullptr &&
2492 mpWindowImpl->mpFrameData->mbHasFocus &&
2493 mpWindowImpl->mpFrameData->mpFocusWin == this )
2494 pSVData->maWinData.mpFocusWin = this;
2496 if ( mpWindowImpl->mbDisabled != !bEnable )
2498 mpWindowImpl->mbDisabled = !bEnable;
2499 if ( mpWindowImpl->mpSysObj )
2500 mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
2501 CompatStateChanged( StateChangedType::Enable );
2503 CallEventListeners( bEnable ? VCLEVENT_WINDOW_ENABLED : VCLEVENT_WINDOW_DISABLED );
2506 if ( bChild )
2508 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2509 while ( pChild )
2511 pChild->Enable( bEnable, bChild );
2512 pChild = pChild->mpWindowImpl->mpNext;
2516 if ( IsReallyVisible() )
2517 ImplGenerateMouseMove();
2520 void Window::SetCallHandlersOnInputDisabled( bool bCall )
2522 mpWindowImpl->mbCallHandlersDuringInputDisabled = bCall;
2524 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2525 while ( pChild )
2527 pChild->SetCallHandlersOnInputDisabled( bCall );
2528 pChild = pChild->mpWindowImpl->mpNext;
2532 bool Window::IsCallHandlersOnInputDisabled() const
2534 return mpWindowImpl->mbCallHandlersDuringInputDisabled;
2537 void Window::EnableInput( bool bEnable, bool bChild )
2539 if (!mpWindowImpl)
2540 return;
2542 bool bNotify = (bEnable != mpWindowImpl->mbInputDisabled);
2543 if ( mpWindowImpl->mpBorderWindow )
2545 mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
2546 if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
2547 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2548 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
2551 if ( (! bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) ||
2552 ( bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled) )
2554 // automatically stop the tracking mode or steal capture
2555 // if the window is disabled
2556 if ( !bEnable )
2558 if ( IsTracking() )
2559 EndTracking( TrackingEventFlags::Cancel );
2560 if ( IsMouseCaptured() )
2561 ReleaseMouse();
2564 if ( mpWindowImpl->mbInputDisabled != !bEnable )
2566 mpWindowImpl->mbInputDisabled = !bEnable;
2567 if ( mpWindowImpl->mpSysObj )
2568 mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
2572 // #i56102# restore app focus win in case the
2573 // window was disabled when the frame focus changed
2574 ImplSVData* pSVData = ImplGetSVData();
2575 if( bEnable &&
2576 pSVData->maWinData.mpFocusWin == nullptr &&
2577 mpWindowImpl->mpFrameData->mbHasFocus &&
2578 mpWindowImpl->mpFrameData->mpFocusWin == this )
2579 pSVData->maWinData.mpFocusWin = this;
2581 if ( bChild )
2583 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2584 while ( pChild )
2586 pChild->EnableInput( bEnable, bChild );
2587 pChild = pChild->mpWindowImpl->mpNext;
2591 if ( IsReallyVisible() )
2592 ImplGenerateMouseMove();
2594 // #104827# notify parent
2595 if ( bNotify )
2597 NotifyEvent aNEvt( bEnable ? MouseNotifyEvent::INPUTENABLE : MouseNotifyEvent::INPUTDISABLE, this );
2598 CompatNotify( aNEvt );
2602 void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
2604 if (!mpWindowImpl)
2605 return;
2607 EnableInput( bEnable );
2609 // pExecuteWindow is the first Overlap-Frame --> if this
2610 // shouldn't be the case, than this must be changed in dialog.cxx
2611 if( pExcludeWindow )
2612 pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
2613 vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
2614 while ( pSysWin )
2616 // Is Window in the path from this window
2617 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
2619 // Is Window not in the exclude window path or not the
2620 // exclude window, than change the status
2621 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
2622 pSysWin->EnableInput( bEnable );
2624 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
2627 // enable/disable floating system windows as well
2628 vcl::Window* pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
2629 while ( pFrameWin )
2631 if( pFrameWin->ImplIsFloatingWindow() )
2633 // Is Window in the path from this window
2634 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
2636 // Is Window not in the exclude window path or not the
2637 // exclude window, than change the status
2638 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
2639 pFrameWin->EnableInput( bEnable );
2642 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
2645 // the same for ownerdraw floating windows
2646 if( mpWindowImpl->mbFrame )
2648 ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
2649 auto p = rList.begin();
2650 while( p != rList.end() )
2652 // Is Window in the path from this window
2653 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( (*p), true ) )
2655 // Is Window not in the exclude window path or not the
2656 // exclude window, than change the status
2657 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( (*p), true ) )
2658 (*p)->EnableInput( bEnable );
2660 ++p;
2665 void Window::AlwaysEnableInput( bool bAlways, bool bChild )
2668 if ( mpWindowImpl->mpBorderWindow )
2669 mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
2671 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
2673 mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
2675 if ( bAlways )
2676 EnableInput( true, false );
2678 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
2680 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2683 if ( bChild )
2685 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2686 while ( pChild )
2688 pChild->AlwaysEnableInput( bAlways, bChild );
2689 pChild = pChild->mpWindowImpl->mpNext;
2694 void Window::AlwaysDisableInput( bool bAlways, bool bChild )
2697 if ( mpWindowImpl->mpBorderWindow )
2698 mpWindowImpl->mpBorderWindow->AlwaysDisableInput( bAlways, false );
2700 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled )
2702 mpWindowImpl->meAlwaysInputMode = AlwaysInputDisabled;
2704 if ( bAlways )
2705 EnableInput( false, false );
2707 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled )
2709 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2712 if ( bChild )
2714 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2715 while ( pChild )
2717 pChild->AlwaysDisableInput( bAlways, bChild );
2718 pChild = pChild->mpWindowImpl->mpNext;
2723 void Window::SetActivateMode( ActivateModeFlags nMode )
2726 if ( mpWindowImpl->mpBorderWindow )
2727 mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
2729 if ( mpWindowImpl->mnActivateMode != nMode )
2731 mpWindowImpl->mnActivateMode = nMode;
2733 // possibly trigger Decativate/Activate
2734 if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
2736 if ( (mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW)) &&
2737 !HasChildPathFocus( true ) )
2739 mpWindowImpl->mbActive = false;
2740 Deactivate();
2743 else
2745 if ( !mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW) )
2747 mpWindowImpl->mbActive = true;
2748 Activate();
2754 void Window::setPosSizePixel( long nX, long nY,
2755 long nWidth, long nHeight, PosSizeFlags nFlags )
2757 bool bHasValidSize = !mpWindowImpl->mbDefSize;
2759 if ( nFlags & PosSizeFlags::Pos )
2760 mpWindowImpl->mbDefPos = false;
2761 if ( nFlags & PosSizeFlags::Size )
2762 mpWindowImpl->mbDefSize = false;
2764 // The top BorderWindow is the window which is to be positioned
2765 VclPtr<vcl::Window> pWindow = this;
2766 while ( pWindow->mpWindowImpl->mpBorderWindow )
2767 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
2769 if ( pWindow->mpWindowImpl->mbFrame )
2771 // Note: if we're positioning a frame, the coordinates are interpreted
2772 // as being the top-left corner of the window's client area and NOT
2773 // as the position of the border ! (due to limitations of several UNIX window managers)
2774 long nOldWidth = pWindow->mnOutWidth;
2776 if ( !(nFlags & PosSizeFlags::Width) )
2777 nWidth = pWindow->mnOutWidth;
2778 if ( !(nFlags & PosSizeFlags::Height) )
2779 nHeight = pWindow->mnOutHeight;
2781 sal_uInt16 nSysFlags=0;
2782 VclPtr<vcl::Window> pParent = GetParent();
2783 VclPtr<vcl::Window> pWinParent = pWindow->GetParent();
2785 if( nFlags & PosSizeFlags::Width )
2786 nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
2787 if( nFlags & PosSizeFlags::Height )
2788 nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
2789 if( nFlags & PosSizeFlags::X )
2791 nSysFlags |= SAL_FRAME_POSSIZE_X;
2792 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2794 nX += pWinParent->mnOutOffX;
2796 if( pParent && pParent->ImplIsAntiparallel() )
2798 // --- RTL --- (re-mirror at parent window)
2799 Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
2800 const OutputDevice *pParentOutDev = pParent->GetOutDev();
2801 pParentOutDev->ReMirror( aRect );
2802 nX = aRect.Left();
2805 if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
2807 // --- RTL --- make sure the old right aligned position is not changed
2808 // system windows will always grow to the right
2809 if ( pWinParent )
2811 OutputDevice *pParentOutDev = pWinParent->GetOutDev();
2812 if( pParentOutDev->HasMirroredGraphics() )
2814 long myWidth = nOldWidth;
2815 if( !myWidth )
2816 myWidth = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth;
2817 if( !myWidth )
2818 myWidth = nWidth;
2819 nFlags |= PosSizeFlags::X;
2820 nSysFlags |= SAL_FRAME_POSSIZE_X;
2821 nX = pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration +
2822 pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth - myWidth - 1 - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX;
2823 if(!(nFlags & PosSizeFlags::Y))
2825 nFlags |= PosSizeFlags::Y;
2826 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2827 nY = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY - pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY -
2828 mpWindowImpl->mpFrame->GetUnmirroredGeometry().nTopDecoration;
2833 if( nFlags & PosSizeFlags::Y )
2835 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2836 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2838 nY += pWinParent->mnOutOffY;
2842 if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
2844 // check for min/max client size and adjust size accordingly
2845 // otherwise it may happen that the resize event is ignored, i.e. the old size remains
2846 // unchanged but ImplHandleResize() is called with the wrong size
2847 SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() );
2848 if( pSystemWindow )
2850 Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
2851 Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
2852 if( nWidth < aMinSize.Width() )
2853 nWidth = aMinSize.Width();
2854 if( nHeight < aMinSize.Height() )
2855 nHeight = aMinSize.Height();
2857 if( nWidth > aMaxSize.Width() )
2858 nWidth = aMaxSize.Width();
2859 if( nHeight > aMaxSize.Height() )
2860 nHeight = aMaxSize.Height();
2864 pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
2866 // Resize should be called directly. If we haven't
2867 // set the correct size, we get a second resize from
2868 // the system with the correct size. This can be happened
2869 // if the size is to small or to large.
2870 ImplHandleResize( pWindow, nWidth, nHeight );
2872 else
2874 pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
2875 if ( IsReallyVisible() )
2876 ImplGenerateMouseMove();
2880 Point Window::GetPosPixel() const
2882 return mpWindowImpl->maPos;
2885 Rectangle Window::GetDesktopRectPixel() const
2887 Rectangle rRect;
2888 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
2889 return rRect;
2892 Point Window::OutputToScreenPixel( const Point& rPos ) const
2894 // relative to top level parent
2895 return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
2898 Point Window::ScreenToOutputPixel( const Point& rPos ) const
2900 // relative to top level parent
2901 return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
2904 long Window::ImplGetUnmirroredOutOffX()
2906 // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
2907 long offx = mnOutOffX;
2908 OutputDevice *pOutDev = GetOutDev();
2909 if( pOutDev->HasMirroredGraphics() )
2911 if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
2913 if ( !ImplIsOverlapWindow() )
2914 offx -= mpWindowImpl->mpParent->mnOutOffX;
2916 offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx;
2918 if ( !ImplIsOverlapWindow() )
2919 offx += mpWindowImpl->mpParent->mnOutOffX;
2923 return offx;
2926 // normalized screen pixel are independent of mirroring
2927 Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
2929 // relative to top level parent
2930 long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2931 return Point( rPos.X()+offx, rPos.Y()+mnOutOffY );
2934 Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
2936 // relative to top level parent
2937 long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2938 return Point( rPos.X()-offx, rPos.Y()-mnOutOffY );
2941 Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
2943 // relative to the screen
2944 Point p = OutputToScreenPixel( rPos );
2945 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2946 p.X() += g.nX;
2947 p.Y() += g.nY;
2948 return p;
2951 Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
2953 // relative to the screen
2954 Point p = ScreenToOutputPixel( rPos );
2955 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2956 p.X() -= g.nX;
2957 p.Y() -= g.nY;
2958 return p;
2961 Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const Rectangle &rRect ) const
2963 // this method creates unmirrored screen coordinates to be compared with the desktop
2964 // and is used for positioning of RTL popup windows correctly on the screen
2965 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2967 Point p1 = OutputToScreenPixel( rRect.TopRight() );
2968 p1.X() = g.nX+g.nWidth-p1.X();
2969 p1.Y() += g.nY;
2971 Point p2 = OutputToScreenPixel( rRect.BottomLeft() );
2972 p2.X() = g.nX+g.nWidth-p2.X();
2973 p2.Y() += g.nY;
2975 return Rectangle( p1, p2 );
2978 Rectangle Window::GetWindowExtentsRelative( vcl::Window *pRelativeWindow ) const
2980 // with decoration
2981 return ImplGetWindowExtentsRelative( pRelativeWindow, false );
2984 Rectangle Window::GetClientWindowExtentsRelative() const
2986 // without decoration
2987 return ImplGetWindowExtentsRelative( nullptr, true );
2990 Rectangle Window::ImplGetWindowExtentsRelative( vcl::Window *pRelativeWindow, bool bClientOnly ) const
2992 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2993 // make sure we use the extent of our border window,
2994 // otherwise we miss a few pixels
2995 const vcl::Window *pWin = (!bClientOnly && mpWindowImpl->mpBorderWindow) ? mpWindowImpl->mpBorderWindow : this;
2997 Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
2998 aPos.X() += g.nX;
2999 aPos.Y() += g.nY;
3000 Size aSize ( pWin->GetSizePixel() );
3001 // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
3002 if( !bClientOnly && (mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WINDOW_WORKWINDOW)) )
3004 aPos.X() -= g.nLeftDecoration;
3005 aPos.Y() -= g.nTopDecoration;
3006 aSize.Width() += g.nLeftDecoration + g.nRightDecoration;
3007 aSize.Height() += g.nTopDecoration + g.nBottomDecoration;
3009 if( pRelativeWindow )
3011 // #106399# express coordinates relative to borderwindow
3012 vcl::Window *pRelWin = (!bClientOnly && pRelativeWindow->mpWindowImpl->mpBorderWindow) ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow;
3013 aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
3015 return Rectangle( aPos, aSize );
3018 void Window::Scroll( long nHorzScroll, long nVertScroll, ScrollFlags nFlags )
3021 ImplScroll( Rectangle( Point( mnOutOffX, mnOutOffY ),
3022 Size( mnOutWidth, mnOutHeight ) ),
3023 nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
3026 void Window::Scroll( long nHorzScroll, long nVertScroll,
3027 const Rectangle& rRect, ScrollFlags nFlags )
3029 OutputDevice *pOutDev = GetOutDev();
3030 Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
3031 aRect.Intersection( Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
3032 if ( !aRect.IsEmpty() )
3033 ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
3036 void Window::Flush()
3039 const Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
3040 mpWindowImpl->mpFrame->Flush( aWinRect );
3043 void Window::SetUpdateMode( bool bUpdate )
3045 mpWindowImpl->mbNoUpdate = !bUpdate;
3046 CompatStateChanged( StateChangedType::UpdateMode );
3049 void Window::GrabFocus()
3051 ImplGrabFocus( GetFocusFlags::NONE );
3054 bool Window::HasFocus() const
3056 return (this == ImplGetSVData()->maWinData.mpFocusWin);
3059 void Window::GrabFocusToDocument()
3061 ImplGrabFocusToDocument(GetFocusFlags::NONE);
3064 void Window::SetFakeFocus( bool bFocus )
3066 ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
3069 bool Window::HasChildPathFocus( bool bSystemWindow ) const
3072 vcl::Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
3073 if ( pFocusWin )
3074 return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
3075 return false;
3078 void Window::SetCursor( vcl::Cursor* pCursor )
3081 if ( mpWindowImpl->mpCursor != pCursor )
3083 if ( mpWindowImpl->mpCursor )
3084 mpWindowImpl->mpCursor->ImplHide();
3085 mpWindowImpl->mpCursor = pCursor;
3086 if ( pCursor )
3087 pCursor->ImplShow();
3091 void Window::SetText( const OUString& rStr )
3093 if (!mpWindowImpl || rStr == mpWindowImpl->maText)
3094 return;
3096 OUString oldTitle( mpWindowImpl->maText );
3097 mpWindowImpl->maText = rStr;
3099 if ( mpWindowImpl->mpBorderWindow )
3100 mpWindowImpl->mpBorderWindow->SetText( rStr );
3101 else if ( mpWindowImpl->mbFrame )
3102 mpWindowImpl->mpFrame->SetTitle( rStr );
3104 CallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
3106 // #107247# needed for accessibility
3107 // The VCLEVENT_WINDOW_FRAMETITLECHANGED is (mis)used to notify accessible name changes.
3108 // Therefore a window, which is labeled by this window, must also notify an accessible
3109 // name change.
3110 if ( IsReallyVisible() )
3112 vcl::Window* pWindow = GetAccessibleRelationLabelFor();
3113 if ( pWindow && pWindow != this )
3114 pWindow->CallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
3117 CompatStateChanged( StateChangedType::Text );
3120 OUString Window::GetText() const
3123 return mpWindowImpl->maText;
3126 OUString Window::GetDisplayText() const
3129 return GetText();
3132 const Wallpaper& Window::GetDisplayBackground() const
3134 // FIXME: fix issue 52349, need to fix this really in
3135 // all NWF enabled controls
3136 const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
3137 if( pTB )
3139 if( IsNativeWidgetEnabled() )
3140 return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
3143 if( !IsBackground() )
3145 if( mpWindowImpl->mpParent )
3146 return mpWindowImpl->mpParent->GetDisplayBackground();
3149 const Wallpaper& rBack = GetBackground();
3150 if( ! rBack.IsBitmap() &&
3151 ! rBack.IsGradient() &&
3152 rBack.GetColor().GetColor() == COL_TRANSPARENT &&
3153 mpWindowImpl->mpParent )
3154 return mpWindowImpl->mpParent->GetDisplayBackground();
3155 return rBack;
3158 const OUString& Window::GetHelpText() const
3160 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
3161 bool bStrHelpId = !aStrHelpId.isEmpty();
3163 if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId )
3165 if ( !IsDialog() && (mpWindowImpl->mnType != WINDOW_TABPAGE) && (mpWindowImpl->mnType != WINDOW_FLOATINGWINDOW) )
3167 Help* pHelp = Application::GetHelp();
3168 if ( pHelp )
3170 mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this);
3171 mpWindowImpl->mbHelpTextDynamic = false;
3175 else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
3177 static const char* pEnv = getenv( "HELP_DEBUG" );
3178 if( pEnv && *pEnv )
3180 OUStringBuffer aTxt( 64+mpWindowImpl->maHelpText.getLength() );
3181 aTxt.append( mpWindowImpl->maHelpText );
3182 aTxt.append( "\n------------------\n" );
3183 aTxt.append( OUString( aStrHelpId ) );
3184 mpWindowImpl->maHelpText = aTxt.makeStringAndClear();
3186 mpWindowImpl->mbHelpTextDynamic = false;
3189 return mpWindowImpl->maHelpText;
3192 void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
3194 assert(mpWindowImpl);
3196 // be safe against re-entrance: first clear the old ref, then assign the new one
3197 mpWindowImpl->mxWindowPeer.clear();
3198 mpWindowImpl->mxWindowPeer = xPeer;
3200 mpWindowImpl->mpVCLXWindow = pVCLXWindow;
3203 Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate )
3205 if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
3207 UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
3208 if ( pWrapper )
3209 mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
3211 return mpWindowImpl->mxWindowPeer;
3214 void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace )
3216 UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
3217 SAL_WARN_IF( !pWrapper, "vcl", "SetComponentInterface: No Wrapper!" );
3218 if ( pWrapper )
3219 pWrapper->SetWindowInterface( this, xIFace );
3222 typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap;
3224 namespace {
3226 LOKWindowsMap& GetLOKWindowsMap()
3228 // never use this in the desktop case
3229 assert(comphelper::LibreOfficeKit::isActive());
3231 // Map to remember the LOKWindowId <-> Window binding.
3232 static std::unique_ptr<LOKWindowsMap> s_pLOKWindowsMap;
3234 if (!s_pLOKWindowsMap)
3235 s_pLOKWindowsMap.reset(new LOKWindowsMap);
3237 return *s_pLOKWindowsMap.get();
3242 void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
3244 // don't allow setting this twice
3245 assert(mpWindowImpl->mpLOKNotifier == nullptr);
3246 assert(pNotifier);
3248 if (!bParent)
3250 // Counter to be able to have unique id's for each window.
3251 static vcl::LOKWindowId sLastLOKWindowId = 1;
3253 // assign the LOK window id
3254 assert(mpWindowImpl->mnLOKWindowId == 0);
3255 mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
3256 GetLOKWindowsMap().insert(std::map<vcl::LOKWindowId, VclPtr<vcl::Window>>::value_type(mpWindowImpl->mnLOKWindowId, this));
3258 else
3259 mpWindowImpl->mbLOKParentNotifier = true;
3261 mpWindowImpl->mpLOKNotifier = pNotifier;
3264 VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
3266 const auto it = GetLOKWindowsMap().find(nWindowId);
3267 if (it != GetLOKWindowsMap().end())
3268 return it->second;
3270 return VclPtr<Window>();
3273 void Window::ReleaseLOKNotifier()
3275 // unregister the LOK window binding
3276 if (mpWindowImpl->mnLOKWindowId > 0)
3277 GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
3279 mpWindowImpl->mpLOKNotifier = nullptr;
3280 mpWindowImpl->mnLOKWindowId = 0;
3283 const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const
3285 return mpWindowImpl->mpLOKNotifier;
3288 vcl::LOKWindowId Window::GetLOKWindowId() const
3290 return mpWindowImpl->mnLOKWindowId;
3293 VclPtr<vcl::Window> Window::GetParentWithLOKNotifier()
3295 VclPtr<vcl::Window> pWindow(this);
3297 while (pWindow && !pWindow->GetLOKNotifier())
3298 pWindow = pWindow->GetParent();
3300 return pWindow;
3303 void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
3305 // no deactivation if the newly activated window is my child
3306 if ( !pNew || !ImplIsChild( pNew ) )
3308 VclPtr<vcl::Window> xWindow(this);
3309 CallEventListeners( VCLEVENT_WINDOW_DEACTIVATE );
3310 if( xWindow->IsDisposed() )
3311 return;
3313 // #100759#, avoid walking the wrong frame's hierarchy
3314 // eg, undocked docking windows (ImplDockFloatWin)
3315 if ( ImplGetParent() && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
3316 ImplGetParent()->ImplCallDeactivateListeners( pNew );
3320 void Window::ImplCallActivateListeners( vcl::Window *pOld )
3322 // no activation if the old active window is my child
3323 if ( !pOld || !ImplIsChild( pOld ) )
3325 VclPtr<vcl::Window> xWindow(this);
3326 CallEventListeners( VCLEVENT_WINDOW_ACTIVATE, pOld );
3327 if( xWindow->IsDisposed() )
3328 return;
3330 if ( ImplGetParent() )
3331 ImplGetParent()->ImplCallActivateListeners( pOld );
3332 else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
3334 // top level frame reached: store hint for DefModalDialogParent
3335 ImplGetSVData()->maWinData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
3340 void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
3342 if (mpWindowImpl->mpFrameData)
3343 mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
3346 Reference< XClipboard > Window::GetClipboard()
3349 if( mpWindowImpl->mpFrameData )
3351 if( ! mpWindowImpl->mpFrameData->mxClipboard.is() )
3355 mpWindowImpl->mpFrameData->mxClipboard
3356 = css::datatransfer::clipboard::SystemClipboard::create(
3357 comphelper::getProcessComponentContext());
3359 catch (DeploymentException & e)
3361 SAL_WARN(
3362 "vcl.window",
3363 "ignoring DeploymentException \"" << e.Message << "\"");
3367 return mpWindowImpl->mpFrameData->mxClipboard;
3370 return static_cast < XClipboard * > (nullptr);
3373 Reference< XClipboard > Window::GetPrimarySelection()
3376 if( mpWindowImpl->mpFrameData )
3378 if( ! mpWindowImpl->mpFrameData->mxSelection.is() )
3382 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
3384 #if HAVE_FEATURE_X11
3385 // A hack, making the primary selection available as an instance
3386 // of the SystemClipboard service on X11:
3387 Sequence< Any > args(1);
3388 args[0] <<= OUString("PRIMARY");
3389 mpWindowImpl->mpFrameData->mxSelection.set(
3390 (xContext->getServiceManager()->
3391 createInstanceWithArgumentsAndContext(
3392 "com.sun.star.datatransfer.clipboard.SystemClipboard",
3393 args, xContext)),
3394 UNO_QUERY_THROW);
3395 #else
3396 static Reference< XClipboard > s_xSelection(
3397 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.datatransfer.clipboard.GenericClipboard", xContext ), UNO_QUERY );
3399 mpWindowImpl->mpFrameData->mxSelection = s_xSelection;
3400 #endif
3402 catch (RuntimeException & e)
3404 SAL_WARN(
3405 "vcl.window",
3406 "ignoring RuntimeException \"" << e.Message << "\"");
3410 return mpWindowImpl->mpFrameData->mxSelection;
3413 return static_cast < XClipboard * > (nullptr);
3416 void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const Rectangle& rRect )
3418 assert(mpOutDevData);
3419 mpOutDevData->mpRecordLayout = pLayout;
3420 mpOutDevData->maRecordRect = rRect;
3421 Paint(*this, rRect);
3422 mpOutDevData->mpRecordLayout = nullptr;
3425 void Window::DrawSelectionBackground( const Rectangle& rRect,
3426 sal_uInt16 highlight,
3427 bool bChecked,
3428 bool bDrawBorder
3431 if( rRect.IsEmpty() )
3432 return;
3434 const StyleSettings& rStyles = GetSettings().GetStyleSettings();
3436 // colors used for item highlighting
3437 Color aSelectionBorderCol( rStyles.GetHighlightColor() );
3438 Color aSelectionFillCol( aSelectionBorderCol );
3440 bool bDark = rStyles.GetFaceColor().IsDark();
3441 bool bBright = ( rStyles.GetFaceColor() == Color( COL_WHITE ) );
3443 int c1 = aSelectionBorderCol.GetLuminance();
3444 int c2 = GetDisplayBackground().GetColor().GetLuminance();
3446 if( !bDark && !bBright && abs( c2-c1 ) < 75 )
3448 // constrast too low
3449 sal_uInt16 h,s,b;
3450 aSelectionFillCol.RGBtoHSB( h, s, b );
3451 if( b > 50 ) b -= 40;
3452 else b += 40;
3453 aSelectionFillCol.SetColor( Color::HSBtoRGB( h, s, b ) );
3454 aSelectionBorderCol = aSelectionFillCol;
3457 Rectangle aRect( rRect );
3458 Color oldFillCol = GetFillColor();
3459 Color oldLineCol = GetLineColor();
3461 if( bDrawBorder )
3462 SetLineColor( bDark ? Color(COL_WHITE) : ( bBright ? Color(COL_BLACK) : aSelectionBorderCol ) );
3463 else
3464 SetLineColor();
3466 sal_uInt16 nPercent = 0;
3467 if( !highlight )
3469 if( bDark )
3470 aSelectionFillCol = COL_BLACK;
3471 else
3472 nPercent = 80; // just checked (light)
3474 else
3476 if( bChecked && highlight == 2 )
3478 if( bDark )
3479 aSelectionFillCol = COL_LIGHTGRAY;
3480 else if ( bBright )
3482 aSelectionFillCol = COL_BLACK;
3483 SetLineColor( COL_BLACK );
3484 nPercent = 0;
3486 else
3487 nPercent = 20; // selected, pressed or checked ( very dark )
3489 else if( bChecked || highlight == 1 )
3491 if( bDark )
3492 aSelectionFillCol = COL_GRAY;
3493 else if ( bBright )
3495 aSelectionFillCol = COL_BLACK;
3496 SetLineColor( COL_BLACK );
3497 nPercent = 0;
3499 else
3500 nPercent = 35; // selected, pressed or checked ( very dark )
3502 else
3504 if( bDark )
3505 aSelectionFillCol = COL_LIGHTGRAY;
3506 else if ( bBright )
3508 aSelectionFillCol = COL_BLACK;
3509 SetLineColor( COL_BLACK );
3510 if( highlight == 3 )
3511 nPercent = 80;
3512 else
3513 nPercent = 0;
3515 else
3516 nPercent = 70; // selected ( dark )
3520 SetFillColor( aSelectionFillCol );
3522 if( bDark )
3524 DrawRect( aRect );
3526 else
3528 tools::Polygon aPoly( aRect );
3529 tools::PolyPolygon aPolyPoly( aPoly );
3530 DrawTransparent( aPolyPoly, nPercent );
3533 SetFillColor( oldFillCol );
3534 SetLineColor( oldLineCol );
3537 bool Window::IsScrollable() const
3539 // check for scrollbars
3540 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3541 while( pChild )
3543 if( pChild->GetType() == WINDOW_SCROLLBAR )
3544 return true;
3545 else
3546 pChild = pChild->mpWindowImpl->mpNext;
3548 return false;
3551 void Window::ImplMirrorFramePos( Point &pt ) const
3553 pt.X() = mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X();
3556 // frame based modal counter (dialogs are not modal to the whole application anymore)
3557 bool Window::IsInModalMode() const
3559 return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
3562 void Window::ImplIncModalCount()
3564 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3565 vcl::Window* pParent = pFrameWindow;
3566 while( pFrameWindow )
3568 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
3569 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3571 pParent = pParent->GetParent();
3573 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3576 void Window::ImplDecModalCount()
3578 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3579 vcl::Window* pParent = pFrameWindow;
3580 while( pFrameWindow )
3582 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
3583 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3585 pParent = pParent->GetParent();
3587 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3591 void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
3593 mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
3596 void Window::ImplNotifyIconifiedState( bool bIconified )
3598 mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
3599 // #109206# notify client window as well to have toolkit topwindow listeners notified
3600 if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
3601 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
3604 bool Window::HasActiveChildFrame()
3606 bool bRet = false;
3607 vcl::Window *pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
3608 while( pFrameWin )
3610 if( pFrameWin != mpWindowImpl->mpFrameWindow )
3612 bool bDecorated = false;
3613 VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow();
3614 // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
3615 // be removed for ToolBoxes to influence the keyboard accessibility
3616 // thus WB_MOVEABLE is no indicator for decoration anymore
3617 // but FloatingWindows carry this information in their TitleType...
3618 // TODO: avoid duplicate WinBits !!!
3619 if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
3620 bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE;
3621 if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
3622 if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
3624 if( ImplIsChild( pChildFrame, true ) )
3626 bRet = true;
3627 break;
3631 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
3633 return bRet;
3636 LanguageType Window::GetInputLanguage() const
3638 return mpWindowImpl->mpFrame->GetInputLanguage();
3641 void Window::EnableNativeWidget( bool bEnable )
3643 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
3644 if( pNoNWF && *pNoNWF )
3645 bEnable = false;
3647 if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
3649 ImplGetWinData()->mbEnableNativeWidget = bEnable;
3651 // send datachanged event to allow for internal changes required for NWF
3652 // like clipmode, transparency, etc.
3653 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, mxSettings.get(), AllSettingsFlags::STYLE );
3654 CompatDataChanged( aDCEvt );
3656 // sometimes the borderwindow is queried, so keep it in sync
3657 if( mpWindowImpl->mpBorderWindow )
3658 mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
3661 // push down, useful for compound controls
3662 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3663 while( pChild )
3665 pChild->EnableNativeWidget( bEnable );
3666 pChild = pChild->mpWindowImpl->mpNext;
3670 bool Window::IsNativeWidgetEnabled() const
3672 return ImplGetWinData()->mbEnableNativeWidget;
3675 Reference< css::rendering::XCanvas > Window::ImplGetCanvas( bool bSpriteCanvas ) const
3677 // try to retrieve hard reference from weak member
3678 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
3680 // canvas still valid? Then we're done.
3681 if( xCanvas.is() )
3682 return xCanvas;
3684 Sequence< Any > aArg(6);
3686 // Feed any with operating system's window handle
3688 // common: first any is VCL pointer to window (for VCL canvas)
3689 aArg[ 0 ] = makeAny( reinterpret_cast<sal_Int64>(this) );
3690 aArg[ 1 ] = GetSystemDataAny();
3691 aArg[ 2 ] = makeAny( css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
3692 aArg[ 3 ] = makeAny( mpWindowImpl->mbAlwaysOnTop );
3693 aArg[ 4 ] = makeAny( Reference< css::awt::XWindow >(
3694 const_cast<vcl::Window*>(this)->GetComponentInterface(),
3695 UNO_QUERY ));
3696 aArg[ 5 ] = GetSystemGfxDataAny();
3698 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
3700 // Create canvas instance with window handle
3702 static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
3703 css::rendering::CanvasFactory::create( xContext ) );
3704 Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
3706 if(xCanvasFactory.is())
3708 #ifdef _WIN32
3709 // see #140456# - if we're running on a multiscreen setup,
3710 // request special, multi-screen safe sprite canvas
3711 // implementation (not DX5 canvas, as it cannot cope with
3712 // surfaces spanning multiple displays). Note: canvas
3713 // (without sprite) stays the same)
3714 const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay;
3715 if( (nDisplay >= Application::GetScreenCount()) )
3717 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3718 bSpriteCanvas ?
3719 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3720 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3721 aArg,
3722 xContext ),
3723 UNO_QUERY );
3726 else
3728 #endif
3729 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3730 bSpriteCanvas ?
3731 OUString( "com.sun.star.rendering.SpriteCanvas" ) :
3732 OUString( "com.sun.star.rendering.Canvas" ),
3733 aArg,
3734 xContext ),
3735 UNO_QUERY );
3737 #ifdef _WIN32
3739 #endif
3740 mpWindowImpl->mxCanvas = xCanvas;
3743 // no factory??? Empty reference, then.
3744 return xCanvas;
3747 Reference< css::rendering::XCanvas > Window::GetCanvas() const
3749 return ImplGetCanvas( false );
3752 Reference< css::rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
3754 Reference< css::rendering::XSpriteCanvas > xSpriteCanvas(
3755 ImplGetCanvas( true ), UNO_QUERY );
3756 return xSpriteCanvas;
3759 OUString Window::GetSurroundingText() const
3761 return OUString();
3764 Selection Window::GetSurroundingTextSelection() const
3766 return Selection( 0, 0 );
3769 bool Window::UsePolyPolygonForComplexGradient()
3771 if ( meRasterOp != RasterOp::OverPaint )
3772 return true;
3774 return false;
3777 void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
3781 const SystemEnvData* Window::GetSystemData() const
3784 return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr;
3787 Any Window::GetSystemDataAny() const
3789 Any aRet;
3790 const SystemEnvData* pSysData = GetSystemData();
3791 if( pSysData )
3793 Sequence< sal_Int8 > aSeq( reinterpret_cast<sal_Int8 const *>(pSysData), pSysData->nSize );
3794 aRet <<= aSeq;
3796 return aRet;
3799 bool Window::SupportsDoubleBuffering() const
3801 return mpWindowImpl->mpFrameData->mpBuffer;
3804 void Window::RequestDoubleBuffering(bool bRequest)
3806 if (bRequest)
3808 mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
3809 // Make sure that the buffer size matches the frame size.
3810 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
3812 else
3813 mpWindowImpl->mpFrameData->mpBuffer.reset();
3817 * The rational here is that we moved destructors to
3818 * dispose and this altered a lot of code paths, that
3819 * are better left unchanged for now.
3821 #define COMPAT_BODY(method,args) \
3822 if (!mpWindowImpl || mpWindowImpl->mbInDispose) \
3823 Window::method args; \
3824 else \
3825 method args;
3827 void Window::CompatGetFocus()
3829 COMPAT_BODY(GetFocus,())
3832 void Window::CompatLoseFocus()
3834 COMPAT_BODY(LoseFocus,())
3837 void Window::CompatStateChanged( StateChangedType nStateChange )
3839 COMPAT_BODY(StateChanged,(nStateChange))
3842 void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
3844 COMPAT_BODY(DataChanged,(rDCEvt))
3847 bool Window::CompatPreNotify( NotifyEvent& rNEvt )
3849 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3850 return Window::PreNotify( rNEvt );
3851 else
3852 return PreNotify( rNEvt );
3855 bool Window::CompatNotify( NotifyEvent& rNEvt )
3857 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3858 return Window::EventNotify( rNEvt );
3859 else
3860 return EventNotify( rNEvt );
3863 void Window::set_id(const OUString& rID)
3865 mpWindowImpl->maID = rID;
3868 const OUString& Window::get_id() const
3870 return mpWindowImpl->maID;
3873 FactoryFunction Window::GetUITestFactory() const
3875 return WindowUIObject::create;
3878 } /* namespace vcl */
3880 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */