1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
54 #include <salinst.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>
84 #ifdef _WIN32 // see #140456#
85 #include <win/salframe.h>
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
;
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
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
130 return OString::Concat(" ") +
131 typeid( *pWindow
).name() +
135 RTL_TEXTENCODING_UTF8
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() )
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 );
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
);
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)
241 if (IsMouseCaptured())
244 #if OSL_DEBUG_LEVEL > 0
245 // always perform these tests in debug builds
247 OStringBuffer aErrorStr
;
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
;
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
;
271 if ( ImplIsRealParentPath( pTempWin
) )
274 aErrorStr
.append(lcl_createWindowInfo(pTempWin
));
276 pTempWin
= pTempWin
->mpWindowImpl
->mpNextOverlap
;
282 lcl_createWindowInfo(this) +
283 ") with live SystemWindows destroyed: " +
285 OSL_FAIL(aTempStr
.getStr());
286 Application::Abort(OStringToOUString(aTempStr
, RTL_TEXTENCODING_UTF8
));
291 pTempWin
= pSVData
->maFrameData
.mpFirstFrame
;
294 if ( ImplIsRealParentPath( pTempWin
) )
297 aErrorStr
.append(lcl_createWindowInfo(pTempWin
));
299 pTempWin
= pTempWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
303 OString aTempStr
= "Window (" +
304 lcl_createWindowInfo(this) +
305 ") with live SystemWindows destroyed: " +
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
;
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;
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
));
348 if( mpWindowImpl
->mbIsInTaskPaneList
)
350 vcl::Window
* pMyParent
= GetParent();
351 SystemWindow
* pMySysWin
= nullptr;
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 );
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
384 // EndExtTextInputMode
385 if (pSVData
->mpWinData
->mpExtTextInputWin
== this)
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
);
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;
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
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();
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
)
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
;
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
;
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();
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
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
;
653 mnGridLeftAttach
= -1;
654 mnGridTopAttach
= -1;
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.
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;
739 mbUseFrameData
= false;
742 WindowImpl::~WindowImpl()
744 mpChildClipRegion
.reset();
745 mpAccessibleInfos
.reset();
748 ImplWinData::ImplWinData() :
751 mnCompositionCharRects(0),
752 mnTrackFlags(ShowTrackFlags::NONE
),
753 mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
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
;
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;
792 mnFirstMouseCode
= 0;
794 mnMouseMode
= MouseEventModifiers::NONE
;
796 mbInMouseMove
= false;
798 mbStartDragCalled
= false;
799 mbNeedSysWindow
= 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;
811 mbInBufferedPaint
= false;
814 mnTouchPanPositionX
= -1;
815 mnTouchPanPositionY
= -1;
820 bool WindowOutputDevice::AcquireGraphics() const
822 DBG_TESTSOLARMUTEX();
830 mbInitLineColor
= true;
831 mbInitFillColor
= 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
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
)
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 );
859 // if needed retry after releasing least recently used wingraphics
860 while ( !mpGraphics
)
862 if ( !pSVData
->maGDIData
.mpLastWinGraphics
)
864 pSVData
->maGDIData
.mpLastWinGraphics
->ReleaseGraphics();
865 mpGraphics
= mxOwnerWindow
->mpWindowImpl
->mpFrame
->AcquireGraphics();
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();
894 // release the fonts of the physically released graphics device
898 ImplSVData
* pSVData
= ImplGetSVData();
900 vcl::Window
* pWindow
= mxOwnerWindow
.get();
905 pWindow
->mpWindowImpl
->mpFrame
->ReleaseGraphics( mpGraphics
);
906 // remove from global LRU list of window graphics
907 if ( mpPrevGraphics
)
908 mpPrevGraphics
->mpNextGraphics
= mpNextGraphics
;
910 pSVData
->maGDIData
.mpFirstWinGraphics
= static_cast<vcl::WindowOutputDevice
*>(mpNextGraphics
.get());
911 if ( mpNextGraphics
)
912 mpNextGraphics
->mpPrevGraphics
= mpPrevGraphics
;
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
)
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
931 else if (nDPI
> 168) // 96 * 2 - 96 / 4
933 else if (nDPI
> 120) // 96 * 1.5 - 96 / 4
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
;
951 if ( !mpWindowImpl
->mbOverlapWin
&& pParent
&& (pParent
->GetStyle() & 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
;
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
)
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
;
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;
1051 pParentFrame
= pParent
->mpWindowImpl
->mpFrame
;
1053 if ( pSystemParentData
)
1054 pFrame
= pSVData
->mpDefInst
->CreateChildFrame( pSystemParentData
, nFrameStyle
| SalFrameStyleFlags::PLUG
);
1056 pFrame
= pSVData
->mpDefInst
->CreateFrame( pParentFrame
, nFrameStyle
);
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 );
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
)
1094 mpWindowImpl
->mpFrameData
->mnDPIX
= pParent
->mpWindowImpl
->mpFrameData
->mnDPIX
;
1095 mpWindowImpl
->mpFrameData
->mnDPIY
= pParent
->mpWindowImpl
->mpFrameData
->mnDPIY
;
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
);
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() ) );
1167 SetTextColor( rStyleSettings
.GetWindowTextColor() );
1168 SetBackground( Wallpaper( rStyleSettings
.GetWindowColor() ) );
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;
1203 // FIXME: this is currently only on macOS, check with other
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;
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)
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
,
1256 mpGraphics
->CopyArea(aPosAry
.mnDestX
, aPosAry
.mnDestY
,
1257 aPosAry
.mnSrcX
, aPosAry
.mnSrcY
,
1258 aPosAry
.mnSrcWidth
, aPosAry
.mnSrcHeight
,
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;
1277 pSrcDevChecked
= &rSrcDev
;
1279 return pSrcDevChecked
;
1282 void WindowOutputDevice::DrawOutDevDirectProcess( const OutputDevice
& rSrcDev
, SalTwoRect
& rPosAry
, SalGraphics
* pSrcGraphics
)
1285 mpGraphics
->CopyBits(rPosAry
, *pSrcGraphics
, *this, rSrcDev
);
1287 mpGraphics
->CopyBits(rPosAry
, *this);
1290 SalGraphics
* Window::ImplGetFrameGraphics() const
1292 if ( mpWindowImpl
->mpFrameWindow
->GetOutDev()->mpGraphics
)
1294 mpWindowImpl
->mpFrameWindow
->GetOutDev()->mbInitClipRegion
= true;
1298 OutputDevice
* pFrameWinOutDev
= mpWindowImpl
->mpFrameWindow
->GetOutDev();
1299 if ( ! pFrameWinOutDev
->AcquireGraphics() )
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
)
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
;
1334 if ( pWindow
->mpWindowImpl
->mbVisible
)
1335 pWindow
->ImplSetReallyVisible();
1336 pWindow
= pWindow
->mpWindowImpl
->mpNext
;
1339 pWindow
= mpWindowImpl
->mpFirstChild
;
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();
1374 SetMapMode( aMapMode
);
1378 void Window::ImplPointToLogic(vcl::RenderContext
const & rRenderContext
, vcl::Font
& rFont
,
1379 bool bUseRenderContextDPI
) const
1381 Size aSize
= rFont
.GetFontSize();
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
);
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
;
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
;
1438 if ( pChild
->ImplUpdatePos() )
1440 pChild
= pChild
->mpWindowImpl
->mpNext
;
1443 if ( mpWindowImpl
->mpSysObj
)
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
;
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() &&
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
1501 if ( nWidth
!= GetOutDev()->mnOutWidth
)
1503 GetOutDev()->mnOutWidth
= nWidth
;
1508 if ( nFlags
& PosSizeFlags::Height
)
1512 if ( nHeight
!= GetOutDev()->mnOutHeight
)
1514 GetOutDev()->mnOutHeight
= nHeight
;
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
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();
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
);
1586 if ( !(bNewPos
|| bNewSize
) )
1589 bool bUpdateSysObjPos
= false;
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
;
1610 if ( mpWindowImpl
->mpClientWindow
->IsVisible() )
1612 mpWindowImpl
->mpClientWindow
->ImplCallMove();
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()
1637 mpWindowImpl
->mbCallMove
= true;
1639 mpWindowImpl
->mbCallResize
= true;
1642 bool bUpdateSysObjClip
= false;
1643 if ( IsReallyVisible() )
1645 if ( bNewPos
|| bNewSize
)
1648 bUpdateSysObjClip
= !ImplSetClipFlag( true );
1651 // invalidate window content ?
1652 if ( bNewPos
|| (GetOutDev()->mnOutWidth
> nOldOutWidth
) || (GetOutDev()->mnOutHeight
> nOldOutHeight
) )
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
,
1678 SalGraphics
* pGraphics
= ImplGetFrameGraphics();
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
,
1698 if ( !pOverlapRegion
->IsEmpty() )
1699 ImplInvalidateFrameRegion( pOverlapRegion
.get(), InvalidateFlags::Children
);
1708 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children
);
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
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() )
1751 // Is InputContext changed?
1752 const InputContext
& rInputContext
= pFocusWin
->GetInputContext();
1753 if ( rInputContext
== pFocusWin
->mpWindowImpl
->mpFrameData
->maOldInputContext
)
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 );
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
))
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() )
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
);
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
);
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
);
1914 Help
* pHelp
= Application::GetHelp();
1917 if( !aStrHelpId
.isEmpty() )
1918 pHelp
->Start( aStrHelpId
, this );
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 );
1940 pWrapper
->Tracking( rTEvt
);
1943 void Window::StateChanged(StateChangedType 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
:
1958 //stuff that does invalidate the layout
1960 queue_resize(eType
);
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
)
1981 vcl::Window
* pWindow
= ImplGetBorderWindow();
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
)
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
) );
2030 if ( mpWindowImpl
->mpBorderWindow
->GetType() == WindowType::BORDERWINDOW
)
2031 static_cast<ImplBorderWindow
*>(mpWindowImpl
->mpBorderWindow
.get())->SetBorderStyle( nBorderStyle
);
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();
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();
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;
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
)
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
);
2101 case VclEventId::EndExtTextInput
:
2102 ImplWindowFrameProc(this, SalEvent::EndExtTextInput
, nullptr);
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
)
2122 pWinData
->mpCursorRect
= *pRect
;
2124 pWinData
->mpCursorRect
.reset();
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
;
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
);
2191 void Window::Show(bool bVisible
, ShowFlags nFlags
)
2193 if ( !mpWindowImpl
|| mpWindowImpl
->mbVisible
== bVisible
)
2196 VclPtr
<vcl::Window
> xWindow(this);
2198 bool bRealVisibilityChanged
= false;
2199 mpWindowImpl
->mbVisible
= bVisible
;
2203 ImplHideAllOverlaps();
2204 if( !xWindow
->mpWindowImpl
)
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
)
2233 bRealVisibilityChanged
= mpWindowImpl
->mbReallyVisible
;
2234 ImplResetReallyVisible();
2237 if ( ImplIsOverlapWindow() && !mpWindowImpl
->mbFrame
)
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();
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
)
2295 if ( mpWindowImpl
->mbCallResize
)
2300 CompatStateChanged( StateChangedType::Visible
);
2302 vcl::Window
* pTestParent
;
2303 if ( ImplIsOverlapWindow() )
2304 pTestParent
= mpWindowImpl
->mpOverlapWindow
;
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
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
2331 // adjust mpWindowImpl->mbReallyVisible
2332 bRealVisibilityChanged
= !mpWindowImpl
->mbReallyVisible
;
2333 ImplSetReallyVisible();
2335 // assure clip rectangles will be recalculated
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();
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
)
2380 // Query the correct size of the window, if we are waiting for
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
)
2398 ImplShowAllOverlaps();
2401 if( !xWindow
->mpWindowImpl
)
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
2417 SAL_WARN("vcl.layout", "WTF no windowimpl");
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() )
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
)
2451 // the tracking mode will be stopped or the capture will be stolen
2452 // when a window is disabled,
2454 EndTracking( TrackingEventFlags::Cancel
);
2455 if ( IsMouseCaptured() )
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
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
);
2492 VclPtr
< vcl::Window
> pChild
= mpWindowImpl
->mpFirstChild
;
2495 pChild
->Enable( bEnable
, bChild
);
2496 pChild
= pChild
->mpWindowImpl
->mpNext
;
2500 if ( IsReallyVisible() )
2501 ImplGenerateMouseMove();
2504 void Window::EnableInput( bool bEnable
, bool bChild
)
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
2524 EndTracking( TrackingEventFlags::Cancel
);
2525 if ( IsMouseCaptured() )
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;
2546 VclPtr
< vcl::Window
> pChild
= mpWindowImpl
->mpFirstChild
;
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
)
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
;
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
;
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
)
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
;
2637 VclPtr
< vcl::Window
> pChild
= mpWindowImpl
->mpFirstChild
;
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
)
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;
2669 if ( !mpWindowImpl
->mbActive
|| (GetType() == WindowType::BORDERWINDOW
) )
2671 mpWindowImpl
->mbActive
= true;
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
);
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
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
;
2744 myWidth
= aSysGeometry
.width();
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() );
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
);
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
);
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
;
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();
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()) );
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() );
2897 Point p2
= rRect
.BottomLeft();
2898 p2
= OutputToScreenPixel(p2
);
2899 p2
.setX( g
.x()+g
.width()-p2
.X() );
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() );
2917 p2
.setX( g
.x()+g
.width()-p2
.X() );
2918 p2
= ScreenToOutputPixel(p2
);
2920 return tools::Rectangle( p1
, p2
);
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() ),
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
)
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
;
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
;
3021 return ImplIsWindowOrChild( pFocusWin
, bSystemWindow
);
3025 void Window::SetCursor( vcl::Cursor
* pCursor
)
3028 if ( mpWindowImpl
->mpCursor
!= pCursor
)
3030 if ( mpWindowImpl
->mpCursor
)
3031 mpWindowImpl
->mpCursor
->ImplHide();
3032 mpWindowImpl
->mpCursor
= pCursor
;
3034 pCursor
->ImplShow();
3038 void Window::SetText( const OUString
& rStr
)
3040 if (!mpWindowImpl
|| rStr
== mpWindowImpl
->maText
)
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
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
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();
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" );
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
)
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!" );
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();
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!" );
3160 pWrapper
->SetWindowInterface( this, xIFace
);
3163 typedef std::map
<vcl::LOKWindowId
, VclPtr
<vcl::Window
>> LOKWindowsMap
;
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);
3182 // never use this in the desktop case
3183 assert(comphelper::LibreOfficeKit::isActive());
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())
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())
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
);
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();
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";
3357 void Window::DumpAsPropertyTree(tools::JsonWriter
& rJsonWriter
)
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());
3367 rJsonWriter
.put("visible", false);
3369 if (vcl::Window
* pChild
= mpWindowImpl
->mpFirstChild
)
3371 auto childrenNode
= rJsonWriter
.startArray("children");
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();
3387 rJsonWriter
.put("width", nWidth
);
3389 pChild
= pChild
->mpWindowImpl
->mpNext
;
3393 vcl::Window
* pAccLabelFor
= getAccessibleRelationLabelFor();
3395 rJsonWriter
.put("labelFor", pAccLabelFor
->get_id());
3397 vcl::Window
* pAccLabelledBy
= GetAccessibleRelationLabeledBy();
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
)
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
))
3443 VclPtr
<vcl::Window
> xWindow(this);
3444 CallEventListeners( VclEventId::WindowActivate
, pOld
);
3445 if( !xWindow
->mpWindowImpl
)
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
,
3487 if( rRect
.IsEmpty() )
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 )
3506 aSelectionFillCol
.RGBtoHSB( h
, s
, b
);
3507 if( b
> 50 ) 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();
3518 GetOutDev()->SetLineColor( bDark
? COL_WHITE
: ( bBright
? COL_BLACK
: aSelectionBorderCol
) );
3520 GetOutDev()->SetLineColor();
3522 sal_uInt16 nPercent
= 0;
3526 aSelectionFillCol
= COL_BLACK
;
3528 nPercent
= 80; // just checked (light)
3532 if( bChecked
&& highlight
== 2 )
3535 aSelectionFillCol
= COL_LIGHTGRAY
;
3538 aSelectionFillCol
= COL_BLACK
;
3539 GetOutDev()->SetLineColor( COL_BLACK
);
3543 nPercent
= 20; // selected, pressed or checked ( very dark )
3545 else if( bChecked
|| highlight
== 1 )
3548 aSelectionFillCol
= COL_GRAY
;
3551 aSelectionFillCol
= COL_BLACK
;
3552 GetOutDev()->SetLineColor( COL_BLACK
);
3556 nPercent
= 35; // selected, pressed or checked ( very dark )
3561 aSelectionFillCol
= COL_LIGHTGRAY
;
3564 aSelectionFillCol
= COL_BLACK
;
3565 GetOutDev()->SetLineColor( COL_BLACK
);
3566 if( highlight
== 3 )
3572 nPercent
= 70; // selected ( dark )
3576 GetOutDev()->SetFillColor( aSelectionFillCol
);
3580 GetOutDev()->DrawRect( aRect
);
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
;
3599 if( pChild
->GetType() == WindowType::SCROLLBAR
)
3602 pChild
= pChild
->mpWindowImpl
->mpNext
;
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
3663 vcl::Window
*pFrameWin
= ImplGetSVData()->maFrameData
.mpFirstFrame
;
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 ) )
3687 pFrameWin
= pFrameWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
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
)
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
;
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(),
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())
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(
3768 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3769 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3778 xCanvas
.set( xCanvasFactory
->createInstanceWithArgumentsAndContext(
3780 u
"com.sun.star.rendering.SpriteCanvas"_ustr
:
3781 u
"com.sun.star.rendering.Canvas"_ustr
,
3789 // no factory??? Empty reference, then.
3793 OUString
Window::GetSurroundingText() const
3798 Selection
Window::GetSurroundingTextSelection() const
3800 return Selection( 0, 0 );
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");
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);
3832 sal_Int32 nPosition
= xText
->getCaretPosition();
3833 // #i111768# range checking
3834 sal_Int32 nDeletePos
= rSelection
.Min();
3835 sal_Int32 nDeleteEnd
= rSelection
.Max();
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
);
3850 nPosition
= nDeletePos
;
3852 if (xText
->getCharacterCount() >= nPosition
)
3853 xText
->setCaretPosition( nPosition
);
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
)
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());
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
)
3906 void Window::CompatLoseFocus()
3908 if (!mpWindowImpl
|| mpWindowImpl
->mbInDispose
)
3909 Window::LoseFocus();
3914 void Window::CompatStateChanged( StateChangedType nStateChange
)
3916 if (!mpWindowImpl
|| mpWindowImpl
->mbInDispose
)
3917 Window::StateChanged(nStateChange
);
3919 StateChanged(nStateChange
);
3922 void Window::CompatDataChanged( const DataChangedEvent
& rDCEvt
)
3924 if (!mpWindowImpl
|| mpWindowImpl
->mbInDispose
)
3925 Window::DataChanged(rDCEvt
);
3927 DataChanged(rDCEvt
);
3930 bool Window::CompatPreNotify( NotifyEvent
& rNEvt
)
3932 if (!mpWindowImpl
|| mpWindowImpl
->mbInDispose
)
3933 return Window::PreNotify( rNEvt
);
3935 return PreNotify( rNEvt
);
3938 bool Window::CompatNotify( NotifyEvent
& rNEvt
)
3940 if (!mpWindowImpl
|| mpWindowImpl
->mbInDispose
)
3941 return Window::EventNotify( rNEvt
);
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()
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
);
3991 } /* namespace vcl */
3993 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */