Avoid segv when co-editing around SvxColorTabPage.
[LibreOffice.git] / vcl / source / window / window.cxx
blobbd2b95e44ec8bb7b90180c951c7b0f7a115deb39
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <rtl/strbuf.hxx>
23 #include <sal/log.hxx>
25 #include <sal/types.h>
26 #include <tools/diagnose_ex.h>
27 #include <vcl/salgtype.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/help.hxx>
30 #include <vcl/cursor.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/transfer.hxx>
33 #include <vcl/vclevent.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/syswin.hxx>
36 #include <vcl/dockwin.hxx>
37 #include <vcl/wall.hxx>
38 #include <vcl/toolkit/fixed.hxx>
39 #include <vcl/taskpanelist.hxx>
40 #include <vcl/toolkit/unowrap.hxx>
41 #include <vcl/lazydelete.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/settings.hxx>
44 #include <vcl/sysdata.hxx>
45 #include <vcl/ptrstyle.hxx>
46 #include <vcl/IDialogRenderable.hxx>
48 #include <vcl/uitest/uiobject.hxx>
50 #include <ImplOutDevData.hxx>
51 #include <impfontcache.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 <brdwin.hxx>
60 #include <helpwin.hxx>
62 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
63 #include <com/sun/star/accessibility/XAccessible.hpp>
64 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
65 #include <com/sun/star/awt/XWindowPeer.hpp>
66 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
67 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
68 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
69 #include <com/sun/star/rendering/CanvasFactory.hpp>
70 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
71 #include <comphelper/lok.hxx>
72 #include <comphelper/processfactory.hxx>
73 #include <unotools/configmgr.hxx>
74 #include <osl/diagnose.h>
75 #include <tools/debug.hxx>
76 #include <tools/json_writer.hxx>
77 #include <boost/property_tree/ptree.hpp>
79 #include <cassert>
80 #include <typeinfo>
82 #ifdef _WIN32 // see #140456#
83 #include <win/salframe.h>
84 #endif
86 #include "impldockingwrapper.hxx"
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::lang;
90 using namespace ::com::sun::star::datatransfer::clipboard;
91 using namespace ::com::sun::star::datatransfer::dnd;
93 namespace vcl {
95 Window::Window( WindowType nType )
96 : mpWindowImpl(new WindowImpl( *this, nType ))
98 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
99 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
102 Window::Window( vcl::Window* pParent, WinBits nStyle )
103 : mpWindowImpl(new WindowImpl( *this, WindowType::WINDOW ))
105 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
106 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
108 ImplInit( pParent, nStyle, nullptr );
111 #if OSL_DEBUG_LEVEL > 0
112 namespace
114 OString lcl_createWindowInfo(const vcl::Window* pWindow)
116 // skip border windows, they do not carry information that
117 // would help with diagnosing the problem
118 const vcl::Window* pTempWin( pWindow );
119 while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) {
120 pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
122 // check if pTempWin is not null, otherwise use the
123 // original address
124 if ( pTempWin ) {
125 pWindow = pTempWin;
128 return OString::Concat(" ") +
129 typeid( *pWindow ).name() +
130 "(" +
131 OUStringToOString(
132 pWindow->GetText(),
133 RTL_TEXTENCODING_UTF8
135 ")";
138 #endif
140 void Window::dispose()
142 assert( mpWindowImpl );
143 assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
144 assert( (!mpWindowImpl->mpParent ||
145 mpWindowImpl->mpParent->mpWindowImpl) &&
146 "vcl::Window child should have its parent disposed first" );
148 // remove Key and Mouse events issued by Application::PostKey/MouseEvent
149 Application::RemoveMouseAndKeyEvents( this );
151 // Dispose of the canvas implementation (which, currently, has an
152 // own wrapper window as a child to this one.
153 GetOutDev()->ImplDisposeCanvas();
155 mpWindowImpl->mbInDispose = true;
157 CallEventListeners( VclEventId::ObjectDying );
159 // do not send child events for frames that were registered as native frames
160 if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
161 if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
162 GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this );
164 // remove associated data structures from dockingmanager
165 ImplGetDockingManager()->RemoveWindow( this );
167 // remove ownerdraw decorated windows from list in the top-most frame window
168 if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
170 ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList();
171 auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) );
172 if( p != rList.end() )
173 rList.erase( p );
176 // shutdown drag and drop
177 Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
179 if( xDnDComponent.is() )
180 xDnDComponent->dispose();
182 if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
186 // deregister drop target listener
187 if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
189 Reference< XDragGestureRecognizer > xDragGestureRecognizer(mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
190 if( xDragGestureRecognizer.is() )
192 xDragGestureRecognizer->removeDragGestureListener(
193 Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
196 mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
197 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
200 // shutdown drag and drop for this frame window
201 Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
203 // DNDEventDispatcher does not hold a reference of the DropTarget,
204 // so it's ok if it does not support XComponent
205 if( xComponent.is() )
206 xComponent->dispose();
208 catch (const Exception&)
210 // can be safely ignored here.
214 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false );
215 if ( pWrapper )
216 pWrapper->WindowDestroyed( this );
218 // MT: Must be called after WindowDestroyed!
219 // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
220 // But accessibility implementations from applications need this dispose.
221 if ( mpWindowImpl->mxAccessible.is() )
223 Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY );
224 if ( xC.is() )
225 xC->dispose();
228 ImplSVData* pSVData = ImplGetSVData();
230 if ( ImplGetSVHelpData().mpHelpWin && (ImplGetSVHelpData().mpHelpWin->GetParent() == this) )
231 ImplDestroyHelpWindow( true );
233 SAL_WARN_IF(pSVData->mpWinData->mpTrackWin.get() == this, "vcl.window",
234 "Window::~Window(): Window is in TrackingMode");
235 SAL_WARN_IF(IsMouseCaptured(), "vcl.window",
236 "Window::~Window(): Window has the mouse captured");
238 // due to old compatibility
239 if (pSVData->mpWinData->mpTrackWin == this)
240 EndTracking();
241 if (IsMouseCaptured())
242 ReleaseMouse();
244 #if OSL_DEBUG_LEVEL > 0
245 // always perform these tests in debug builds
247 OStringBuffer aErrorStr;
248 bool bError = false;
249 vcl::Window* pTempWin;
251 if ( mpWindowImpl->mpFirstChild )
253 OStringBuffer aTempStr = "Window (" +
254 lcl_createWindowInfo(this) +
255 ") with live children destroyed: ";
256 pTempWin = mpWindowImpl->mpFirstChild;
257 while ( pTempWin )
259 aTempStr.append(lcl_createWindowInfo(pTempWin));
260 pTempWin = pTempWin->mpWindowImpl->mpNext;
262 OSL_FAIL( aTempStr.getStr() );
263 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
266 if (mpWindowImpl->mpFrameData != nullptr)
268 pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
269 while ( pTempWin )
271 if ( ImplIsRealParentPath( pTempWin ) )
273 bError = true;
274 aErrorStr.append(lcl_createWindowInfo(pTempWin));
276 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
278 if ( bError )
280 OString aTempStr =
281 "Window (" +
282 lcl_createWindowInfo(this) +
283 ") with live SystemWindows destroyed: " +
284 aErrorStr;
285 OSL_FAIL(aTempStr.getStr());
286 // abort in debug builds, must be fixed!
287 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8));
291 bError = false;
292 pTempWin = pSVData->maFrameData.mpFirstFrame;
293 while ( pTempWin )
295 if ( ImplIsRealParentPath( pTempWin ) )
297 bError = true;
298 aErrorStr.append(lcl_createWindowInfo(pTempWin));
300 pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
302 if ( bError )
304 OString aTempStr = "Window (" +
305 lcl_createWindowInfo(this) +
306 ") with live SystemWindows destroyed: " +
307 aErrorStr;
308 OSL_FAIL( aTempStr.getStr() );
309 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
312 if ( mpWindowImpl->mpFirstOverlap )
314 OStringBuffer aTempStr = "Window (" +
315 lcl_createWindowInfo(this) +
316 ") with live SystemWindows destroyed: ";
317 pTempWin = mpWindowImpl->mpFirstOverlap;
318 while ( pTempWin )
320 aTempStr.append(lcl_createWindowInfo(pTempWin));
321 pTempWin = pTempWin->mpWindowImpl->mpNext;
323 OSL_FAIL( aTempStr.getStr() );
324 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
327 vcl::Window* pMyParent = GetParent();
328 SystemWindow* pMySysWin = nullptr;
330 while ( pMyParent )
332 if ( pMyParent->IsSystemWindow() )
334 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
336 pMyParent = pMyParent->GetParent();
338 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
340 OString aTempStr = "Window (" +
341 lcl_createWindowInfo(this) +
342 ") still in TaskPanelList!";
343 OSL_FAIL( aTempStr.getStr() );
344 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
347 #endif
349 if( mpWindowImpl->mbIsInTaskPaneList )
351 vcl::Window* pMyParent = GetParent();
352 SystemWindow* pMySysWin = nullptr;
354 while ( pMyParent )
356 if ( pMyParent->IsSystemWindow() )
358 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
360 pMyParent = pMyParent->GetParent();
362 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
364 pMySysWin->GetTaskPaneList()->RemoveWindow( this );
366 else
368 SAL_WARN( "vcl", "Window (" << GetText() << ") not found in TaskPanelList");
372 // remove from size-group if necessary
373 remove_from_all_size_groups();
375 // clear mnemonic labels
376 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
377 for (auto const& mnemonicLabel : aMnemonicLabels)
379 remove_mnemonic_label(mnemonicLabel);
382 // hide window in order to trigger the Paint-Handling
383 Hide();
385 // EndExtTextInputMode
386 if (pSVData->mpWinData->mpExtTextInputWin == this)
388 EndExtTextInput();
389 if (pSVData->mpWinData->mpExtTextInputWin == this)
390 pSVData->mpWinData->mpExtTextInputWin = nullptr;
393 // check if the focus window is our child
394 bool bHasFocusedChild = false;
395 if (pSVData->mpWinData->mpFocusWin && ImplIsRealParentPath(pSVData->mpWinData->mpFocusWin))
397 // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
398 bHasFocusedChild = true;
399 #if OSL_DEBUG_LEVEL > 0
400 OUString aTempStr = "Window (" + GetText() +
401 ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
402 SAL_WARN( "vcl", aTempStr );
403 Application::Abort(aTempStr); // abort in debug build version, this must be fixed!
404 #endif
407 // if we get focus pass focus to another window
408 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
409 if (pSVData->mpWinData->mpFocusWin == this
410 || bHasFocusedChild) // #122232#, see above, try some cleanup
412 if ( mpWindowImpl->mbFrame )
414 pSVData->mpWinData->mpFocusWin = nullptr;
415 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
417 else
419 vcl::Window* pParent = GetParent();
420 vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
421 // when windows overlap, give focus to the parent
422 // of the next FrameWindow
423 if ( pBorderWindow )
425 if ( pBorderWindow->ImplIsOverlapWindow() )
426 pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
428 else if ( ImplIsOverlapWindow() )
429 pParent = mpWindowImpl->mpOverlapWindow;
431 if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
432 pParent->GrabFocus();
433 else
434 mpWindowImpl->mpFrameWindow->GrabFocus();
436 // If the focus was set back to 'this' set it to nothing
437 if (pSVData->mpWinData->mpFocusWin == this)
439 pSVData->mpWinData->mpFocusWin = nullptr;
440 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
445 if ( pOverlapWindow != nullptr &&
446 pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
447 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
449 // reset hint for DefModalDialogParent
450 if( pSVData->maFrameData.mpActiveApplicationFrame == this )
451 pSVData->maFrameData.mpActiveApplicationFrame = nullptr;
453 // reset hint of what was the last wheeled window
454 if (pSVData->mpWinData->mpLastWheelWindow == this)
455 pSVData->mpWinData->mpLastWheelWindow = nullptr;
457 // reset marked windows
458 if ( mpWindowImpl->mpFrameData != nullptr )
460 if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
461 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
462 if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
463 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
464 if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
465 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
468 // reset Deactivate-Window
469 if (pSVData->mpWinData->mpLastDeacWin == this)
470 pSVData->mpWinData->mpLastDeacWin = nullptr;
472 if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
474 if ( mpWindowImpl->mpFrameData->mnFocusId )
475 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
476 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
477 if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
478 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
479 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
482 // release SalGraphics
483 VclPtr<OutputDevice> pOutDev = GetOutDev();
484 pOutDev->ReleaseGraphics();
486 // remove window from the lists
487 ImplRemoveWindow( true );
489 // de-register as "top window child" at our parent, if necessary
490 if ( mpWindowImpl->mbFrame )
492 bool bIsTopWindow
493 = mpWindowImpl->mpWinData && (mpWindowImpl->mpWinData->mnIsTopWindow == 1);
494 if ( mpWindowImpl->mpRealParent && bIsTopWindow )
496 ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
498 auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
499 pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
500 SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" );
501 if ( myPos != pParentWinData->maTopWindowChildren.end() )
502 pParentWinData->maTopWindowChildren.erase( myPos );
506 mpWindowImpl->mpWinData.reset();
508 // remove BorderWindow or Frame window data
509 mpWindowImpl->mpBorderWindow.disposeAndClear();
510 if ( mpWindowImpl->mbFrame )
512 if ( pSVData->maFrameData.mpFirstFrame == this )
513 pSVData->maFrameData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
514 else
516 sal_Int32 nWindows = 0;
517 vcl::Window* pSysWin = pSVData->maFrameData.mpFirstFrame;
518 while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
520 pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
521 nWindows++;
524 if ( pSysWin )
526 assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
527 pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
529 else // if it is not in the list, we can't remove it.
530 SAL_WARN("vcl.window", "Window " << this << " marked as frame window, "
531 "is missing from list of " << nWindows << " frames");
533 if (mpWindowImpl->mpFrame) // otherwise exception during init
535 mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
536 pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
538 assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
539 assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
541 mpWindowImpl->mpFrameData->mpBuffer.disposeAndClear();
542 delete mpWindowImpl->mpFrameData;
543 mpWindowImpl->mpFrameData = nullptr;
546 if (mpWindowImpl->mxWindowPeer)
547 mpWindowImpl->mxWindowPeer->dispose();
549 // should be the last statements
550 mpWindowImpl.reset();
552 pOutDev.disposeAndClear();
553 // just to make loplugin:vclwidgets happy
554 VclReferenceBase::dispose();
557 Window::~Window()
559 disposeOnce();
562 // We will eventually being removing the inheritance of OutputDevice
563 // from Window. It will be replaced with a transient relationship such
564 // that the OutputDevice is only live for the scope of the Paint method.
565 // In the meantime this can help move us towards a Window use an
566 // OutputDevice, not being one.
568 ::OutputDevice const* Window::GetOutDev() const
570 return mpWindowImpl->mxOutDev.get();
573 ::OutputDevice* Window::GetOutDev()
575 return mpWindowImpl->mxOutDev.get();
578 Color WindowOutputDevice::GetBackgroundColor() const
580 return mxOwnerWindow->GetDisplayBackground().GetColor();
583 bool WindowOutputDevice::CanEnableNativeWidget() const
585 return mxOwnerWindow->IsNativeWidgetEnabled();
588 } /* namespace vcl */
590 WindowImpl::WindowImpl( vcl::Window& rWindow, WindowType nType )
592 mxOutDev = VclPtr<vcl::WindowOutputDevice>::Create(rWindow);
593 maZoom = Fraction( 1, 1 );
594 maWinRegion = vcl::Region(true);
595 maWinClipRegion = vcl::Region(true);
596 mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
597 mpFrameData = nullptr; // Frame Data
598 mpFrame = nullptr; // Pointer to frame window
599 mpSysObj = nullptr;
600 mpFrameWindow = nullptr; // window to top level parent (same as frame window)
601 mpOverlapWindow = nullptr; // first overlap parent
602 mpBorderWindow = nullptr; // Border-Window
603 mpClientWindow = nullptr; // Client-Window of a FrameWindow
604 mpParent = nullptr; // parent (incl. BorderWindow)
605 mpRealParent = nullptr; // real parent (excl. BorderWindow)
606 mpFirstChild = nullptr; // first child window
607 mpLastChild = nullptr; // last child window
608 mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
609 mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
610 mpPrev = nullptr; // prev window
611 mpNext = nullptr; // next window
612 mpNextOverlap = nullptr; // next overlap window of frame
613 mpLastFocusWindow = nullptr; // window for focus restore
614 mpDlgCtrlDownWindow = nullptr; // window for dialog control
615 mnEventListenersIteratingCount = 0;
616 mnChildEventListenersIteratingCount = 0;
617 mpCursor = nullptr; // cursor
618 maPointer = PointerStyle::Arrow;
619 mpVCLXWindow = nullptr;
620 mpAccessibleInfos = nullptr;
621 maControlForeground = COL_TRANSPARENT; // no foreground set
622 maControlBackground = COL_TRANSPARENT; // no background set
623 mnLeftBorder = 0; // left border
624 mnTopBorder = 0; // top border
625 mnRightBorder = 0; // right border
626 mnBottomBorder = 0; // bottom border
627 mnWidthRequest = -1; // width request
628 mnHeightRequest = -1; // height request
629 mnOptimalWidthCache = -1; // optimal width cache
630 mnOptimalHeightCache = -1; // optimal height cache
631 mnX = 0; // X-Position to Parent
632 mnY = 0; // Y-Position to Parent
633 mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
634 mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
635 mpPaintRegion = nullptr; // Paint-ClipRegion
636 mnStyle = 0; // style (init in ImplInitWindow)
637 mnPrevStyle = 0; // prevstyle (set in SetStyle)
638 mnExtendedStyle = WindowExtendedStyle::NONE; // extended style (init in ImplInitWindow)
639 mnType = nType; // type
640 mnGetFocusFlags = GetFocusFlags::NONE; // Flags for GetFocus()-Call
641 mnWaitCount = 0; // Wait-Count (>1 == "wait" mouse pointer)
642 mnPaintFlags = ImplPaintFlags::NONE; // Flags for ImplCallPaint
643 mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
644 mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
645 mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
646 meAlwaysInputMode = AlwaysInputNone; // AlwaysEnableInput not called
647 meHalign = VclAlign::Fill;
648 meValign = VclAlign::Fill;
649 mePackType = VclPackType::Start;
650 mnPadding = 0;
651 mnGridHeight = 1;
652 mnGridLeftAttach = -1;
653 mnGridTopAttach = -1;
654 mnGridWidth = 1;
655 mnBorderWidth = 0;
656 mnMarginLeft = 0;
657 mnMarginRight = 0;
658 mnMarginTop = 0;
659 mnMarginBottom = 0;
660 mbFrame = false; // true: Window is a frame window
661 mbBorderWin = false; // true: Window is a border window
662 mbOverlapWin = false; // true: Window is an overlap window
663 mbSysWin = false; // true: SystemWindow is the base class
664 mbDialog = false; // true: Dialog is the base class
665 mbDockWin = false; // true: DockingWindow is the base class
666 mbFloatWin = false; // true: FloatingWindow is the base class
667 mbPushButton = false; // true: PushButton is the base class
668 mbToolBox = false; // true: ToolBox is the base class
669 mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
670 mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
671 mbSplitter = false; // true: Splitter is the base class
672 mbVisible = false; // true: Show( true ) called
673 mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
674 mbDisabled = false; // true: Enable( false ) called
675 mbInputDisabled = false; // true: EnableInput( false ) called
676 mbNoUpdate = false; // true: SetUpdateMode( false ) called
677 mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
678 mbActive = false; // true: Window Active
679 mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
680 mbReallyShown = false; // true: this and all parents to an overlapped window are shown
681 mbInInitShow = false; // true: we are in InitShow
682 mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
683 mbNoPtrVisible = false; // true: ShowPointer( false ) called
684 mbPaintFrame = false; // true: Paint is visible, but not painted
685 mbInPaint = false; // true: Inside PaintHdl
686 mbMouseButtonDown = false; // true: BaseMouseButtonDown called
687 mbMouseButtonUp = false; // true: BaseMouseButtonUp called
688 mbKeyInput = false; // true: BaseKeyInput called
689 mbKeyUp = false; // true: BaseKeyUp called
690 mbCommand = false; // true: BaseCommand called
691 mbDefPos = true; // true: Position is not Set
692 mbDefSize = true; // true: Size is not Set
693 mbCallMove = true; // true: Move must be called by Show
694 mbCallResize = true; // true: Resize must be called by Show
695 mbWaitSystemResize = true; // true: Wait for System-Resize
696 mbInitWinClipRegion = true; // true: Calc Window Clip Region
697 mbInitChildRegion = false; // true: InitChildClipRegion
698 mbWinRegion = false; // true: Window Region
699 mbClipChildren = false; // true: Child-window should be clipped
700 mbClipSiblings = false; // true: Adjacent Child-window should be clipped
701 mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
702 mbPaintTransparent = false; // true: Paints should be executed on the Parent
703 mbMouseTransparent = false; // true: Window is transparent for Mouse
704 mbDlgCtrlStart = false; // true: From here on own Dialog-Control
705 mbFocusVisible = false; // true: Focus Visible
706 mbUseNativeFocus = false;
707 mbNativeFocusVisible = false; // true: native Focus Visible
708 mbInShowFocus = false; // prevent recursion
709 mbInHideFocus = false; // prevent recursion
710 mbTrackVisible = false; // true: Tracking Visible
711 mbControlForeground = false; // true: Foreground-Property set
712 mbControlBackground = false; // true: Background-Property set
713 mbAlwaysOnTop = false; // true: always visible for all others windows
714 mbCompoundControl = false; // true: Composite Control => Listener...
715 mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
716 mbPaintDisabled = false; // true: Paint should not be executed
717 mbAllResize = false; // true: Also sent ResizeEvents with 0,0
718 mbInDispose = false; // true: We're still in Window::dispose()
719 mbExtTextInput = false; // true: ExtTextInput-Mode is active
720 mbInFocusHdl = false; // true: Within GetFocus-Handler
721 mbCreatedWithToolkit = false;
722 mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
723 mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
724 mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
725 mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
726 mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
727 mbFakeFocusSet = false; // true: pretend as if the window has focus.
728 mbHexpand = false;
729 mbVexpand = false;
730 mbExpand = false;
731 mbFill = true;
732 mbSecondary = false;
733 mbNonHomogeneous = false;
734 static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
735 mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
736 mpLOKNotifier = nullptr;
737 mnLOKWindowId = 0;
738 mbLOKParentNotifier = false;
741 WindowImpl::~WindowImpl()
743 mpChildClipRegion.reset();
744 mpAccessibleInfos.reset();
747 ImplWinData::ImplWinData() :
748 mnCursorExtWidth(0),
749 mbVertical(false),
750 mnCompositionCharRects(0),
751 mnTrackFlags(ShowTrackFlags::NONE),
752 mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
753 mbMouseOver(false),
754 mbEnableNativeWidget(false)
758 ImplWinData::~ImplWinData()
760 mpCompositionCharRects.reset();
763 ImplFrameData::ImplFrameData( vcl::Window *pWindow )
764 : maPaintIdle( "vcl::Window maPaintIdle" ),
765 maResizeIdle( "vcl::Window maResizeIdle" )
767 ImplSVData* pSVData = ImplGetSVData();
768 assert (pSVData->maFrameData.mpFirstFrame.get() != pWindow);
769 mpNextFrame = pSVData->maFrameData.mpFirstFrame;
770 pSVData->maFrameData.mpFirstFrame = pWindow;
771 mpFirstOverlap = nullptr;
772 mpFocusWin = nullptr;
773 mpMouseMoveWin = nullptr;
774 mpMouseDownWin = nullptr;
775 mxFontCollection = pSVData->maGDIData.mxScreenFontList;
776 mxFontCache = pSVData->maGDIData.mxScreenFontCache;
777 mnFocusId = nullptr;
778 mnMouseMoveId = nullptr;
779 mnLastMouseX = -1;
780 mnLastMouseY = -1;
781 mnBeforeLastMouseX = -1;
782 mnBeforeLastMouseY = -1;
783 mnFirstMouseX = -1;
784 mnFirstMouseY = -1;
785 mnLastMouseWinX = -1;
786 mnLastMouseWinY = -1;
787 mnModalMode = 0;
788 mnMouseDownTime = 0;
789 mnClickCount = 0;
790 mnFirstMouseCode = 0;
791 mnMouseCode = 0;
792 mnMouseMode = MouseEventModifiers::NONE;
793 mbHasFocus = false;
794 mbInMouseMove = false;
795 mbMouseIn = false;
796 mbStartDragCalled = false;
797 mbNeedSysWindow = false;
798 mbMinimized = false;
799 mbStartFocusState = false;
800 mbInSysObjFocusHdl = false;
801 mbInSysObjToTopHdl = false;
802 mbSysObjFocus = false;
803 maPaintIdle.SetPriority( TaskPriority::REPAINT );
804 maPaintIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandlePaintHdl ) );
805 maResizeIdle.SetPriority( TaskPriority::RESIZE );
806 maResizeIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandleResizeTimerHdl ) );
807 mbInternalDragGestureRecognizer = false;
808 mbInBufferedPaint = false;
809 mnDPIX = 96;
810 mnDPIY = 96;
811 mnTouchPanPosition = -1;
814 namespace vcl {
816 bool WindowOutputDevice::AcquireGraphics() const
818 DBG_TESTSOLARMUTEX();
820 if (isDisposed())
821 return false;
823 if (mpGraphics)
824 return true;
826 mbInitLineColor = true;
827 mbInitFillColor = true;
828 mbInitFont = true;
829 mbInitTextColor = true;
830 mbInitClipRegion = true;
832 ImplSVData* pSVData = ImplGetSVData();
834 mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics();
835 // try harder if no wingraphics was available directly
836 if ( !mpGraphics )
838 // find another output device in the same frame
839 vcl::WindowOutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics.get();
840 while ( pReleaseOutDev )
842 if ( pReleaseOutDev->mxOwnerWindow && pReleaseOutDev->mxOwnerWindow->mpWindowImpl->mpFrame == mxOwnerWindow->mpWindowImpl->mpFrame )
843 break;
844 pReleaseOutDev = static_cast<vcl::WindowOutputDevice*>(pReleaseOutDev->mpPrevGraphics.get());
847 if ( pReleaseOutDev )
849 // steal the wingraphics from the other outdev
850 mpGraphics = pReleaseOutDev->mpGraphics;
851 pReleaseOutDev->ReleaseGraphics( false );
853 else
855 // if needed retry after releasing least recently used wingraphics
856 while ( !mpGraphics )
858 if ( !pSVData->maGDIData.mpLastWinGraphics )
859 break;
860 pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
861 mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics();
866 if ( mpGraphics )
868 // update global LRU list of wingraphics
869 mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics.get();
870 pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::WindowOutputDevice*>(this);
871 if ( mpNextGraphics )
872 mpNextGraphics->mpPrevGraphics = const_cast<vcl::WindowOutputDevice*>(this);
873 if ( !pSVData->maGDIData.mpLastWinGraphics )
874 pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::WindowOutputDevice*>(this);
876 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
877 mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
880 return mpGraphics != nullptr;
883 void WindowOutputDevice::ReleaseGraphics( bool bRelease )
885 DBG_TESTSOLARMUTEX();
887 if ( !mpGraphics )
888 return;
890 // release the fonts of the physically released graphics device
891 if( bRelease )
892 ImplReleaseFonts();
894 ImplSVData* pSVData = ImplGetSVData();
896 vcl::Window* pWindow = mxOwnerWindow.get();
897 if (!pWindow)
898 return;
900 if ( bRelease )
901 pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
902 // remove from global LRU list of window graphics
903 if ( mpPrevGraphics )
904 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
905 else
906 pSVData->maGDIData.mpFirstWinGraphics = static_cast<vcl::WindowOutputDevice*>(mpNextGraphics.get());
907 if ( mpNextGraphics )
908 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
909 else
910 pSVData->maGDIData.mpLastWinGraphics = static_cast<vcl::WindowOutputDevice*>(mpPrevGraphics.get());
912 mpGraphics = nullptr;
913 mpPrevGraphics = nullptr;
914 mpNextGraphics = nullptr;
917 static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
919 #ifndef MACOSX
920 // Setting of HiDPI is unfortunately all only a heuristic; and to add
921 // insult to an injury, the system is constantly lying to us about
922 // the DPI and whatnot
923 // eg. fdo#77059 - set the value from which we do consider the
924 // screen HiDPI to greater than 168
925 if (nDPI > 216) // 96 * 2 + 96 / 4
926 return 250;
927 else if (nDPI > 168) // 96 * 2 - 96 / 4
928 return 200;
929 else if (nDPI > 120) // 96 * 1.5 - 96 / 4
930 return 150;
931 #else
932 (void)nDPI;
933 #endif
935 return 100;
938 void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
940 SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE, "vcl.window",
941 "Window::Window(): pParent == NULL" );
943 ImplSVData* pSVData = ImplGetSVData();
944 vcl::Window* pRealParent = pParent;
946 // inherit 3D look
947 if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
948 nStyle |= WB_3DLOOK;
950 // create border window if necessary
951 if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
952 && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
954 BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
955 if( nStyle & WB_SYSTEMCHILDWINDOW )
957 // handle WB_SYSTEMCHILDWINDOW
958 // these should be analogous to a top level frame; meaning they
959 // should have a border window with style BorderWindowStyle::Frame
960 // which controls their size
961 nBorderTypeStyle |= BorderWindowStyle::Frame;
962 nStyle |= WB_BORDER;
964 VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
965 static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
966 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
967 mpWindowImpl->mpBorderWindow = pBorderWin;
968 pParent = mpWindowImpl->mpBorderWindow;
970 else if( !mpWindowImpl->mbFrame && ! pParent )
972 mpWindowImpl->mbOverlapWin = true;
973 mpWindowImpl->mbFrame = true;
976 // insert window in list
977 ImplInsertWindow( pParent );
978 mpWindowImpl->mnStyle = nStyle;
980 if( pParent && ! mpWindowImpl->mbFrame )
981 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
983 // test for frame creation
984 if ( mpWindowImpl->mbFrame )
986 // create frame
987 SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
989 if ( nStyle & WB_MOVEABLE )
990 nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
991 if ( nStyle & WB_SIZEABLE )
992 nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
993 if ( nStyle & WB_CLOSEABLE )
994 nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
995 if ( nStyle & WB_APP )
996 nFrameStyle |= SalFrameStyleFlags::DEFAULT;
997 // check for undecorated floating window
998 if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
999 ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
1000 ( mpWindowImpl->mbFloatWin || ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
1001 // 2. borderwindows of floaters with ownerdraw decoration
1002 ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) )
1004 nFrameStyle = SalFrameStyleFlags::FLOAT;
1005 if( nStyle & WB_OWNERDRAWDECORATION )
1006 nFrameStyle |= SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW;
1008 else if( mpWindowImpl->mbFloatWin )
1009 nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
1011 if( nStyle & WB_INTROWIN )
1012 nFrameStyle |= SalFrameStyleFlags::INTRO;
1013 if( nStyle & WB_TOOLTIPWIN )
1014 nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
1016 if( nStyle & WB_NOSHADOW )
1017 nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
1019 if( nStyle & WB_SYSTEMCHILDWINDOW )
1020 nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
1022 switch (mpWindowImpl->mnType)
1024 case WindowType::DIALOG:
1025 case WindowType::TABDIALOG:
1026 case WindowType::MODELESSDIALOG:
1027 case WindowType::MESSBOX:
1028 case WindowType::INFOBOX:
1029 case WindowType::WARNINGBOX:
1030 case WindowType::ERRORBOX:
1031 case WindowType::QUERYBOX:
1032 nFrameStyle |= SalFrameStyleFlags::DIALOG;
1033 break;
1034 default:
1035 break;
1038 // tdf#144624 for the DefaultWindow, which is never visible, don't
1039 // create an icon for it so construction of a DefaultWindow cannot
1040 // trigger creation of a VirtualDevice which itself requires a
1041 // DefaultWindow to exist
1042 if( nStyle & WB_DEFAULTWIN )
1043 nFrameStyle |= SalFrameStyleFlags::NOICON;
1045 SalFrame* pParentFrame = nullptr;
1046 if ( pParent )
1047 pParentFrame = pParent->mpWindowImpl->mpFrame;
1048 SalFrame* pFrame;
1049 if ( pSystemParentData )
1050 pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG );
1051 else
1052 pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
1053 if ( !pFrame )
1055 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
1056 throw RuntimeException(
1057 "Could not create system window!",
1058 Reference< XInterface >() );
1061 pFrame->SetCallback( this, ImplWindowFrameProc );
1063 // set window frame data
1064 mpWindowImpl->mpFrameData = new ImplFrameData( this );
1065 mpWindowImpl->mpFrame = pFrame;
1066 mpWindowImpl->mpFrameWindow = this;
1067 mpWindowImpl->mpOverlapWindow = this;
1069 if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
1070 RequestDoubleBuffering(true);
1072 if ( pRealParent && IsTopWindow() )
1074 ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
1075 pParentWinData->maTopWindowChildren.emplace_back(this );
1079 // init data
1080 mpWindowImpl->mpRealParent = pRealParent;
1082 // #99318: make sure fontcache and list is available before call to SetSettings
1083 mpWindowImpl->mxOutDev->mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection;
1084 mpWindowImpl->mxOutDev->mxFontCache = mpWindowImpl->mpFrameData->mxFontCache;
1086 if ( mpWindowImpl->mbFrame )
1088 if ( pParent )
1090 mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
1091 mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
1093 else
1095 OutputDevice *pOutDev = GetOutDev();
1096 if ( pOutDev->AcquireGraphics() )
1098 mpWindowImpl->mxOutDev->mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
1102 // add ownerdraw decorated frame windows to list in the top-most frame window
1103 // so they can be hidden on lose focus
1104 if( nStyle & WB_OWNERDRAWDECORATION )
1105 ImplGetOwnerDrawList().emplace_back(this );
1107 // delay settings initialization until first "real" frame
1108 // this relies on the IntroWindow not needing any system settings
1109 if ( !pSVData->maAppData.mbSettingsInit &&
1110 ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
1113 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
1114 ImplUpdateGlobalSettings( *pSVData->maAppData.mxSettings );
1115 mpWindowImpl->mxOutDev->SetSettings( *pSVData->maAppData.mxSettings );
1116 pSVData->maAppData.mbSettingsInit = true;
1119 // If we create a Window with default size, query this
1120 // size directly, because we want resize all Controls to
1121 // the correct size before we display the window
1122 if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
1123 mpWindowImpl->mpFrame->GetClientSize( mpWindowImpl->mxOutDev->mnOutWidth, mpWindowImpl->mxOutDev->mnOutHeight );
1125 else
1127 if ( pParent )
1129 if ( !ImplIsOverlapWindow() )
1131 mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
1132 mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
1133 mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
1136 if (!utl::ConfigManager::IsFuzzing())
1138 // we don't want to call the WindowOutputDevice override of this because
1139 // it calls back into us.
1140 mpWindowImpl->mxOutDev->OutputDevice::SetSettings( pParent->GetSettings() );
1146 // setup the scale factor for HiDPI displays
1147 mpWindowImpl->mxOutDev->mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1148 mpWindowImpl->mxOutDev->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1149 mpWindowImpl->mxOutDev->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1151 if (!utl::ConfigManager::IsFuzzing())
1153 const StyleSettings& rStyleSettings = mpWindowImpl->mxOutDev->mxSettings->GetStyleSettings();
1154 mpWindowImpl->mxOutDev->maFont = rStyleSettings.GetAppFont();
1156 if ( nStyle & WB_3DLOOK )
1158 SetTextColor( rStyleSettings.GetButtonTextColor() );
1159 SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
1161 else
1163 SetTextColor( rStyleSettings.GetWindowTextColor() );
1164 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
1167 else
1169 mpWindowImpl->mxOutDev->maFont = OutputDevice::GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
1172 ImplPointToLogic(*GetOutDev(), mpWindowImpl->mxOutDev->maFont);
1174 (void)ImplUpdatePos();
1176 // calculate app font res (except for the Intro Window or the default window)
1177 if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
1178 ImplInitAppFontData( this );
1181 void Window::ImplInitAppFontData( vcl::Window const * pWindow )
1183 ImplSVData* pSVData = ImplGetSVData();
1184 tools::Long nTextHeight = pWindow->GetTextHeight();
1185 tools::Long nTextWidth = pWindow->approximate_char_width() * 8;
1186 tools::Long nSymHeight = nTextHeight*4;
1187 // Make the basis wider if the font is too narrow
1188 // such that the dialog looks symmetrical and does not become too narrow.
1189 // Add some extra space when the dialog has the same width,
1190 // as a little more space is better.
1191 if ( nSymHeight > nTextWidth )
1192 nTextWidth = nSymHeight;
1193 else if ( nSymHeight+5 > nTextWidth )
1194 nTextWidth = nSymHeight+5;
1195 pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
1196 pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
1198 #ifdef MACOSX
1199 // FIXME: this is currently only on macOS, check with other
1200 // platforms
1201 if( pSVData->maNWFData.mbNoFocusRects )
1203 // try to find out whether there is a large correction
1204 // of control sizes, if yes, make app font scalings larger
1205 // so dialog positioning is not completely off
1206 ImplControlValue aControlValue;
1207 tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
1208 tools::Rectangle aBoundingRgn( aCtrlRegion );
1209 tools::Rectangle aContentRgn( aCtrlRegion );
1210 if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
1211 ControlState::ENABLED, aControlValue,
1212 aBoundingRgn, aContentRgn ) )
1214 // comment: the magical +6 is for the extra border in bordered
1215 // (which is the standard) edit fields
1216 if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
1217 pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
1220 #endif
1223 ImplWinData* Window::ImplGetWinData() const
1225 if (!mpWindowImpl->mpWinData)
1227 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
1229 const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData.reset(new ImplWinData);
1230 mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
1233 return mpWindowImpl->mpWinData.get();
1237 void WindowOutputDevice::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
1239 if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
1240 return;
1242 if (bWindowInvalidate)
1244 const tools::Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
1245 Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
1247 mxOwnerWindow->ImplMoveAllInvalidateRegions(aSrcRect,
1248 aPosAry.mnDestX-aPosAry.mnSrcX,
1249 aPosAry.mnDestY-aPosAry.mnSrcY,
1250 false);
1252 mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
1253 aPosAry.mnSrcX, aPosAry.mnSrcY,
1254 aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
1255 *this);
1257 return;
1260 OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
1263 const OutputDevice* WindowOutputDevice::DrawOutDevDirectCheck(const OutputDevice& rSrcDev) const
1265 const OutputDevice* pSrcDevChecked;
1266 if ( this == &rSrcDev )
1267 pSrcDevChecked = nullptr;
1268 else if (GetOutDevType() != rSrcDev.GetOutDevType())
1269 pSrcDevChecked = &rSrcDev;
1270 else if (mxOwnerWindow->mpWindowImpl->mpFrameWindow == static_cast<const vcl::WindowOutputDevice&>(rSrcDev).mxOwnerWindow->mpWindowImpl->mpFrameWindow)
1271 pSrcDevChecked = nullptr;
1272 else
1273 pSrcDevChecked = &rSrcDev;
1275 return pSrcDevChecked;
1278 void WindowOutputDevice::DrawOutDevDirectProcess( const OutputDevice& rSrcDev, SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
1280 if (pSrcGraphics)
1281 mpGraphics->CopyBits(rPosAry, *pSrcGraphics, *this, rSrcDev);
1282 else
1283 mpGraphics->CopyBits(rPosAry, *this);
1286 SalGraphics* Window::ImplGetFrameGraphics() const
1288 if ( mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics )
1290 mpWindowImpl->mpFrameWindow->GetOutDev()->mbInitClipRegion = true;
1292 else
1294 OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow->GetOutDev();
1295 if ( ! pFrameWinOutDev->AcquireGraphics() )
1297 return nullptr;
1300 mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics->ResetClipRegion();
1301 return mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics;
1304 void Window::ImplSetReallyVisible()
1306 // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
1307 // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
1308 // mbReallyShown is a useful indicator
1309 if( !mpWindowImpl->mbReallyShown )
1310 ImplCallInitShow();
1312 bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
1314 GetOutDev()->mbDevOutput = true;
1315 mpWindowImpl->mbReallyVisible = true;
1316 mpWindowImpl->mbReallyShown = true;
1318 // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
1319 // For this, the data member of the event must not be NULL.
1320 // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
1321 // we're doing it when the visibility really changes
1322 if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
1323 CallEventListeners( VclEventId::WindowShow, this );
1324 // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should
1325 // introduce another event which explicitly triggers the Accessibility implementations.
1327 vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
1328 while ( pWindow )
1330 if ( pWindow->mpWindowImpl->mbVisible )
1331 pWindow->ImplSetReallyVisible();
1332 pWindow = pWindow->mpWindowImpl->mpNext;
1335 pWindow = mpWindowImpl->mpFirstChild;
1336 while ( pWindow )
1338 if ( pWindow->mpWindowImpl->mbVisible )
1339 pWindow->ImplSetReallyVisible();
1340 pWindow = pWindow->mpWindowImpl->mpNext;
1344 void Window::ImplInitResolutionSettings()
1346 // recalculate AppFont-resolution and DPI-resolution
1347 if (mpWindowImpl->mbFrame)
1349 GetOutDev()->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1350 GetOutDev()->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1352 // setup the scale factor for HiDPI displays
1353 GetOutDev()->mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1354 const StyleSettings& rStyleSettings = GetOutDev()->mxSettings->GetStyleSettings();
1355 SetPointFont(*GetOutDev(), rStyleSettings.GetAppFont());
1357 else if ( mpWindowImpl->mpParent )
1359 GetOutDev()->mnDPIX = mpWindowImpl->mpParent->GetOutDev()->mnDPIX;
1360 GetOutDev()->mnDPIY = mpWindowImpl->mpParent->GetOutDev()->mnDPIY;
1361 GetOutDev()->mnDPIScalePercentage = mpWindowImpl->mpParent->GetOutDev()->mnDPIScalePercentage;
1364 // update the recalculated values for logical units
1365 // and also tools belonging to the values
1366 if (IsMapModeEnabled())
1368 MapMode aMapMode = GetMapMode();
1369 SetMapMode();
1370 SetMapMode( aMapMode );
1374 void Window::ImplPointToLogic(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1376 Size aSize = rFont.GetFontSize();
1378 if (aSize.Width())
1380 aSize.setWidth( aSize.Width() * ( mpWindowImpl->mpFrameData->mnDPIX) );
1381 aSize.AdjustWidth(72 / 2 );
1382 aSize.setWidth( aSize.Width() / 72 );
1384 aSize.setHeight( aSize.Height() * ( mpWindowImpl->mpFrameData->mnDPIY) );
1385 aSize.AdjustHeight(72/2 );
1386 aSize.setHeight( aSize.Height() / 72 );
1388 if (rRenderContext.IsMapModeEnabled())
1389 aSize = rRenderContext.PixelToLogic(aSize);
1391 rFont.SetFontSize(aSize);
1394 void Window::ImplLogicToPoint(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1396 Size aSize = rFont.GetFontSize();
1398 if (rRenderContext.IsMapModeEnabled())
1399 aSize = rRenderContext.LogicToPixel(aSize);
1401 if (aSize.Width())
1403 aSize.setWidth( aSize.Width() * 72 );
1404 aSize.AdjustWidth(mpWindowImpl->mpFrameData->mnDPIX / 2 );
1405 aSize.setWidth( aSize.Width() / ( mpWindowImpl->mpFrameData->mnDPIX) );
1407 aSize.setHeight( aSize.Height() * 72 );
1408 aSize.AdjustHeight(mpWindowImpl->mpFrameData->mnDPIY / 2 );
1409 aSize.setHeight( aSize.Height() / ( mpWindowImpl->mpFrameData->mnDPIY) );
1411 rFont.SetFontSize(aSize);
1414 bool Window::ImplUpdatePos()
1416 bool bSysChild = false;
1418 if ( ImplIsOverlapWindow() )
1420 GetOutDev()->mnOutOffX = mpWindowImpl->mnX;
1421 GetOutDev()->mnOutOffY = mpWindowImpl->mnY;
1423 else
1425 vcl::Window* pParent = ImplGetParent();
1427 GetOutDev()->mnOutOffX = mpWindowImpl->mnX + pParent->GetOutDev()->mnOutOffX;
1428 GetOutDev()->mnOutOffY = mpWindowImpl->mnY + pParent->GetOutDev()->mnOutOffY;
1431 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1432 while ( pChild )
1434 if ( pChild->ImplUpdatePos() )
1435 bSysChild = true;
1436 pChild = pChild->mpWindowImpl->mpNext;
1439 if ( mpWindowImpl->mpSysObj )
1440 bSysChild = true;
1442 return bSysChild;
1445 void Window::ImplUpdateSysObjPos()
1447 if ( mpWindowImpl->mpSysObj )
1448 mpWindowImpl->mpSysObj->SetPosSize( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY, GetOutDev()->mnOutWidth, GetOutDev()->mnOutHeight );
1450 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1451 while ( pChild )
1453 pChild->ImplUpdateSysObjPos();
1454 pChild = pChild->mpWindowImpl->mpNext;
1458 void Window::ImplPosSizeWindow( tools::Long nX, tools::Long nY,
1459 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
1461 bool bNewPos = false;
1462 bool bNewSize = false;
1463 bool bCopyBits = false;
1464 tools::Long nOldOutOffX = GetOutDev()->mnOutOffX;
1465 tools::Long nOldOutOffY = GetOutDev()->mnOutOffY;
1466 tools::Long nOldOutWidth = GetOutDev()->mnOutWidth;
1467 tools::Long nOldOutHeight = GetOutDev()->mnOutHeight;
1468 std::unique_ptr<vcl::Region> pOverlapRegion;
1469 std::unique_ptr<vcl::Region> pOldRegion;
1471 if ( IsReallyVisible() )
1473 tools::Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
1474 Size( nOldOutWidth, nOldOutHeight ) );
1475 pOldRegion.reset( new vcl::Region( aOldWinRect ) );
1476 if ( mpWindowImpl->mbWinRegion )
1477 pOldRegion->Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1479 if ( GetOutDev()->mnOutWidth && GetOutDev()->mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
1480 !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
1481 !HasPaintEvent() )
1482 bCopyBits = true;
1485 bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
1486 if ( nFlags & PosSizeFlags::Width )
1488 if(!( nFlags & PosSizeFlags::X ))
1490 nX = mpWindowImpl->mnX;
1491 nFlags |= PosSizeFlags::X;
1492 bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
1495 if ( nWidth < 0 )
1496 nWidth = 0;
1497 if ( nWidth != GetOutDev()->mnOutWidth )
1499 GetOutDev()->mnOutWidth = nWidth;
1500 bNewSize = true;
1501 bCopyBits = false;
1504 if ( nFlags & PosSizeFlags::Height )
1506 if ( nHeight < 0 )
1507 nHeight = 0;
1508 if ( nHeight != GetOutDev()->mnOutHeight )
1510 GetOutDev()->mnOutHeight = nHeight;
1511 bNewSize = true;
1512 bCopyBits = false;
1516 if ( nFlags & PosSizeFlags::X )
1518 tools::Long nOrgX = nX;
1519 Point aPtDev( Point( nX+GetOutDev()->mnOutOffX, 0 ) );
1520 OutputDevice *pOutDev = GetOutDev();
1521 if( pOutDev->HasMirroredGraphics() )
1523 aPtDev.setX( GetOutDev()->mpGraphics->mirror2( aPtDev.X(), *GetOutDev() ) );
1525 // #106948# always mirror our pos if our parent is not mirroring, even
1526 // if we are also not mirroring
1527 // RTL: check if parent is in different coordinates
1528 if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
1530 nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
1532 /* #i99166# An LTR window in RTL UI that gets sized only would be
1533 expected to not moved its upper left point
1535 if( bnXRecycled )
1537 if( GetOutDev()->ImplIsAntiparallel() )
1539 aPtDev.setX( mpWindowImpl->mnAbsScreenX );
1540 nOrgX = mpWindowImpl->maPos.X();
1544 else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
1546 // mirrored window in LTR UI
1547 nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
1550 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1551 if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
1553 if ( bCopyBits && !pOverlapRegion )
1555 pOverlapRegion.reset( new vcl::Region() );
1556 ImplCalcOverlapRegion( GetOutputRectPixel(),
1557 *pOverlapRegion, false, true );
1559 mpWindowImpl->mnX = nX;
1560 mpWindowImpl->maPos.setX( nOrgX );
1561 mpWindowImpl->mnAbsScreenX = aPtDev.X();
1562 bNewPos = true;
1565 if ( nFlags & PosSizeFlags::Y )
1567 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1568 if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
1570 if ( bCopyBits && !pOverlapRegion )
1572 pOverlapRegion.reset( new vcl::Region() );
1573 ImplCalcOverlapRegion( GetOutputRectPixel(),
1574 *pOverlapRegion, false, true );
1576 mpWindowImpl->mnY = nY;
1577 mpWindowImpl->maPos.setY( nY );
1578 bNewPos = true;
1582 if ( !(bNewPos || bNewSize) )
1583 return;
1585 bool bUpdateSysObjPos = false;
1586 if ( bNewPos )
1587 bUpdateSysObjPos = ImplUpdatePos();
1589 // the borderwindow always specifies the position for its client window
1590 if ( mpWindowImpl->mpBorderWindow )
1591 mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
1593 if ( mpWindowImpl->mpClientWindow )
1595 mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
1596 mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
1597 GetOutDev()->mnOutWidth - mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
1598 GetOutDev()->mnOutHeight - mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
1599 PosSizeFlags::X | PosSizeFlags::Y |
1600 PosSizeFlags::Width | PosSizeFlags::Height );
1601 // If we have a client window, then this is the position
1602 // of the Application's floating windows
1603 mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
1604 if ( bNewPos )
1606 if ( mpWindowImpl->mpClientWindow->IsVisible() )
1608 mpWindowImpl->mpClientWindow->ImplCallMove();
1610 else
1612 mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
1617 // Move()/Resize() will be called only for Show(), such that
1618 // at least one is called before Show()
1619 if ( IsVisible() )
1621 if ( bNewPos )
1623 ImplCallMove();
1625 if ( bNewSize )
1627 ImplCallResize();
1630 else
1632 if ( bNewPos )
1633 mpWindowImpl->mbCallMove = true;
1634 if ( bNewSize )
1635 mpWindowImpl->mbCallResize = true;
1638 bool bUpdateSysObjClip = false;
1639 if ( IsReallyVisible() )
1641 if ( bNewPos || bNewSize )
1643 // set Clip-Flag
1644 bUpdateSysObjClip = !ImplSetClipFlag( true );
1647 // invalidate window content ?
1648 if ( bNewPos || (GetOutDev()->mnOutWidth > nOldOutWidth) || (GetOutDev()->mnOutHeight > nOldOutHeight) )
1650 if ( bNewPos )
1652 bool bInvalidate = false;
1653 bool bParentPaint = true;
1654 if ( !ImplIsOverlapWindow() )
1655 bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
1656 if ( bCopyBits && bParentPaint && !HasPaintEvent() )
1658 vcl::Region aRegion( GetOutputRectPixel() );
1659 if ( mpWindowImpl->mbWinRegion )
1660 aRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1661 ImplClipBoundaries( aRegion, false, true );
1662 if ( !pOverlapRegion->IsEmpty() )
1664 pOverlapRegion->Move( GetOutDev()->mnOutOffX - nOldOutOffX, GetOutDev()->mnOutOffY - nOldOutOffY );
1665 aRegion.Exclude( *pOverlapRegion );
1667 if ( !aRegion.IsEmpty() )
1669 // adapt Paint areas
1670 ImplMoveAllInvalidateRegions( tools::Rectangle( Point( nOldOutOffX, nOldOutOffY ),
1671 Size( nOldOutWidth, nOldOutHeight ) ),
1672 GetOutDev()->mnOutOffX - nOldOutOffX, GetOutDev()->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( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY,
1683 nOldOutOffX, nOldOutOffY,
1684 nOldOutWidth, nOldOutHeight,
1685 *GetOutDev() );
1687 else
1688 bInvalidate = true;
1690 else
1691 bInvalidate = true;
1692 if ( !bInvalidate )
1694 if ( !pOverlapRegion->IsEmpty() )
1695 ImplInvalidateFrameRegion( pOverlapRegion.get(), InvalidateFlags::Children );
1698 else
1699 bInvalidate = true;
1701 else
1702 bInvalidate = true;
1703 if ( bInvalidate )
1704 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
1706 else
1708 vcl::Region aRegion( GetOutputRectPixel() );
1709 aRegion.Exclude( *pOldRegion );
1710 if ( mpWindowImpl->mbWinRegion )
1711 aRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1712 ImplClipBoundaries( aRegion, false, true );
1713 if ( !aRegion.IsEmpty() )
1714 ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
1718 // invalidate Parent or Overlaps
1719 if ( bNewPos ||
1720 (GetOutDev()->mnOutWidth < nOldOutWidth) || (GetOutDev()->mnOutHeight < nOldOutHeight) )
1722 vcl::Region aRegion( *pOldRegion );
1723 if ( !mpWindowImpl->mbPaintTransparent )
1724 ImplExcludeWindowRegion( aRegion );
1725 ImplClipBoundaries( aRegion, false, true );
1726 if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
1727 ImplInvalidateParentFrameRegion( aRegion );
1731 // adapt system objects
1732 if ( bUpdateSysObjClip )
1733 ImplUpdateSysObjClip();
1734 if ( bUpdateSysObjPos )
1735 ImplUpdateSysObjPos();
1736 if ( bNewSize && mpWindowImpl->mpSysObj )
1737 mpWindowImpl->mpSysObj->SetPosSize( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY, GetOutDev()->mnOutWidth, GetOutDev()->mnOutHeight );
1740 void Window::ImplNewInputContext()
1742 ImplSVData* pSVData = ImplGetSVData();
1743 vcl::Window* pFocusWin = pSVData->mpWinData->mpFocusWin;
1744 if ( !pFocusWin || !pFocusWin->mpWindowImpl || pFocusWin->isDisposed() )
1745 return;
1747 // Is InputContext changed?
1748 const InputContext& rInputContext = pFocusWin->GetInputContext();
1749 if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
1750 return;
1752 pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
1754 SalInputContext aNewContext;
1755 const vcl::Font& rFont = rInputContext.GetFont();
1756 const OUString& rFontName = rFont.GetFamilyName();
1757 rtl::Reference<LogicalFontInstance> pFontInstance;
1758 aNewContext.mpFont = nullptr;
1759 if (!rFontName.isEmpty())
1761 OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
1762 Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() );
1763 if ( !aSize.Height() )
1765 // only set default sizes if the font height in logical
1766 // coordinates equals 0
1767 if ( rFont.GetFontSize().Height() )
1768 aSize.setHeight( 1 );
1769 else
1770 aSize.setHeight( (12*pFocusWin->GetOutDev()->mnDPIY)/72 );
1772 pFontInstance = pFocusWin->GetOutDev()->mxFontCache->GetFontInstance(
1773 pFocusWin->GetOutDev()->mxFontCollection.get(),
1774 rFont, aSize, static_cast<float>(aSize.Height()) );
1775 if ( pFontInstance )
1776 aNewContext.mpFont = pFontInstance;
1778 aNewContext.mnOptions = rInputContext.GetOptions();
1779 pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
1782 void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink)
1784 if (mpWindowImpl) // may be called after dispose
1786 mpWindowImpl->maDumpAsPropertyTreeHdl = rLink;
1790 void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink)
1792 ImplGetFrame()->SetModalHierarchyHdl(rLink);
1795 KeyIndicatorState Window::GetIndicatorState() const
1797 return mpWindowImpl->mpFrame->GetIndicatorState();
1800 void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
1802 mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
1805 void Window::KeyInput( const KeyEvent& rKEvt )
1807 KeyCode cod = rKEvt.GetKeyCode ();
1808 bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
1810 // do not respond to accelerators unless Alt or Ctrl is held
1811 if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
1813 if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1))
1814 return;
1817 NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt );
1818 if ( !CompatNotify( aNEvt ) )
1819 mpWindowImpl->mbKeyInput = true;
1822 void Window::KeyUp( const KeyEvent& rKEvt )
1824 NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt );
1825 if ( !CompatNotify( aNEvt ) )
1826 mpWindowImpl->mbKeyUp = true;
1829 void Window::Draw( OutputDevice*, const Point&, SystemTextColorFlags )
1833 void Window::Move() {}
1835 void Window::Resize() {}
1837 void Window::Activate() {}
1839 void Window::Deactivate() {}
1841 void Window::GetFocus()
1843 if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
1845 VclPtr<vcl::Window> xWindow(this);
1846 mpWindowImpl->mpLastFocusWindow->GrabFocus();
1847 if( xWindow->isDisposed() )
1848 return;
1851 NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
1852 CompatNotify( aNEvt );
1855 void Window::LoseFocus()
1857 NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this );
1858 CompatNotify( aNEvt );
1861 void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink)
1863 if (mpWindowImpl) // may be called after dispose
1865 mpWindowImpl->maHelpRequestHdl = rLink;
1869 void Window::RequestHelp( const HelpEvent& rHEvt )
1871 // if Balloon-Help is requested, show the balloon
1872 // with help text set
1873 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1875 OUString rStr = GetHelpText();
1876 if ( rStr.isEmpty() )
1877 rStr = GetQuickHelpText();
1878 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1879 ImplGetParent()->RequestHelp( rHEvt );
1880 else
1882 Point aPos = GetPosPixel();
1883 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1884 aPos = OutputToScreenPixel(Point(0, 0));
1885 tools::Rectangle aRect( aPos, GetSizePixel() );
1887 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
1890 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1892 const OUString& rStr = GetQuickHelpText();
1893 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1894 ImplGetParent()->RequestHelp( rHEvt );
1895 else
1897 Point aPos = GetPosPixel();
1898 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1899 aPos = OutputToScreenPixel(Point(0, 0));
1900 tools::Rectangle aRect( aPos, GetSizePixel() );
1901 Help::ShowQuickHelp( this, aRect, rStr, QuickHelpFlags::CtrlText );
1904 else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this))
1906 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
1907 if ( aStrHelpId.isEmpty() && ImplGetParent() )
1908 ImplGetParent()->RequestHelp( rHEvt );
1909 else
1911 Help* pHelp = Application::GetHelp();
1912 if ( pHelp )
1914 if( !aStrHelpId.isEmpty() )
1915 pHelp->Start( aStrHelpId, this );
1916 else
1917 pHelp->Start( OOO_HELP_INDEX, this );
1923 void Window::Command( const CommandEvent& rCEvt )
1925 CallEventListeners( VclEventId::WindowCommand, const_cast<CommandEvent *>(&rCEvt) );
1927 NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt );
1928 if ( !CompatNotify( aNEvt ) )
1929 mpWindowImpl->mbCommand = true;
1932 void Window::Tracking( const TrackingEvent& rTEvt )
1935 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1936 if( pWrapper )
1937 pWrapper->Tracking( rTEvt );
1940 void Window::StateChanged(StateChangedType eType)
1942 switch (eType)
1944 //stuff that doesn't invalidate the layout
1945 case StateChangedType::ControlForeground:
1946 case StateChangedType::ControlBackground:
1947 case StateChangedType::UpdateMode:
1948 case StateChangedType::ReadOnly:
1949 case StateChangedType::Enable:
1950 case StateChangedType::State:
1951 case StateChangedType::Data:
1952 case StateChangedType::InitShow:
1953 case StateChangedType::ControlFocus:
1954 break;
1955 //stuff that does invalidate the layout
1956 default:
1957 queue_resize(eType);
1958 break;
1962 void Window::SetStyle( WinBits nStyle )
1964 if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
1966 mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
1967 mpWindowImpl->mnStyle = nStyle;
1968 CompatStateChanged( StateChangedType::Style );
1972 void Window::SetExtendedStyle( WindowExtendedStyle nExtendedStyle )
1975 if ( mpWindowImpl->mnExtendedStyle == nExtendedStyle )
1976 return;
1978 vcl::Window* pWindow = ImplGetBorderWindow();
1979 if( ! pWindow )
1980 pWindow = this;
1981 if( pWindow->mpWindowImpl->mbFrame )
1983 SalExtStyle nExt = 0;
1984 if( nExtendedStyle & WindowExtendedStyle::Document )
1985 nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
1986 if( nExtendedStyle & WindowExtendedStyle::DocModified )
1987 nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
1989 pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
1991 mpWindowImpl->mnExtendedStyle = nExtendedStyle;
1994 void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
1997 if ( !mpWindowImpl->mpBorderWindow )
1998 return;
2000 if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
2001 ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
2002 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
2005 // this is a little awkward: some controls (e.g. svtools ProgressBar)
2006 // cannot avoid getting constructed with WB_BORDER but want to disable
2007 // borders in case of NWF drawing. So they need a method to remove their border window
2008 VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow;
2009 // remove us as border window's client
2010 pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
2011 mpWindowImpl->mpBorderWindow = nullptr;
2012 mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
2013 // reparent us above the border window
2014 SetParent( pBorderWin->mpWindowImpl->mpParent );
2015 // set us to the position and size of our previous border
2016 Point aBorderPos( pBorderWin->GetPosPixel() );
2017 Size aBorderSize( pBorderWin->GetSizePixel() );
2018 setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
2019 // release border window
2020 pBorderWin.disposeAndClear();
2022 // set new style bits
2023 SetStyle( GetStyle() & (~WB_BORDER) );
2025 else
2027 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2028 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
2029 else
2030 mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
2034 WindowBorderStyle Window::GetBorderStyle() const
2037 if ( mpWindowImpl->mpBorderWindow )
2039 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2040 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
2041 else
2042 return mpWindowImpl->mpBorderWindow->GetBorderStyle();
2045 return WindowBorderStyle::NONE;
2048 tools::Long Window::CalcTitleWidth() const
2051 if ( mpWindowImpl->mpBorderWindow )
2053 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2054 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
2055 else
2056 return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
2058 else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
2060 // we guess the width for frame windows as we do not know the
2061 // border of external dialogs
2062 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2063 vcl::Font aFont = GetFont();
2064 const_cast<vcl::Window*>(this)->SetPointFont(const_cast<::OutputDevice&>(*GetOutDev()), rStyleSettings.GetTitleFont());
2065 tools::Long nTitleWidth = GetTextWidth( GetText() );
2066 const_cast<vcl::Window*>(this)->SetFont( aFont );
2067 nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
2068 nTitleWidth += StyleSettings::GetBorderSize() * 2;
2069 nTitleWidth += 10;
2070 return nTitleWidth;
2073 return 0;
2076 void Window::SetInputContext( const InputContext& rInputContext )
2079 mpWindowImpl->maInputContext = rInputContext;
2080 if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
2081 ImplNewInputContext();
2084 void Window::PostExtTextInputEvent(VclEventId nType, const OUString& rText)
2086 switch (nType)
2088 case VclEventId::ExtTextInput:
2090 std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]);
2091 for (int i = 0; i < rText.getLength(); ++i) {
2092 pAttr[i] = ExtTextInputAttr::Underline;
2094 SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE };
2095 ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent);
2097 break;
2098 case VclEventId::EndExtTextInput:
2099 ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr);
2100 break;
2101 default:
2102 assert(false);
2106 void Window::EndExtTextInput()
2108 if ( mpWindowImpl->mbExtTextInput )
2109 ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
2112 void Window::SetCursorRect( const tools::Rectangle* pRect, tools::Long nExtTextInputWidth )
2115 ImplWinData* pWinData = ImplGetWinData();
2116 if ( pWinData->mpCursorRect )
2118 if ( pRect )
2119 pWinData->mpCursorRect = *pRect;
2120 else
2121 pWinData->mpCursorRect.reset();
2123 else
2125 if ( pRect )
2126 pWinData->mpCursorRect = *pRect;
2129 pWinData->mnCursorExtWidth = nExtTextInputWidth;
2133 const tools::Rectangle* Window::GetCursorRect() const
2136 ImplWinData* pWinData = ImplGetWinData();
2137 return pWinData->mpCursorRect ? &*pWinData->mpCursorRect : nullptr;
2140 tools::Long Window::GetCursorExtTextInputWidth() const
2143 ImplWinData* pWinData = ImplGetWinData();
2144 return pWinData->mnCursorExtWidth;
2147 void Window::SetCompositionCharRect( const tools::Rectangle* pRect, tools::Long nCompositionLength, bool bVertical ) {
2149 ImplWinData* pWinData = ImplGetWinData();
2150 pWinData->mpCompositionCharRects.reset();
2151 pWinData->mbVertical = bVertical;
2152 pWinData->mnCompositionCharRects = nCompositionLength;
2153 if ( pRect && (nCompositionLength > 0) )
2155 pWinData->mpCompositionCharRects.reset( new tools::Rectangle[nCompositionLength] );
2156 for (tools::Long i = 0; i < nCompositionLength; ++i)
2157 pWinData->mpCompositionCharRects[i] = pRect[i];
2161 void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
2163 rAllChildren.push_back( this );
2165 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2166 while ( pChild )
2168 pChild->CollectChildren( rAllChildren );
2169 pChild = pChild->mpWindowImpl->mpNext;
2173 void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
2175 vcl::Font aFont = rFont;
2176 ImplPointToLogic(rRenderContext, aFont);
2177 rRenderContext.SetFont(aFont);
2180 vcl::Font Window::GetPointFont(vcl::RenderContext const & rRenderContext) const
2182 vcl::Font aFont = rRenderContext.GetFont();
2183 ImplLogicToPoint(rRenderContext, aFont);
2184 return aFont;
2187 void Window::Show(bool bVisible, ShowFlags nFlags)
2189 if ( !mpWindowImpl || mpWindowImpl->mbVisible == bVisible )
2190 return;
2192 VclPtr<vcl::Window> xWindow(this);
2194 bool bRealVisibilityChanged = false;
2195 mpWindowImpl->mbVisible = bVisible;
2197 if ( !bVisible )
2199 ImplHideAllOverlaps();
2200 if( !xWindow->mpWindowImpl )
2201 return;
2203 if ( mpWindowImpl->mpBorderWindow )
2205 bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
2206 if ( mpWindowImpl->mbNoParentUpdate )
2207 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
2208 mpWindowImpl->mpBorderWindow->Show( false, nFlags );
2209 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
2211 else if ( mpWindowImpl->mbFrame )
2213 mpWindowImpl->mbSuppressAccessibilityEvents = true;
2214 mpWindowImpl->mpFrame->Show( false );
2217 CompatStateChanged( StateChangedType::Visible );
2219 if ( mpWindowImpl->mbReallyVisible )
2221 if ( mpWindowImpl->mbInitWinClipRegion )
2222 ImplInitWinClipRegion();
2224 vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
2226 if( !xWindow->mpWindowImpl )
2227 return;
2229 bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
2230 ImplResetReallyVisible();
2231 ImplSetClipFlag();
2233 if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
2235 // convert focus
2236 if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
2238 if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
2239 mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
2240 ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
2242 mpWindowImpl->mpOverlapWindow->GrabFocus();
2246 if ( !mpWindowImpl->mbFrame )
2248 if (mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget)
2251 * #i48371# native theming: some themes draw outside the control
2252 * area we tell them to (bad thing, but we cannot do much about it ).
2253 * On hiding these controls they get invalidated with their window rectangle
2254 * which leads to the parts outside the control area being left and not
2255 * invalidated. Workaround: invalidate an area on the parent, too
2257 const int workaround_border = 5;
2258 tools::Rectangle aBounds( aInvRegion.GetBoundRect() );
2259 aBounds.AdjustLeft( -workaround_border );
2260 aBounds.AdjustTop( -workaround_border );
2261 aBounds.AdjustRight(workaround_border );
2262 aBounds.AdjustBottom(workaround_border );
2263 aInvRegion = aBounds;
2265 if ( !mpWindowImpl->mbNoParentUpdate )
2267 if ( !aInvRegion.IsEmpty() )
2268 ImplInvalidateParentFrameRegion( aInvRegion );
2270 ImplGenerateMouseMove();
2274 else
2276 // inherit native widget flag for form controls
2277 // required here, because frames never show up in the child hierarchy - which should be fixed...
2278 // eg, the drop down of a combobox which is a system floating window
2279 if( mpWindowImpl->mbFrame && GetParent() && !GetParent()->isDisposed() &&
2280 GetParent()->IsCompoundControl() &&
2281 GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() &&
2282 !(GetStyle() & WB_TOOLTIPWIN) )
2284 EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
2287 if ( mpWindowImpl->mbCallMove )
2289 ImplCallMove();
2291 if ( mpWindowImpl->mbCallResize )
2293 ImplCallResize();
2296 CompatStateChanged( StateChangedType::Visible );
2298 vcl::Window* pTestParent;
2299 if ( ImplIsOverlapWindow() )
2300 pTestParent = mpWindowImpl->mpOverlapWindow;
2301 else
2302 pTestParent = ImplGetParent();
2303 if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
2305 // if a window becomes visible, send all child windows a StateChange,
2306 // such that these can initialise themselves
2307 ImplCallInitShow();
2309 // If it is a SystemWindow it automatically pops up on top of
2310 // all other windows if needed.
2311 if ( ImplIsOverlapWindow() && !(nFlags & ShowFlags::NoActivate) )
2313 ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE );
2314 ImplFocusToTop( ToTopFlags::NONE, false );
2317 // adjust mpWindowImpl->mbReallyVisible
2318 bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
2319 ImplSetReallyVisible();
2321 // assure clip rectangles will be recalculated
2322 ImplSetClipFlag();
2324 if ( !mpWindowImpl->mbFrame )
2326 InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
2327 if( ! IsPaintTransparent() )
2328 nInvalidateFlags |= InvalidateFlags::NoTransparent;
2329 ImplInvalidate( nullptr, nInvalidateFlags );
2330 ImplGenerateMouseMove();
2334 if ( mpWindowImpl->mpBorderWindow )
2335 mpWindowImpl->mpBorderWindow->Show( true, nFlags );
2336 else if ( mpWindowImpl->mbFrame )
2338 // #106431#, hide SplashScreen
2339 ImplSVData* pSVData = ImplGetSVData();
2340 if ( !pSVData->mpIntroWindow )
2342 // The right way would be just to call this (not even in the 'if')
2343 auto pApp = GetpApp();
2344 if ( pApp )
2345 pApp->InitFinished();
2347 else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
2349 // ... but the VCL splash is broken, and it needs this
2350 // (for ./soffice .uno:NewDoc)
2351 pSVData->mpIntroWindow->Hide();
2354 //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
2355 mpWindowImpl->mbSuppressAccessibilityEvents = false;
2357 mpWindowImpl->mbPaintFrame = true;
2358 if (!Application::IsHeadlessModeEnabled())
2360 bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
2361 mpWindowImpl->mpFrame->Show( true, bNoActivate );
2363 if( !xWindow->mpWindowImpl )
2364 return;
2366 // Query the correct size of the window, if we are waiting for
2367 // a system resize
2368 if ( mpWindowImpl->mbWaitSystemResize )
2370 tools::Long nOutWidth;
2371 tools::Long nOutHeight;
2372 mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
2373 ImplHandleResize( this, nOutWidth, nOutHeight );
2376 if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel())
2377 // Make sure that the buffer size matches the window size, even if no resize was needed.
2378 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
2381 if( !xWindow->mpWindowImpl )
2382 return;
2384 ImplShowAllOverlaps();
2387 if( !xWindow->mpWindowImpl )
2388 return;
2390 // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
2391 // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
2392 // we re-use the SHOW/HIDE events this way, with this particular semantics).
2393 // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
2394 // now only notify with a NULL data pointer, for all other clients except the access bridge.
2395 if ( !bRealVisibilityChanged )
2396 CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide );
2397 if( xWindow->isDisposed() )
2398 return;
2402 Size Window::GetSizePixel() const
2404 if (!mpWindowImpl)
2406 SAL_WARN("vcl.layout", "WTF no windowimpl");
2407 return Size(0,0);
2410 // #i43257# trigger pending resize handler to assure correct window sizes
2411 if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
2413 VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
2414 mpWindowImpl->mpFrameData->maResizeIdle.Stop();
2415 mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr );
2416 if( xWindow->isDisposed() )
2417 return Size(0,0);
2420 return Size( GetOutDev()->mnOutWidth + mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
2421 GetOutDev()->mnOutHeight + mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
2424 void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2425 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2427 rLeftBorder = mpWindowImpl->mnLeftBorder;
2428 rTopBorder = mpWindowImpl->mnTopBorder;
2429 rRightBorder = mpWindowImpl->mnRightBorder;
2430 rBottomBorder = mpWindowImpl->mnBottomBorder;
2433 void Window::Enable( bool bEnable, bool bChild )
2435 if ( isDisposed() )
2436 return;
2438 if ( !bEnable )
2440 // the tracking mode will be stopped or the capture will be stolen
2441 // when a window is disabled,
2442 if ( IsTracking() )
2443 EndTracking( TrackingEventFlags::Cancel );
2444 if ( IsMouseCaptured() )
2445 ReleaseMouse();
2446 // try to pass focus to the next control
2447 // if the window has focus and is contained in the dialog control
2448 // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow().
2449 // Otherwise ImplDlgCtrlNextWindow() should be used
2450 if ( HasFocus() )
2451 ImplDlgCtrlNextWindow();
2454 if ( mpWindowImpl->mpBorderWindow )
2456 mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
2457 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2458 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2459 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
2462 // #i56102# restore app focus win in case the
2463 // window was disabled when the frame focus changed
2464 ImplSVData* pSVData = ImplGetSVData();
2465 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2466 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2467 pSVData->mpWinData->mpFocusWin = this;
2469 if ( mpWindowImpl->mbDisabled != !bEnable )
2471 mpWindowImpl->mbDisabled = !bEnable;
2472 if ( mpWindowImpl->mpSysObj )
2473 mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
2474 CompatStateChanged( StateChangedType::Enable );
2476 CallEventListeners( bEnable ? VclEventId::WindowEnabled : VclEventId::WindowDisabled );
2479 if ( bChild )
2481 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2482 while ( pChild )
2484 pChild->Enable( bEnable, bChild );
2485 pChild = pChild->mpWindowImpl->mpNext;
2489 if ( IsReallyVisible() )
2490 ImplGenerateMouseMove();
2493 void Window::EnableInput( bool bEnable, bool bChild )
2495 if (!mpWindowImpl)
2496 return;
2498 if ( mpWindowImpl->mpBorderWindow )
2500 mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
2501 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2502 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2503 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
2506 if ( (!bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) || bEnable )
2508 // automatically stop the tracking mode or steal capture
2509 // if the window is disabled
2510 if ( !bEnable )
2512 if ( IsTracking() )
2513 EndTracking( TrackingEventFlags::Cancel );
2514 if ( IsMouseCaptured() )
2515 ReleaseMouse();
2518 if ( mpWindowImpl->mbInputDisabled != !bEnable )
2520 mpWindowImpl->mbInputDisabled = !bEnable;
2521 if ( mpWindowImpl->mpSysObj )
2522 mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
2526 // #i56102# restore app focus win in case the
2527 // window was disabled when the frame focus changed
2528 ImplSVData* pSVData = ImplGetSVData();
2529 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2530 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2531 pSVData->mpWinData->mpFocusWin = this;
2533 if ( bChild )
2535 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2536 while ( pChild )
2538 pChild->EnableInput( bEnable, bChild );
2539 pChild = pChild->mpWindowImpl->mpNext;
2543 if ( IsReallyVisible() )
2544 ImplGenerateMouseMove();
2547 void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
2549 if (!mpWindowImpl)
2550 return;
2552 EnableInput( bEnable );
2554 // pExecuteWindow is the first Overlap-Frame --> if this
2555 // shouldn't be the case, then this must be changed in dialog.cxx
2556 if( pExcludeWindow )
2557 pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
2558 vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
2559 while ( pSysWin )
2561 // Is Window in the path from this window
2562 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
2564 // Is Window not in the exclude window path or not the
2565 // exclude window, then change the status
2566 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
2567 pSysWin->EnableInput( bEnable );
2569 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
2572 // enable/disable floating system windows as well
2573 vcl::Window* pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
2574 while ( pFrameWin )
2576 if( pFrameWin->ImplIsFloatingWindow() )
2578 // Is Window in the path from this window
2579 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
2581 // Is Window not in the exclude window path or not the
2582 // exclude window, then change the status
2583 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
2584 pFrameWin->EnableInput( bEnable );
2587 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
2590 // the same for ownerdraw floating windows
2591 if( !mpWindowImpl->mbFrame )
2592 return;
2594 ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
2595 for (auto const& elem : rList)
2597 // Is Window in the path from this window
2598 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) )
2600 // Is Window not in the exclude window path or not the
2601 // exclude window, then change the status
2602 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) )
2603 elem->EnableInput( bEnable );
2608 void Window::AlwaysEnableInput( bool bAlways, bool bChild )
2611 if ( mpWindowImpl->mpBorderWindow )
2612 mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
2614 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
2616 mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
2617 EnableInput(true, false);
2619 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
2621 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2624 if ( bChild )
2626 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2627 while ( pChild )
2629 pChild->AlwaysEnableInput( bAlways, bChild );
2630 pChild = pChild->mpWindowImpl->mpNext;
2635 void Window::SetActivateMode( ActivateModeFlags nMode )
2638 if ( mpWindowImpl->mpBorderWindow )
2639 mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
2641 if ( mpWindowImpl->mnActivateMode == nMode )
2642 return;
2644 mpWindowImpl->mnActivateMode = nMode;
2646 // possibly trigger Deactivate/Activate
2647 if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
2649 if ( (mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW)) &&
2650 !HasChildPathFocus( true ) )
2652 mpWindowImpl->mbActive = false;
2653 Deactivate();
2656 else
2658 if ( !mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW) )
2660 mpWindowImpl->mbActive = true;
2661 Activate();
2666 void Window::setPosSizePixel( tools::Long nX, tools::Long nY,
2667 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
2669 bool bHasValidSize = !mpWindowImpl->mbDefSize;
2671 if ( nFlags & PosSizeFlags::Pos )
2672 mpWindowImpl->mbDefPos = false;
2673 if ( nFlags & PosSizeFlags::Size )
2674 mpWindowImpl->mbDefSize = false;
2676 // The top BorderWindow is the window which is to be positioned
2677 VclPtr<vcl::Window> pWindow = this;
2678 while ( pWindow->mpWindowImpl->mpBorderWindow )
2679 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
2681 if ( pWindow->mpWindowImpl->mbFrame )
2683 // Note: if we're positioning a frame, the coordinates are interpreted
2684 // as being the top-left corner of the window's client area and NOT
2685 // as the position of the border ! (due to limitations of several UNIX window managers)
2686 tools::Long nOldWidth = pWindow->GetOutDev()->mnOutWidth;
2688 if ( !(nFlags & PosSizeFlags::Width) )
2689 nWidth = pWindow->GetOutDev()->mnOutWidth;
2690 if ( !(nFlags & PosSizeFlags::Height) )
2691 nHeight = pWindow->GetOutDev()->mnOutHeight;
2693 sal_uInt16 nSysFlags=0;
2694 VclPtr<vcl::Window> pParent = GetParent();
2695 VclPtr<vcl::Window> pWinParent = pWindow->GetParent();
2697 if( nFlags & PosSizeFlags::Width )
2698 nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
2699 if( nFlags & PosSizeFlags::Height )
2700 nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
2701 if( nFlags & PosSizeFlags::X )
2703 nSysFlags |= SAL_FRAME_POSSIZE_X;
2704 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2706 nX += pWinParent->GetOutDev()->mnOutOffX;
2708 if( pParent && pParent->GetOutDev()->ImplIsAntiparallel() )
2710 tools::Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
2711 const OutputDevice *pParentOutDev = pParent->GetOutDev();
2712 pParentOutDev->ReMirror( aRect );
2713 nX = aRect.Left();
2716 if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
2718 // RTL: make sure the old right aligned position is not changed
2719 // system windows will always grow to the right
2720 if ( pWinParent )
2722 OutputDevice *pParentOutDev = pWinParent->GetOutDev();
2723 if( pParentOutDev->HasMirroredGraphics() )
2725 const SalFrameGeometry& aSysGeometry = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2726 const SalFrameGeometry& aParentSysGeometry =
2727 pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2728 tools::Long myWidth = nOldWidth;
2729 if( !myWidth )
2730 myWidth = aSysGeometry.nWidth;
2731 if( !myWidth )
2732 myWidth = nWidth;
2733 nFlags |= PosSizeFlags::X;
2734 nSysFlags |= SAL_FRAME_POSSIZE_X;
2735 nX = aParentSysGeometry.nX - aSysGeometry.nLeftDecoration + aParentSysGeometry.nWidth
2736 - myWidth - 1 - aSysGeometry.nX;
2740 if( nFlags & PosSizeFlags::Y )
2742 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2743 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2745 nY += pWinParent->GetOutDev()->mnOutOffY;
2749 if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
2751 // check for min/max client size and adjust size accordingly
2752 // otherwise it may happen that the resize event is ignored, i.e. the old size remains
2753 // unchanged but ImplHandleResize() is called with the wrong size
2754 SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() );
2755 if( pSystemWindow )
2757 Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
2758 Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
2759 if( nWidth < aMinSize.Width() )
2760 nWidth = aMinSize.Width();
2761 if( nHeight < aMinSize.Height() )
2762 nHeight = aMinSize.Height();
2764 if( nWidth > aMaxSize.Width() )
2765 nWidth = aMaxSize.Width();
2766 if( nHeight > aMaxSize.Height() )
2767 nHeight = aMaxSize.Height();
2771 pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
2773 // Adjust resize with the hack of different client size and frame geometries to fix
2774 // native menu bars. Eventually this should be replaced by proper mnTopBorder usage.
2775 pWindow->mpWindowImpl->mpFrame->GetClientSize(nWidth, nHeight);
2777 // Resize should be called directly. If we haven't
2778 // set the correct size, we get a second resize from
2779 // the system with the correct size. This can be happened
2780 // if the size is too small or too large.
2781 ImplHandleResize( pWindow, nWidth, nHeight );
2783 else
2785 pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
2786 if ( IsReallyVisible() )
2787 ImplGenerateMouseMove();
2791 Point Window::GetPosPixel() const
2793 return mpWindowImpl->maPos;
2796 tools::Rectangle Window::GetDesktopRectPixel() const
2798 tools::Rectangle rRect;
2799 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
2800 return rRect;
2803 Point Window::OutputToScreenPixel( const Point& rPos ) const
2805 // relative to top level parent
2806 return Point( rPos.X() + GetOutDev()->mnOutOffX, rPos.Y() + GetOutDev()->mnOutOffY );
2809 Point Window::ScreenToOutputPixel( const Point& rPos ) const
2811 // relative to top level parent
2812 return Point( rPos.X() - GetOutDev()->mnOutOffX, rPos.Y() - GetOutDev()->mnOutOffY );
2815 tools::Long Window::ImplGetUnmirroredOutOffX()
2817 // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
2818 tools::Long offx = GetOutDev()->mnOutOffX;
2819 OutputDevice *pOutDev = GetOutDev();
2820 if( pOutDev->HasMirroredGraphics() )
2822 if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
2824 if ( !ImplIsOverlapWindow() )
2825 offx -= mpWindowImpl->mpParent->GetOutDev()->mnOutOffX;
2827 offx = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - offx;
2829 if ( !ImplIsOverlapWindow() )
2830 offx += mpWindowImpl->mpParent->GetOutDev()->mnOutOffX;
2834 return offx;
2837 // normalized screen pixel are independent of mirroring
2838 Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
2840 // relative to top level parent
2841 tools::Long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2842 return Point( rPos.X()+offx, rPos.Y() + GetOutDev()->mnOutOffY );
2845 Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
2847 // relative to top level parent
2848 tools::Long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2849 return Point( rPos.X()-offx, rPos.Y() - GetOutDev()->mnOutOffY );
2852 Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
2854 // relative to the screen
2855 Point p = OutputToScreenPixel( rPos );
2856 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2857 p.AdjustX(g.nX );
2858 p.AdjustY(g.nY );
2859 return p;
2862 Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
2864 // relative to the screen
2865 Point p = ScreenToOutputPixel( rPos );
2866 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2867 p.AdjustX( -(g.nX) );
2868 p.AdjustY( -(g.nY) );
2869 return p;
2872 tools::Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const
2874 // this method creates unmirrored screen coordinates to be compared with the desktop
2875 // and is used for positioning of RTL popup windows correctly on the screen
2876 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2878 Point p1 = rRect.TopRight();
2879 p1 = OutputToScreenPixel(p1);
2880 p1.setX( g.nX+g.nWidth-p1.X() );
2881 p1.AdjustY(g.nY );
2883 Point p2 = rRect.BottomLeft();
2884 p2 = OutputToScreenPixel(p2);
2885 p2.setX( g.nX+g.nWidth-p2.X() );
2886 p2.AdjustY(g.nY );
2888 return tools::Rectangle( p1, p2 );
2891 tools::Rectangle Window::ImplUnmirroredAbsoluteScreenToOutputPixel( const tools::Rectangle &rRect ) const
2893 // undo ImplOutputToUnmirroredAbsoluteScreenPixel
2894 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2896 Point p1 = rRect.TopRight();
2897 p1.AdjustY(-g.nY );
2898 p1.setX( g.nX+g.nWidth-p1.X() );
2899 p1 = ScreenToOutputPixel(p1);
2901 Point p2 = rRect.BottomLeft();
2902 p2.AdjustY(-g.nY);
2903 p2.setX( g.nX+g.nWidth-p2.X() );
2904 p2 = ScreenToOutputPixel(p2);
2906 return tools::Rectangle( p1, p2 );
2910 tools::Rectangle Window::GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
2912 // with decoration
2913 return ImplGetWindowExtentsRelative( pRelativeWindow );
2916 tools::Rectangle Window::ImplGetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
2918 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2919 // make sure we use the extent of our border window,
2920 // otherwise we miss a few pixels
2921 const vcl::Window *pWin = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow : this;
2923 Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
2924 aPos.AdjustX(g.nX );
2925 aPos.AdjustY(g.nY );
2926 Size aSize ( pWin->GetSizePixel() );
2927 // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
2928 if( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW) )
2930 aPos.AdjustX( -sal_Int32(g.nLeftDecoration) );
2931 aPos.AdjustY( -sal_Int32(g.nTopDecoration) );
2932 aSize.AdjustWidth(g.nLeftDecoration + g.nRightDecoration );
2933 aSize.AdjustHeight(g.nTopDecoration + g.nBottomDecoration );
2935 if( pRelativeWindow )
2937 // #106399# express coordinates relative to borderwindow
2938 const vcl::Window *pRelWin = pRelativeWindow->mpWindowImpl->mpBorderWindow ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow;
2939 aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
2941 return tools::Rectangle( aPos, aSize );
2944 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags )
2947 ImplScroll( GetOutputRectPixel(),
2948 nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
2951 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll,
2952 const tools::Rectangle& rRect, ScrollFlags nFlags )
2954 OutputDevice *pOutDev = GetOutDev();
2955 tools::Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
2956 aRect.Intersection( GetOutputRectPixel() );
2957 if ( !aRect.IsEmpty() )
2958 ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
2961 void WindowOutputDevice::Flush()
2963 if (mxOwnerWindow->mpWindowImpl)
2964 mxOwnerWindow->mpWindowImpl->mpFrame->Flush( GetOutputRectPixel() );
2967 void Window::SetUpdateMode( bool bUpdate )
2969 if (mpWindowImpl)
2971 mpWindowImpl->mbNoUpdate = !bUpdate;
2972 CompatStateChanged( StateChangedType::UpdateMode );
2976 void Window::GrabFocus()
2978 ImplGrabFocus( GetFocusFlags::NONE );
2981 bool Window::HasFocus() const
2983 return (this == ImplGetSVData()->mpWinData->mpFocusWin);
2986 void Window::GrabFocusToDocument()
2988 ImplGrabFocusToDocument(GetFocusFlags::NONE);
2991 VclPtr<vcl::Window> Window::GetFocusedWindow() const
2993 if (mpWindowImpl && mpWindowImpl->mpFrameData)
2994 return mpWindowImpl->mpFrameData->mpFocusWin;
2995 else
2996 return VclPtr<vcl::Window>();
2999 void Window::SetFakeFocus( bool bFocus )
3001 ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
3004 bool Window::HasChildPathFocus( bool bSystemWindow ) const
3007 vcl::Window* pFocusWin = ImplGetSVData()->mpWinData->mpFocusWin;
3008 if ( pFocusWin )
3009 return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
3010 return false;
3013 void Window::SetCursor( vcl::Cursor* pCursor )
3016 if ( mpWindowImpl->mpCursor != pCursor )
3018 if ( mpWindowImpl->mpCursor )
3019 mpWindowImpl->mpCursor->ImplHide();
3020 mpWindowImpl->mpCursor = pCursor;
3021 if ( pCursor )
3022 pCursor->ImplShow();
3026 void Window::SetText( const OUString& rStr )
3028 if (!mpWindowImpl || rStr == mpWindowImpl->maText)
3029 return;
3031 OUString oldTitle( mpWindowImpl->maText );
3032 mpWindowImpl->maText = rStr;
3034 if ( mpWindowImpl->mpBorderWindow )
3035 mpWindowImpl->mpBorderWindow->SetText( rStr );
3036 else if ( mpWindowImpl->mbFrame )
3037 mpWindowImpl->mpFrame->SetTitle( rStr );
3039 CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3041 // #107247# needed for accessibility
3042 // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes.
3043 // Therefore a window, which is labeled by this window, must also notify an accessible
3044 // name change.
3045 if ( IsReallyVisible() )
3047 vcl::Window* pWindow = GetAccessibleRelationLabelFor();
3048 if ( pWindow && pWindow != this )
3049 pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3052 CompatStateChanged( StateChangedType::Text );
3055 OUString Window::GetText() const
3058 return mpWindowImpl->maText;
3061 OUString Window::GetDisplayText() const
3064 return GetText();
3067 const Wallpaper& Window::GetDisplayBackground() const
3069 // FIXME: fix issue 52349, need to fix this really in
3070 // all NWF enabled controls
3071 const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
3072 if( pTB && IsNativeWidgetEnabled() )
3073 return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
3075 if( !IsBackground() )
3077 if( mpWindowImpl->mpParent )
3078 return mpWindowImpl->mpParent->GetDisplayBackground();
3081 const Wallpaper& rBack = GetBackground();
3082 if( ! rBack.IsBitmap() &&
3083 ! rBack.IsGradient() &&
3084 rBack.GetColor()== COL_TRANSPARENT &&
3085 mpWindowImpl->mpParent )
3086 return mpWindowImpl->mpParent->GetDisplayBackground();
3087 return rBack;
3090 const OUString& Window::GetHelpText() const
3092 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
3093 bool bStrHelpId = !aStrHelpId.isEmpty();
3095 if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId )
3097 if ( !IsDialog() && (mpWindowImpl->mnType != WindowType::TABPAGE) && (mpWindowImpl->mnType != WindowType::FLOATINGWINDOW) )
3099 Help* pHelp = Application::GetHelp();
3100 if ( pHelp )
3102 mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this);
3103 mpWindowImpl->mbHelpTextDynamic = false;
3107 else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
3109 static const char* pEnv = getenv( "HELP_DEBUG" );
3110 if( pEnv && *pEnv )
3112 OUString aTxt = mpWindowImpl->maHelpText + "\n------------------\n" + aStrHelpId;
3113 mpWindowImpl->maHelpText = aTxt;
3115 mpWindowImpl->mbHelpTextDynamic = false;
3118 //Fallback to Window::GetAccessibleDescription without reentry to GetHelpText()
3119 if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription)
3120 return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
3121 return mpWindowImpl->maHelpText;
3124 void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
3126 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3127 return;
3129 // be safe against re-entrance: first clear the old ref, then assign the new one
3130 if (mpWindowImpl->mxWindowPeer)
3132 // first, disconnect the peer from ourself, otherwise disposing it, will dispose us
3133 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3134 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3135 if ( pWrapper )
3136 pWrapper->SetWindowInterface( nullptr, mpWindowImpl->mxWindowPeer );
3137 mpWindowImpl->mxWindowPeer->dispose();
3138 mpWindowImpl->mxWindowPeer.clear();
3140 mpWindowImpl->mxWindowPeer = xPeer;
3142 mpWindowImpl->mpVCLXWindow = pVCLXWindow;
3145 Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate )
3147 if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
3149 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3150 if ( pWrapper )
3151 mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
3153 return mpWindowImpl->mxWindowPeer;
3156 void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace )
3158 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3159 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3160 if ( pWrapper )
3161 pWrapper->SetWindowInterface( this, xIFace );
3164 typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap;
3166 namespace {
3168 LOKWindowsMap& GetLOKWindowsMap()
3170 // Map to remember the LOKWindowId <-> Window binding.
3171 static LOKWindowsMap s_aLOKWindowsMap;
3173 return s_aLOKWindowsMap;
3178 void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
3180 // don't allow setting this twice
3181 assert(mpWindowImpl->mpLOKNotifier == nullptr);
3182 assert(pNotifier);
3183 // never use this in the desktop case
3184 assert(comphelper::LibreOfficeKit::isActive());
3186 if (!bParent)
3188 // Counter to be able to have unique id's for each window.
3189 static vcl::LOKWindowId sLastLOKWindowId = 1;
3191 // assign the LOK window id
3192 assert(mpWindowImpl->mnLOKWindowId == 0);
3193 mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
3194 GetLOKWindowsMap().emplace(mpWindowImpl->mnLOKWindowId, this);
3196 else
3197 mpWindowImpl->mbLOKParentNotifier = true;
3199 mpWindowImpl->mpLOKNotifier = pNotifier;
3202 VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
3204 const auto it = GetLOKWindowsMap().find(nWindowId);
3205 if (it != GetLOKWindowsMap().end())
3206 return it->second;
3208 return VclPtr<Window>();
3211 bool Window::IsLOKWindowsEmpty()
3213 return GetLOKWindowsMap().empty();
3216 void Window::ReleaseLOKNotifier()
3218 // unregister the LOK window binding
3219 if (mpWindowImpl->mnLOKWindowId > 0)
3220 GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
3222 mpWindowImpl->mpLOKNotifier = nullptr;
3223 mpWindowImpl->mnLOKWindowId = 0;
3226 ILibreOfficeKitNotifier::~ILibreOfficeKitNotifier()
3228 if (!comphelper::LibreOfficeKit::isActive())
3230 return;
3233 for (auto it = GetLOKWindowsMap().begin(); it != GetLOKWindowsMap().end();)
3235 WindowImpl* pWindowImpl = it->second->ImplGetWindowImpl();
3236 if (pWindowImpl && pWindowImpl->mpLOKNotifier == this)
3238 pWindowImpl->mpLOKNotifier = nullptr;
3239 pWindowImpl->mnLOKWindowId = 0;
3240 it = GetLOKWindowsMap().erase(it);
3241 continue;
3244 ++it;
3248 const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const
3250 return mpWindowImpl ? mpWindowImpl->mpLOKNotifier : nullptr;
3253 vcl::LOKWindowId Window::GetLOKWindowId() const
3255 return mpWindowImpl ? mpWindowImpl->mnLOKWindowId : 0;
3258 VclPtr<vcl::Window> Window::GetParentWithLOKNotifier()
3260 VclPtr<vcl::Window> pWindow(this);
3262 while (pWindow && !pWindow->GetLOKNotifier())
3263 pWindow = pWindow->GetParent();
3265 return pWindow;
3268 namespace
3271 const char* windowTypeName(WindowType nWindowType)
3273 switch (nWindowType)
3275 case WindowType::NONE: return "none";
3276 case WindowType::MESSBOX: return "messagebox";
3277 case WindowType::INFOBOX: return "infobox";
3278 case WindowType::WARNINGBOX: return "warningbox";
3279 case WindowType::ERRORBOX: return "errorbox";
3280 case WindowType::QUERYBOX: return "querybox";
3281 case WindowType::WINDOW: return "window";
3282 case WindowType::WORKWINDOW: return "workwindow";
3283 case WindowType::CONTAINER: return "container";
3284 case WindowType::FLOATINGWINDOW: return "floatingwindow";
3285 case WindowType::DIALOG: return "dialog";
3286 case WindowType::MODELESSDIALOG: return "modelessdialog";
3287 case WindowType::CONTROL: return "control";
3288 case WindowType::PUSHBUTTON: return "pushbutton";
3289 case WindowType::OKBUTTON: return "okbutton";
3290 case WindowType::CANCELBUTTON: return "cancelbutton";
3291 case WindowType::HELPBUTTON: return "helpbutton";
3292 case WindowType::IMAGEBUTTON: return "imagebutton";
3293 case WindowType::MENUBUTTON: return "menubutton";
3294 case WindowType::MOREBUTTON: return "morebutton";
3295 case WindowType::SPINBUTTON: return "spinbutton";
3296 case WindowType::RADIOBUTTON: return "radiobutton";
3297 case WindowType::CHECKBOX: return "checkbox";
3298 case WindowType::TRISTATEBOX: return "tristatebox";
3299 case WindowType::EDIT: return "edit";
3300 case WindowType::MULTILINEEDIT: return "multilineedit";
3301 case WindowType::COMBOBOX: return "combobox";
3302 case WindowType::LISTBOX: return "listbox";
3303 case WindowType::MULTILISTBOX: return "multilistbox";
3304 case WindowType::FIXEDTEXT: return "fixedtext";
3305 case WindowType::FIXEDLINE: return "fixedline";
3306 case WindowType::FIXEDBITMAP: return "fixedbitmap";
3307 case WindowType::FIXEDIMAGE: return "fixedimage";
3308 case WindowType::GROUPBOX: return "groupbox";
3309 case WindowType::SCROLLBAR: return "scrollbar";
3310 case WindowType::SCROLLBARBOX: return "scrollbarbox";
3311 case WindowType::SPLITTER: return "splitter";
3312 case WindowType::SPLITWINDOW: return "splitwindow";
3313 case WindowType::SPINFIELD: return "spinfield";
3314 case WindowType::PATTERNFIELD: return "patternfield";
3315 case WindowType::METRICFIELD: return "metricfield";
3316 case WindowType::FORMATTEDFIELD: return "formattedfield";
3317 case WindowType::CURRENCYFIELD: return "currencyfield";
3318 case WindowType::DATEFIELD: return "datefield";
3319 case WindowType::TIMEFIELD: return "timefield";
3320 case WindowType::PATTERNBOX: return "patternbox";
3321 case WindowType::NUMERICBOX: return "numericbox";
3322 case WindowType::METRICBOX: return "metricbox";
3323 case WindowType::CURRENCYBOX: return "currencybox";
3324 case WindowType::DATEBOX: return "datebox";
3325 case WindowType::TIMEBOX: return "timebox";
3326 case WindowType::LONGCURRENCYBOX: return "longcurrencybox";
3327 case WindowType::SCROLLWINDOW: return "scrollwindow";
3328 case WindowType::TOOLBOX: return "toolbox";
3329 case WindowType::DOCKINGWINDOW: return "dockingwindow";
3330 case WindowType::STATUSBAR: return "statusbar";
3331 case WindowType::TABPAGE: return "tabpage";
3332 case WindowType::TABCONTROL: return "tabcontrol";
3333 case WindowType::TABDIALOG: return "tabdialog";
3334 case WindowType::BORDERWINDOW: return "borderwindow";
3335 case WindowType::BUTTONDIALOG: return "buttondialog";
3336 case WindowType::SYSTEMCHILDWINDOW: return "systemchildwindow";
3337 case WindowType::SLIDER: return "slider";
3338 case WindowType::MENUBARWINDOW: return "menubarwindow";
3339 case WindowType::TREELISTBOX: return "treelistbox";
3340 case WindowType::HELPTEXTWINDOW: return "helptextwindow";
3341 case WindowType::INTROWINDOW: return "introwindow";
3342 case WindowType::LISTBOXWINDOW: return "listboxwindow";
3343 case WindowType::DOCKINGAREA: return "dockingarea";
3344 case WindowType::RULER: return "ruler";
3345 case WindowType::HEADERBAR: return "headerbar";
3346 case WindowType::VERTICALTABCONTROL: return "verticaltabcontrol";
3348 // nothing to do here, but for completeness
3349 case WindowType::TOOLKIT_FRAMEWINDOW: return "toolkit_framewindow";
3350 case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return "toolkit_systemchildwindow";
3353 return "none";
3358 void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
3360 if (!mpWindowImpl)
3361 return;
3363 rJsonWriter.put("id", get_id()); // TODO could be missing - sort out
3364 rJsonWriter.put("type", windowTypeName(GetType()));
3365 rJsonWriter.put("text", GetText());
3366 rJsonWriter.put("enabled", IsEnabled());
3367 if (!IsVisible())
3368 rJsonWriter.put("visible", false);
3370 if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
3372 auto childrenNode = rJsonWriter.startArray("children");
3373 while (pChild)
3376 auto childNode = rJsonWriter.startStruct();
3377 pChild->DumpAsPropertyTree(rJsonWriter);
3378 sal_Int32 nLeft = pChild->get_grid_left_attach();
3379 sal_Int32 nTop = pChild->get_grid_top_attach();
3380 if (nLeft != -1 && nTop != -1)
3382 rJsonWriter.put("left", nLeft);
3383 rJsonWriter.put("top", nTop);
3386 sal_Int32 nWidth = pChild->get_grid_width();
3387 if (nWidth > 1)
3388 rJsonWriter.put("width", nWidth);
3390 pChild = pChild->mpWindowImpl->mpNext;
3394 mpWindowImpl->maDumpAsPropertyTreeHdl.Call(rJsonWriter);
3397 void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
3399 // no deactivation if the newly activated window is my child
3400 if ( !pNew || !ImplIsChild( pNew ) )
3402 VclPtr<vcl::Window> xWindow(this);
3403 CallEventListeners( VclEventId::WindowDeactivate, pNew );
3404 if( !xWindow->mpWindowImpl )
3405 return;
3407 // #100759#, avoid walking the wrong frame's hierarchy
3408 // eg, undocked docking windows (ImplDockFloatWin)
3409 if ( ImplGetParent() && ImplGetParent()->mpWindowImpl &&
3410 mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
3411 ImplGetParent()->ImplCallDeactivateListeners( pNew );
3415 void Window::ImplCallActivateListeners( vcl::Window *pOld )
3417 // no activation if the old active window is my child
3418 if ( pOld && ImplIsChild( pOld ))
3419 return;
3421 VclPtr<vcl::Window> xWindow(this);
3422 CallEventListeners( VclEventId::WindowActivate, pOld );
3423 if( !xWindow->mpWindowImpl )
3424 return;
3426 if ( ImplGetParent() )
3427 ImplGetParent()->ImplCallActivateListeners( pOld );
3428 else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
3430 // top level frame reached: store hint for DefModalDialogParent
3431 ImplGetSVData()->maFrameData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
3435 void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
3437 if (mpWindowImpl->mpFrameData)
3438 mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
3441 Reference< XClipboard > Window::GetClipboard()
3443 if (!mpWindowImpl->mpFrameData)
3444 return static_cast<XClipboard*>(nullptr);
3445 if (!mpWindowImpl->mpFrameData->mxClipboard.is())
3446 mpWindowImpl->mpFrameData->mxClipboard = GetSystemClipboard();
3447 return mpWindowImpl->mpFrameData->mxClipboard;
3450 void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const tools::Rectangle& rRect )
3452 assert(GetOutDev()->mpOutDevData);
3453 GetOutDev()->mpOutDevData->mpRecordLayout = pLayout;
3454 GetOutDev()->mpOutDevData->maRecordRect = rRect;
3455 Paint(*GetOutDev(), rRect);
3456 GetOutDev()->mpOutDevData->mpRecordLayout = nullptr;
3459 void Window::DrawSelectionBackground( const tools::Rectangle& rRect,
3460 sal_uInt16 highlight,
3461 bool bChecked,
3462 bool bDrawBorder
3465 if( rRect.IsEmpty() )
3466 return;
3468 const StyleSettings& rStyles = GetSettings().GetStyleSettings();
3470 // colors used for item highlighting
3471 Color aSelectionBorderCol( rStyles.GetHighlightColor() );
3472 Color aSelectionFillCol( aSelectionBorderCol );
3474 bool bDark = rStyles.GetFaceColor().IsDark();
3475 bool bBright = ( rStyles.GetFaceColor() == COL_WHITE );
3477 int c1 = aSelectionBorderCol.GetLuminance();
3478 int c2 = GetBackgroundColor().GetLuminance();
3480 if( !bDark && !bBright && abs( c2-c1 ) < 75 )
3482 // contrast too low
3483 sal_uInt16 h,s,b;
3484 aSelectionFillCol.RGBtoHSB( h, s, b );
3485 if( b > 50 ) b -= 40;
3486 else b += 40;
3487 aSelectionFillCol = Color::HSBtoRGB( h, s, b );
3488 aSelectionBorderCol = aSelectionFillCol;
3491 tools::Rectangle aRect( rRect );
3492 Color oldFillCol = GetOutDev()->GetFillColor();
3493 Color oldLineCol = GetOutDev()->GetLineColor();
3495 if( bDrawBorder )
3496 GetOutDev()->SetLineColor( bDark ? COL_WHITE : ( bBright ? COL_BLACK : aSelectionBorderCol ) );
3497 else
3498 GetOutDev()->SetLineColor();
3500 sal_uInt16 nPercent = 0;
3501 if( !highlight )
3503 if( bDark )
3504 aSelectionFillCol = COL_BLACK;
3505 else
3506 nPercent = 80; // just checked (light)
3508 else
3510 if( bChecked && highlight == 2 )
3512 if( bDark )
3513 aSelectionFillCol = COL_LIGHTGRAY;
3514 else if ( bBright )
3516 aSelectionFillCol = COL_BLACK;
3517 GetOutDev()->SetLineColor( COL_BLACK );
3518 nPercent = 0;
3520 else
3521 nPercent = 20; // selected, pressed or checked ( very dark )
3523 else if( bChecked || highlight == 1 )
3525 if( bDark )
3526 aSelectionFillCol = COL_GRAY;
3527 else if ( bBright )
3529 aSelectionFillCol = COL_BLACK;
3530 GetOutDev()->SetLineColor( COL_BLACK );
3531 nPercent = 0;
3533 else
3534 nPercent = 35; // selected, pressed or checked ( very dark )
3536 else
3538 if( bDark )
3539 aSelectionFillCol = COL_LIGHTGRAY;
3540 else if ( bBright )
3542 aSelectionFillCol = COL_BLACK;
3543 GetOutDev()->SetLineColor( COL_BLACK );
3544 if( highlight == 3 )
3545 nPercent = 80;
3546 else
3547 nPercent = 0;
3549 else
3550 nPercent = 70; // selected ( dark )
3554 GetOutDev()->SetFillColor( aSelectionFillCol );
3556 if( bDark )
3558 GetOutDev()->DrawRect( aRect );
3560 else
3562 tools::Polygon aPoly( aRect );
3563 tools::PolyPolygon aPolyPoly( aPoly );
3564 GetOutDev()->DrawTransparent( aPolyPoly, nPercent );
3567 GetOutDev()->SetFillColor( oldFillCol );
3568 GetOutDev()->SetLineColor( oldLineCol );
3571 bool Window::IsScrollable() const
3573 // check for scrollbars
3574 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3575 while( pChild )
3577 if( pChild->GetType() == WindowType::SCROLLBAR )
3578 return true;
3579 else
3580 pChild = pChild->mpWindowImpl->mpNext;
3582 return false;
3585 void Window::ImplMirrorFramePos( Point &pt ) const
3587 pt.setX( mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X() );
3590 // frame based modal counter (dialogs are not modal to the whole application anymore)
3591 bool Window::IsInModalMode() const
3593 return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
3596 void Window::IncModalCount()
3598 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3599 vcl::Window* pParent = pFrameWindow;
3600 while( pFrameWindow )
3602 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
3603 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3605 pParent = pParent->GetParent();
3607 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3610 void Window::DecModalCount()
3612 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3613 vcl::Window* pParent = pFrameWindow;
3614 while( pFrameWindow )
3616 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
3617 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3619 pParent = pParent->GetParent();
3621 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3625 void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
3627 mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
3630 void Window::ImplNotifyIconifiedState( bool bIconified )
3632 mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3633 // #109206# notify client window as well to have toolkit topwindow listeners notified
3634 if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
3635 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3638 bool Window::HasActiveChildFrame() const
3640 bool bRet = false;
3641 vcl::Window *pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
3642 while( pFrameWin )
3644 if( pFrameWin != mpWindowImpl->mpFrameWindow )
3646 bool bDecorated = false;
3647 VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow();
3648 // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
3649 // be removed for ToolBoxes to influence the keyboard accessibility
3650 // thus WB_MOVEABLE is no indicator for decoration anymore
3651 // but FloatingWindows carry this information in their TitleType...
3652 // TODO: avoid duplicate WinBits !!!
3653 if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
3654 bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE;
3655 if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
3656 if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
3658 if( ImplIsChild( pChildFrame, true ) )
3660 bRet = true;
3661 break;
3665 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
3667 return bRet;
3670 LanguageType Window::GetInputLanguage() const
3672 return mpWindowImpl->mpFrame->GetInputLanguage();
3675 void Window::EnableNativeWidget( bool bEnable )
3677 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
3678 if( pNoNWF && *pNoNWF )
3679 bEnable = false;
3681 if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
3683 ImplGetWinData()->mbEnableNativeWidget = bEnable;
3685 // send datachanged event to allow for internal changes required for NWF
3686 // like clipmode, transparency, etc.
3687 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, GetOutDev()->mxSettings.get(), AllSettingsFlags::STYLE );
3688 CompatDataChanged( aDCEvt );
3690 // sometimes the borderwindow is queried, so keep it in sync
3691 if( mpWindowImpl->mpBorderWindow )
3692 mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
3695 // push down, useful for compound controls
3696 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3697 while( pChild )
3699 pChild->EnableNativeWidget( bEnable );
3700 pChild = pChild->mpWindowImpl->mpNext;
3704 bool Window::IsNativeWidgetEnabled() const
3706 return mpWindowImpl && ImplGetWinData()->mbEnableNativeWidget;
3709 Reference< css::rendering::XCanvas > WindowOutputDevice::ImplGetCanvas( bool bSpriteCanvas ) const
3711 // Feed any with operating system's window handle
3713 // common: first any is VCL pointer to window (for VCL canvas)
3714 Sequence< Any > aArg{
3715 Any(reinterpret_cast<sal_Int64>(this)),
3716 Any(css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight )),
3717 Any(mxOwnerWindow->mpWindowImpl->mbAlwaysOnTop),
3718 Any(Reference< css::awt::XWindow >(
3719 mxOwnerWindow->GetComponentInterface(),
3720 UNO_QUERY )),
3721 GetSystemGfxDataAny()
3724 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
3726 // Create canvas instance with window handle
3728 static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
3729 css::rendering::CanvasFactory::create( xContext ) );
3730 Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
3731 Reference< css::rendering::XCanvas > xCanvas;
3733 if(xCanvasFactory.is())
3735 #ifdef _WIN32
3736 // see #140456# - if we're running on a multiscreen setup,
3737 // request special, multi-screen safe sprite canvas
3738 // implementation (not DX5 canvas, as it cannot cope with
3739 // surfaces spanning multiple displays). Note: canvas
3740 // (without sprite) stays the same)
3741 const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mxOwnerWindow->mpWindowImpl->mpFrame )->mnDisplay;
3742 if( nDisplay >= Application::GetScreenCount() )
3744 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3745 bSpriteCanvas ?
3746 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3747 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3748 aArg,
3749 xContext ),
3750 UNO_QUERY );
3753 else
3754 #endif
3756 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3757 bSpriteCanvas ?
3758 OUString( "com.sun.star.rendering.SpriteCanvas" ) :
3759 OUString( "com.sun.star.rendering.Canvas" ),
3760 aArg,
3761 xContext ),
3762 UNO_QUERY );
3767 // no factory??? Empty reference, then.
3768 return xCanvas;
3771 OUString Window::GetSurroundingText() const
3773 return OUString();
3776 Selection Window::GetSurroundingTextSelection() const
3778 return Selection( 0, 0 );
3781 namespace
3783 using namespace com::sun::star;
3785 uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin)
3787 uno::Reference<accessibility::XAccessibleEditableText> xText;
3790 uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() );
3791 if (xAccessible.is())
3792 xText = FindFocusedEditableText(xAccessible->getAccessibleContext());
3794 catch(const uno::Exception&)
3796 TOOLS_WARN_EXCEPTION( "vcl.gtk3", "Exception in getting input method surrounding text");
3798 return xText;
3802 // this is a rubbish implementation using a11y, ideally all subclasses implementing
3803 // GetSurroundingText/GetSurroundingTextSelection should implement this and then this
3804 // should be removed in favor of a stub that returns false
3805 bool Window::DeleteSurroundingText(const Selection& rSelection)
3807 uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(this);
3808 if (xText.is())
3810 sal_Int32 nPosition = xText->getCaretPosition();
3811 // #i111768# range checking
3812 sal_Int32 nDeletePos = rSelection.Min();
3813 sal_Int32 nDeleteEnd = rSelection.Max();
3814 if (nDeletePos < 0)
3815 nDeletePos = 0;
3816 if (nDeleteEnd < 0)
3817 nDeleteEnd = 0;
3818 if (nDeleteEnd > xText->getCharacterCount())
3819 nDeleteEnd = xText->getCharacterCount();
3821 xText->deleteText(nDeletePos, nDeleteEnd);
3822 //tdf91641 adjust cursor if deleted chars shift it forward (normal case)
3823 if (nDeletePos < nPosition)
3825 if (nDeleteEnd <= nPosition)
3826 nPosition = nPosition - (nDeleteEnd - nDeletePos);
3827 else
3828 nPosition = nDeletePos;
3830 if (xText->getCharacterCount() >= nPosition)
3831 xText->setCaretPosition( nPosition );
3833 return true;
3836 return false;
3839 bool WindowOutputDevice::UsePolyPolygonForComplexGradient()
3841 return meRasterOp != RasterOp::OverPaint;
3844 void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
3848 const SystemEnvData* Window::GetSystemData() const
3851 return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr;
3854 bool Window::SupportsDoubleBuffering() const
3856 return mpWindowImpl->mpFrameData->mpBuffer;
3859 void Window::RequestDoubleBuffering(bool bRequest)
3861 if (bRequest)
3863 mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
3864 // Make sure that the buffer size matches the frame size.
3865 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
3867 else
3868 mpWindowImpl->mpFrameData->mpBuffer.reset();
3872 * The rationale here is that we moved destructors to
3873 * dispose and this altered a lot of code paths, that
3874 * are better left unchanged for now.
3876 void Window::CompatGetFocus()
3878 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3879 Window::GetFocus();
3880 else
3881 GetFocus();
3884 void Window::CompatLoseFocus()
3886 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3887 Window::LoseFocus();
3888 else
3889 LoseFocus();
3892 void Window::CompatStateChanged( StateChangedType nStateChange )
3894 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3895 Window::StateChanged(nStateChange);
3896 else
3897 StateChanged(nStateChange);
3900 void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
3902 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3903 Window::DataChanged(rDCEvt);
3904 else
3905 DataChanged(rDCEvt);
3908 bool Window::CompatPreNotify( NotifyEvent& rNEvt )
3910 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3911 return Window::PreNotify( rNEvt );
3912 else
3913 return PreNotify( rNEvt );
3916 bool Window::CompatNotify( NotifyEvent& rNEvt )
3918 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3919 return Window::EventNotify( rNEvt );
3920 else
3921 return EventNotify( rNEvt );
3924 void Window::set_id(const OUString& rID)
3926 mpWindowImpl->maID = rID;
3929 const OUString& Window::get_id() const
3931 static OUString empty;
3932 return mpWindowImpl ? mpWindowImpl->maID : empty;
3935 FactoryFunction Window::GetUITestFactory() const
3937 return WindowUIObject::create;
3940 WindowOutputDevice::WindowOutputDevice(vcl::Window& rOwnerWindow) :
3941 ::OutputDevice(OUTDEV_WINDOW),
3942 mxOwnerWindow(&rOwnerWindow)
3944 assert(mxOwnerWindow);
3947 WindowOutputDevice::~WindowOutputDevice()
3949 disposeOnce();
3952 void WindowOutputDevice::dispose()
3954 assert((!mxOwnerWindow || mxOwnerWindow->isDisposed()) && "This belongs to the associated window and must be disposed after it");
3955 ::OutputDevice::dispose();
3956 // need to do this after OutputDevice::dispose so that the call to WindowOutputDevice::ReleaseGraphics
3957 // can release the graphics properly
3958 mxOwnerWindow.clear();
3961 css::awt::DeviceInfo WindowOutputDevice::GetDeviceInfo() const
3963 css::awt::DeviceInfo aInfo = GetCommonDeviceInfo(mxOwnerWindow->GetSizePixel());
3964 mxOwnerWindow->GetBorder(aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset);
3965 return aInfo;
3969 } /* namespace vcl */
3971 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */