tdf#164393 Change themes UI as per UX feedback
[LibreOffice.git] / vcl / source / window / window.cxx
blob23df41fa50ce2b9c81cd935b63f0ea85985562a3
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 <comphelper/diagnose_ex.hxx>
27 #include <vcl/salgtype.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/cursor.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/transfer.hxx>
32 #include <vcl/vclevent.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/syswin.hxx>
35 #include <vcl/dockwin.hxx>
36 #include <vcl/wall.hxx>
37 #include <vcl/toolkit/fixed.hxx>
38 #include <vcl/toolkit/button.hxx>
39 #include <vcl/taskpanelist.hxx>
40 #include <vcl/toolkit/unowrap.hxx>
41 #include <tools/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>
61 #include <dndlistenercontainer.hxx>
62 #include <dndeventdispatcher.hxx>
64 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
65 #include <com/sun/star/accessibility/XAccessible.hpp>
66 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
67 #include <com/sun/star/awt/XVclWindowPeer.hpp>
68 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
69 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
70 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
71 #include <com/sun/star/rendering/CanvasFactory.hpp>
72 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
73 #include <comphelper/configuration.hxx>
74 #include <comphelper/lok.hxx>
75 #include <comphelper/processfactory.hxx>
76 #include <osl/diagnose.h>
77 #include <tools/debug.hxx>
78 #include <tools/json_writer.hxx>
79 #include <boost/property_tree/ptree.hpp>
81 #include <cassert>
82 #include <typeinfo>
84 #ifdef _WIN32 // see #140456#
85 #include <win/salframe.h>
86 #endif
88 #include "impldockingwrapper.hxx"
90 using namespace ::com::sun::star::uno;
91 using namespace ::com::sun::star::lang;
92 using namespace ::com::sun::star::datatransfer::clipboard;
93 using namespace ::com::sun::star::datatransfer::dnd;
95 namespace vcl {
97 Window::Window( WindowType nType )
98 : mpWindowImpl(new WindowImpl( *this, nType ))
100 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
101 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
104 Window::Window( vcl::Window* pParent, WinBits nStyle )
105 : mpWindowImpl(new WindowImpl( *this, WindowType::WINDOW ))
107 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
108 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
110 ImplInit( pParent, nStyle, nullptr );
113 #if OSL_DEBUG_LEVEL > 0
114 namespace
116 OString lcl_createWindowInfo(const vcl::Window* pWindow)
118 // skip border windows, they do not carry information that
119 // would help with diagnosing the problem
120 const vcl::Window* pTempWin( pWindow );
121 while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) {
122 pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
124 // check if pTempWin is not null, otherwise use the
125 // original address
126 if ( pTempWin ) {
127 pWindow = pTempWin;
130 return OString::Concat(" ") +
131 typeid( *pWindow ).name() +
132 "(" +
133 OUStringToOString(
134 pWindow->GetText(),
135 RTL_TEXTENCODING_UTF8
137 ")";
140 #endif
142 void Window::dispose()
144 assert( mpWindowImpl );
145 assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
146 assert( (!mpWindowImpl->mpParent ||
147 mpWindowImpl->mpParent->mpWindowImpl) &&
148 "vcl::Window child should have its parent disposed first" );
150 // remove Key and Mouse events issued by Application::PostKey/MouseEvent
151 Application::RemoveMouseAndKeyEvents( this );
153 // Dispose of the canvas implementation (which, currently, has an
154 // own wrapper window as a child to this one.
155 GetOutDev()->ImplDisposeCanvas();
157 mpWindowImpl->mbInDispose = true;
159 CallEventListeners( VclEventId::ObjectDying );
161 // do not send child events for frames that were registered as native frames
162 if( !IsNativeFrame() && mpWindowImpl->mbReallyVisible )
163 if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
164 GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this );
166 // remove associated data structures from dockingmanager
167 ImplGetDockingManager()->RemoveWindow( this );
169 // remove ownerdraw decorated windows from list in the top-most frame window
170 if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
172 ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList();
173 auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) );
174 if( p != rList.end() )
175 rList.erase( p );
178 // shutdown drag and drop
179 if( mpWindowImpl->mxDNDListenerContainer.is() )
180 mpWindowImpl->mxDNDListenerContainer->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(mpWindowImpl->mpFrameData->mxDropTargetListener);
195 mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
196 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
199 // shutdown drag and drop for this frame window
200 Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
202 // DNDEventDispatcher does not hold a reference of the DropTarget,
203 // so it's ok if it does not support XComponent
204 if( xComponent.is() )
205 xComponent->dispose();
207 catch (const Exception&)
209 // can be safely ignored here.
213 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false );
214 if ( pWrapper )
215 pWrapper->WindowDestroyed( this );
217 // MT: Must be called after WindowDestroyed!
218 // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
219 // But accessibility implementations from applications need this dispose.
220 if ( mpWindowImpl->mxAccessible.is() )
222 Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY );
223 if ( xC.is() )
224 xC->dispose();
225 mpWindowImpl->mxAccessible.clear();
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, RTL_TEXTENCODING_UTF8));
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 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8));
290 bError = false;
291 pTempWin = pSVData->maFrameData.mpFirstFrame;
292 while ( pTempWin )
294 if ( ImplIsRealParentPath( pTempWin ) )
296 bError = true;
297 aErrorStr.append(lcl_createWindowInfo(pTempWin));
299 pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
301 if ( bError )
303 OString aTempStr = "Window (" +
304 lcl_createWindowInfo(this) +
305 ") with live SystemWindows destroyed: " +
306 aErrorStr;
307 OSL_FAIL( aTempStr.getStr() );
308 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8));
311 if ( mpWindowImpl->mpFirstOverlap )
313 OStringBuffer aTempStr = "Window (" +
314 lcl_createWindowInfo(this) +
315 ") with live SystemWindows destroyed: ";
316 pTempWin = mpWindowImpl->mpFirstOverlap;
317 while ( pTempWin )
319 aTempStr.append(lcl_createWindowInfo(pTempWin));
320 pTempWin = pTempWin->mpWindowImpl->mpNext;
322 OSL_FAIL( aTempStr.getStr() );
323 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8));
326 vcl::Window* pMyParent = GetParent();
327 SystemWindow* pMySysWin = nullptr;
329 while ( pMyParent )
331 if ( pMyParent->IsSystemWindow() )
333 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
335 pMyParent = pMyParent->GetParent();
337 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
339 OString aTempStr = "Window (" +
340 lcl_createWindowInfo(this) +
341 ") still in TaskPanelList!";
342 OSL_FAIL( aTempStr.getStr() );
343 Application::Abort(OStringToOUString(aTempStr, RTL_TEXTENCODING_UTF8));
346 #endif
348 if( mpWindowImpl->mbIsInTaskPaneList )
350 vcl::Window* pMyParent = GetParent();
351 SystemWindow* pMySysWin = nullptr;
353 while ( pMyParent )
355 if ( pMyParent->IsSystemWindow() )
357 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
359 pMyParent = pMyParent->GetParent();
361 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
363 pMySysWin->GetTaskPaneList()->RemoveWindow( this );
365 else
367 SAL_WARN( "vcl", "Window (" << GetText() << ") not found in TaskPanelList");
371 // remove from size-group if necessary
372 remove_from_all_size_groups();
374 // clear mnemonic labels
375 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
376 for (auto const& mnemonicLabel : aMnemonicLabels)
378 remove_mnemonic_label(mnemonicLabel);
381 // hide window in order to trigger the Paint-Handling
382 Hide();
384 // EndExtTextInputMode
385 if (pSVData->mpWinData->mpExtTextInputWin == this)
387 EndExtTextInput();
388 if (pSVData->mpWinData->mpExtTextInputWin == this)
389 pSVData->mpWinData->mpExtTextInputWin = nullptr;
392 // check if the focus window is our child
393 bool bHasFocusedChild = false;
394 if (pSVData->mpWinData->mpFocusWin && ImplIsRealParentPath(pSVData->mpWinData->mpFocusWin))
396 // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
397 bHasFocusedChild = true;
398 #if OSL_DEBUG_LEVEL > 0
399 OUString aTempStr = "Window (" + GetText() +
400 ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
401 SAL_WARN( "vcl", aTempStr );
402 Application::Abort(aTempStr);
403 #endif
406 // if we get focus pass focus to another window
407 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
408 if (pSVData->mpWinData->mpFocusWin == this
409 || bHasFocusedChild) // #122232#, see above, try some cleanup
411 if ( mpWindowImpl->mbFrame )
413 pSVData->mpWinData->mpFocusWin = nullptr;
414 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
416 else
418 vcl::Window* pParent = GetParent();
419 vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
420 // when windows overlap, give focus to the parent
421 // of the next FrameWindow
422 if ( pBorderWindow )
424 if ( pBorderWindow->ImplIsOverlapWindow() )
425 pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
427 else if ( ImplIsOverlapWindow() )
428 pParent = mpWindowImpl->mpOverlapWindow;
430 if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
431 pParent->GrabFocus();
432 else
433 mpWindowImpl->mpFrameWindow->GrabFocus();
435 // If the focus was set back to 'this' set it to nothing
436 if (pSVData->mpWinData->mpFocusWin == this)
438 pSVData->mpWinData->mpFocusWin = nullptr;
439 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
444 if ( pOverlapWindow != nullptr &&
445 pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
446 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
448 // reset hint for DefModalDialogParent
449 if( pSVData->maFrameData.mpActiveApplicationFrame == this )
450 pSVData->maFrameData.mpActiveApplicationFrame = nullptr;
452 // reset hint of what was the last wheeled window
453 if (pSVData->mpWinData->mpLastWheelWindow == this)
454 pSVData->mpWinData->mpLastWheelWindow = nullptr;
456 // reset marked windows
457 if ( mpWindowImpl->mpFrameData != nullptr )
459 if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
460 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
461 if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
462 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
463 if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
464 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
467 // reset Deactivate-Window
468 if (pSVData->mpWinData->mpLastDeacWin == this)
469 pSVData->mpWinData->mpLastDeacWin = nullptr;
471 if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
473 if ( mpWindowImpl->mpFrameData->mnFocusId )
474 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
475 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
476 if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
477 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
478 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
481 // release SalGraphics
482 VclPtr<OutputDevice> pOutDev = GetOutDev();
483 pOutDev->ReleaseGraphics();
485 // remove window from the lists
486 ImplRemoveWindow( true );
488 // de-register as "top window child" at our parent, if necessary
489 if ( mpWindowImpl->mbFrame )
491 bool bIsTopWindow
492 = mpWindowImpl->mpWinData && (mpWindowImpl->mpWinData->mnIsTopWindow == 1);
493 if ( mpWindowImpl->mpRealParent && bIsTopWindow )
495 ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
497 auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
498 pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
499 SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" );
500 if ( myPos != pParentWinData->maTopWindowChildren.end() )
501 pParentWinData->maTopWindowChildren.erase( myPos );
505 mpWindowImpl->mpWinData.reset();
507 // remove BorderWindow or Frame window data
508 mpWindowImpl->mpBorderWindow.disposeAndClear();
509 if ( mpWindowImpl->mbFrame )
511 if ( pSVData->maFrameData.mpFirstFrame == this )
512 pSVData->maFrameData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
513 else
515 sal_Int32 nWindows = 0;
516 vcl::Window* pSysWin = pSVData->maFrameData.mpFirstFrame;
517 while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
519 pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
520 nWindows++;
523 if ( pSysWin )
525 assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
526 pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
528 else // if it is not in the list, we can't remove it.
529 SAL_WARN("vcl.window", "Window " << this << " marked as frame window, "
530 "is missing from list of " << nWindows << " frames");
532 if (mpWindowImpl->mpFrame) // otherwise exception during init
534 mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
535 pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
537 assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
538 assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
540 mpWindowImpl->mpFrameData->mpBuffer.disposeAndClear();
541 delete mpWindowImpl->mpFrameData;
542 mpWindowImpl->mpFrameData = nullptr;
545 if (mpWindowImpl->mxWindowPeer)
546 mpWindowImpl->mxWindowPeer->dispose();
548 // should be the last statements
549 mpWindowImpl.reset();
551 pOutDev.disposeAndClear();
552 // just to make loplugin:vclwidgets happy
553 VclReferenceBase::dispose();
556 Window::~Window()
558 disposeOnce();
561 // We will eventually being removing the inheritance of OutputDevice
562 // from Window. It will be replaced with a transient relationship such
563 // that the OutputDevice is only live for the scope of the Paint method.
564 // In the meantime this can help move us towards a Window use an
565 // OutputDevice, not being one.
567 ::OutputDevice const* Window::GetOutDev() const
569 return mpWindowImpl ? mpWindowImpl->mxOutDev.get() : nullptr;
572 ::OutputDevice* Window::GetOutDev()
574 return mpWindowImpl ? mpWindowImpl->mxOutDev.get() : nullptr;
577 Color WindowOutputDevice::GetBackgroundColor() const
579 return mxOwnerWindow->GetDisplayBackground().GetColor();
582 bool WindowOutputDevice::CanEnableNativeWidget() const
584 return mxOwnerWindow->IsNativeWidgetEnabled();
587 } /* namespace vcl */
589 WindowImpl::WindowImpl( vcl::Window& rWindow, WindowType nType )
591 mxOutDev = VclPtr<vcl::WindowOutputDevice>::Create(rWindow);
592 maZoom = Fraction( 1, 1 );
593 mfPartialScrollX = 0.0;
594 mfPartialScrollY = 0.0;
595 maWinRegion = vcl::Region(true);
596 maWinClipRegion = vcl::Region(true);
597 mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
598 mpFrameData = nullptr; // Frame Data
599 mpFrame = nullptr; // Pointer to frame window
600 mpSysObj = nullptr;
601 mpFrameWindow = nullptr; // window to top level parent (same as frame window)
602 mpOverlapWindow = nullptr; // first overlap parent
603 mpBorderWindow = nullptr; // Border-Window
604 mpClientWindow = nullptr; // Client-Window of a FrameWindow
605 mpParent = nullptr; // parent (incl. BorderWindow)
606 mpRealParent = nullptr; // real parent (excl. BorderWindow)
607 mpFirstChild = nullptr; // first child window
608 mpLastChild = nullptr; // last child window
609 mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
610 mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
611 mpPrev = nullptr; // prev window
612 mpNext = nullptr; // next window
613 mpNextOverlap = nullptr; // next overlap window of frame
614 mpLastFocusWindow = nullptr; // window for focus restore
615 mpDlgCtrlDownWindow = nullptr; // window for dialog control
616 mnEventListenersIteratingCount = 0;
617 mnChildEventListenersIteratingCount = 0;
618 mpCursor = nullptr; // cursor
619 maPointer = PointerStyle::Arrow;
620 mpVCLXWindow = nullptr;
621 mpAccessibleInfos = nullptr;
622 maControlForeground = COL_TRANSPARENT; // no foreground set
623 maControlBackground = COL_TRANSPARENT; // no background set
624 mnLeftBorder = 0; // left border
625 mnTopBorder = 0; // top border
626 mnRightBorder = 0; // right border
627 mnBottomBorder = 0; // bottom border
628 mnWidthRequest = -1; // width request
629 mnHeightRequest = -1; // height request
630 mnOptimalWidthCache = -1; // optimal width cache
631 mnOptimalHeightCache = -1; // optimal height cache
632 mnX = 0; // X-Position to Parent
633 mnY = 0; // Y-Position to Parent
634 mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
635 mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
636 mpPaintRegion = nullptr; // Paint-ClipRegion
637 mnStyle = 0; // style (init in ImplInitWindow)
638 mnPrevStyle = 0; // prevstyle (set in SetStyle)
639 mnExtendedStyle = WindowExtendedStyle::NONE; // extended style (init in ImplInitWindow)
640 mnType = nType; // type
641 mnGetFocusFlags = GetFocusFlags::NONE; // Flags for GetFocus()-Call
642 mnWaitCount = 0; // Wait-Count (>1 == "wait" mouse pointer)
643 mnPaintFlags = ImplPaintFlags::NONE; // Flags for ImplCallPaint
644 mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
645 mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
646 mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
647 meAlwaysInputMode = AlwaysInputNone; // AlwaysEnableInput not called
648 meHalign = VclAlign::Fill;
649 meValign = VclAlign::Fill;
650 mePackType = VclPackType::Start;
651 mnPadding = 0;
652 mnGridHeight = 1;
653 mnGridLeftAttach = -1;
654 mnGridTopAttach = -1;
655 mnGridWidth = 1;
656 mnBorderWidth = 0;
657 mnMarginLeft = 0;
658 mnMarginRight = 0;
659 mnMarginTop = 0;
660 mnMarginBottom = 0;
661 mbFrame = false; // true: Window is a frame window
662 mbBorderWin = false; // true: Window is a border window
663 mbOverlapWin = false; // true: Window is an overlap window
664 mbSysWin = false; // true: SystemWindow is the base class
665 mbDialog = false; // true: Dialog is the base class
666 mbDockWin = false; // true: DockingWindow is the base class
667 mbFloatWin = false; // true: FloatingWindow is the base class
668 mbPushButton = false; // true: PushButton is the base class
669 mbToolBox = false; // true: ToolBox is the base class
670 mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
671 mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
672 mbSplitter = false; // true: Splitter is the base class
673 mbVisible = false; // true: Show( true ) called
674 mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
675 mbDisabled = false; // true: Enable( false ) called
676 mbInputDisabled = false; // true: EnableInput( false ) called
677 mbNoUpdate = false; // true: SetUpdateMode( false ) called
678 mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
679 mbActive = false; // true: Window Active
680 mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
681 mbReallyShown = false; // true: this and all parents to an overlapped window are shown
682 mbInInitShow = false; // true: we are in InitShow
683 mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
684 mbNoPtrVisible = false; // true: ShowPointer( false ) called
685 mbPaintFrame = false; // true: Paint is visible, but not painted
686 mbInPaint = false; // true: Inside PaintHdl
687 mbMouseButtonDown = false; // true: BaseMouseButtonDown called
688 mbMouseButtonUp = false; // true: BaseMouseButtonUp called
689 mbKeyInput = false; // true: BaseKeyInput called
690 mbKeyUp = false; // true: BaseKeyUp called
691 mbCommand = false; // true: BaseCommand called
692 mbDefPos = true; // true: Position is not Set
693 mbDefSize = true; // true: Size is not Set
694 mbCallMove = true; // true: Move must be called by Show
695 mbCallResize = true; // true: Resize must be called by Show
696 mbWaitSystemResize = true; // true: Wait for System-Resize
697 mbInitWinClipRegion = true; // true: Calc Window Clip Region
698 mbInitChildRegion = false; // true: InitChildClipRegion
699 mbWinRegion = false; // true: Window Region
700 mbClipChildren = false; // true: Child-window should be clipped
701 mbClipSiblings = false; // true: Adjacent Child-window should be clipped
702 mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
703 mbPaintTransparent = false; // true: Paints should be executed on the Parent
704 mbMouseTransparent = false; // true: Window is transparent for Mouse
705 mbDlgCtrlStart = false; // true: From here on own Dialog-Control
706 mbFocusVisible = false; // true: Focus Visible
707 mbUseNativeFocus = false;
708 mbNativeFocusVisible = false; // true: native Focus Visible
709 mbInShowFocus = false; // prevent recursion
710 mbInHideFocus = false; // prevent recursion
711 mbTrackVisible = false; // true: Tracking Visible
712 mbControlForeground = false; // true: Foreground-Property set
713 mbControlBackground = false; // true: Background-Property set
714 mbAlwaysOnTop = false; // true: always visible for all others windows
715 mbCompoundControl = false; // true: Composite Control => Listener...
716 mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
717 mbPaintDisabled = false; // true: Paint should not be executed
718 mbAllResize = false; // true: Also sent ResizeEvents with 0,0
719 mbInDispose = false; // true: We're still in Window::dispose()
720 mbExtTextInput = false; // true: ExtTextInput-Mode is active
721 mbInFocusHdl = false; // true: Within GetFocus-Handler
722 mbCreatedWithToolkit = false;
723 mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
724 mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
725 mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
726 mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
727 mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
728 mbFakeFocusSet = false; // true: pretend as if the window has focus.
729 mbHexpand = false;
730 mbVexpand = false;
731 mbExpand = false;
732 mbFill = true;
733 mbSecondary = false;
734 mbNonHomogeneous = false;
735 static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
736 mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
737 mpLOKNotifier = nullptr;
738 mnLOKWindowId = 0;
739 mbUseFrameData = false;
742 WindowImpl::~WindowImpl()
744 mpChildClipRegion.reset();
745 mpAccessibleInfos.reset();
748 ImplWinData::ImplWinData() :
749 mnCursorExtWidth(0),
750 mbVertical(false),
751 mnCompositionCharRects(0),
752 mnTrackFlags(ShowTrackFlags::NONE),
753 mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
754 mbMouseOver(false),
755 mbEnableNativeWidget(false)
759 ImplWinData::~ImplWinData()
761 mpCompositionCharRects.reset();
764 ImplFrameData::ImplFrameData( vcl::Window *pWindow )
765 : maPaintIdle( "vcl::Window maPaintIdle" ),
766 maResizeIdle( "vcl::Window maResizeIdle" )
768 ImplSVData* pSVData = ImplGetSVData();
769 assert (pSVData->maFrameData.mpFirstFrame.get() != pWindow);
770 mpNextFrame = pSVData->maFrameData.mpFirstFrame;
771 pSVData->maFrameData.mpFirstFrame = pWindow;
772 mpFirstOverlap = nullptr;
773 mpFocusWin = nullptr;
774 mpMouseMoveWin = nullptr;
775 mpMouseDownWin = nullptr;
776 mpTrackWin = nullptr;
777 mxFontCollection = pSVData->maGDIData.mxScreenFontList;
778 mxFontCache = pSVData->maGDIData.mxScreenFontCache;
779 mnFocusId = nullptr;
780 mnMouseMoveId = nullptr;
781 mnLastMouseX = -32767;
782 mnLastMouseY = -32767;
783 mnBeforeLastMouseX = -32767;
784 mnBeforeLastMouseY = -32767;
785 mnFirstMouseX = -32767;
786 mnFirstMouseY = -32767;
787 mnLastMouseWinX = -32767;
788 mnLastMouseWinY = -32767;
789 mnModalMode = 0;
790 mnMouseDownTime = 0;
791 mnClickCount = 0;
792 mnFirstMouseCode = 0;
793 mnMouseCode = 0;
794 mnMouseMode = MouseEventModifiers::NONE;
795 mbHasFocus = false;
796 mbInMouseMove = false;
797 mbMouseIn = false;
798 mbStartDragCalled = false;
799 mbNeedSysWindow = false;
800 mbMinimized = false;
801 mbStartFocusState = false;
802 mbInSysObjFocusHdl = false;
803 mbInSysObjToTopHdl = false;
804 mbSysObjFocus = false;
805 maPaintIdle.SetPriority( TaskPriority::REPAINT );
806 maPaintIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandlePaintHdl ) );
807 maResizeIdle.SetPriority( TaskPriority::RESIZE );
808 maResizeIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandleResizeTimerHdl ) );
809 mbInternalDragGestureRecognizer = false;
810 mbDragging = false;
811 mbInBufferedPaint = false;
812 mnDPIX = 96;
813 mnDPIY = 96;
814 mnTouchPanPositionX = -1;
815 mnTouchPanPositionY = -1;
818 namespace vcl {
820 bool WindowOutputDevice::AcquireGraphics() const
822 DBG_TESTSOLARMUTEX();
824 if (isDisposed())
825 return false;
827 if (mpGraphics)
828 return true;
830 mbInitLineColor = true;
831 mbInitFillColor = true;
832 mbInitFont = true;
833 mbInitTextColor = true;
834 mbInitClipRegion = true;
836 ImplSVData* pSVData = ImplGetSVData();
838 mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics();
839 // try harder if no wingraphics was available directly
840 if ( !mpGraphics )
842 // find another output device in the same frame
843 vcl::WindowOutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics.get();
844 while ( pReleaseOutDev )
846 if ( pReleaseOutDev->mxOwnerWindow && pReleaseOutDev->mxOwnerWindow->mpWindowImpl->mpFrame == mxOwnerWindow->mpWindowImpl->mpFrame )
847 break;
848 pReleaseOutDev = static_cast<vcl::WindowOutputDevice*>(pReleaseOutDev->mpPrevGraphics.get());
851 if ( pReleaseOutDev )
853 // steal the wingraphics from the other outdev
854 mpGraphics = pReleaseOutDev->mpGraphics;
855 pReleaseOutDev->ReleaseGraphics( false );
857 else
859 // if needed retry after releasing least recently used wingraphics
860 while ( !mpGraphics )
862 if ( !pSVData->maGDIData.mpLastWinGraphics )
863 break;
864 pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
865 mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics();
870 if ( mpGraphics )
872 // update global LRU list of wingraphics
873 mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics.get();
874 pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::WindowOutputDevice*>(this);
875 if ( mpNextGraphics )
876 mpNextGraphics->mpPrevGraphics = const_cast<vcl::WindowOutputDevice*>(this);
877 if ( !pSVData->maGDIData.mpLastWinGraphics )
878 pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::WindowOutputDevice*>(this);
880 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
881 mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
884 return mpGraphics != nullptr;
887 void WindowOutputDevice::ReleaseGraphics( bool bRelease )
889 DBG_TESTSOLARMUTEX();
891 if ( !mpGraphics )
892 return;
894 // release the fonts of the physically released graphics device
895 if( bRelease )
896 ImplReleaseFonts();
898 ImplSVData* pSVData = ImplGetSVData();
900 vcl::Window* pWindow = mxOwnerWindow.get();
901 if (!pWindow)
902 return;
904 if ( bRelease )
905 pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
906 // remove from global LRU list of window graphics
907 if ( mpPrevGraphics )
908 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
909 else
910 pSVData->maGDIData.mpFirstWinGraphics = static_cast<vcl::WindowOutputDevice*>(mpNextGraphics.get());
911 if ( mpNextGraphics )
912 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
913 else
914 pSVData->maGDIData.mpLastWinGraphics = static_cast<vcl::WindowOutputDevice*>(mpPrevGraphics.get());
916 mpGraphics = nullptr;
917 mpPrevGraphics = nullptr;
918 mpNextGraphics = nullptr;
921 static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
923 #ifndef MACOSX
924 // Setting of HiDPI is unfortunately all only a heuristic; and to add
925 // insult to an injury, the system is constantly lying to us about
926 // the DPI and whatnot
927 // eg. fdo#77059 - set the value from which we do consider the
928 // screen HiDPI to greater than 168
929 if (nDPI > 216) // 96 * 2 + 96 / 4
930 return 250;
931 else if (nDPI > 168) // 96 * 2 - 96 / 4
932 return 200;
933 else if (nDPI > 120) // 96 * 1.5 - 96 / 4
934 return 150;
935 #else
936 (void)nDPI;
937 #endif
939 return 100;
942 void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
944 SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE, "vcl.window",
945 "Window::Window(): pParent == NULL" );
947 ImplSVData* pSVData = ImplGetSVData();
948 vcl::Window* pRealParent = pParent;
950 // inherit 3D look
951 if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
952 nStyle |= WB_3DLOOK;
954 // create border window if necessary
955 if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
956 && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
958 BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
959 if( nStyle & WB_SYSTEMCHILDWINDOW )
961 // handle WB_SYSTEMCHILDWINDOW
962 // these should be analogous to a top level frame; meaning they
963 // should have a border window with style BorderWindowStyle::Frame
964 // which controls their size
965 nBorderTypeStyle |= BorderWindowStyle::Frame;
966 nStyle |= WB_BORDER;
968 VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
969 static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
970 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
971 mpWindowImpl->mpBorderWindow = pBorderWin;
972 pParent = mpWindowImpl->mpBorderWindow;
974 else if( !mpWindowImpl->mbFrame && ! pParent )
976 mpWindowImpl->mbOverlapWin = true;
977 mpWindowImpl->mbFrame = true;
980 // insert window in list
981 ImplInsertWindow( pParent );
982 mpWindowImpl->mnStyle = nStyle;
984 if( pParent && ! mpWindowImpl->mbFrame )
985 mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
987 // test for frame creation
988 if ( mpWindowImpl->mbFrame )
990 // create frame
991 SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
993 if ( nStyle & WB_MOVEABLE )
994 nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
995 if ( nStyle & WB_SIZEABLE )
996 nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
997 if ( nStyle & WB_CLOSEABLE )
998 nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
999 if ( nStyle & WB_APP )
1000 nFrameStyle |= SalFrameStyleFlags::DEFAULT;
1001 // check for undecorated floating window
1002 if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
1003 ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
1004 ( mpWindowImpl->mbFloatWin || ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
1005 // 2. borderwindows of floaters with ownerdraw decoration
1006 ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) )
1008 nFrameStyle = SalFrameStyleFlags::FLOAT;
1009 if( nStyle & WB_OWNERDRAWDECORATION )
1010 nFrameStyle |= SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW;
1012 else if( mpWindowImpl->mbFloatWin )
1013 nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
1015 if( nStyle & WB_INTROWIN )
1016 nFrameStyle |= SalFrameStyleFlags::INTRO;
1017 if( nStyle & WB_TOOLTIPWIN )
1018 nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
1020 if( nStyle & WB_NOSHADOW )
1021 nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
1023 if( nStyle & WB_SYSTEMCHILDWINDOW )
1024 nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
1026 switch (mpWindowImpl->mnType)
1028 case WindowType::DIALOG:
1029 case WindowType::TABDIALOG:
1030 case WindowType::MODELESSDIALOG:
1031 case WindowType::MESSBOX:
1032 case WindowType::INFOBOX:
1033 case WindowType::WARNINGBOX:
1034 case WindowType::ERRORBOX:
1035 case WindowType::QUERYBOX:
1036 nFrameStyle |= SalFrameStyleFlags::DIALOG;
1037 break;
1038 default:
1039 break;
1042 // tdf#144624 for the DefaultWindow, which is never visible, don't
1043 // create an icon for it so construction of a DefaultWindow cannot
1044 // trigger creation of a VirtualDevice which itself requires a
1045 // DefaultWindow to exist
1046 if( nStyle & WB_DEFAULTWIN )
1047 nFrameStyle |= SalFrameStyleFlags::NOICON;
1049 SalFrame* pParentFrame = nullptr;
1050 if ( pParent )
1051 pParentFrame = pParent->mpWindowImpl->mpFrame;
1052 SalFrame* pFrame;
1053 if ( pSystemParentData )
1054 pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG );
1055 else
1056 pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
1057 if ( !pFrame )
1059 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
1060 throw RuntimeException(
1061 u"Could not create system window!"_ustr,
1062 Reference< XInterface >() );
1065 pFrame->SetCallback( this, ImplWindowFrameProc );
1067 // set window frame data
1068 mpWindowImpl->mpFrameData = new ImplFrameData( this );
1069 mpWindowImpl->mpFrame = pFrame;
1070 mpWindowImpl->mpFrameWindow = this;
1071 mpWindowImpl->mpOverlapWindow = this;
1073 if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
1074 RequestDoubleBuffering(true);
1076 if ( pRealParent && IsTopWindow() )
1078 ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
1079 pParentWinData->maTopWindowChildren.emplace_back(this );
1083 // init data
1084 mpWindowImpl->mpRealParent = pRealParent;
1086 // #99318: make sure fontcache and list is available before call to SetSettings
1087 mpWindowImpl->mxOutDev->mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection;
1088 mpWindowImpl->mxOutDev->mxFontCache = mpWindowImpl->mpFrameData->mxFontCache;
1090 if ( mpWindowImpl->mbFrame )
1092 if ( pParent )
1094 mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
1095 mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
1097 else
1099 OutputDevice *pOutDev = GetOutDev();
1100 if ( pOutDev->AcquireGraphics() )
1102 mpWindowImpl->mxOutDev->mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
1106 // add ownerdraw decorated frame windows to list in the top-most frame window
1107 // so they can be hidden on lose focus
1108 if( nStyle & WB_OWNERDRAWDECORATION )
1109 ImplGetOwnerDrawList().emplace_back(this );
1111 // delay settings initialization until first "real" frame
1112 // this relies on the IntroWindow not needing any system settings
1113 if ( !pSVData->maAppData.mbSettingsInit &&
1114 ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
1117 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
1118 ImplUpdateGlobalSettings( *pSVData->maAppData.mxSettings );
1119 mpWindowImpl->mxOutDev->SetSettings( *pSVData->maAppData.mxSettings );
1120 pSVData->maAppData.mbSettingsInit = true;
1123 // If we create a Window with default size, query this
1124 // size directly, because we want resize all Controls to
1125 // the correct size before we display the window
1126 if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
1127 mpWindowImpl->mpFrame->GetClientSize( mpWindowImpl->mxOutDev->mnOutWidth, mpWindowImpl->mxOutDev->mnOutHeight );
1129 else
1131 if ( pParent )
1133 if ( !ImplIsOverlapWindow() )
1135 mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
1136 mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
1137 mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
1140 if (!comphelper::IsFuzzing())
1142 // we don't want to call the WindowOutputDevice override of this because
1143 // it calls back into us.
1144 mpWindowImpl->mxOutDev->OutputDevice::SetSettings( pParent->GetSettings() );
1150 // setup the scale factor for HiDPI displays
1151 mpWindowImpl->mxOutDev->mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1152 mpWindowImpl->mxOutDev->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1153 mpWindowImpl->mxOutDev->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1155 if (!comphelper::IsFuzzing())
1157 const StyleSettings& rStyleSettings = mpWindowImpl->mxOutDev->moSettings->GetStyleSettings();
1158 mpWindowImpl->mxOutDev->maFont = rStyleSettings.GetAppFont();
1160 if ( nStyle & WB_3DLOOK )
1162 SetTextColor( rStyleSettings.GetButtonTextColor() );
1163 SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
1165 else
1167 SetTextColor( rStyleSettings.GetWindowTextColor() );
1168 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
1171 else
1173 mpWindowImpl->mxOutDev->maFont = OutputDevice::GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
1176 ImplPointToLogic(*GetOutDev(), mpWindowImpl->mxOutDev->maFont);
1178 (void)ImplUpdatePos();
1180 // calculate app font res (except for the Intro Window or the default window)
1181 if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
1182 ImplInitAppFontData( this );
1185 void Window::ImplInitAppFontData( vcl::Window const * pWindow )
1187 ImplSVData* pSVData = ImplGetSVData();
1188 tools::Long nTextHeight = pWindow->GetTextHeight();
1189 tools::Long nTextWidth = pWindow->approximate_char_width() * 8;
1190 tools::Long nSymHeight = nTextHeight*4;
1191 // Make the basis wider if the font is too narrow
1192 // such that the dialog looks symmetrical and does not become too narrow.
1193 // Add some extra space when the dialog has the same width,
1194 // as a little more space is better.
1195 if ( nSymHeight > nTextWidth )
1196 nTextWidth = nSymHeight;
1197 else if ( nSymHeight+5 > nTextWidth )
1198 nTextWidth = nSymHeight+5;
1199 pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
1200 pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
1202 #ifdef MACOSX
1203 // FIXME: this is currently only on macOS, check with other
1204 // platforms
1205 if( pSVData->maNWFData.mbNoFocusRects )
1207 // try to find out whether there is a large correction
1208 // of control sizes, if yes, make app font scalings larger
1209 // so dialog positioning is not completely off
1210 ImplControlValue aControlValue;
1211 tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
1212 tools::Rectangle aBoundingRgn( aCtrlRegion );
1213 tools::Rectangle aContentRgn( aCtrlRegion );
1214 if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
1215 ControlState::ENABLED, aControlValue,
1216 aBoundingRgn, aContentRgn ) )
1218 // comment: the magical +6 is for the extra border in bordered
1219 // (which is the standard) edit fields
1220 if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
1221 pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
1224 #endif
1227 ImplWinData* Window::ImplGetWinData() const
1229 if (!mpWindowImpl->mpWinData)
1231 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
1233 const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData.reset(new ImplWinData);
1234 mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
1237 return mpWindowImpl->mpWinData.get();
1241 void WindowOutputDevice::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
1243 if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
1244 return;
1246 if (bWindowInvalidate)
1248 const tools::Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
1249 Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
1251 mxOwnerWindow->ImplMoveAllInvalidateRegions(aSrcRect,
1252 aPosAry.mnDestX-aPosAry.mnSrcX,
1253 aPosAry.mnDestY-aPosAry.mnSrcY,
1254 false);
1256 mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
1257 aPosAry.mnSrcX, aPosAry.mnSrcY,
1258 aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
1259 *this);
1261 return;
1264 OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
1267 const OutputDevice* WindowOutputDevice::DrawOutDevDirectCheck(const OutputDevice& rSrcDev) const
1269 const OutputDevice* pSrcDevChecked;
1270 if ( this == &rSrcDev )
1271 pSrcDevChecked = nullptr;
1272 else if (GetOutDevType() != rSrcDev.GetOutDevType())
1273 pSrcDevChecked = &rSrcDev;
1274 else if (mxOwnerWindow->mpWindowImpl->mpFrameWindow == static_cast<const vcl::WindowOutputDevice&>(rSrcDev).mxOwnerWindow->mpWindowImpl->mpFrameWindow)
1275 pSrcDevChecked = nullptr;
1276 else
1277 pSrcDevChecked = &rSrcDev;
1279 return pSrcDevChecked;
1282 void WindowOutputDevice::DrawOutDevDirectProcess( const OutputDevice& rSrcDev, SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
1284 if (pSrcGraphics)
1285 mpGraphics->CopyBits(rPosAry, *pSrcGraphics, *this, rSrcDev);
1286 else
1287 mpGraphics->CopyBits(rPosAry, *this);
1290 SalGraphics* Window::ImplGetFrameGraphics() const
1292 if ( mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics )
1294 mpWindowImpl->mpFrameWindow->GetOutDev()->mbInitClipRegion = true;
1296 else
1298 OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow->GetOutDev();
1299 if ( ! pFrameWinOutDev->AcquireGraphics() )
1301 return nullptr;
1304 mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics->ResetClipRegion();
1305 return mpWindowImpl->mpFrameWindow->GetOutDev()->mpGraphics;
1308 void Window::ImplSetReallyVisible()
1310 // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
1311 // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
1312 // mbReallyShown is a useful indicator
1313 if( !mpWindowImpl->mbReallyShown )
1314 ImplCallInitShow();
1316 bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
1318 GetOutDev()->mbDevOutput = true;
1319 mpWindowImpl->mbReallyVisible = true;
1320 mpWindowImpl->mbReallyShown = true;
1322 // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
1323 // For this, the data member of the event must not be NULL.
1324 // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
1325 // we're doing it when the visibility really changes
1326 if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
1327 CallEventListeners( VclEventId::WindowShow, this );
1328 // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should
1329 // introduce another event which explicitly triggers the Accessibility implementations.
1331 vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
1332 while ( pWindow )
1334 if ( pWindow->mpWindowImpl->mbVisible )
1335 pWindow->ImplSetReallyVisible();
1336 pWindow = pWindow->mpWindowImpl->mpNext;
1339 pWindow = mpWindowImpl->mpFirstChild;
1340 while ( pWindow )
1342 if ( pWindow->mpWindowImpl->mbVisible )
1343 pWindow->ImplSetReallyVisible();
1344 pWindow = pWindow->mpWindowImpl->mpNext;
1348 void Window::ImplInitResolutionSettings()
1350 // recalculate AppFont-resolution and DPI-resolution
1351 if (mpWindowImpl->mbFrame)
1353 GetOutDev()->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1354 GetOutDev()->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1356 // setup the scale factor for HiDPI displays
1357 GetOutDev()->mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1358 const StyleSettings& rStyleSettings = GetOutDev()->moSettings->GetStyleSettings();
1359 SetPointFont(*GetOutDev(), rStyleSettings.GetAppFont());
1361 else if ( mpWindowImpl->mpParent )
1363 GetOutDev()->mnDPIX = mpWindowImpl->mpParent->GetOutDev()->mnDPIX;
1364 GetOutDev()->mnDPIY = mpWindowImpl->mpParent->GetOutDev()->mnDPIY;
1365 GetOutDev()->mnDPIScalePercentage = mpWindowImpl->mpParent->GetOutDev()->mnDPIScalePercentage;
1368 // update the recalculated values for logical units
1369 // and also tools belonging to the values
1370 if (IsMapModeEnabled())
1372 MapMode aMapMode = GetMapMode();
1373 SetMapMode();
1374 SetMapMode( aMapMode );
1378 void Window::ImplPointToLogic(vcl::RenderContext const & rRenderContext, vcl::Font& rFont,
1379 bool bUseRenderContextDPI) const
1381 Size aSize = rFont.GetFontSize();
1383 if (aSize.Width())
1385 aSize.setWidth( aSize.Width() *
1386 ( bUseRenderContextDPI ? rRenderContext.GetDPIX() : mpWindowImpl->mpFrameData->mnDPIX) );
1387 aSize.AdjustWidth(72 / 2 );
1388 aSize.setWidth( aSize.Width() / 72 );
1390 aSize.setHeight( aSize.Height()
1391 * ( bUseRenderContextDPI ? rRenderContext.GetDPIY() : mpWindowImpl->mpFrameData->mnDPIY) );
1392 aSize.AdjustHeight(72/2 );
1393 aSize.setHeight( aSize.Height() / 72 );
1395 aSize = rRenderContext.PixelToLogic(aSize);
1397 rFont.SetFontSize(aSize);
1400 void Window::ImplLogicToPoint(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1402 Size aSize = rFont.GetFontSize();
1403 aSize = rRenderContext.LogicToPixel(aSize);
1405 if (aSize.Width())
1407 aSize.setWidth( aSize.Width() * 72 );
1408 aSize.AdjustWidth(mpWindowImpl->mpFrameData->mnDPIX / 2 );
1409 aSize.setWidth( aSize.Width() / ( mpWindowImpl->mpFrameData->mnDPIX) );
1411 aSize.setHeight( aSize.Height() * 72 );
1412 aSize.AdjustHeight(mpWindowImpl->mpFrameData->mnDPIY / 2 );
1413 aSize.setHeight( aSize.Height() / ( mpWindowImpl->mpFrameData->mnDPIY) );
1415 rFont.SetFontSize(aSize);
1418 bool Window::ImplUpdatePos()
1420 bool bSysChild = false;
1422 if ( ImplIsOverlapWindow() )
1424 GetOutDev()->mnOutOffX = mpWindowImpl->mnX;
1425 GetOutDev()->mnOutOffY = mpWindowImpl->mnY;
1427 else
1429 vcl::Window* pParent = ImplGetParent();
1431 GetOutDev()->mnOutOffX = mpWindowImpl->mnX + pParent->GetOutDev()->mnOutOffX;
1432 GetOutDev()->mnOutOffY = mpWindowImpl->mnY + pParent->GetOutDev()->mnOutOffY;
1435 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1436 while ( pChild )
1438 if ( pChild->ImplUpdatePos() )
1439 bSysChild = true;
1440 pChild = pChild->mpWindowImpl->mpNext;
1443 if ( mpWindowImpl->mpSysObj )
1444 bSysChild = true;
1446 return bSysChild;
1449 void Window::ImplUpdateSysObjPos()
1451 if ( mpWindowImpl->mpSysObj )
1452 mpWindowImpl->mpSysObj->SetPosSize( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY, GetOutDev()->mnOutWidth, GetOutDev()->mnOutHeight );
1454 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1455 while ( pChild )
1457 pChild->ImplUpdateSysObjPos();
1458 pChild = pChild->mpWindowImpl->mpNext;
1462 void Window::ImplPosSizeWindow( tools::Long nX, tools::Long nY,
1463 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
1465 bool bNewPos = false;
1466 bool bNewSize = false;
1467 bool bCopyBits = false;
1468 tools::Long nOldOutOffX = GetOutDev()->mnOutOffX;
1469 tools::Long nOldOutOffY = GetOutDev()->mnOutOffY;
1470 tools::Long nOldOutWidth = GetOutDev()->mnOutWidth;
1471 tools::Long nOldOutHeight = GetOutDev()->mnOutHeight;
1472 std::unique_ptr<vcl::Region> pOverlapRegion;
1473 std::unique_ptr<vcl::Region> pOldRegion;
1475 if ( IsReallyVisible() )
1477 tools::Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
1478 Size( nOldOutWidth, nOldOutHeight ) );
1479 pOldRegion.reset( new vcl::Region( aOldWinRect ) );
1480 if ( mpWindowImpl->mbWinRegion )
1481 pOldRegion->Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1483 if ( GetOutDev()->mnOutWidth && GetOutDev()->mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
1484 !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
1485 !HasPaintEvent() )
1486 bCopyBits = true;
1489 bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
1490 if ( nFlags & PosSizeFlags::Width )
1492 if(!( nFlags & PosSizeFlags::X ))
1494 nX = mpWindowImpl->mnX;
1495 nFlags |= PosSizeFlags::X;
1496 bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
1499 if ( nWidth < 0 )
1500 nWidth = 0;
1501 if ( nWidth != GetOutDev()->mnOutWidth )
1503 GetOutDev()->mnOutWidth = nWidth;
1504 bNewSize = true;
1505 bCopyBits = false;
1508 if ( nFlags & PosSizeFlags::Height )
1510 if ( nHeight < 0 )
1511 nHeight = 0;
1512 if ( nHeight != GetOutDev()->mnOutHeight )
1514 GetOutDev()->mnOutHeight = nHeight;
1515 bNewSize = true;
1516 bCopyBits = false;
1520 if ( nFlags & PosSizeFlags::X )
1522 tools::Long nOrgX = nX;
1523 Point aPtDev( nX+GetOutDev()->mnOutOffX, 0 );
1524 OutputDevice *pOutDev = GetOutDev();
1525 if( pOutDev->HasMirroredGraphics() )
1527 aPtDev.setX( GetOutDev()->mpGraphics->mirror2( aPtDev.X(), *GetOutDev() ) );
1529 // #106948# always mirror our pos if our parent is not mirroring, even
1530 // if we are also not mirroring
1531 // RTL: check if parent is in different coordinates
1532 if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
1534 nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
1536 /* #i99166# An LTR window in RTL UI that gets sized only would be
1537 expected to not moved its upper left point
1539 if( bnXRecycled )
1541 if( GetOutDev()->ImplIsAntiparallel() )
1543 aPtDev.setX( mpWindowImpl->mnAbsScreenX );
1544 nOrgX = mpWindowImpl->maPos.X();
1548 else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
1550 // mirrored window in LTR UI
1551 nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
1554 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1555 if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
1557 if ( bCopyBits && !pOverlapRegion )
1559 pOverlapRegion.reset( new vcl::Region() );
1560 ImplCalcOverlapRegion( GetOutputRectPixel(),
1561 *pOverlapRegion, false, true );
1563 mpWindowImpl->mnX = nX;
1564 mpWindowImpl->maPos.setX( nOrgX );
1565 mpWindowImpl->mnAbsScreenX = aPtDev.X();
1566 bNewPos = true;
1569 if ( nFlags & PosSizeFlags::Y )
1571 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1572 if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
1574 if ( bCopyBits && !pOverlapRegion )
1576 pOverlapRegion.reset( new vcl::Region() );
1577 ImplCalcOverlapRegion( GetOutputRectPixel(),
1578 *pOverlapRegion, false, true );
1580 mpWindowImpl->mnY = nY;
1581 mpWindowImpl->maPos.setY( nY );
1582 bNewPos = true;
1586 if ( !(bNewPos || bNewSize) )
1587 return;
1589 bool bUpdateSysObjPos = false;
1590 if ( bNewPos )
1591 bUpdateSysObjPos = ImplUpdatePos();
1593 // the borderwindow always specifies the position for its client window
1594 if ( mpWindowImpl->mpBorderWindow )
1595 mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
1597 if ( mpWindowImpl->mpClientWindow )
1599 mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
1600 mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
1601 GetOutDev()->mnOutWidth - mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
1602 GetOutDev()->mnOutHeight - mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
1603 PosSizeFlags::X | PosSizeFlags::Y |
1604 PosSizeFlags::Width | PosSizeFlags::Height );
1605 // If we have a client window, then this is the position
1606 // of the Application's floating windows
1607 mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
1608 if ( bNewPos )
1610 if ( mpWindowImpl->mpClientWindow->IsVisible() )
1612 mpWindowImpl->mpClientWindow->ImplCallMove();
1614 else
1616 mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
1621 // Move()/Resize() will be called only for Show(), such that
1622 // at least one is called before Show()
1623 if ( IsVisible() )
1625 if ( bNewPos )
1627 ImplCallMove();
1629 if ( bNewSize )
1631 ImplCallResize();
1634 else
1636 if ( bNewPos )
1637 mpWindowImpl->mbCallMove = true;
1638 if ( bNewSize )
1639 mpWindowImpl->mbCallResize = true;
1642 bool bUpdateSysObjClip = false;
1643 if ( IsReallyVisible() )
1645 if ( bNewPos || bNewSize )
1647 // set Clip-Flag
1648 bUpdateSysObjClip = !ImplSetClipFlag( true );
1651 // invalidate window content ?
1652 if ( bNewPos || (GetOutDev()->mnOutWidth > nOldOutWidth) || (GetOutDev()->mnOutHeight > nOldOutHeight) )
1654 if ( bNewPos )
1656 bool bInvalidate = false;
1657 bool bParentPaint = true;
1658 if ( !ImplIsOverlapWindow() )
1659 bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
1660 if ( bCopyBits && bParentPaint && !HasPaintEvent() )
1662 vcl::Region aRegion( GetOutputRectPixel() );
1663 if ( mpWindowImpl->mbWinRegion )
1664 aRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1665 ImplClipBoundaries( aRegion, false, true );
1666 if ( !pOverlapRegion->IsEmpty() )
1668 pOverlapRegion->Move( GetOutDev()->mnOutOffX - nOldOutOffX, GetOutDev()->mnOutOffY - nOldOutOffY );
1669 aRegion.Exclude( *pOverlapRegion );
1671 if ( !aRegion.IsEmpty() )
1673 // adapt Paint areas
1674 ImplMoveAllInvalidateRegions( tools::Rectangle( Point( nOldOutOffX, nOldOutOffY ),
1675 Size( nOldOutWidth, nOldOutHeight ) ),
1676 GetOutDev()->mnOutOffX - nOldOutOffX, GetOutDev()->mnOutOffY - nOldOutOffY,
1677 true );
1678 SalGraphics* pGraphics = ImplGetFrameGraphics();
1679 if ( pGraphics )
1682 OutputDevice *pOutDev = GetOutDev();
1683 const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics );
1684 if ( bSelectClipRegion )
1686 pGraphics->CopyArea( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY,
1687 nOldOutOffX, nOldOutOffY,
1688 nOldOutWidth, nOldOutHeight,
1689 *GetOutDev() );
1691 else
1692 bInvalidate = true;
1694 else
1695 bInvalidate = true;
1696 if ( !bInvalidate )
1698 if ( !pOverlapRegion->IsEmpty() )
1699 ImplInvalidateFrameRegion( pOverlapRegion.get(), InvalidateFlags::Children );
1702 else
1703 bInvalidate = true;
1705 else
1706 bInvalidate = true;
1707 if ( bInvalidate )
1708 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
1710 else
1712 vcl::Region aRegion( GetOutputRectPixel() );
1713 aRegion.Exclude( *pOldRegion );
1714 if ( mpWindowImpl->mbWinRegion )
1715 aRegion.Intersect( GetOutDev()->ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1716 ImplClipBoundaries( aRegion, false, true );
1717 if ( !aRegion.IsEmpty() )
1718 ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
1722 // invalidate Parent or Overlaps
1723 if ( bNewPos ||
1724 (GetOutDev()->mnOutWidth < nOldOutWidth) || (GetOutDev()->mnOutHeight < nOldOutHeight) )
1726 vcl::Region aRegion( *pOldRegion );
1727 if ( !mpWindowImpl->mbPaintTransparent )
1728 ImplExcludeWindowRegion( aRegion );
1729 ImplClipBoundaries( aRegion, false, true );
1730 if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
1731 ImplInvalidateParentFrameRegion( aRegion );
1735 // adapt system objects
1736 if ( bUpdateSysObjClip )
1737 ImplUpdateSysObjClip();
1738 if ( bUpdateSysObjPos )
1739 ImplUpdateSysObjPos();
1740 if ( bNewSize && mpWindowImpl->mpSysObj )
1741 mpWindowImpl->mpSysObj->SetPosSize( GetOutDev()->mnOutOffX, GetOutDev()->mnOutOffY, GetOutDev()->mnOutWidth, GetOutDev()->mnOutHeight );
1744 void Window::ImplNewInputContext()
1746 ImplSVData* pSVData = ImplGetSVData();
1747 vcl::Window* pFocusWin = pSVData->mpWinData->mpFocusWin;
1748 if ( !pFocusWin || !pFocusWin->mpWindowImpl || pFocusWin->isDisposed() )
1749 return;
1751 // Is InputContext changed?
1752 const InputContext& rInputContext = pFocusWin->GetInputContext();
1753 if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
1754 return;
1756 pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
1758 SalInputContext aNewContext;
1759 const vcl::Font& rFont = rInputContext.GetFont();
1760 const OUString& rFontName = rFont.GetFamilyName();
1761 if (!rFontName.isEmpty())
1763 OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
1764 Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() );
1765 if ( !aSize.Height() )
1767 // only set default sizes if the font height in logical
1768 // coordinates equals 0
1769 if ( rFont.GetFontSize().Height() )
1770 aSize.setHeight( 1 );
1771 else
1772 aSize.setHeight( (12*pFocusWin->GetOutDev()->mnDPIY)/72 );
1774 aNewContext.mpFont =
1775 pFocusWin->GetOutDev()->mxFontCache->GetFontInstance(
1776 pFocusWin->GetOutDev()->mxFontCollection.get(),
1777 rFont, aSize, static_cast<float>(aSize.Height()) );
1779 aNewContext.mnOptions = rInputContext.GetOptions();
1780 pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
1783 void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink)
1785 if (mpWindowImpl) // may be called after dispose
1787 mpWindowImpl->maDumpAsPropertyTreeHdl = rLink;
1791 void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink)
1793 ImplGetFrame()->SetModalHierarchyHdl(rLink);
1796 KeyIndicatorState Window::GetIndicatorState() const
1798 return mpWindowImpl->mpFrame->GetIndicatorState();
1801 void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
1803 mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
1806 void Window::KeyInput( const KeyEvent& rKEvt )
1808 #ifndef _WIN32 // On Windows, dialogs react to accelerators without Alt (tdf#157649)
1809 KeyCode cod = rKEvt.GetKeyCode ();
1811 // do not respond to accelerators unless Alt or Ctrl is held
1812 if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
1814 bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
1815 if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1))
1816 return;
1818 #endif
1820 NotifyEvent aNEvt( NotifyEventType::KEYINPUT, this, &rKEvt );
1821 if ( !CompatNotify( aNEvt ) )
1822 mpWindowImpl->mbKeyInput = true;
1825 void Window::KeyUp( const KeyEvent& rKEvt )
1827 NotifyEvent aNEvt( NotifyEventType::KEYUP, this, &rKEvt );
1828 if ( !CompatNotify( aNEvt ) )
1829 mpWindowImpl->mbKeyUp = true;
1832 void Window::Draw( OutputDevice*, const Point&, SystemTextColorFlags )
1836 void Window::Move() {}
1838 void Window::Resize() {}
1840 void Window::Activate() {}
1842 void Window::Deactivate() {}
1844 void Window::GetFocus()
1846 if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
1848 VclPtr<vcl::Window> xWindow(this);
1849 mpWindowImpl->mpLastFocusWindow->GrabFocus();
1850 if( xWindow->isDisposed() )
1851 return;
1854 NotifyEvent aNEvt( NotifyEventType::GETFOCUS, this );
1855 CompatNotify( aNEvt );
1858 void Window::LoseFocus()
1860 NotifyEvent aNEvt( NotifyEventType::LOSEFOCUS, this );
1861 CompatNotify( aNEvt );
1864 void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink)
1866 if (mpWindowImpl) // may be called after dispose
1868 mpWindowImpl->maHelpRequestHdl = rLink;
1872 void Window::RequestHelp( const HelpEvent& rHEvt )
1874 // if Balloon-Help is requested, show the balloon
1875 // with help text set
1876 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1878 OUString rStr = GetHelpText();
1879 if ( rStr.isEmpty() )
1880 rStr = GetQuickHelpText();
1881 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1882 ImplGetParent()->RequestHelp( rHEvt );
1883 else
1885 Point aPos = GetPosPixel();
1886 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1887 aPos = OutputToScreenPixel(Point(0, 0));
1888 tools::Rectangle aRect( aPos, GetSizePixel() );
1890 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
1893 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1895 const OUString& rStr = GetQuickHelpText();
1896 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1897 ImplGetParent()->RequestHelp( rHEvt );
1898 else
1900 Point aPos = GetPosPixel();
1901 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1902 aPos = OutputToScreenPixel(Point(0, 0));
1903 tools::Rectangle aRect( aPos, GetSizePixel() );
1904 Help::ShowQuickHelp( this, aRect, rStr, QuickHelpFlags::CtrlText );
1907 else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this))
1909 OUString aStrHelpId( GetHelpId() );
1910 if ( aStrHelpId.isEmpty() && ImplGetParent() )
1911 ImplGetParent()->RequestHelp( rHEvt );
1912 else
1914 Help* pHelp = Application::GetHelp();
1915 if ( pHelp )
1917 if( !aStrHelpId.isEmpty() )
1918 pHelp->Start( aStrHelpId, this );
1919 else
1920 pHelp->Start( u"" OOO_HELP_INDEX ""_ustr, this );
1926 void Window::Command( const CommandEvent& rCEvt )
1928 CallEventListeners( VclEventId::WindowCommand, const_cast<CommandEvent *>(&rCEvt) );
1930 NotifyEvent aNEvt( NotifyEventType::COMMAND, this, &rCEvt );
1931 if ( !CompatNotify( aNEvt ) )
1932 mpWindowImpl->mbCommand = true;
1935 void Window::Tracking( const TrackingEvent& rTEvt )
1938 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1939 if( pWrapper )
1940 pWrapper->Tracking( rTEvt );
1943 void Window::StateChanged(StateChangedType eType)
1945 switch (eType)
1947 //stuff that doesn't invalidate the layout
1948 case StateChangedType::ControlForeground:
1949 case StateChangedType::ControlBackground:
1950 case StateChangedType::UpdateMode:
1951 case StateChangedType::ReadOnly:
1952 case StateChangedType::Enable:
1953 case StateChangedType::State:
1954 case StateChangedType::Data:
1955 case StateChangedType::InitShow:
1956 case StateChangedType::ControlFocus:
1957 break;
1958 //stuff that does invalidate the layout
1959 default:
1960 queue_resize(eType);
1961 break;
1965 void Window::SetStyle( WinBits nStyle )
1967 if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
1969 mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
1970 mpWindowImpl->mnStyle = nStyle;
1971 CompatStateChanged( StateChangedType::Style );
1975 void Window::SetExtendedStyle( WindowExtendedStyle nExtendedStyle )
1978 if ( mpWindowImpl->mnExtendedStyle == nExtendedStyle )
1979 return;
1981 vcl::Window* pWindow = ImplGetBorderWindow();
1982 if( ! pWindow )
1983 pWindow = this;
1984 if( pWindow->mpWindowImpl->mbFrame )
1986 SalExtStyle nExt = 0;
1987 if( nExtendedStyle & WindowExtendedStyle::Document )
1988 nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
1989 if( nExtendedStyle & WindowExtendedStyle::DocModified )
1990 nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
1992 pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
1994 mpWindowImpl->mnExtendedStyle = nExtendedStyle;
1997 void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
2000 if ( !mpWindowImpl->mpBorderWindow )
2001 return;
2003 if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
2004 ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
2005 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
2008 // this is a little awkward: some controls (e.g. svtools ProgressBar)
2009 // cannot avoid getting constructed with WB_BORDER but want to disable
2010 // borders in case of NWF drawing. So they need a method to remove their border window
2011 VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow;
2012 // remove us as border window's client
2013 pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
2014 mpWindowImpl->mpBorderWindow = nullptr;
2015 mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
2016 // reparent us above the border window
2017 SetParent( pBorderWin->mpWindowImpl->mpParent );
2018 // set us to the position and size of our previous border
2019 Point aBorderPos( pBorderWin->GetPosPixel() );
2020 Size aBorderSize( pBorderWin->GetSizePixel() );
2021 setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
2022 // release border window
2023 pBorderWin.disposeAndClear();
2025 // set new style bits
2026 SetStyle( GetStyle() & (~WB_BORDER) );
2028 else
2030 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2031 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
2032 else
2033 mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
2037 WindowBorderStyle Window::GetBorderStyle() const
2040 if ( mpWindowImpl->mpBorderWindow )
2042 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2043 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
2044 else
2045 return mpWindowImpl->mpBorderWindow->GetBorderStyle();
2048 return WindowBorderStyle::NONE;
2051 tools::Long Window::CalcTitleWidth() const
2054 if ( mpWindowImpl->mpBorderWindow )
2056 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2057 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
2058 else
2059 return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
2061 else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
2063 // we guess the width for frame windows as we do not know the
2064 // border of external dialogs
2065 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2066 vcl::Font aFont = GetFont();
2067 const_cast<vcl::Window*>(this)->SetPointFont(const_cast<::OutputDevice&>(*GetOutDev()), rStyleSettings.GetTitleFont());
2068 tools::Long nTitleWidth = GetTextWidth( GetText() );
2069 const_cast<vcl::Window*>(this)->SetFont( aFont );
2070 nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
2071 nTitleWidth += StyleSettings::GetBorderSize() * 2;
2072 nTitleWidth += 10;
2073 return nTitleWidth;
2076 return 0;
2079 void Window::SetInputContext( const InputContext& rInputContext )
2082 mpWindowImpl->maInputContext = rInputContext;
2083 if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
2084 ImplNewInputContext();
2087 void Window::PostExtTextInputEvent(VclEventId nType, const OUString& rText)
2089 switch (nType)
2091 case VclEventId::ExtTextInput:
2093 std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]);
2094 for (int i = 0; i < rText.getLength(); ++i) {
2095 pAttr[i] = ExtTextInputAttr::Underline;
2097 SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE };
2098 ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent);
2100 break;
2101 case VclEventId::EndExtTextInput:
2102 ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr);
2103 break;
2104 default:
2105 assert(false);
2109 void Window::EndExtTextInput()
2111 if ( mpWindowImpl->mbExtTextInput )
2112 ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
2115 void Window::SetCursorRect( const tools::Rectangle* pRect, tools::Long nExtTextInputWidth )
2118 ImplWinData* pWinData = ImplGetWinData();
2119 if ( pWinData->mpCursorRect )
2121 if ( pRect )
2122 pWinData->mpCursorRect = *pRect;
2123 else
2124 pWinData->mpCursorRect.reset();
2126 else
2128 if ( pRect )
2129 pWinData->mpCursorRect = *pRect;
2132 pWinData->mnCursorExtWidth = nExtTextInputWidth;
2136 const tools::Rectangle* Window::GetCursorRect() const
2139 ImplWinData* pWinData = ImplGetWinData();
2140 return pWinData->mpCursorRect ? &*pWinData->mpCursorRect : nullptr;
2143 tools::Long Window::GetCursorExtTextInputWidth() const
2146 ImplWinData* pWinData = ImplGetWinData();
2147 return pWinData->mnCursorExtWidth;
2150 void Window::SetCompositionCharRect( const tools::Rectangle* pRect, tools::Long nCompositionLength, bool bVertical ) {
2152 ImplWinData* pWinData = ImplGetWinData();
2153 pWinData->mpCompositionCharRects.reset();
2154 pWinData->mbVertical = bVertical;
2155 pWinData->mnCompositionCharRects = nCompositionLength;
2156 if ( pRect && (nCompositionLength > 0) )
2158 pWinData->mpCompositionCharRects.reset( new tools::Rectangle[nCompositionLength] );
2159 for (tools::Long i = 0; i < nCompositionLength; ++i)
2160 pWinData->mpCompositionCharRects[i] = pRect[i];
2164 void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
2166 rAllChildren.push_back( this );
2168 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2169 while ( pChild )
2171 pChild->CollectChildren( rAllChildren );
2172 pChild = pChild->mpWindowImpl->mpNext;
2176 void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont,
2177 bool bUseRenderContextDPI)
2179 vcl::Font aFont = rFont;
2180 ImplPointToLogic(rRenderContext, aFont, bUseRenderContextDPI);
2181 rRenderContext.SetFont(aFont);
2184 vcl::Font Window::GetPointFont(vcl::RenderContext const & rRenderContext) const
2186 vcl::Font aFont = rRenderContext.GetFont();
2187 ImplLogicToPoint(rRenderContext, aFont);
2188 return aFont;
2191 void Window::Show(bool bVisible, ShowFlags nFlags)
2193 if ( !mpWindowImpl || mpWindowImpl->mbVisible == bVisible )
2194 return;
2196 VclPtr<vcl::Window> xWindow(this);
2198 bool bRealVisibilityChanged = false;
2199 mpWindowImpl->mbVisible = bVisible;
2201 if ( !bVisible )
2203 ImplHideAllOverlaps();
2204 if( !xWindow->mpWindowImpl )
2205 return;
2207 if ( mpWindowImpl->mpBorderWindow )
2209 bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
2210 if ( mpWindowImpl->mbNoParentUpdate )
2211 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
2212 mpWindowImpl->mpBorderWindow->Show( false, nFlags );
2213 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
2215 else if ( mpWindowImpl->mbFrame )
2217 mpWindowImpl->mbSuppressAccessibilityEvents = true;
2218 mpWindowImpl->mpFrame->Show( false );
2221 CompatStateChanged( StateChangedType::Visible );
2223 if ( mpWindowImpl->mbReallyVisible )
2225 if ( mpWindowImpl->mbInitWinClipRegion )
2226 ImplInitWinClipRegion();
2228 vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
2230 if( !xWindow->mpWindowImpl )
2231 return;
2233 bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
2234 ImplResetReallyVisible();
2235 ImplSetClipFlag();
2237 if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
2239 // convert focus
2240 if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
2242 if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
2243 mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
2244 ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
2246 mpWindowImpl->mpOverlapWindow->GrabFocus();
2250 if ( !mpWindowImpl->mbFrame )
2252 if (mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget)
2255 * #i48371# native theming: some themes draw outside the control
2256 * area we tell them to (bad thing, but we cannot do much about it ).
2257 * On hiding these controls they get invalidated with their window rectangle
2258 * which leads to the parts outside the control area being left and not
2259 * invalidated. Workaround: invalidate an area on the parent, too
2261 const int workaround_border = 5;
2262 tools::Rectangle aBounds( aInvRegion.GetBoundRect() );
2263 aBounds.AdjustLeft( -workaround_border );
2264 aBounds.AdjustTop( -workaround_border );
2265 aBounds.AdjustRight(workaround_border );
2266 aBounds.AdjustBottom(workaround_border );
2267 aInvRegion = aBounds;
2269 if ( !mpWindowImpl->mbNoParentUpdate )
2271 if ( !aInvRegion.IsEmpty() )
2272 ImplInvalidateParentFrameRegion( aInvRegion );
2274 ImplGenerateMouseMove();
2278 else
2280 // inherit native widget flag for form controls
2281 // required here, because frames never show up in the child hierarchy - which should be fixed...
2282 // eg, the drop down of a combobox which is a system floating window
2283 if( mpWindowImpl->mbFrame && GetParent() && !GetParent()->isDisposed() &&
2284 GetParent()->IsCompoundControl() &&
2285 GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() &&
2286 !(GetStyle() & WB_TOOLTIPWIN) )
2288 EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
2291 if ( mpWindowImpl->mbCallMove )
2293 ImplCallMove();
2295 if ( mpWindowImpl->mbCallResize )
2297 ImplCallResize();
2300 CompatStateChanged( StateChangedType::Visible );
2302 vcl::Window* pTestParent;
2303 if ( ImplIsOverlapWindow() )
2304 pTestParent = mpWindowImpl->mpOverlapWindow;
2305 else
2306 pTestParent = ImplGetParent();
2307 if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
2309 // if a window becomes visible, send all child windows a StateChange,
2310 // such that these can initialise themselves
2311 ImplCallInitShow();
2313 // If it is a SystemWindow it automatically pops up on top of
2314 // all other windows if needed.
2315 if (ImplIsOverlapWindow())
2317 if (!(nFlags & ShowFlags::NoActivate))
2319 ImplStartToTop((nFlags & ShowFlags::ForegroundTask) ? ToTopFlags::ForegroundTask
2320 : ToTopFlags::NONE);
2321 ImplFocusToTop(ToTopFlags::NONE, false);
2323 if (!(nFlags & ShowFlags::ForegroundTask))
2325 // Inform user about window if we did not popup it at foreground
2326 FlashWindow();
2331 // adjust mpWindowImpl->mbReallyVisible
2332 bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
2333 ImplSetReallyVisible();
2335 // assure clip rectangles will be recalculated
2336 ImplSetClipFlag();
2338 if ( !mpWindowImpl->mbFrame )
2340 InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
2341 if( ! IsPaintTransparent() )
2342 nInvalidateFlags |= InvalidateFlags::NoTransparent;
2343 ImplInvalidate( nullptr, nInvalidateFlags );
2344 ImplGenerateMouseMove();
2348 if ( mpWindowImpl->mpBorderWindow )
2349 mpWindowImpl->mpBorderWindow->Show( true, nFlags );
2350 else if ( mpWindowImpl->mbFrame )
2352 // #106431#, hide SplashScreen
2353 ImplSVData* pSVData = ImplGetSVData();
2354 if ( !pSVData->mpIntroWindow )
2356 // The right way would be just to call this (not even in the 'if')
2357 auto pApp = GetpApp();
2358 if ( pApp )
2359 pApp->InitFinished();
2361 else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
2363 // ... but the VCL splash is broken, and it needs this
2364 // (for ./soffice .uno:NewDoc)
2365 pSVData->mpIntroWindow->Hide();
2368 //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
2369 mpWindowImpl->mbSuppressAccessibilityEvents = false;
2371 mpWindowImpl->mbPaintFrame = true;
2372 if (!Application::IsHeadlessModeEnabled())
2374 bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
2375 mpWindowImpl->mpFrame->Show( true, bNoActivate );
2377 if( !xWindow->mpWindowImpl )
2378 return;
2380 // Query the correct size of the window, if we are waiting for
2381 // a system resize
2382 if ( mpWindowImpl->mbWaitSystemResize )
2384 tools::Long nOutWidth;
2385 tools::Long nOutHeight;
2386 mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
2387 ImplHandleResize( this, nOutWidth, nOutHeight );
2390 if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel())
2391 // Make sure that the buffer size matches the window size, even if no resize was needed.
2392 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
2395 if( !xWindow->mpWindowImpl )
2396 return;
2398 ImplShowAllOverlaps();
2401 if( !xWindow->mpWindowImpl )
2402 return;
2404 // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
2405 // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
2406 // we re-use the SHOW/HIDE events this way, with this particular semantics).
2407 // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
2408 // now only notify with a NULL data pointer, for all other clients except the access bridge.
2409 if ( !bRealVisibilityChanged )
2410 CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide );
2413 Size Window::GetSizePixel() const
2415 if (!mpWindowImpl)
2417 SAL_WARN("vcl.layout", "WTF no windowimpl");
2418 return Size(0,0);
2421 // #i43257# trigger pending resize handler to assure correct window sizes
2422 if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
2424 VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
2425 mpWindowImpl->mpFrameData->maResizeIdle.Stop();
2426 mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr );
2427 if( xWindow->isDisposed() )
2428 return Size(0,0);
2431 return Size( GetOutDev()->mnOutWidth + mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
2432 GetOutDev()->mnOutHeight + mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
2435 void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2436 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2438 rLeftBorder = mpWindowImpl->mnLeftBorder;
2439 rTopBorder = mpWindowImpl->mnTopBorder;
2440 rRightBorder = mpWindowImpl->mnRightBorder;
2441 rBottomBorder = mpWindowImpl->mnBottomBorder;
2444 void Window::Enable( bool bEnable, bool bChild )
2446 if ( isDisposed() )
2447 return;
2449 if ( !bEnable )
2451 // the tracking mode will be stopped or the capture will be stolen
2452 // when a window is disabled,
2453 if ( IsTracking() )
2454 EndTracking( TrackingEventFlags::Cancel );
2455 if ( IsMouseCaptured() )
2456 ReleaseMouse();
2457 // try to pass focus to the next control
2458 // if the window has focus and is contained in the dialog control
2459 // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow().
2460 // Otherwise ImplDlgCtrlNextWindow() should be used
2461 if ( HasFocus() )
2462 ImplDlgCtrlNextWindow();
2465 if ( mpWindowImpl->mpBorderWindow )
2467 mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
2468 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2469 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2470 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
2473 // #i56102# restore app focus win in case the
2474 // window was disabled when the frame focus changed
2475 ImplSVData* pSVData = ImplGetSVData();
2476 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2477 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2478 pSVData->mpWinData->mpFocusWin = this;
2480 if ( mpWindowImpl->mbDisabled != !bEnable )
2482 mpWindowImpl->mbDisabled = !bEnable;
2483 if ( mpWindowImpl->mpSysObj )
2484 mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
2485 CompatStateChanged( StateChangedType::Enable );
2487 CallEventListeners( bEnable ? VclEventId::WindowEnabled : VclEventId::WindowDisabled );
2490 if ( bChild )
2492 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2493 while ( pChild )
2495 pChild->Enable( bEnable, bChild );
2496 pChild = pChild->mpWindowImpl->mpNext;
2500 if ( IsReallyVisible() )
2501 ImplGenerateMouseMove();
2504 void Window::EnableInput( bool bEnable, bool bChild )
2506 if (!mpWindowImpl)
2507 return;
2509 if ( mpWindowImpl->mpBorderWindow )
2511 mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
2512 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2513 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2514 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
2517 if ( (!bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) || bEnable )
2519 // automatically stop the tracking mode or steal capture
2520 // if the window is disabled
2521 if ( !bEnable )
2523 if ( IsTracking() )
2524 EndTracking( TrackingEventFlags::Cancel );
2525 if ( IsMouseCaptured() )
2526 ReleaseMouse();
2529 if ( mpWindowImpl->mbInputDisabled != !bEnable )
2531 mpWindowImpl->mbInputDisabled = !bEnable;
2532 if ( mpWindowImpl->mpSysObj )
2533 mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
2537 // #i56102# restore app focus win in case the
2538 // window was disabled when the frame focus changed
2539 ImplSVData* pSVData = ImplGetSVData();
2540 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2541 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2542 pSVData->mpWinData->mpFocusWin = this;
2544 if ( bChild )
2546 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2547 while ( pChild )
2549 pChild->EnableInput( bEnable, bChild );
2550 pChild = pChild->mpWindowImpl->mpNext;
2554 if ( IsReallyVisible() )
2555 ImplGenerateMouseMove();
2558 void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
2560 if (!mpWindowImpl)
2561 return;
2563 EnableInput( bEnable );
2565 // pExecuteWindow is the first Overlap-Frame --> if this
2566 // shouldn't be the case, then this must be changed in dialog.cxx
2567 if( pExcludeWindow )
2568 pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
2569 vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
2570 while ( pSysWin )
2572 // Is Window in the path from this window
2573 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
2575 // Is Window not in the exclude window path or not the
2576 // exclude window, then change the status
2577 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
2578 pSysWin->EnableInput( bEnable );
2580 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
2583 // enable/disable floating system windows as well
2584 vcl::Window* pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
2585 while ( pFrameWin )
2587 if( pFrameWin->ImplIsFloatingWindow() )
2589 // Is Window in the path from this window
2590 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
2592 // Is Window not in the exclude window path or not the
2593 // exclude window, then change the status
2594 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
2595 pFrameWin->EnableInput( bEnable );
2598 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
2601 // the same for ownerdraw floating windows
2602 if( !mpWindowImpl->mbFrame )
2603 return;
2605 ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
2606 for (auto const& elem : rList)
2608 // Is Window in the path from this window
2609 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) )
2611 // Is Window not in the exclude window path or not the
2612 // exclude window, then change the status
2613 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) )
2614 elem->EnableInput( bEnable );
2619 void Window::AlwaysEnableInput( bool bAlways, bool bChild )
2622 if ( mpWindowImpl->mpBorderWindow )
2623 mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
2625 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
2627 mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
2628 EnableInput(true, false);
2630 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
2632 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2635 if ( bChild )
2637 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2638 while ( pChild )
2640 pChild->AlwaysEnableInput( bAlways, bChild );
2641 pChild = pChild->mpWindowImpl->mpNext;
2646 void Window::SetActivateMode( ActivateModeFlags nMode )
2649 if ( mpWindowImpl->mpBorderWindow )
2650 mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
2652 if ( mpWindowImpl->mnActivateMode == nMode )
2653 return;
2655 mpWindowImpl->mnActivateMode = nMode;
2657 // possibly trigger Deactivate/Activate
2658 if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
2660 if ( (mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW)) &&
2661 !HasChildPathFocus( true ) )
2663 mpWindowImpl->mbActive = false;
2664 Deactivate();
2667 else
2669 if ( !mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW) )
2671 mpWindowImpl->mbActive = true;
2672 Activate();
2677 void Window::setPosSizePixel( tools::Long nX, tools::Long nY,
2678 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
2680 bool bHasValidSize = !mpWindowImpl->mbDefSize;
2682 if ( nFlags & PosSizeFlags::Pos )
2683 mpWindowImpl->mbDefPos = false;
2684 if ( nFlags & PosSizeFlags::Size )
2685 mpWindowImpl->mbDefSize = false;
2687 // The top BorderWindow is the window which is to be positioned
2688 VclPtr<vcl::Window> pWindow = this;
2689 while ( pWindow->mpWindowImpl->mpBorderWindow )
2690 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
2692 if ( pWindow->mpWindowImpl->mbFrame )
2694 // Note: if we're positioning a frame, the coordinates are interpreted
2695 // as being the top-left corner of the window's client area and NOT
2696 // as the position of the border ! (due to limitations of several UNIX window managers)
2697 tools::Long nOldWidth = pWindow->GetOutDev()->mnOutWidth;
2699 if ( !(nFlags & PosSizeFlags::Width) )
2700 nWidth = pWindow->GetOutDev()->mnOutWidth;
2701 if ( !(nFlags & PosSizeFlags::Height) )
2702 nHeight = pWindow->GetOutDev()->mnOutHeight;
2704 sal_uInt16 nSysFlags=0;
2705 VclPtr<vcl::Window> pParent = GetParent();
2706 VclPtr<vcl::Window> pWinParent = pWindow->GetParent();
2708 if( nFlags & PosSizeFlags::Width )
2709 nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
2710 if( nFlags & PosSizeFlags::Height )
2711 nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
2712 if( nFlags & PosSizeFlags::X )
2714 nSysFlags |= SAL_FRAME_POSSIZE_X;
2715 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2717 nX += pWinParent->GetOutDev()->mnOutOffX;
2719 if( pParent && pParent->GetOutDev()->ImplIsAntiparallel() )
2721 tools::Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
2722 const OutputDevice *pParentOutDev = pParent->GetOutDev();
2723 if (!comphelper::LibreOfficeKit::isActive())
2724 pParentOutDev->ReMirror( aRect );
2725 nX = aRect.Left();
2728 if( !comphelper::LibreOfficeKit::isActive() &&
2729 !(nFlags & PosSizeFlags::X) && bHasValidSize &&
2730 pWindow->mpWindowImpl->mpFrame->GetWidth())
2732 // RTL: make sure the old right aligned position is not changed
2733 // system windows will always grow to the right
2734 if ( pWinParent )
2736 OutputDevice *pParentOutDev = pWinParent->GetOutDev();
2737 if( pParentOutDev->HasMirroredGraphics() )
2739 const SalFrameGeometry aSysGeometry = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2740 const SalFrameGeometry aParentSysGeometry =
2741 pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2742 tools::Long myWidth = nOldWidth;
2743 if( !myWidth )
2744 myWidth = aSysGeometry.width();
2745 if( !myWidth )
2746 myWidth = nWidth;
2747 nFlags |= PosSizeFlags::X;
2748 nSysFlags |= SAL_FRAME_POSSIZE_X;
2749 nX = aParentSysGeometry.x() - aSysGeometry.leftDecoration() + aParentSysGeometry.width()
2750 - myWidth - 1 - aSysGeometry.x();
2754 if( nFlags & PosSizeFlags::Y )
2756 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2757 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2759 nY += pWinParent->GetOutDev()->mnOutOffY;
2763 if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
2765 // check for min/max client size and adjust size accordingly
2766 // otherwise it may happen that the resize event is ignored, i.e. the old size remains
2767 // unchanged but ImplHandleResize() is called with the wrong size
2768 SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() );
2769 if( pSystemWindow )
2771 Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
2772 Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
2773 if( nWidth < aMinSize.Width() )
2774 nWidth = aMinSize.Width();
2775 if( nHeight < aMinSize.Height() )
2776 nHeight = aMinSize.Height();
2778 if( nWidth > aMaxSize.Width() )
2779 nWidth = aMaxSize.Width();
2780 if( nHeight > aMaxSize.Height() )
2781 nHeight = aMaxSize.Height();
2785 pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
2787 // Adjust resize with the hack of different client size and frame geometries to fix
2788 // native menu bars. Eventually this should be replaced by proper mnTopBorder usage.
2789 pWindow->mpWindowImpl->mpFrame->GetClientSize(nWidth, nHeight);
2791 // Resize should be called directly. If we haven't
2792 // set the correct size, we get a second resize from
2793 // the system with the correct size. This can be happened
2794 // if the size is too small or too large.
2795 ImplHandleResize( pWindow, nWidth, nHeight );
2797 else
2799 pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
2800 if ( IsReallyVisible() )
2801 ImplGenerateMouseMove();
2805 Point Window::GetPosPixel() const
2807 return mpWindowImpl->maPos;
2810 AbsoluteScreenPixelRectangle Window::GetDesktopRectPixel() const
2812 AbsoluteScreenPixelRectangle rRect;
2813 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
2814 return rRect;
2817 Point Window::OutputToScreenPixel( const Point& rPos ) const
2819 // relative to top level parent
2820 return Point( rPos.X() + GetOutDev()->mnOutOffX, rPos.Y() + GetOutDev()->mnOutOffY );
2823 Point Window::ScreenToOutputPixel( const Point& rPos ) const
2825 // relative to top level parent
2826 return Point( rPos.X() - GetOutDev()->mnOutOffX, rPos.Y() - GetOutDev()->mnOutOffY );
2829 tools::Long Window::ImplGetUnmirroredOutOffX() const
2831 // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
2832 tools::Long offx = GetOutDev()->mnOutOffX;
2833 const OutputDevice *pOutDev = GetOutDev();
2834 if( pOutDev->HasMirroredGraphics() )
2836 if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
2838 if ( !ImplIsOverlapWindow() )
2839 offx -= mpWindowImpl->mpParent->GetOutDev()->mnOutOffX;
2841 offx = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - offx;
2843 if ( !ImplIsOverlapWindow() )
2844 offx += mpWindowImpl->mpParent->GetOutDev()->mnOutOffX;
2848 return offx;
2851 // normalized screen pixel are independent of mirroring
2852 Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
2854 // relative to top level parent
2855 tools::Long offx = ImplGetUnmirroredOutOffX();
2856 return Point( rPos.X()+offx, rPos.Y() + GetOutDev()->mnOutOffY );
2859 Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
2861 // relative to top level parent
2862 tools::Long offx = ImplGetUnmirroredOutOffX();
2863 return Point( rPos.X()-offx, rPos.Y() - GetOutDev()->mnOutOffY );
2866 AbsoluteScreenPixelPoint Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
2868 // relative to the screen
2869 Point p = OutputToScreenPixel( rPos );
2870 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2871 p.AdjustX(g.x() );
2872 p.AdjustY(g.y() );
2873 return AbsoluteScreenPixelPoint(p);
2876 Point Window::AbsoluteScreenToOutputPixel( const AbsoluteScreenPixelPoint& rPos ) const
2878 // relative to the screen
2879 Point p = ScreenToOutputPixel( Point(rPos) );
2880 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2881 p.AdjustX( -(g.x()) );
2882 p.AdjustY( -(g.y()) );
2883 return p;
2886 AbsoluteScreenPixelRectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const
2888 // this method creates unmirrored screen coordinates to be compared with the desktop
2889 // and is used for positioning of RTL popup windows correctly on the screen
2890 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2892 Point p1 = rRect.TopRight();
2893 p1 = OutputToScreenPixel(p1);
2894 p1.setX( g.x()+g.width()-p1.X() );
2895 p1.AdjustY(g.y() );
2897 Point p2 = rRect.BottomLeft();
2898 p2 = OutputToScreenPixel(p2);
2899 p2.setX( g.x()+g.width()-p2.X() );
2900 p2.AdjustY(g.y() );
2902 return AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint(p1), AbsoluteScreenPixelPoint(p2) );
2905 tools::Rectangle Window::ImplUnmirroredAbsoluteScreenToOutputPixel( const AbsoluteScreenPixelRectangle &rRect ) const
2907 // undo ImplOutputToUnmirroredAbsoluteScreenPixel
2908 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2910 Point p1( rRect.TopRight() );
2911 p1.AdjustY(-g.y() );
2912 p1.setX( g.x()+g.width()-p1.X() );
2913 p1 = ScreenToOutputPixel(p1);
2915 Point p2( rRect.BottomLeft() );
2916 p2.AdjustY(-g.y());
2917 p2.setX( g.x()+g.width()-p2.X() );
2918 p2 = ScreenToOutputPixel(p2);
2920 return tools::Rectangle( p1, p2 );
2924 // with decoration
2925 tools::Rectangle Window::GetWindowExtentsRelative(const vcl::Window & rRelativeWindow) const
2927 AbsoluteScreenPixelRectangle aRect = GetWindowExtentsAbsolute();
2928 // #106399# express coordinates relative to borderwindow
2929 const vcl::Window *pRelWin = rRelativeWindow.mpWindowImpl->mpBorderWindow ? rRelativeWindow.mpWindowImpl->mpBorderWindow.get() : &rRelativeWindow;
2930 return tools::Rectangle(
2931 pRelWin->AbsoluteScreenToOutputPixel( aRect.GetPos() ),
2932 aRect.GetSize() );
2935 // with decoration
2936 AbsoluteScreenPixelRectangle Window::GetWindowExtentsAbsolute() const
2938 // make sure we use the extent of our border window,
2939 // otherwise we miss a few pixels
2940 const vcl::Window *pWin = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow : this;
2942 AbsoluteScreenPixelPoint aPos( pWin->OutputToAbsoluteScreenPixel( Point(0,0) ) );
2943 Size aSize ( pWin->GetSizePixel() );
2944 // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
2945 if( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW) )
2947 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2948 aPos.AdjustX( -sal_Int32(g.leftDecoration()) );
2949 aPos.AdjustY( -sal_Int32(g.topDecoration()) );
2950 aSize.AdjustWidth(g.leftDecoration() + g.rightDecoration() );
2951 aSize.AdjustHeight(g.topDecoration() + g.bottomDecoration() );
2953 return AbsoluteScreenPixelRectangle( aPos, aSize );
2956 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags )
2959 ImplScroll( GetOutputRectPixel(),
2960 nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
2963 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll,
2964 const tools::Rectangle& rRect, ScrollFlags nFlags )
2966 OutputDevice *pOutDev = GetOutDev();
2967 tools::Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
2968 aRect.Intersection( GetOutputRectPixel() );
2969 if ( !aRect.IsEmpty() )
2970 ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
2973 void WindowOutputDevice::Flush()
2975 if (mxOwnerWindow->mpWindowImpl)
2976 mxOwnerWindow->mpWindowImpl->mpFrame->Flush( GetOutputRectPixel() );
2979 void Window::SetUpdateMode( bool bUpdate )
2981 if (mpWindowImpl)
2983 mpWindowImpl->mbNoUpdate = !bUpdate;
2984 CompatStateChanged( StateChangedType::UpdateMode );
2988 void Window::GrabFocus()
2990 ImplGrabFocus( GetFocusFlags::NONE );
2993 bool Window::HasFocus() const
2995 return (this == ImplGetSVData()->mpWinData->mpFocusWin);
2998 void Window::GrabFocusToDocument()
3000 ImplGrabFocusToDocument(GetFocusFlags::NONE);
3003 VclPtr<vcl::Window> Window::GetFocusedWindow() const
3005 if (mpWindowImpl && mpWindowImpl->mpFrameData)
3006 return mpWindowImpl->mpFrameData->mpFocusWin;
3007 else
3008 return VclPtr<vcl::Window>();
3011 void Window::SetFakeFocus( bool bFocus )
3013 ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
3016 bool Window::HasChildPathFocus( bool bSystemWindow ) const
3019 vcl::Window* pFocusWin = ImplGetSVData()->mpWinData->mpFocusWin;
3020 if ( pFocusWin )
3021 return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
3022 return false;
3025 void Window::SetCursor( vcl::Cursor* pCursor )
3028 if ( mpWindowImpl->mpCursor != pCursor )
3030 if ( mpWindowImpl->mpCursor )
3031 mpWindowImpl->mpCursor->ImplHide();
3032 mpWindowImpl->mpCursor = pCursor;
3033 if ( pCursor )
3034 pCursor->ImplShow();
3038 void Window::SetText( const OUString& rStr )
3040 if (!mpWindowImpl || rStr == mpWindowImpl->maText)
3041 return;
3043 OUString oldTitle( mpWindowImpl->maText );
3044 mpWindowImpl->maText = rStr;
3046 if ( mpWindowImpl->mpBorderWindow )
3047 mpWindowImpl->mpBorderWindow->SetText( rStr );
3048 else if ( mpWindowImpl->mbFrame )
3049 mpWindowImpl->mpFrame->SetTitle( rStr );
3051 CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3053 // #107247# needed for accessibility
3054 // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes.
3055 // Therefore a window, which is labeled by this window, must also notify an accessible
3056 // name change.
3057 if ( IsReallyVisible() )
3059 vcl::Window* pWindow = GetAccessibleRelationLabelFor();
3060 if ( pWindow && pWindow != this )
3061 pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3064 CompatStateChanged( StateChangedType::Text );
3067 OUString Window::GetText() const
3070 return mpWindowImpl->maText;
3073 OUString Window::GetDisplayText() const
3076 return GetText();
3079 const Wallpaper& Window::GetDisplayBackground() const
3081 // FIXME: fix issue 52349, need to fix this really in
3082 // all NWF enabled controls
3083 const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
3084 if( pTB && IsNativeWidgetEnabled() )
3085 return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
3087 if( !IsBackground() )
3089 if( mpWindowImpl->mpParent )
3090 return mpWindowImpl->mpParent->GetDisplayBackground();
3093 const Wallpaper& rBack = GetBackground();
3094 if( ! rBack.IsBitmap() &&
3095 ! rBack.IsGradient() &&
3096 rBack.GetColor()== COL_TRANSPARENT &&
3097 mpWindowImpl->mpParent )
3098 return mpWindowImpl->mpParent->GetDisplayBackground();
3099 return rBack;
3102 const OUString& Window::GetHelpText() const
3104 const OUString& rStrHelpId(GetHelpId());
3105 const bool bStrHelpId = !rStrHelpId.isEmpty();
3107 if (mpWindowImpl->mbHelpTextDynamic && bStrHelpId)
3109 static const char* pEnv = getenv( "HELP_DEBUG" );
3110 if( pEnv && *pEnv )
3112 mpWindowImpl->maHelpText = mpWindowImpl->maHelpText + "\n------------------\n" + rStrHelpId;
3114 mpWindowImpl->mbHelpTextDynamic = false;
3117 //Fallback to Window::GetAccessibleDescription without reentry to GetHelpText()
3118 if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription)
3119 return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
3120 return mpWindowImpl->maHelpText;
3123 void Window::SetWindowPeer( Reference< css::awt::XVclWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
3125 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3126 return;
3128 // be safe against re-entrance: first clear the old ref, then assign the new one
3129 if (mpWindowImpl->mxWindowPeer)
3131 // first, disconnect the peer from ourself, otherwise disposing it, will dispose us
3132 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3133 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3134 if ( pWrapper )
3135 pWrapper->SetWindowInterface( nullptr, mpWindowImpl->mxWindowPeer );
3136 mpWindowImpl->mxWindowPeer->dispose();
3137 mpWindowImpl->mxWindowPeer.clear();
3139 mpWindowImpl->mxWindowPeer = xPeer;
3141 mpWindowImpl->mpVCLXWindow = pVCLXWindow;
3144 Reference< css::awt::XVclWindowPeer > Window::GetComponentInterface( bool bCreate )
3146 if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
3148 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3149 if ( pWrapper )
3150 mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
3152 return mpWindowImpl->mxWindowPeer;
3155 void Window::SetComponentInterface( Reference< css::awt::XVclWindowPeer > const & xIFace )
3157 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3158 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3159 if ( pWrapper )
3160 pWrapper->SetWindowInterface( this, xIFace );
3163 typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap;
3165 namespace {
3167 LOKWindowsMap& GetLOKWindowsMap()
3169 // Map to remember the LOKWindowId <-> Window binding.
3170 static LOKWindowsMap s_aLOKWindowsMap;
3172 return s_aLOKWindowsMap;
3177 void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
3179 // don't allow setting this twice
3180 assert(mpWindowImpl->mpLOKNotifier == nullptr);
3181 assert(pNotifier);
3182 // never use this in the desktop case
3183 assert(comphelper::LibreOfficeKit::isActive());
3185 if (!bParent)
3187 // Counter to be able to have unique id's for each window.
3188 static vcl::LOKWindowId sLastLOKWindowId = 1;
3190 // assign the LOK window id
3191 assert(mpWindowImpl->mnLOKWindowId == 0);
3192 mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
3193 GetLOKWindowsMap().emplace(mpWindowImpl->mnLOKWindowId, this);
3196 mpWindowImpl->mpLOKNotifier = pNotifier;
3199 VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
3201 const auto it = GetLOKWindowsMap().find(nWindowId);
3202 if (it != GetLOKWindowsMap().end())
3203 return it->second;
3205 return VclPtr<Window>();
3208 bool Window::IsLOKWindowsEmpty()
3210 return GetLOKWindowsMap().empty();
3213 void Window::ReleaseLOKNotifier()
3215 // unregister the LOK window binding
3216 if (mpWindowImpl->mnLOKWindowId > 0)
3217 GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
3219 mpWindowImpl->mpLOKNotifier = nullptr;
3220 mpWindowImpl->mnLOKWindowId = 0;
3223 ILibreOfficeKitNotifier::~ILibreOfficeKitNotifier()
3225 if (!comphelper::LibreOfficeKit::isActive())
3227 return;
3230 for (auto it = GetLOKWindowsMap().begin(); it != GetLOKWindowsMap().end();)
3232 WindowImpl* pWindowImpl = it->second->ImplGetWindowImpl();
3233 if (pWindowImpl && pWindowImpl->mpLOKNotifier == this)
3235 pWindowImpl->mpLOKNotifier = nullptr;
3236 pWindowImpl->mnLOKWindowId = 0;
3237 it = GetLOKWindowsMap().erase(it);
3238 continue;
3241 ++it;
3245 const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const
3247 return mpWindowImpl ? mpWindowImpl->mpLOKNotifier : nullptr;
3250 vcl::LOKWindowId Window::GetLOKWindowId() const
3252 return mpWindowImpl ? mpWindowImpl->mnLOKWindowId : 0;
3255 VclPtr<vcl::Window> Window::GetParentWithLOKNotifier()
3257 VclPtr<vcl::Window> pWindow(this);
3259 while (pWindow && !pWindow->GetLOKNotifier())
3260 pWindow = pWindow->GetParent();
3262 return pWindow;
3265 namespace
3268 std::string_view windowTypeName(WindowType nWindowType)
3270 switch (nWindowType)
3272 case WindowType::NONE: return "none";
3273 case WindowType::MESSBOX: return "messagebox";
3274 case WindowType::INFOBOX: return "infobox";
3275 case WindowType::WARNINGBOX: return "warningbox";
3276 case WindowType::ERRORBOX: return "errorbox";
3277 case WindowType::QUERYBOX: return "querybox";
3278 case WindowType::WINDOW: return "window";
3279 case WindowType::WORKWINDOW: return "workwindow";
3280 case WindowType::CONTAINER: return "container";
3281 case WindowType::FLOATINGWINDOW: return "floatingwindow";
3282 case WindowType::DIALOG: return "dialog";
3283 case WindowType::MODELESSDIALOG: return "modelessdialog";
3284 case WindowType::CONTROL: return "control";
3285 case WindowType::PUSHBUTTON: return "pushbutton";
3286 case WindowType::OKBUTTON: return "okbutton";
3287 case WindowType::CANCELBUTTON: return "cancelbutton";
3288 case WindowType::HELPBUTTON: return "helpbutton";
3289 case WindowType::IMAGEBUTTON: return "imagebutton";
3290 case WindowType::MENUBUTTON: return "menubutton";
3291 case WindowType::MOREBUTTON: return "morebutton";
3292 case WindowType::SPINBUTTON: return "spinbutton";
3293 case WindowType::RADIOBUTTON: return "radiobutton";
3294 case WindowType::CHECKBOX: return "checkbox";
3295 case WindowType::TRISTATEBOX: return "tristatebox";
3296 case WindowType::EDIT: return "edit";
3297 case WindowType::MULTILINEEDIT: return "multilineedit";
3298 case WindowType::COMBOBOX: return "combobox";
3299 case WindowType::LISTBOX: return "listbox";
3300 case WindowType::MULTILISTBOX: return "multilistbox";
3301 case WindowType::FIXEDTEXT: return "fixedtext";
3302 case WindowType::FIXEDLINE: return "fixedline";
3303 case WindowType::FIXEDBITMAP: return "fixedbitmap";
3304 case WindowType::FIXEDIMAGE: return "fixedimage";
3305 case WindowType::GROUPBOX: return "groupbox";
3306 case WindowType::SCROLLBAR: return "scrollbar";
3307 case WindowType::SCROLLBARBOX: return "scrollbarbox";
3308 case WindowType::SPLITTER: return "splitter";
3309 case WindowType::SPLITWINDOW: return "splitwindow";
3310 case WindowType::SPINFIELD: return "spinfield";
3311 case WindowType::PATTERNFIELD: return "patternfield";
3312 case WindowType::METRICFIELD: return "metricfield";
3313 case WindowType::FORMATTEDFIELD: return "formattedfield";
3314 case WindowType::CURRENCYFIELD: return "currencyfield";
3315 case WindowType::DATEFIELD: return "datefield";
3316 case WindowType::TIMEFIELD: return "timefield";
3317 case WindowType::PATTERNBOX: return "patternbox";
3318 case WindowType::NUMERICBOX: return "numericbox";
3319 case WindowType::METRICBOX: return "metricbox";
3320 case WindowType::CURRENCYBOX: return "currencybox";
3321 case WindowType::DATEBOX: return "datebox";
3322 case WindowType::TIMEBOX: return "timebox";
3323 case WindowType::LONGCURRENCYBOX: return "longcurrencybox";
3324 case WindowType::SCROLLWINDOW: return "scrollwindow";
3325 case WindowType::TOOLBOX: return "toolbox";
3326 case WindowType::DOCKINGWINDOW: return "dockingwindow";
3327 case WindowType::STATUSBAR: return "statusbar";
3328 case WindowType::TABPAGE: return "tabpage";
3329 case WindowType::TABCONTROL: return "tabcontrol";
3330 case WindowType::TABDIALOG: return "tabdialog";
3331 case WindowType::BORDERWINDOW: return "borderwindow";
3332 case WindowType::BUTTONDIALOG: return "buttondialog";
3333 case WindowType::SYSTEMCHILDWINDOW: return "systemchildwindow";
3334 case WindowType::SLIDER: return "slider";
3335 case WindowType::MENUBARWINDOW: return "menubarwindow";
3336 case WindowType::TREELISTBOX: return "treelistbox";
3337 case WindowType::HELPTEXTWINDOW: return "helptextwindow";
3338 case WindowType::INTROWINDOW: return "introwindow";
3339 case WindowType::LISTBOXWINDOW: return "listboxwindow";
3340 case WindowType::DOCKINGAREA: return "dockingarea";
3341 case WindowType::RULER: return "ruler";
3342 case WindowType::HEADERBAR: return "headerbar";
3343 case WindowType::VERTICALTABCONTROL: return "verticaltabcontrol";
3344 case WindowType::PROGRESSBAR: return "progressbar";
3345 case WindowType::LINK_BUTTON: return "linkbutton";
3347 // nothing to do here, but for completeness
3348 case WindowType::TOOLKIT_FRAMEWINDOW: return "toolkit_framewindow";
3349 case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return "toolkit_systemchildwindow";
3352 return "none";
3357 void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
3359 if (!mpWindowImpl)
3360 return;
3362 rJsonWriter.put("id", get_id()); // TODO could be missing - sort out
3363 rJsonWriter.put("type", windowTypeName(GetType()));
3364 rJsonWriter.put("text", GetText());
3365 rJsonWriter.put("enabled", IsEnabled());
3366 if (!IsVisible())
3367 rJsonWriter.put("visible", false);
3369 if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
3371 auto childrenNode = rJsonWriter.startArray("children");
3372 while (pChild)
3375 auto childNode = rJsonWriter.startStruct();
3376 pChild->DumpAsPropertyTree(rJsonWriter);
3377 sal_Int32 nLeft = pChild->get_grid_left_attach();
3378 sal_Int32 nTop = pChild->get_grid_top_attach();
3379 if (nLeft != -1 && nTop != -1)
3381 rJsonWriter.put("left", nLeft);
3382 rJsonWriter.put("top", nTop);
3385 sal_Int32 nWidth = pChild->get_grid_width();
3386 if (nWidth > 1)
3387 rJsonWriter.put("width", nWidth);
3389 pChild = pChild->mpWindowImpl->mpNext;
3393 vcl::Window* pAccLabelFor = getAccessibleRelationLabelFor();
3394 if (pAccLabelFor)
3395 rJsonWriter.put("labelFor", pAccLabelFor->get_id());
3397 vcl::Window* pAccLabelledBy = GetAccessibleRelationLabeledBy();
3398 if (pAccLabelledBy)
3399 rJsonWriter.put("labelledBy", pAccLabelledBy->get_id());
3401 if(!pAccLabelFor && !pAccLabelledBy)
3403 OUString sAccName = GetAccessibleName();
3404 OUString sAccDesc = GetAccessibleDescription();
3406 if (!sAccName.isEmpty() || !sAccDesc.isEmpty())
3408 auto aAria = rJsonWriter.startNode("aria");
3409 if (!sAccName.isEmpty())
3410 rJsonWriter.put("label", sAccName);
3411 if (!sAccDesc.isEmpty())
3412 rJsonWriter.put("description", sAccDesc);
3416 mpWindowImpl->maDumpAsPropertyTreeHdl.Call(rJsonWriter);
3419 void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
3421 // no deactivation if the newly activated window is my child
3422 if ( !pNew || !ImplIsChild( pNew ) )
3424 VclPtr<vcl::Window> xWindow(this);
3425 CallEventListeners( VclEventId::WindowDeactivate, pNew );
3426 if( !xWindow->mpWindowImpl )
3427 return;
3429 // #100759#, avoid walking the wrong frame's hierarchy
3430 // eg, undocked docking windows (ImplDockFloatWin)
3431 if ( ImplGetParent() && ImplGetParent()->mpWindowImpl &&
3432 mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
3433 ImplGetParent()->ImplCallDeactivateListeners( pNew );
3437 void Window::ImplCallActivateListeners( vcl::Window *pOld )
3439 // no activation if the old active window is my child
3440 if ( pOld && ImplIsChild( pOld ))
3441 return;
3443 VclPtr<vcl::Window> xWindow(this);
3444 CallEventListeners( VclEventId::WindowActivate, pOld );
3445 if( !xWindow->mpWindowImpl )
3446 return;
3448 if ( ImplGetParent() )
3449 ImplGetParent()->ImplCallActivateListeners( pOld );
3450 else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
3452 // top level frame reached: store hint for DefModalDialogParent
3453 ImplGetSVData()->maFrameData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
3457 void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
3459 if (mpWindowImpl->mpFrameData)
3460 mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
3463 Reference< XClipboard > Window::GetClipboard()
3465 if (!mpWindowImpl->mpFrameData)
3466 return static_cast<XClipboard*>(nullptr);
3467 if (!mpWindowImpl->mpFrameData->mxClipboard.is())
3468 mpWindowImpl->mpFrameData->mxClipboard = GetSystemClipboard();
3469 return mpWindowImpl->mpFrameData->mxClipboard;
3472 void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const tools::Rectangle& rRect )
3474 assert(GetOutDev()->mpOutDevData);
3475 GetOutDev()->mpOutDevData->mpRecordLayout = pLayout;
3476 GetOutDev()->mpOutDevData->maRecordRect = rRect;
3477 Paint(*GetOutDev(), rRect);
3478 GetOutDev()->mpOutDevData->mpRecordLayout = nullptr;
3481 void Window::DrawSelectionBackground( const tools::Rectangle& rRect,
3482 sal_uInt16 highlight,
3483 bool bChecked,
3484 bool bDrawBorder
3487 if( rRect.IsEmpty() )
3488 return;
3490 const StyleSettings& rStyles = GetSettings().GetStyleSettings();
3492 // colors used for item highlighting
3493 Color aSelectionBorderCol( rStyles.GetHighlightColor() );
3494 Color aSelectionFillCol( aSelectionBorderCol );
3496 bool bDark = rStyles.GetFaceColor().IsDark();
3497 bool bBright = ( rStyles.GetFaceColor() == COL_WHITE );
3499 int c1 = aSelectionBorderCol.GetLuminance();
3500 int c2 = GetBackgroundColor().GetLuminance();
3502 if( !bDark && !bBright && abs( c2-c1 ) < 75 )
3504 // contrast too low
3505 sal_uInt16 h,s,b;
3506 aSelectionFillCol.RGBtoHSB( h, s, b );
3507 if( b > 50 ) b -= 40;
3508 else b += 40;
3509 aSelectionFillCol = Color::HSBtoRGB( h, s, b );
3510 aSelectionBorderCol = aSelectionFillCol;
3513 tools::Rectangle aRect( rRect );
3514 Color oldFillCol = GetOutDev()->GetFillColor();
3515 Color oldLineCol = GetOutDev()->GetLineColor();
3517 if( bDrawBorder )
3518 GetOutDev()->SetLineColor( bDark ? COL_WHITE : ( bBright ? COL_BLACK : aSelectionBorderCol ) );
3519 else
3520 GetOutDev()->SetLineColor();
3522 sal_uInt16 nPercent = 0;
3523 if( !highlight )
3525 if( bDark )
3526 aSelectionFillCol = COL_BLACK;
3527 else
3528 nPercent = 80; // just checked (light)
3530 else
3532 if( bChecked && highlight == 2 )
3534 if( bDark )
3535 aSelectionFillCol = COL_LIGHTGRAY;
3536 else if ( bBright )
3538 aSelectionFillCol = COL_BLACK;
3539 GetOutDev()->SetLineColor( COL_BLACK );
3540 nPercent = 0;
3542 else
3543 nPercent = 20; // selected, pressed or checked ( very dark )
3545 else if( bChecked || highlight == 1 )
3547 if( bDark )
3548 aSelectionFillCol = COL_GRAY;
3549 else if ( bBright )
3551 aSelectionFillCol = COL_BLACK;
3552 GetOutDev()->SetLineColor( COL_BLACK );
3553 nPercent = 0;
3555 else
3556 nPercent = 35; // selected, pressed or checked ( very dark )
3558 else
3560 if( bDark )
3561 aSelectionFillCol = COL_LIGHTGRAY;
3562 else if ( bBright )
3564 aSelectionFillCol = COL_BLACK;
3565 GetOutDev()->SetLineColor( COL_BLACK );
3566 if( highlight == 3 )
3567 nPercent = 80;
3568 else
3569 nPercent = 0;
3571 else
3572 nPercent = 70; // selected ( dark )
3576 GetOutDev()->SetFillColor( aSelectionFillCol );
3578 if( bDark )
3580 GetOutDev()->DrawRect( aRect );
3582 else
3584 tools::Polygon aPoly( aRect );
3585 tools::PolyPolygon aPolyPoly( aPoly );
3586 GetOutDev()->DrawTransparent( aPolyPoly, nPercent );
3589 GetOutDev()->SetFillColor( oldFillCol );
3590 GetOutDev()->SetLineColor( oldLineCol );
3593 bool Window::IsScrollable() const
3595 // check for scrollbars
3596 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3597 while( pChild )
3599 if( pChild->GetType() == WindowType::SCROLLBAR )
3600 return true;
3601 else
3602 pChild = pChild->mpWindowImpl->mpNext;
3604 return false;
3607 void Window::ImplMirrorFramePos( Point &pt ) const
3609 pt.setX(mpWindowImpl->mpFrame->GetWidth() - 1 - pt.X());
3612 // frame based modal counter (dialogs are not modal to the whole application anymore)
3613 bool Window::IsInModalMode() const
3615 return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
3618 void Window::IncModalCount()
3620 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3621 vcl::Window* pParent = pFrameWindow;
3622 while( pFrameWindow )
3624 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
3625 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3627 pParent = pParent->GetParent();
3629 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3632 void Window::DecModalCount()
3634 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3635 vcl::Window* pParent = pFrameWindow;
3636 while( pFrameWindow )
3638 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
3639 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3641 pParent = pParent->GetParent();
3643 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3647 void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
3649 mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
3652 void Window::ImplNotifyIconifiedState( bool bIconified )
3654 mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3655 // #109206# notify client window as well to have toolkit topwindow listeners notified
3656 if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
3657 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3660 bool Window::HasActiveChildFrame() const
3662 bool bRet = false;
3663 vcl::Window *pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
3664 while( pFrameWin )
3666 if( pFrameWin != mpWindowImpl->mpFrameWindow )
3668 bool bDecorated = false;
3669 VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow();
3670 // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
3671 // be removed for ToolBoxes to influence the keyboard accessibility
3672 // thus WB_MOVEABLE is no indicator for decoration anymore
3673 // but FloatingWindows carry this information in their TitleType...
3674 // TODO: avoid duplicate WinBits !!!
3675 if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
3676 bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE;
3677 if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
3678 if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
3680 if( ImplIsChild( pChildFrame, true ) )
3682 bRet = true;
3683 break;
3687 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
3689 return bRet;
3692 LanguageType Window::GetInputLanguage() const
3694 return mpWindowImpl->mpFrame->GetInputLanguage();
3697 void Window::EnableNativeWidget( bool bEnable )
3699 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
3700 if( pNoNWF && *pNoNWF )
3701 bEnable = false;
3703 if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
3705 ImplGetWinData()->mbEnableNativeWidget = bEnable;
3707 // send datachanged event to allow for internal changes required for NWF
3708 // like clipmode, transparency, etc.
3709 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &*GetOutDev()->moSettings, AllSettingsFlags::STYLE );
3710 CompatDataChanged( aDCEvt );
3712 // sometimes the borderwindow is queried, so keep it in sync
3713 if( mpWindowImpl->mpBorderWindow )
3714 mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
3717 // push down, useful for compound controls
3718 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3719 while( pChild )
3721 pChild->EnableNativeWidget( bEnable );
3722 pChild = pChild->mpWindowImpl->mpNext;
3726 bool Window::IsNativeWidgetEnabled() const
3728 return mpWindowImpl && ImplGetWinData()->mbEnableNativeWidget;
3731 Reference< css::rendering::XCanvas > WindowOutputDevice::ImplGetCanvas( bool bSpriteCanvas ) const
3733 // Feed any with operating system's window handle
3735 // common: first any is VCL pointer to window (for VCL canvas)
3736 Sequence< Any > aArg{
3737 Any(reinterpret_cast<sal_Int64>(this)),
3738 Any(css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight )),
3739 Any(mxOwnerWindow->mpWindowImpl->mbAlwaysOnTop),
3740 Any(Reference< css::awt::XWindow >(
3741 mxOwnerWindow->GetComponentInterface(),
3742 UNO_QUERY )),
3743 GetSystemGfxDataAny()
3746 const Reference< XComponentContext >& xContext = comphelper::getProcessComponentContext();
3748 // Create canvas instance with window handle
3750 static tools::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
3751 css::rendering::CanvasFactory::create( xContext ) );
3752 Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
3753 Reference< css::rendering::XCanvas > xCanvas;
3755 if(xCanvasFactory.is())
3757 #ifdef _WIN32
3758 // see #140456# - if we're running on a multiscreen setup,
3759 // request special, multi-screen safe sprite canvas
3760 // implementation (not DX5 canvas, as it cannot cope with
3761 // surfaces spanning multiple displays). Note: canvas
3762 // (without sprite) stays the same)
3763 const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mxOwnerWindow->mpWindowImpl->mpFrame )->mnDisplay;
3764 if( nDisplay >= Application::GetScreenCount() )
3766 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3767 bSpriteCanvas ?
3768 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3769 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3770 aArg,
3771 xContext ),
3772 UNO_QUERY );
3775 else
3776 #endif
3778 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3779 bSpriteCanvas ?
3780 u"com.sun.star.rendering.SpriteCanvas"_ustr :
3781 u"com.sun.star.rendering.Canvas"_ustr,
3782 aArg,
3783 xContext ),
3784 UNO_QUERY );
3789 // no factory??? Empty reference, then.
3790 return xCanvas;
3793 OUString Window::GetSurroundingText() const
3795 return OUString();
3798 Selection Window::GetSurroundingTextSelection() const
3800 return Selection( 0, 0 );
3803 namespace
3805 using namespace com::sun::star;
3807 uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin)
3809 uno::Reference<accessibility::XAccessibleEditableText> xText;
3812 uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() );
3813 if (xAccessible.is())
3814 xText = FindFocusedEditableText(xAccessible->getAccessibleContext());
3816 catch(const uno::Exception&)
3818 TOOLS_WARN_EXCEPTION( "vcl.gtk3", "Exception in getting input method surrounding text");
3820 return xText;
3824 // this is a rubbish implementation using a11y, ideally all subclasses implementing
3825 // GetSurroundingText/GetSurroundingTextSelection should implement this and then this
3826 // should be removed in favor of a stub that returns false
3827 bool Window::DeleteSurroundingText(const Selection& rSelection)
3829 uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(this);
3830 if (xText.is())
3832 sal_Int32 nPosition = xText->getCaretPosition();
3833 // #i111768# range checking
3834 sal_Int32 nDeletePos = rSelection.Min();
3835 sal_Int32 nDeleteEnd = rSelection.Max();
3836 if (nDeletePos < 0)
3837 nDeletePos = 0;
3838 if (nDeleteEnd < 0)
3839 nDeleteEnd = 0;
3840 if (nDeleteEnd > xText->getCharacterCount())
3841 nDeleteEnd = xText->getCharacterCount();
3843 xText->deleteText(nDeletePos, nDeleteEnd);
3844 //tdf91641 adjust cursor if deleted chars shift it forward (normal case)
3845 if (nDeletePos < nPosition)
3847 if (nDeleteEnd <= nPosition)
3848 nPosition = nPosition - (nDeleteEnd - nDeletePos);
3849 else
3850 nPosition = nDeletePos;
3852 if (xText->getCharacterCount() >= nPosition)
3853 xText->setCaretPosition( nPosition );
3855 return true;
3858 return false;
3861 bool WindowOutputDevice::UsePolyPolygonForComplexGradient()
3863 return meRasterOp != RasterOp::OverPaint;
3866 void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
3870 const SystemEnvData* Window::GetSystemData() const
3873 return mpWindowImpl->mpFrame ? &mpWindowImpl->mpFrame->GetSystemData() : nullptr;
3876 bool Window::SupportsDoubleBuffering() const
3878 return mpWindowImpl->mpFrameData->mpBuffer;
3881 void Window::RequestDoubleBuffering(bool bRequest)
3883 if (bRequest)
3885 mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
3886 // Make sure that the buffer size matches the frame size.
3887 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
3889 else
3890 mpWindowImpl->mpFrameData->mpBuffer.reset();
3894 * The rationale here is that we moved destructors to
3895 * dispose and this altered a lot of code paths, that
3896 * are better left unchanged for now.
3898 void Window::CompatGetFocus()
3900 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3901 Window::GetFocus();
3902 else
3903 GetFocus();
3906 void Window::CompatLoseFocus()
3908 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3909 Window::LoseFocus();
3910 else
3911 LoseFocus();
3914 void Window::CompatStateChanged( StateChangedType nStateChange )
3916 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3917 Window::StateChanged(nStateChange);
3918 else
3919 StateChanged(nStateChange);
3922 void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
3924 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3925 Window::DataChanged(rDCEvt);
3926 else
3927 DataChanged(rDCEvt);
3930 bool Window::CompatPreNotify( NotifyEvent& rNEvt )
3932 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3933 return Window::PreNotify( rNEvt );
3934 else
3935 return PreNotify( rNEvt );
3938 bool Window::CompatNotify( NotifyEvent& rNEvt )
3940 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3941 return Window::EventNotify( rNEvt );
3942 else
3943 return EventNotify( rNEvt );
3946 void Window::set_id(const OUString& rID)
3948 mpWindowImpl->maID = rID;
3951 const OUString& Window::get_id() const
3953 static OUString empty;
3954 return mpWindowImpl ? mpWindowImpl->maID : empty;
3957 FactoryFunction Window::GetUITestFactory() const
3959 return WindowUIObject::create;
3962 WindowOutputDevice::WindowOutputDevice(vcl::Window& rOwnerWindow) :
3963 ::OutputDevice(OUTDEV_WINDOW),
3964 mxOwnerWindow(&rOwnerWindow)
3966 assert(mxOwnerWindow);
3969 WindowOutputDevice::~WindowOutputDevice()
3971 disposeOnce();
3974 void WindowOutputDevice::dispose()
3976 assert((!mxOwnerWindow || mxOwnerWindow->isDisposed()) && "This belongs to the associated window and must be disposed after it");
3977 ::OutputDevice::dispose();
3978 // need to do this after OutputDevice::dispose so that the call to WindowOutputDevice::ReleaseGraphics
3979 // can release the graphics properly
3980 mxOwnerWindow.clear();
3983 css::awt::DeviceInfo WindowOutputDevice::GetDeviceInfo() const
3985 css::awt::DeviceInfo aInfo = GetCommonDeviceInfo(mxOwnerWindow->GetSizePixel());
3986 mxOwnerWindow->GetBorder(aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset);
3987 return aInfo;
3991 } /* namespace vcl */
3993 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */